@shival99/z-ui 1.4.2 → 1.4.3

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.
Files changed (76) hide show
  1. package/fesm2022/shival99-z-ui-components-z-accordion.mjs +2 -2
  2. package/fesm2022/shival99-z-ui-components-z-accordion.mjs.map +1 -1
  3. package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs +3 -3
  4. package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs.map +1 -1
  5. package/fesm2022/shival99-z-ui-components-z-button.mjs +2 -2
  6. package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -1
  7. package/fesm2022/shival99-z-ui-components-z-calendar.mjs +31 -18
  8. package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
  9. package/fesm2022/shival99-z-ui-components-z-card.mjs +5 -5
  10. package/fesm2022/shival99-z-ui-components-z-card.mjs.map +1 -1
  11. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +16 -10
  12. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -1
  13. package/fesm2022/shival99-z-ui-components-z-code.mjs +7 -7
  14. package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -1
  15. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +4 -4
  16. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -1
  17. package/fesm2022/shival99-z-ui-components-z-editor.mjs +4 -4
  18. package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
  19. package/fesm2022/shival99-z-ui-components-z-filter.mjs +8 -8
  20. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
  21. package/fesm2022/shival99-z-ui-components-z-input.mjs +192 -182
  22. package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -1
  23. package/fesm2022/shival99-z-ui-components-z-menu.mjs +5 -5
  24. package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
  25. package/fesm2022/shival99-z-ui-components-z-pagination.mjs +5 -5
  26. package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -1
  27. package/fesm2022/shival99-z-ui-components-z-popover.mjs +12 -12
  28. package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -1
  29. package/fesm2022/shival99-z-ui-components-z-radio.mjs +4 -4
  30. package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -1
  31. package/fesm2022/shival99-z-ui-components-z-select.mjs +179 -168
  32. package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -1
  33. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +2 -2
  34. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -1
  35. package/fesm2022/shival99-z-ui-components-z-steps.mjs +5 -5
  36. package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -1
  37. package/fesm2022/shival99-z-ui-components-z-switch.mjs +4 -4
  38. package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -1
  39. package/fesm2022/shival99-z-ui-components-z-table.mjs +343 -36
  40. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -1
  41. package/fesm2022/shival99-z-ui-components-z-tags.mjs +12 -11
  42. package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -1
  43. package/fesm2022/shival99-z-ui-components-z-timeline.mjs +0 -2
  44. package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -1
  45. package/fesm2022/shival99-z-ui-components-z-toast.mjs +3 -3
  46. package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -1
  47. package/fesm2022/shival99-z-ui-components-z-upload.mjs +12 -12
  48. package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -1
  49. package/fesm2022/shival99-z-ui-services.mjs +9 -9
  50. package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
  51. package/package.json +1 -1
  52. package/types/shival99-z-ui-components-z-accordion.d.ts +1 -1
  53. package/types/shival99-z-ui-components-z-breadcrumb.d.ts +1 -1
  54. package/types/shival99-z-ui-components-z-button.d.ts +1 -1
  55. package/types/shival99-z-ui-components-z-calendar.d.ts +22 -8
  56. package/types/shival99-z-ui-components-z-card.d.ts +3 -3
  57. package/types/shival99-z-ui-components-z-checkbox.d.ts +8 -5
  58. package/types/shival99-z-ui-components-z-code.d.ts +5 -5
  59. package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +2 -2
  60. package/types/shival99-z-ui-components-z-editor.d.ts +4 -4
  61. package/types/shival99-z-ui-components-z-filter.d.ts +8 -8
  62. package/types/shival99-z-ui-components-z-input.d.ts +47 -35
  63. package/types/shival99-z-ui-components-z-menu.d.ts +3 -3
  64. package/types/shival99-z-ui-components-z-modal.d.ts +1 -1
  65. package/types/shival99-z-ui-components-z-pagination.d.ts +3 -3
  66. package/types/shival99-z-ui-components-z-popover.d.ts +10 -10
  67. package/types/shival99-z-ui-components-z-radio.d.ts +2 -2
  68. package/types/shival99-z-ui-components-z-select.d.ts +59 -46
  69. package/types/shival99-z-ui-components-z-skeleton.d.ts +1 -1
  70. package/types/shival99-z-ui-components-z-steps.d.ts +3 -3
  71. package/types/shival99-z-ui-components-z-switch.d.ts +2 -2
  72. package/types/shival99-z-ui-components-z-table.d.ts +77 -9
  73. package/types/shival99-z-ui-components-z-tags.d.ts +4 -2
  74. package/types/shival99-z-ui-components-z-timeline.d.ts +6 -6
  75. package/types/shival99-z-ui-components-z-toast.d.ts +2 -2
  76. package/types/shival99-z-ui-components-z-upload.d.ts +13 -13
@@ -1,6 +1,6 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { input, output, viewChild, signal, computed, inject, Injector, DestroyRef, TemplateRef, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { inject, Injector, DestroyRef, viewChild, output, input, signal, computed, TemplateRef, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import * as i1 from '@angular/forms';
6
6
  import { NgControl, NgModel, PristineChangeEvent, TouchedChangeEvent, FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -70,6 +70,14 @@ const zTextareaVariants = cva([
70
70
  });
71
71
 
72
72
  class ZInputComponent {
73
+ _injector = inject(Injector);
74
+ _destroyRef = inject(DestroyRef);
75
+ _toastService = inject(ZToastService);
76
+ _zTranslate = inject(ZTranslateService);
77
+ inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
78
+ zOnSearch = output();
79
+ zOnChange = output();
80
+ zControl = output();
73
81
  class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
74
82
  zType = input('text', ...(ngDevMode ? [{ debugName: "zType" }] : []));
75
83
  zSize = input('default', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
@@ -105,32 +113,6 @@ class ZInputComponent {
105
113
  zResize = input(true, { ...(ngDevMode ? { debugName: "zResize" } : {}), transform: zTransform });
106
114
  zMaxLength = input(undefined, ...(ngDevMode ? [{ debugName: "zMaxLength" }] : []));
107
115
  zAutoSuggest = input(undefined, ...(ngDevMode ? [{ debugName: "zAutoSuggest" }] : []));
108
- zOnSearch = output();
109
- zOnChange = output();
110
- zControl = output();
111
- inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
112
- inputId = zUuid('z-input');
113
- passwordVisible = signal(false, ...(ngDevMode ? [{ debugName: "passwordVisible" }] : []));
114
- isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
115
- suggestHistory = signal([], ...(ngDevMode ? [{ debugName: "suggestHistory" }] : []));
116
- suggestActiveIndex = signal(-1, ...(ngDevMode ? [{ debugName: "suggestActiveIndex" }] : []));
117
- showSuggestPopover = signal(false, ...(ngDevMode ? [{ debugName: "showSuggestPopover" }] : []));
118
- filteredSuggestHistory = computed(() => {
119
- const history = this.suggestHistory();
120
- const currentValue = String(this._value() ?? '')
121
- .toLowerCase()
122
- .trim();
123
- if (!currentValue) {
124
- return history;
125
- }
126
- const matching = [];
127
- const nonMatching = [];
128
- for (const item of history) {
129
- const target = item.toLowerCase().includes(currentValue) ? matching : nonMatching;
130
- target.push(item);
131
- }
132
- return [...matching, ...nonMatching];
133
- }, ...(ngDevMode ? [{ debugName: "filteredSuggestHistory" }] : []));
134
116
  _value = signal(null, ...(ngDevMode ? [{ debugName: "_value" }] : []));
135
117
  _touched = signal(false, ...(ngDevMode ? [{ debugName: "_touched" }] : []));
136
118
  _disabled = signal(false, ...(ngDevMode ? [{ debugName: "_disabled" }] : []));
@@ -138,29 +120,25 @@ class ZInputComponent {
138
120
  _formControl = signal(null, ...(ngDevMode ? [{ debugName: "_formControl" }] : []));
139
121
  _formStateVersion = signal(0, ...(ngDevMode ? [{ debugName: "_formStateVersion" }] : []));
140
122
  _isNgModel = signal(false, ...(ngDevMode ? [{ debugName: "_isNgModel" }] : []));
141
- _injector = inject(Injector);
142
- _destroyRef = inject(DestroyRef);
143
- _toastService = inject(ZToastService);
144
- _zTranslate = inject(ZTranslateService);
145
- _searchSubject = new Subject();
146
- _changeSubject = new Subject();
147
- _asyncValidationSubject = new Subject();
148
- isValidating = signal(false, ...(ngDevMode ? [{ debugName: "isValidating" }] : []));
149
123
  _asyncErrors = signal(new Map(), ...(ngDevMode ? [{ debugName: "_asyncErrors" }] : []));
150
- _asyncCancelSubject = new Subject();
151
- _asyncValidationAbortController = null;
152
- _onChange = () => void 0;
153
- _onTouched = () => void 0;
154
- _ngControl = null;
124
+ inputId = zUuid('z-input');
125
+ suggestHistory = signal([], ...(ngDevMode ? [{ debugName: "suggestHistory" }] : []));
126
+ suggestActiveIndex = signal(-1, ...(ngDevMode ? [{ debugName: "suggestActiveIndex" }] : []));
127
+ isValidating = signal(false, ...(ngDevMode ? [{ debugName: "isValidating" }] : []));
128
+ uiState = signal({
129
+ passwordVisible: false,
130
+ isFocused: false,
131
+ showSuggestPopover: false,
132
+ colorCopied: false,
133
+ }, ...(ngDevMode ? [{ debugName: "uiState" }] : []));
155
134
  isDisabled = computed(() => this._disabled() || this.zDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
156
135
  isPasswordType = computed(() => this.zType() === 'password', ...(ngDevMode ? [{ debugName: "isPasswordType" }] : []));
157
136
  isColorType = computed(() => this.zType() === 'color', ...(ngDevMode ? [{ debugName: "isColorType" }] : []));
158
- colorCopied = signal(false, ...(ngDevMode ? [{ debugName: "colorCopied" }] : []));
159
137
  isPrefixTemplate = computed(() => this.zPrefix() instanceof TemplateRef, ...(ngDevMode ? [{ debugName: "isPrefixTemplate" }] : []));
160
138
  isSuffixTemplate = computed(() => this.zSuffix() instanceof TemplateRef, ...(ngDevMode ? [{ debugName: "isSuffixTemplate" }] : []));
161
139
  isTextarea = computed(() => this.zType() === 'textarea', ...(ngDevMode ? [{ debugName: "isTextarea" }] : []));
162
140
  effectiveType = computed(() => {
163
- if (this.zType() === 'password' && this.passwordVisible()) {
141
+ if (this.zType() === 'password' && this.uiState().passwordVisible) {
164
142
  return 'text';
165
143
  }
166
144
  if (this.zType() === 'number' && this.effectiveMask()) {
@@ -200,6 +178,22 @@ class ZInputComponent {
200
178
  }
201
179
  return String(val);
202
180
  }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
181
+ filteredSuggestHistory = computed(() => {
182
+ const history = this.suggestHistory();
183
+ const currentValue = String(this._value() ?? '')
184
+ .toLowerCase()
185
+ .trim();
186
+ if (!currentValue) {
187
+ return history;
188
+ }
189
+ const matching = [];
190
+ const nonMatching = [];
191
+ for (const item of history) {
192
+ const target = item.toLowerCase().includes(currentValue) ? matching : nonMatching;
193
+ target.push(item);
194
+ }
195
+ return [...matching, ...nonMatching];
196
+ }, ...(ngDevMode ? [{ debugName: "filteredSuggestHistory" }] : []));
203
197
  _shouldShowValidation = computed(() => {
204
198
  const control = this._formControl();
205
199
  this._formStateVersion();
@@ -290,6 +284,22 @@ class ZInputComponent {
290
284
  return value !== null && value !== undefined && value !== '';
291
285
  }, ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
292
286
  showClearButton = computed(() => this.zAllowClear() && this.hasValue() && !this.isDisabled() && !this.zReadonly(), ...(ngDevMode ? [{ debugName: "showClearButton" }] : []));
287
+ state = computed(() => ({
288
+ focused: this.uiState().isFocused,
289
+ touched: this._touched(),
290
+ blurred: !this.uiState().isFocused,
291
+ dirty: this._dirty(),
292
+ disabled: this.isDisabled(),
293
+ readonly: this.zReadonly(),
294
+ }), ...(ngDevMode ? [{ debugName: "state" }] : []));
295
+ _searchSubject = new Subject();
296
+ _changeSubject = new Subject();
297
+ _asyncValidationSubject = new Subject();
298
+ _asyncCancelSubject = new Subject();
299
+ _asyncValidationAbortController = null;
300
+ _onChange = () => void 0;
301
+ _onTouched = () => void 0;
302
+ _ngControl = null;
293
303
  ngOnInit() {
294
304
  queueMicrotask(() => {
295
305
  try {
@@ -331,86 +341,6 @@ class ZInputComponent {
331
341
  }, 20);
332
342
  }
333
343
  }
334
- async _runAsyncValidation(value) {
335
- const asyncValidators = this.zAsyncValidators();
336
- if (asyncValidators.length === 0) {
337
- return;
338
- }
339
- if ((value === null || value === undefined || value === '') && !this.zRequired()) {
340
- this._asyncErrors.set(new Map());
341
- this.isValidating.set(false);
342
- return;
343
- }
344
- this._cancelAsyncValidation();
345
- this._asyncValidationAbortController = new AbortController();
346
- const { signal } = this._asyncValidationAbortController;
347
- this.isValidating.set(true);
348
- const errors = new Map();
349
- try {
350
- const validationPromises = asyncValidators.map(async (validator) => {
351
- if (signal.aborted) {
352
- return null;
353
- }
354
- try {
355
- const result = validator.validate(value);
356
- if (!isObservable(result)) {
357
- const isValid = await result;
358
- if (signal.aborted) {
359
- return null;
360
- }
361
- return { validator, isValid };
362
- }
363
- const safeResult$ = result.pipe(takeUntil(this._asyncCancelSubject), catchError(err => {
364
- console.error(`Async validation error for ${validator.error}:`, err);
365
- return of(false);
366
- }));
367
- const isValid = await firstValueFrom(safeResult$);
368
- if (signal.aborted) {
369
- return null;
370
- }
371
- return { validator, isValid };
372
- }
373
- catch (error) {
374
- if (!signal.aborted) {
375
- console.error(`Async validation error for ${validator.error}:`, error);
376
- return {
377
- validator,
378
- isValid: false,
379
- error: true,
380
- };
381
- }
382
- return null;
383
- }
384
- });
385
- const results = await Promise.all(validationPromises);
386
- if (signal.aborted) {
387
- return;
388
- }
389
- for (const result of results) {
390
- if (result && !result.isValid) {
391
- errors.set(result.validator.error, result.validator.message);
392
- }
393
- }
394
- this._asyncErrors.set(errors);
395
- }
396
- catch (error) {
397
- if (!signal.aborted) {
398
- console.error('Async validation error:', error);
399
- }
400
- }
401
- finally {
402
- if (!signal.aborted) {
403
- this.isValidating.set(false);
404
- }
405
- }
406
- }
407
- _cancelAsyncValidation() {
408
- if (this._asyncValidationAbortController) {
409
- this._asyncValidationAbortController.abort();
410
- this._asyncValidationAbortController = null;
411
- }
412
- this._asyncCancelSubject.next();
413
- }
414
344
  writeValue(value) {
415
345
  this._value.set(value);
416
346
  }
@@ -471,6 +401,22 @@ class ZInputComponent {
471
401
  getValue() {
472
402
  return this._value();
473
403
  }
404
+ saveToSuggestHistory(value) {
405
+ const key = this.zAutoSuggest();
406
+ if (!key || !value || value.trim() === '') {
407
+ return;
408
+ }
409
+ const cacheKey = `autosuggest-${key}`;
410
+ let history = ZCacheService.get(cacheKey, []) ?? [];
411
+ const trimmedValue = value.trim();
412
+ history = history.filter(item => item !== trimmedValue);
413
+ history.unshift(trimmedValue);
414
+ if (history.length > 5) {
415
+ history = history.slice(0, 5);
416
+ }
417
+ ZCacheService.set(cacheKey, history);
418
+ this.suggestHistory.set(history);
419
+ }
474
420
  clearValue(event) {
475
421
  event.stopPropagation();
476
422
  this._value.set(null);
@@ -482,23 +428,6 @@ class ZInputComponent {
482
428
  }
483
429
  this.focus();
484
430
  }
485
- _emitControl() {
486
- this.zControl.emit({
487
- validate: () => this.validate(),
488
- reset: () => this.reset(),
489
- focus: () => this.focus(),
490
- blur: () => this.blur(),
491
- markAsTouched: () => this.markAsTouched(),
492
- markAsUntouched: () => this.markAsUntouched(),
493
- markAsDirty: () => this.markAsDirty(),
494
- markAsPristine: () => this.markAsPristine(),
495
- setValue: (value) => this.setValue(value),
496
- hasError: this.hasError,
497
- isValidating: this.isValidating,
498
- value: this._value.asReadonly(),
499
- errorMessage: this.errorMessage,
500
- });
501
- }
502
431
  onInput(event) {
503
432
  const { value: rawValue } = event.target;
504
433
  let value = rawValue;
@@ -528,7 +457,6 @@ class ZInputComponent {
528
457
  this._value.set(value);
529
458
  this._dirty.set(true);
530
459
  this._onChange(value);
531
- // Emit debounced change event
532
460
  this._changeSubject.next(value);
533
461
  if (this.zSearch()) {
534
462
  this._searchSubject.next(value);
@@ -536,7 +464,7 @@ class ZInputComponent {
536
464
  if (this.zAsyncValidators().length > 0 && this.zAsyncValidateOn() === 'change') {
537
465
  this._asyncValidationSubject.next(value);
538
466
  }
539
- if (this.hasAutoSuggest() && this.isFocused()) {
467
+ if (this.hasAutoSuggest() && this.uiState().isFocused) {
540
468
  this._loadSuggestHistory();
541
469
  if (this.suggestHistory().length > 0) {
542
470
  this._showSuggestPopover();
@@ -549,7 +477,7 @@ class ZInputComponent {
549
477
  this._touched.set(true);
550
478
  }
551
479
  this._onTouched();
552
- this.isFocused.set(false);
480
+ this.uiState.update(s => ({ ...s, isFocused: false }));
553
481
  if (this.zAsyncValidators().length > 0 && this.zAsyncValidateOn() === 'blur') {
554
482
  this._asyncValidationSubject.next(this._value());
555
483
  }
@@ -564,7 +492,7 @@ class ZInputComponent {
564
492
  }
565
493
  }
566
494
  onFocus() {
567
- this.isFocused.set(true);
495
+ this.uiState.update(s => ({ ...s, isFocused: true }));
568
496
  this._loadSuggestHistory();
569
497
  if (this.hasAutoSuggest() && this.suggestHistory().length > 0) {
570
498
  this._showSuggestPopover();
@@ -588,7 +516,7 @@ class ZInputComponent {
588
516
  if (event.key === 'Enter' && this.hasAutoSuggest()) {
589
517
  const activeIndex = this.suggestActiveIndex();
590
518
  const history = this.filteredSuggestHistory();
591
- if (this.showSuggestPopover() && activeIndex >= 0 && activeIndex < history.length) {
519
+ if (this.uiState().showSuggestPopover && activeIndex >= 0 && activeIndex < history.length) {
592
520
  event.preventDefault();
593
521
  this.selectSuggestItem(history[activeIndex]);
594
522
  return;
@@ -604,7 +532,7 @@ class ZInputComponent {
604
532
  }
605
533
  return;
606
534
  }
607
- if (!this.hasAutoSuggest() || !this.showSuggestPopover()) {
535
+ if (!this.hasAutoSuggest() || !this.uiState().showSuggestPopover) {
608
536
  return;
609
537
  }
610
538
  const history = this.filteredSuggestHistory();
@@ -647,27 +575,127 @@ class ZInputComponent {
647
575
  this.suggestActiveIndex.set(-1);
648
576
  }, 150);
649
577
  }
650
- _showSuggestPopover() {
651
- this.showSuggestPopover.set(true);
578
+ onArrowClick(event, direction) {
579
+ event.preventDefault();
580
+ const multiplier = direction === 'up' ? 1 : -1;
581
+ this._incrementValue(multiplier);
652
582
  }
653
- _hideSuggestPopover() {
654
- this.showSuggestPopover.set(false);
583
+ togglePasswordVisibility() {
584
+ this.uiState.update(s => ({ ...s, passwordVisible: !s.passwordVisible }));
655
585
  }
656
- saveToSuggestHistory(value) {
657
- const key = this.zAutoSuggest();
658
- if (!key || !value || value.trim() === '') {
586
+ copyColorToClipboard() {
587
+ const colorValue = String(this._value() || '#000000').toUpperCase();
588
+ void navigator.clipboard.writeText(colorValue).then(() => {
589
+ this.uiState.update(s => ({ ...s, colorCopied: true }));
590
+ this._toastService.success(`Copied ${colorValue}`);
591
+ setTimeout(() => {
592
+ this.uiState.update(s => ({ ...s, colorCopied: false }));
593
+ }, 1500);
594
+ });
595
+ }
596
+ _emitControl() {
597
+ this.zControl.emit({
598
+ validate: () => this.validate(),
599
+ reset: () => this.reset(),
600
+ focus: () => this.focus(),
601
+ blur: () => this.blur(),
602
+ markAsTouched: () => this.markAsTouched(),
603
+ markAsUntouched: () => this.markAsUntouched(),
604
+ markAsDirty: () => this.markAsDirty(),
605
+ markAsPristine: () => this.markAsPristine(),
606
+ setValue: (value) => this.setValue(value),
607
+ hasError: this.hasError,
608
+ isValidating: this.isValidating,
609
+ value: this._value.asReadonly(),
610
+ errorMessage: this.errorMessage,
611
+ state: this.state,
612
+ });
613
+ }
614
+ async _runAsyncValidation(value) {
615
+ const asyncValidators = this.zAsyncValidators();
616
+ if (asyncValidators.length === 0) {
659
617
  return;
660
618
  }
661
- const cacheKey = `autosuggest-${key}`;
662
- let history = ZCacheService.get(cacheKey, []) ?? [];
663
- const trimmedValue = value.trim();
664
- history = history.filter(item => item !== trimmedValue);
665
- history.unshift(trimmedValue);
666
- if (history.length > 5) {
667
- history = history.slice(0, 5);
619
+ if ((value === null || value === undefined || value === '') && !this.zRequired()) {
620
+ this._asyncErrors.set(new Map());
621
+ this.isValidating.set(false);
622
+ return;
668
623
  }
669
- ZCacheService.set(cacheKey, history);
670
- this.suggestHistory.set(history);
624
+ this._cancelAsyncValidation();
625
+ this._asyncValidationAbortController = new AbortController();
626
+ const { signal } = this._asyncValidationAbortController;
627
+ this.isValidating.set(true);
628
+ const errors = new Map();
629
+ try {
630
+ const validationPromises = asyncValidators.map(async (validator) => {
631
+ if (signal.aborted) {
632
+ return null;
633
+ }
634
+ try {
635
+ const result = validator.validate(value);
636
+ if (!isObservable(result)) {
637
+ const isValid = await result;
638
+ if (signal.aborted) {
639
+ return null;
640
+ }
641
+ return { validator, isValid };
642
+ }
643
+ const safeResult$ = result.pipe(takeUntil(this._asyncCancelSubject), catchError(err => {
644
+ console.error(`Async validation error for ${validator.error}:`, err);
645
+ return of(false);
646
+ }));
647
+ const isValid = await firstValueFrom(safeResult$);
648
+ if (signal.aborted) {
649
+ return null;
650
+ }
651
+ return { validator, isValid };
652
+ }
653
+ catch (error) {
654
+ if (!signal.aborted) {
655
+ console.error(`Async validation error for ${validator.error}:`, error);
656
+ return {
657
+ validator,
658
+ isValid: false,
659
+ error: true,
660
+ };
661
+ }
662
+ return null;
663
+ }
664
+ });
665
+ const results = await Promise.all(validationPromises);
666
+ if (signal.aborted) {
667
+ return;
668
+ }
669
+ for (const result of results) {
670
+ if (result && !result.isValid) {
671
+ errors.set(result.validator.error, result.validator.message);
672
+ }
673
+ }
674
+ this._asyncErrors.set(errors);
675
+ }
676
+ catch (error) {
677
+ if (!signal.aborted) {
678
+ console.error('Async validation error:', error);
679
+ }
680
+ }
681
+ finally {
682
+ if (!signal.aborted) {
683
+ this.isValidating.set(false);
684
+ }
685
+ }
686
+ }
687
+ _cancelAsyncValidation() {
688
+ if (this._asyncValidationAbortController) {
689
+ this._asyncValidationAbortController.abort();
690
+ this._asyncValidationAbortController = null;
691
+ }
692
+ this._asyncCancelSubject.next();
693
+ }
694
+ _showSuggestPopover() {
695
+ this.uiState.update(s => ({ ...s, showSuggestPopover: true }));
696
+ }
697
+ _hideSuggestPopover() {
698
+ this.uiState.update(s => ({ ...s, showSuggestPopover: false }));
671
699
  }
672
700
  _loadSuggestHistory() {
673
701
  const key = this.zAutoSuggest();
@@ -679,24 +707,6 @@ class ZInputComponent {
679
707
  const history = ZCacheService.get(cacheKey, []) ?? [];
680
708
  this.suggestHistory.set(history);
681
709
  }
682
- onArrowClick(event, direction) {
683
- event.preventDefault();
684
- const multiplier = direction === 'up' ? 1 : -1;
685
- this._incrementValue(multiplier);
686
- }
687
- togglePasswordVisibility() {
688
- this.passwordVisible.update(v => !v);
689
- }
690
- copyColorToClipboard() {
691
- const colorValue = String(this._value() || '#000000').toUpperCase();
692
- void navigator.clipboard.writeText(colorValue).then(() => {
693
- this.colorCopied.set(true);
694
- this._toastService.success(`Copied ${colorValue}`);
695
- setTimeout(() => {
696
- this.colorCopied.set(false);
697
- }, 1500);
698
- });
699
- }
700
710
  _incrementValue(multiplier) {
701
711
  const currentValue = this._value();
702
712
  const numValue = typeof currentValue === 'number' ? currentValue : parseFloat(String(currentValue)) || 0;
@@ -776,7 +786,7 @@ class ZInputComponent {
776
786
  useExisting: forwardRef(() => ZInputComponent),
777
787
  multi: true,
778
788
  },
779
- ], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], exportAs: ["zInput"], ngImport: i0, template: "<div class=\"z-input-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"inputId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() | translate }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n @if (isTextarea()) {\n <div class=\"relative w-full\" [class]=\"textareaClasses()\" [class.overflow-auto]=\"zAutoSizeContent()\">\n <textarea\n #inputEl\n [id]=\"inputId\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground m-0 block min-h-14 w-full resize-none bg-transparent p-2 text-sm outline-none\"\n [class.resize-y]=\"zResize() && !isDisabled() && !zReadonly()\"\n [class.field-sizing-content]=\"zAutoSizeContent()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n [autocomplete]=\"zAutoComplete()\"\n [rows]=\"zRows()\"\n [attr.maxlength]=\"zMaxLength()\"\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"></textarea>\n @if (zMaxLength()) {\n <div class=\"flex justify-end pr-1 pb-1\">\n <span class=\"text-muted-foreground text-xs\">{{ displayValue().length }} / {{ zMaxLength() }}</span>\n </div>\n }\n @if (zResize() && !isDisabled() && !zReadonly() && !zMaxLength()) {\n <svg\n class=\"text-muted-foreground pointer-events-none absolute right-0.5 bottom-0.5 opacity-40\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\">\n <path d=\"M10 2L2 10\" />\n <path d=\"M10 6L6 10\" />\n </svg>\n }\n </div>\n } @else {\n <div class=\"relative w-full\">\n <div class=\"z-input-container flex w-full items-center\" [class]=\"inputClasses()\">\n <!-- Color picker square (prefix for color type) -->\n @if (isColorType()) {\n <label\n [for]=\"inputId\"\n class=\"border-input relative z-10 size-6 shrink-0 cursor-pointer overflow-hidden rounded border\">\n <input\n type=\"color\"\n [id]=\"inputId + '-picker'\"\n class=\"absolute -top-2 -left-2 size-12 cursor-pointer border-none bg-transparent p-0\"\n [disabled]=\"isDisabled()\"\n [ngModel]=\"displayValue() || '#000000'\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\" />\n </label>\n }\n\n @if (hasPrefix() && !isColorType()) {\n <div class=\"text-muted-foreground left-3 flex items-center justify-center\">\n @if (zSearch()) {\n <z-icon zType=\"lucideSearch\" zSize=\"16\" />\n } @else if (isPrefixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zPrefix())\" />\n } @else {\n {{ zPrefix() }}\n }\n </div>\n }\n\n <input\n #inputEl\n [id]=\"inputId\"\n [type]=\"isColorType() ? 'text' : effectiveType()\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground h-full min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"isColorType() ? true : zReadonly()\"\n [attr.min]=\"zMin()\"\n [attr.max]=\"zMax()\"\n [attr.step]=\"zStep()\"\n [autocomplete]=\"zAutoComplete()\"\n [ngModel]=\"isColorType() ? (displayValue() || '#000000').toUpperCase() : displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"\n [mask]=\"effectiveMask()\"\n [thousandSeparator]=\"zThousandSeparator()\"\n [decimalMarker]=\"effectiveDecimalMarker()\"\n [allowNegativeNumbers]=\"zAllowNegative()\"\n [dropSpecialCharacters]=\"false\"\n (keydown)=\"onSuggestKeydown($event)\"\n (blur)=\"closeSuggestPopover()\" />\n\n @if (hasSuffix() && !isColorType()) {\n <div class=\"text-muted-foreground flex items-center justify-center text-sm\">\n @if (isSuffixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zSuffix())\" />\n } @else {\n {{ zSuffix() }}\n }\n </div>\n }\n\n <!-- Async validation loading indicator -->\n @if (isValidating()) {\n <div class=\"text-muted-foreground flex items-center justify-center\">\n <z-icon zType=\"lucideLoader2\" zSize=\"16\" class=\"animate-spin\" />\n </div>\n }\n\n <!-- Clear button -->\n @if (showClearButton()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"clearValue($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n\n <!-- Copy button for color type -->\n @if (isColorType()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-accent flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"copyColorToClipboard()\">\n <span class=\"relative flex size-4 items-center justify-center\">\n <z-icon\n zType=\"lucideCopy\"\n [class]=\"colorCopied() ? 'scale-0 rotate-90 opacity-0' : 'scale-100 rotate-0 opacity-100'\"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n <z-icon\n zType=\"lucideCheck\"\n [class]=\"colorCopied() ? 'text-success scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'\"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n </span>\n </button>\n }\n\n @if (showArrows() && !isDisabled()) {\n <div class=\"-mr-1 flex h-[calc(100%-4px)] shrink-0 flex-col\">\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'up')\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"12\" />\n </button>\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'down')\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" />\n </button>\n </div>\n }\n\n @if (isPasswordType() && zShowPasswordToggle()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"togglePasswordVisibility()\">\n @if (passwordVisible()) {\n <z-icon zType=\"lucideEyeOff\" zSize=\"16\" />\n } @else {\n <z-icon zType=\"lucideEye\" zSize=\"16\" />\n }\n </button>\n }\n </div>\n\n @if (hasAutoSuggest() && showSuggestPopover() && suggestHistory().length > 0) {\n <div\n class=\"bg-popover text-popover-foreground border-border z-animate-in z-fade-in z-duration-200 z-slide-in-from-top-4 absolute top-full left-0 z-50 mt-1 flex w-full flex-col gap-[3px] rounded-[6px] border p-1 shadow-md\">\n @for (item of filteredSuggestHistory(); track item; let i = $index) {\n <button\n type=\"button\"\n class=\"hover:bg-primary/10 hover:text-foreground flex w-full cursor-pointer items-center gap-2 rounded-[4px] px-2 py-1.5 text-left text-sm transition-colors\"\n [class.bg-primary/15]=\"suggestActiveIndex() === i\"\n [class.text-primary]=\"suggestActiveIndex() === i\"\n (mousedown)=\"selectSuggestItem(item)\">\n <z-icon zType=\"lucideClock\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n <span class=\"truncate\">{{ item }}</span>\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (showError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n", styles: [".z-input-native{text-overflow:ellipsis;overflow:hidden}.z-input-native:-webkit-autofill,.z-input-native:-webkit-autofill:hover,.z-input-native:-webkit-autofill:focus,.z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px white inset!important;-webkit-text-fill-color:var(--color-foreground)!important;transition:background-color 9999s ease-in-out 0s!important;caret-color:var(--color-foreground)}:is(.dark,.dark *) .z-input-native:-webkit-autofill,:is(.dark,.dark *) .z-input-native:-webkit-autofill:hover,:is(.dark,.dark *) .z-input-native:-webkit-autofill:focus,:is(.dark,.dark *) .z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px var(--input-autofill) inset!important;transition:background-color 9999s ease-in-out 0s!important}textarea.z-input-native::-webkit-resizer{display:none}input[type=color]{cursor:pointer}input[type=color]::-webkit-color-swatch-wrapper{padding:0}input[type=color]::-webkit-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}input[type=color]::-moz-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}\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: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: NgxMaskDirective, selector: "input[mask], textarea[mask]", inputs: ["mask", "specialCharacters", "patterns", "prefix", "suffix", "thousandSeparator", "decimalMarker", "dropSpecialCharacters", "hiddenInput", "showMaskTyped", "placeHolderCharacter", "shownMaskExpression", "clearIfNotMatch", "validation", "separatorLimit", "allowNegativeNumbers", "leadZeroDateTime", "leadZero", "triggerOnMaskChange", "apm", "inputTransformFn", "outputTransformFn", "keepCharacterPositions", "instantPrefix"], outputs: ["maskFilled"], exportAs: ["mask", "ngxMask"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
789
+ ], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], exportAs: ["zInput"], ngImport: i0, template: "<div class=\"z-input-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"inputId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() | translate }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n @if (isTextarea()) {\n <div class=\"relative w-full\" [class]=\"textareaClasses()\" [class.overflow-auto]=\"zAutoSizeContent()\">\n <textarea\n #inputEl\n [id]=\"inputId\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground m-0 block min-h-14 w-full resize-none bg-transparent p-2 text-sm outline-none\"\n [class.resize-y]=\"zResize() && !isDisabled() && !zReadonly()\"\n [class.field-sizing-content]=\"zAutoSizeContent()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n [autocomplete]=\"zAutoComplete()\"\n [rows]=\"zRows()\"\n [attr.maxlength]=\"zMaxLength()\"\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"></textarea>\n @if (zMaxLength()) {\n <div class=\"flex justify-end pr-1 pb-1\">\n <span class=\"text-muted-foreground text-xs\">{{ displayValue().length }} / {{ zMaxLength() }}</span>\n </div>\n }\n @if (zResize() && !isDisabled() && !zReadonly() && !zMaxLength()) {\n <svg\n class=\"text-muted-foreground pointer-events-none absolute right-0.5 bottom-0.5 opacity-40\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\">\n <path d=\"M10 2L2 10\" />\n <path d=\"M10 6L6 10\" />\n </svg>\n }\n </div>\n } @else {\n <div class=\"relative w-full\">\n <div class=\"z-input-container flex w-full items-center\" [class]=\"inputClasses()\">\n <!-- Color picker square (prefix for color type) -->\n @if (isColorType()) {\n <label\n [for]=\"inputId\"\n class=\"border-input relative z-10 size-6 shrink-0 cursor-pointer overflow-hidden rounded border\">\n <input\n type=\"color\"\n [id]=\"inputId + '-picker'\"\n class=\"absolute -top-2 -left-2 size-12 cursor-pointer border-none bg-transparent p-0\"\n [disabled]=\"isDisabled()\"\n [ngModel]=\"displayValue() || '#000000'\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\" />\n </label>\n }\n\n @if (hasPrefix() && !isColorType()) {\n <div class=\"text-muted-foreground left-3 flex items-center justify-center\">\n @if (zSearch()) {\n <z-icon zType=\"lucideSearch\" zSize=\"16\" />\n } @else if (isPrefixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zPrefix())\" />\n } @else {\n {{ zPrefix() }}\n }\n </div>\n }\n\n <input\n #inputEl\n [id]=\"inputId\"\n [type]=\"isColorType() ? 'text' : effectiveType()\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground h-full min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"isColorType() ? true : zReadonly()\"\n [attr.min]=\"zMin()\"\n [attr.max]=\"zMax()\"\n [attr.step]=\"zStep()\"\n [autocomplete]=\"zAutoComplete()\"\n [ngModel]=\"isColorType() ? (displayValue() || '#000000').toUpperCase() : displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"\n [mask]=\"effectiveMask()\"\n [thousandSeparator]=\"zThousandSeparator()\"\n [decimalMarker]=\"effectiveDecimalMarker()\"\n [allowNegativeNumbers]=\"zAllowNegative()\"\n [dropSpecialCharacters]=\"false\"\n (keydown)=\"onSuggestKeydown($event)\"\n (blur)=\"closeSuggestPopover()\" />\n\n @if (hasSuffix() && !isColorType()) {\n <div class=\"text-muted-foreground flex items-center justify-center text-sm\">\n @if (isSuffixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zSuffix())\" />\n } @else {\n {{ zSuffix() }}\n }\n </div>\n }\n\n <!-- Async validation loading indicator -->\n @if (isValidating()) {\n <div class=\"text-muted-foreground flex items-center justify-center\">\n <z-icon zType=\"lucideLoader2\" zSize=\"16\" class=\"animate-spin\" />\n </div>\n }\n\n <!-- Clear button -->\n @if (showClearButton()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"clearValue($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n\n <!-- Copy button for color type -->\n @if (isColorType()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-accent flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"copyColorToClipboard()\">\n <span class=\"relative flex size-4 items-center justify-center\">\n <z-icon\n zType=\"lucideCopy\"\n [class]=\"uiState().colorCopied ? 'scale-0 rotate-90 opacity-0' : 'scale-100 rotate-0 opacity-100'\"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n <z-icon\n zType=\"lucideCheck\"\n [class]=\"\n uiState().colorCopied ? 'text-success scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'\n \"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n </span>\n </button>\n }\n\n @if (showArrows() && !isDisabled()) {\n <div class=\"-mr-1 flex h-[calc(100%-4px)] shrink-0 flex-col\">\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'up')\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"12\" />\n </button>\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'down')\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" />\n </button>\n </div>\n }\n\n @if (isPasswordType() && zShowPasswordToggle()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"togglePasswordVisibility()\">\n @if (uiState().passwordVisible) {\n <z-icon zType=\"lucideEyeOff\" zSize=\"16\" />\n } @else {\n <z-icon zType=\"lucideEye\" zSize=\"16\" />\n }\n </button>\n }\n </div>\n\n @if (hasAutoSuggest() && uiState().showSuggestPopover && suggestHistory().length > 0) {\n <div\n class=\"bg-popover text-popover-foreground border-border z-animate-in z-fade-in z-duration-200 z-slide-in-from-top-4 absolute top-full left-0 z-50 mt-1 flex w-full flex-col gap-[3px] rounded-[6px] border p-1 shadow-md\">\n @for (item of filteredSuggestHistory(); track item; let i = $index) {\n <button\n type=\"button\"\n class=\"hover:bg-primary/10 hover:text-foreground flex w-full cursor-pointer items-center gap-2 rounded-[4px] px-2 py-1.5 text-left text-sm transition-colors\"\n [class.bg-primary/15]=\"suggestActiveIndex() === i\"\n [class.text-primary]=\"suggestActiveIndex() === i\"\n (mousedown)=\"selectSuggestItem(item)\">\n <z-icon zType=\"lucideClock\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n <span class=\"truncate\">{{ item }}</span>\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (showError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n", styles: [".z-input-native{text-overflow:ellipsis;overflow:hidden}.z-input-native:-webkit-autofill,.z-input-native:-webkit-autofill:hover,.z-input-native:-webkit-autofill:focus,.z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px white inset!important;-webkit-text-fill-color:var(--color-foreground)!important;transition:background-color 9999s ease-in-out 0s!important;caret-color:var(--color-foreground)}:is(.dark,.dark *) .z-input-native:-webkit-autofill,:is(.dark,.dark *) .z-input-native:-webkit-autofill:hover,:is(.dark,.dark *) .z-input-native:-webkit-autofill:focus,:is(.dark,.dark *) .z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px var(--input-autofill) inset!important;transition:background-color 9999s ease-in-out 0s!important}textarea.z-input-native::-webkit-resizer{display:none}input[type=color]{cursor:pointer}input[type=color]::-webkit-color-swatch-wrapper{padding:0}input[type=color]::-webkit-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}input[type=color]::-moz-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}\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: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: NgxMaskDirective, selector: "input[mask], textarea[mask]", inputs: ["mask", "specialCharacters", "patterns", "prefix", "suffix", "thousandSeparator", "decimalMarker", "dropSpecialCharacters", "hiddenInput", "showMaskTyped", "placeHolderCharacter", "shownMaskExpression", "clearIfNotMatch", "validation", "separatorLimit", "allowNegativeNumbers", "leadZeroDateTime", "leadZero", "triggerOnMaskChange", "apm", "inputTransformFn", "outputTransformFn", "keepCharacterPositions", "instantPrefix"], outputs: ["maskFilled"], exportAs: ["mask", "ngxMask"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
780
790
  }
781
791
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZInputComponent, decorators: [{
782
792
  type: Component,
@@ -787,8 +797,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
787
797
  useExisting: forwardRef(() => ZInputComponent),
788
798
  multi: true,
789
799
  },
790
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'zInput', template: "<div class=\"z-input-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"inputId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() | translate }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n @if (isTextarea()) {\n <div class=\"relative w-full\" [class]=\"textareaClasses()\" [class.overflow-auto]=\"zAutoSizeContent()\">\n <textarea\n #inputEl\n [id]=\"inputId\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground m-0 block min-h-14 w-full resize-none bg-transparent p-2 text-sm outline-none\"\n [class.resize-y]=\"zResize() && !isDisabled() && !zReadonly()\"\n [class.field-sizing-content]=\"zAutoSizeContent()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n [autocomplete]=\"zAutoComplete()\"\n [rows]=\"zRows()\"\n [attr.maxlength]=\"zMaxLength()\"\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"></textarea>\n @if (zMaxLength()) {\n <div class=\"flex justify-end pr-1 pb-1\">\n <span class=\"text-muted-foreground text-xs\">{{ displayValue().length }} / {{ zMaxLength() }}</span>\n </div>\n }\n @if (zResize() && !isDisabled() && !zReadonly() && !zMaxLength()) {\n <svg\n class=\"text-muted-foreground pointer-events-none absolute right-0.5 bottom-0.5 opacity-40\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\">\n <path d=\"M10 2L2 10\" />\n <path d=\"M10 6L6 10\" />\n </svg>\n }\n </div>\n } @else {\n <div class=\"relative w-full\">\n <div class=\"z-input-container flex w-full items-center\" [class]=\"inputClasses()\">\n <!-- Color picker square (prefix for color type) -->\n @if (isColorType()) {\n <label\n [for]=\"inputId\"\n class=\"border-input relative z-10 size-6 shrink-0 cursor-pointer overflow-hidden rounded border\">\n <input\n type=\"color\"\n [id]=\"inputId + '-picker'\"\n class=\"absolute -top-2 -left-2 size-12 cursor-pointer border-none bg-transparent p-0\"\n [disabled]=\"isDisabled()\"\n [ngModel]=\"displayValue() || '#000000'\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\" />\n </label>\n }\n\n @if (hasPrefix() && !isColorType()) {\n <div class=\"text-muted-foreground left-3 flex items-center justify-center\">\n @if (zSearch()) {\n <z-icon zType=\"lucideSearch\" zSize=\"16\" />\n } @else if (isPrefixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zPrefix())\" />\n } @else {\n {{ zPrefix() }}\n }\n </div>\n }\n\n <input\n #inputEl\n [id]=\"inputId\"\n [type]=\"isColorType() ? 'text' : effectiveType()\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground h-full min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"isColorType() ? true : zReadonly()\"\n [attr.min]=\"zMin()\"\n [attr.max]=\"zMax()\"\n [attr.step]=\"zStep()\"\n [autocomplete]=\"zAutoComplete()\"\n [ngModel]=\"isColorType() ? (displayValue() || '#000000').toUpperCase() : displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"\n [mask]=\"effectiveMask()\"\n [thousandSeparator]=\"zThousandSeparator()\"\n [decimalMarker]=\"effectiveDecimalMarker()\"\n [allowNegativeNumbers]=\"zAllowNegative()\"\n [dropSpecialCharacters]=\"false\"\n (keydown)=\"onSuggestKeydown($event)\"\n (blur)=\"closeSuggestPopover()\" />\n\n @if (hasSuffix() && !isColorType()) {\n <div class=\"text-muted-foreground flex items-center justify-center text-sm\">\n @if (isSuffixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zSuffix())\" />\n } @else {\n {{ zSuffix() }}\n }\n </div>\n }\n\n <!-- Async validation loading indicator -->\n @if (isValidating()) {\n <div class=\"text-muted-foreground flex items-center justify-center\">\n <z-icon zType=\"lucideLoader2\" zSize=\"16\" class=\"animate-spin\" />\n </div>\n }\n\n <!-- Clear button -->\n @if (showClearButton()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"clearValue($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n\n <!-- Copy button for color type -->\n @if (isColorType()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-accent flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"copyColorToClipboard()\">\n <span class=\"relative flex size-4 items-center justify-center\">\n <z-icon\n zType=\"lucideCopy\"\n [class]=\"colorCopied() ? 'scale-0 rotate-90 opacity-0' : 'scale-100 rotate-0 opacity-100'\"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n <z-icon\n zType=\"lucideCheck\"\n [class]=\"colorCopied() ? 'text-success scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'\"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n </span>\n </button>\n }\n\n @if (showArrows() && !isDisabled()) {\n <div class=\"-mr-1 flex h-[calc(100%-4px)] shrink-0 flex-col\">\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'up')\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"12\" />\n </button>\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'down')\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" />\n </button>\n </div>\n }\n\n @if (isPasswordType() && zShowPasswordToggle()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"togglePasswordVisibility()\">\n @if (passwordVisible()) {\n <z-icon zType=\"lucideEyeOff\" zSize=\"16\" />\n } @else {\n <z-icon zType=\"lucideEye\" zSize=\"16\" />\n }\n </button>\n }\n </div>\n\n @if (hasAutoSuggest() && showSuggestPopover() && suggestHistory().length > 0) {\n <div\n class=\"bg-popover text-popover-foreground border-border z-animate-in z-fade-in z-duration-200 z-slide-in-from-top-4 absolute top-full left-0 z-50 mt-1 flex w-full flex-col gap-[3px] rounded-[6px] border p-1 shadow-md\">\n @for (item of filteredSuggestHistory(); track item; let i = $index) {\n <button\n type=\"button\"\n class=\"hover:bg-primary/10 hover:text-foreground flex w-full cursor-pointer items-center gap-2 rounded-[4px] px-2 py-1.5 text-left text-sm transition-colors\"\n [class.bg-primary/15]=\"suggestActiveIndex() === i\"\n [class.text-primary]=\"suggestActiveIndex() === i\"\n (mousedown)=\"selectSuggestItem(item)\">\n <z-icon zType=\"lucideClock\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n <span class=\"truncate\">{{ item }}</span>\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (showError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n", styles: [".z-input-native{text-overflow:ellipsis;overflow:hidden}.z-input-native:-webkit-autofill,.z-input-native:-webkit-autofill:hover,.z-input-native:-webkit-autofill:focus,.z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px white inset!important;-webkit-text-fill-color:var(--color-foreground)!important;transition:background-color 9999s ease-in-out 0s!important;caret-color:var(--color-foreground)}:is(.dark,.dark *) .z-input-native:-webkit-autofill,:is(.dark,.dark *) .z-input-native:-webkit-autofill:hover,:is(.dark,.dark *) .z-input-native:-webkit-autofill:focus,:is(.dark,.dark *) .z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px var(--input-autofill) inset!important;transition:background-color 9999s ease-in-out 0s!important}textarea.z-input-native::-webkit-resizer{display:none}input[type=color]{cursor:pointer}input[type=color]::-webkit-color-swatch-wrapper{padding:0}input[type=color]::-webkit-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}input[type=color]::-moz-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}\n"] }]
791
- }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zType: [{ type: i0.Input, args: [{ isSignal: true, alias: "zType", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLabel", required: false }] }], zLabelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLabelClass", required: false }] }], zPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPlaceholder", required: false }] }], zRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRequired", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "zReadonly", required: false }] }], zPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPrefix", required: false }] }], zSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSuffix", required: false }] }], zMin: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMin", required: false }] }], zMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMax", required: false }] }], zStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "zStep", required: false }] }], zShowArrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowArrows", required: false }] }], zMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMask", required: false }] }], zDecimalPlaces: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDecimalPlaces", required: false }] }], zAllowNegative: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowNegative", required: false }] }], zThousandSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "zThousandSeparator", required: false }] }], zDecimalMarker: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDecimalMarker", required: false }] }], zValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "zValidators", required: false }] }], zAsyncValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAsyncValidators", required: false }] }], zAsyncDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAsyncDebounce", required: false }] }], zAsyncValidateOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAsyncValidateOn", required: false }] }], zShowPasswordToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowPasswordToggle", required: false }] }], zSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSearch", required: false }] }], zDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDebounce", required: false }] }], zAutofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutofocus", required: false }] }], zAutoComplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoComplete", required: false }] }], zAllowClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowClear", required: false }] }], zAutoSizeContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoSizeContent", required: false }] }], zRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRows", required: false }] }], zResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zResize", required: false }] }], zMaxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMaxLength", required: false }] }], zAutoSuggest: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoSuggest", required: false }] }], zOnSearch: [{ type: i0.Output, args: ["zOnSearch"] }], zOnChange: [{ type: i0.Output, args: ["zOnChange"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], inputRef: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }] } });
800
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'zInput', template: "<div class=\"z-input-wrapper flex w-full flex-col gap-2\">\n @if (zLabel()) {\n <label [for]=\"inputId\" class=\"text-xs leading-none font-medium\" [class]=\"zLabelClass()\">\n {{ zLabel() | translate }}\n @if (zRequired()) {\n <span class=\"text-destructive! ml-0.5\">*</span>\n }\n </label>\n }\n\n @if (isTextarea()) {\n <div class=\"relative w-full\" [class]=\"textareaClasses()\" [class.overflow-auto]=\"zAutoSizeContent()\">\n <textarea\n #inputEl\n [id]=\"inputId\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground m-0 block min-h-14 w-full resize-none bg-transparent p-2 text-sm outline-none\"\n [class.resize-y]=\"zResize() && !isDisabled() && !zReadonly()\"\n [class.field-sizing-content]=\"zAutoSizeContent()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"zReadonly()\"\n [autocomplete]=\"zAutoComplete()\"\n [rows]=\"zRows()\"\n [attr.maxlength]=\"zMaxLength()\"\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"></textarea>\n @if (zMaxLength()) {\n <div class=\"flex justify-end pr-1 pb-1\">\n <span class=\"text-muted-foreground text-xs\">{{ displayValue().length }} / {{ zMaxLength() }}</span>\n </div>\n }\n @if (zResize() && !isDisabled() && !zReadonly() && !zMaxLength()) {\n <svg\n class=\"text-muted-foreground pointer-events-none absolute right-0.5 bottom-0.5 opacity-40\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\">\n <path d=\"M10 2L2 10\" />\n <path d=\"M10 6L6 10\" />\n </svg>\n }\n </div>\n } @else {\n <div class=\"relative w-full\">\n <div class=\"z-input-container flex w-full items-center\" [class]=\"inputClasses()\">\n <!-- Color picker square (prefix for color type) -->\n @if (isColorType()) {\n <label\n [for]=\"inputId\"\n class=\"border-input relative z-10 size-6 shrink-0 cursor-pointer overflow-hidden rounded border\">\n <input\n type=\"color\"\n [id]=\"inputId + '-picker'\"\n class=\"absolute -top-2 -left-2 size-12 cursor-pointer border-none bg-transparent p-0\"\n [disabled]=\"isDisabled()\"\n [ngModel]=\"displayValue() || '#000000'\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\" />\n </label>\n }\n\n @if (hasPrefix() && !isColorType()) {\n <div class=\"text-muted-foreground left-3 flex items-center justify-center\">\n @if (zSearch()) {\n <z-icon zType=\"lucideSearch\" zSize=\"16\" />\n } @else if (isPrefixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zPrefix())\" />\n } @else {\n {{ zPrefix() }}\n }\n </div>\n }\n\n <input\n #inputEl\n [id]=\"inputId\"\n [type]=\"isColorType() ? 'text' : effectiveType()\"\n [placeholder]=\"zPlaceholder() | translate\"\n class=\"z-input-native placeholder:text-muted-foreground h-full min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"isColorType() ? true : zReadonly()\"\n [attr.min]=\"zMin()\"\n [attr.max]=\"zMax()\"\n [attr.step]=\"zStep()\"\n [autocomplete]=\"zAutoComplete()\"\n [ngModel]=\"isColorType() ? (displayValue() || '#000000').toUpperCase() : displayValue()\"\n (ngModelChange)=\"onModelChange($event)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (keydown)=\"onKeydown($event)\"\n [mask]=\"effectiveMask()\"\n [thousandSeparator]=\"zThousandSeparator()\"\n [decimalMarker]=\"effectiveDecimalMarker()\"\n [allowNegativeNumbers]=\"zAllowNegative()\"\n [dropSpecialCharacters]=\"false\"\n (keydown)=\"onSuggestKeydown($event)\"\n (blur)=\"closeSuggestPopover()\" />\n\n @if (hasSuffix() && !isColorType()) {\n <div class=\"text-muted-foreground flex items-center justify-center text-sm\">\n @if (isSuffixTemplate()) {\n <ng-container *ngTemplateOutlet=\"$any(zSuffix())\" />\n } @else {\n {{ zSuffix() }}\n }\n </div>\n }\n\n <!-- Async validation loading indicator -->\n @if (isValidating()) {\n <div class=\"text-muted-foreground flex items-center justify-center\">\n <z-icon zType=\"lucideLoader2\" zSize=\"16\" class=\"animate-spin\" />\n </div>\n }\n\n <!-- Clear button -->\n @if (showClearButton()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-5 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"clearValue($event)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n }\n\n <!-- Copy button for color type -->\n @if (isColorType()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-accent flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"copyColorToClipboard()\">\n <span class=\"relative flex size-4 items-center justify-center\">\n <z-icon\n zType=\"lucideCopy\"\n [class]=\"uiState().colorCopied ? 'scale-0 rotate-90 opacity-0' : 'scale-100 rotate-0 opacity-100'\"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n <z-icon\n zType=\"lucideCheck\"\n [class]=\"\n uiState().colorCopied ? 'text-success scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0'\n \"\n class=\"absolute transition-all duration-200 ease-out\"\n zSize=\"14\" />\n </span>\n </button>\n }\n\n @if (showArrows() && !isDisabled()) {\n <div class=\"-mr-1 flex h-[calc(100%-4px)] shrink-0 flex-col\">\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'up')\">\n <z-icon zType=\"lucideChevronUp\" zSize=\"12\" />\n </button>\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:bg-accent hover:text-foreground flex w-5 flex-1 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"onArrowClick($event, 'down')\">\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" />\n </button>\n </div>\n }\n\n @if (isPasswordType() && zShowPasswordToggle()) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"text-muted-foreground hover:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-all\"\n (click)=\"togglePasswordVisibility()\">\n @if (uiState().passwordVisible) {\n <z-icon zType=\"lucideEyeOff\" zSize=\"16\" />\n } @else {\n <z-icon zType=\"lucideEye\" zSize=\"16\" />\n }\n </button>\n }\n </div>\n\n @if (hasAutoSuggest() && uiState().showSuggestPopover && suggestHistory().length > 0) {\n <div\n class=\"bg-popover text-popover-foreground border-border z-animate-in z-fade-in z-duration-200 z-slide-in-from-top-4 absolute top-full left-0 z-50 mt-1 flex w-full flex-col gap-[3px] rounded-[6px] border p-1 shadow-md\">\n @for (item of filteredSuggestHistory(); track item; let i = $index) {\n <button\n type=\"button\"\n class=\"hover:bg-primary/10 hover:text-foreground flex w-full cursor-pointer items-center gap-2 rounded-[4px] px-2 py-1.5 text-left text-sm transition-colors\"\n [class.bg-primary/15]=\"suggestActiveIndex() === i\"\n [class.text-primary]=\"suggestActiveIndex() === i\"\n (mousedown)=\"selectSuggestItem(item)\">\n <z-icon zType=\"lucideClock\" zSize=\"14\" class=\"text-muted-foreground shrink-0\" />\n <span class=\"truncate\">{{ item }}</span>\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (showError()) {\n <p class=\"text-destructive animate-in fade-in slide-in-from-top-1 m-0 text-xs duration-200\">\n {{ errorMessage() }}\n </p>\n }\n</div>\n", styles: [".z-input-native{text-overflow:ellipsis;overflow:hidden}.z-input-native:-webkit-autofill,.z-input-native:-webkit-autofill:hover,.z-input-native:-webkit-autofill:focus,.z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px white inset!important;-webkit-text-fill-color:var(--color-foreground)!important;transition:background-color 9999s ease-in-out 0s!important;caret-color:var(--color-foreground)}:is(.dark,.dark *) .z-input-native:-webkit-autofill,:is(.dark,.dark *) .z-input-native:-webkit-autofill:hover,:is(.dark,.dark *) .z-input-native:-webkit-autofill:focus,:is(.dark,.dark *) .z-input-native:-webkit-autofill:active{-webkit-box-shadow:0 0 0 1000px var(--input-autofill) inset!important;transition:background-color 9999s ease-in-out 0s!important}textarea.z-input-native::-webkit-resizer{display:none}input[type=color]{cursor:pointer}input[type=color]::-webkit-color-swatch-wrapper{padding:0}input[type=color]::-webkit-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}input[type=color]::-moz-color-swatch{border:none;border-radius:calc(var(--radius) - 2px)}\n"] }]
801
+ }], propDecorators: { inputRef: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], zOnSearch: [{ type: i0.Output, args: ["zOnSearch"] }], zOnChange: [{ type: i0.Output, args: ["zOnChange"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zType: [{ type: i0.Input, args: [{ isSignal: true, alias: "zType", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLabel", required: false }] }], zLabelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLabelClass", required: false }] }], zPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPlaceholder", required: false }] }], zRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRequired", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "zReadonly", required: false }] }], zPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPrefix", required: false }] }], zSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSuffix", required: false }] }], zMin: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMin", required: false }] }], zMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMax", required: false }] }], zStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "zStep", required: false }] }], zShowArrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowArrows", required: false }] }], zMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMask", required: false }] }], zDecimalPlaces: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDecimalPlaces", required: false }] }], zAllowNegative: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowNegative", required: false }] }], zThousandSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "zThousandSeparator", required: false }] }], zDecimalMarker: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDecimalMarker", required: false }] }], zValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "zValidators", required: false }] }], zAsyncValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAsyncValidators", required: false }] }], zAsyncDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAsyncDebounce", required: false }] }], zAsyncValidateOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAsyncValidateOn", required: false }] }], zShowPasswordToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowPasswordToggle", required: false }] }], zSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSearch", required: false }] }], zDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDebounce", required: false }] }], zAutofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutofocus", required: false }] }], zAutoComplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoComplete", required: false }] }], zAllowClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowClear", required: false }] }], zAutoSizeContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoSizeContent", required: false }] }], zRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRows", required: false }] }], zResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zResize", required: false }] }], zMaxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMaxLength", required: false }] }], zAutoSuggest: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoSuggest", required: false }] }] } });
792
802
 
793
803
  /**
794
804
  * Generated bundle index. Do not edit.