valtech-components 2.0.383 → 2.0.384

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.
@@ -19,7 +19,7 @@ import 'prismjs/components/prism-markup';
19
19
  import 'prismjs/components/prism-typescript';
20
20
  import * as i1$2 from '@angular/forms';
21
21
  import { ReactiveFormsModule, FormsModule, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
22
- import { map as map$1 } from 'rxjs/operators';
22
+ import { map as map$1, distinctUntilChanged as distinctUntilChanged$1 } from 'rxjs/operators';
23
23
  import * as i1$3 from 'ng-otp-input';
24
24
  import { NgOtpInputComponent, NgOtpInputModule } from 'ng-otp-input';
25
25
  import 'prismjs/components/prism-bash';
@@ -5705,7 +5705,7 @@ class MultiSelectSimpleComponent {
5705
5705
  });
5706
5706
  this.searchPlaceholder = '';
5707
5707
  // ControlValueAccessor
5708
- this.onChange = (value) => { };
5708
+ this.onChange = (_value) => { };
5709
5709
  this.onTouched = () => { };
5710
5710
  this.placeholder = this.langService.getText('_global', 'selectOptions', 'Seleccione opciones');
5711
5711
  this.searchPlaceholder = this.langService.getText('_global', 'search', 'Buscar');
@@ -5719,6 +5719,11 @@ class MultiSelectSimpleComponent {
5719
5719
  ngOnDestroy() {
5720
5720
  document.removeEventListener('click', this.handleClickOutside.bind(this));
5721
5721
  }
5722
+ ngOnChanges(changes) {
5723
+ if (changes['props'] && this.props) {
5724
+ this.syncSelectedValues();
5725
+ }
5726
+ }
5722
5727
  // ControlValueAccessor implementation
5723
5728
  writeValue(value) {
5724
5729
  const valueArray = this.parseValue(value);
@@ -5730,7 +5735,7 @@ class MultiSelectSimpleComponent {
5730
5735
  registerOnTouched(fn) {
5731
5736
  this.onTouched = fn;
5732
5737
  }
5733
- setDisabledState(isDisabled) {
5738
+ setDisabledState(_isDisabled) {
5734
5739
  // Handle disabled state if needed
5735
5740
  }
5736
5741
  // Component methods
@@ -5779,7 +5784,7 @@ class MultiSelectSimpleComponent {
5779
5784
  isSelected(option) {
5780
5785
  return this.selectedValues().includes(option[this.valueProperty]);
5781
5786
  }
5782
- trackByFn(index, option) {
5787
+ trackByFn(_index, option) {
5783
5788
  return option[this.valueProperty];
5784
5789
  }
5785
5790
  handleClickOutside(event) {
@@ -5830,7 +5835,7 @@ class MultiSelectSimpleComponent {
5830
5835
  useExisting: forwardRef(() => MultiSelectSimpleComponent),
5831
5836
  multi: true
5832
5837
  }
5833
- ], viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "mainInputRef", first: true, predicate: ["mainInput"], descendants: true }], ngImport: i0, template: `
5838
+ ], viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "mainInputRef", first: true, predicate: ["mainInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
5834
5839
  <div class="multi-select-container" (click)="toggleDropdown($event)">
5835
5840
  <!-- Main input display -->
5836
5841
  <ion-input
@@ -6748,376 +6753,274 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6748
6753
  type: Input
6749
6754
  }] } });
6750
6755
 
6751
- /**
6752
- * val-select-search
6753
- *
6754
- * A searchable select/dropdown input with modal and filtering, integrated with Angular forms.
6755
- *
6756
- * @example
6757
- * <val-select-search [props]="{ control: myControl, label: 'Choose', options: [{ id: '1', name: 'Option 1' }] }"></val-select-search>
6758
- *
6759
- * @input props: InputMetadata - Configuration for the select input (form control, label, options, etc.)
6760
- */
6761
6756
  class SelectSearchComponent {
6762
6757
  constructor() {
6763
6758
  this.labelProperty = 'name';
6764
6759
  this.valueProperty = 'id';
6765
- this.multiple = false;
6760
+ this.placeholder = '';
6766
6761
  this.langService = inject(LangService);
6767
- this.icon = inject(IconService);
6768
- this.changeDetector = inject(ChangeDetectorRef);
6769
- this.searchTerm = '';
6770
- this.filteredItems = [];
6771
- this.selectedItems = [];
6772
- this.displayValue = '';
6773
- this.previousOptions = [];
6774
- this.isProcessingChanges = false;
6775
- this.label = this.langService.getText('_global', 'select', 'Seleccionar');
6762
+ // Signals for reactive state management
6763
+ this.isOpen = signal(false);
6764
+ this.searchTerm = signal('');
6765
+ this.selectedValue = signal(null);
6766
+ // Computed signals
6767
+ this.displayValue = computed(() => {
6768
+ const value = this.selectedValue();
6769
+ if (!value)
6770
+ return '';
6771
+ const option = this.getOptionByValue(value);
6772
+ return option ? option[this.labelProperty] : '';
6773
+ });
6774
+ this.filteredOptions = computed(() => {
6775
+ const options = this.props?.options || [];
6776
+ const search = this.searchTerm().toLowerCase();
6777
+ if (!search) {
6778
+ return options;
6779
+ }
6780
+ return options.filter(option => {
6781
+ const label = option[this.labelProperty]
6782
+ ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
6783
+ : '';
6784
+ const value = option[this.valueProperty]
6785
+ ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
6786
+ : '';
6787
+ const searchTerm = replaceSpecialChars(search);
6788
+ return label.includes(searchTerm) || value.includes(searchTerm);
6789
+ });
6790
+ });
6776
6791
  this.placeholder = this.langService.getText('_global', 'selectOption', 'Seleccione una opción');
6792
+ // Close dropdown when clicking outside
6793
+ document.addEventListener('click', this.handleClickOutside.bind(this));
6777
6794
  }
6778
6795
  ngOnInit() {
6779
6796
  this.applyDefaultValue();
6780
- this.initializeItems();
6781
- this.syncControlValueWithSelectedItems();
6782
- this.updateDisplayValue();
6783
- this.subscribeToValueChanges();
6797
+ this.syncSelectedValue();
6784
6798
  }
6785
6799
  ngOnDestroy() {
6786
- // Limpiar suscripciones para evitar memory leaks
6787
- if (this.valueChangesSubscription) {
6788
- this.valueChangesSubscription.unsubscribe();
6789
- }
6800
+ document.removeEventListener('click', this.handleClickOutside.bind(this));
6790
6801
  }
6791
- ngOnChanges(changes) {
6792
- // Evitar bucles infinitos
6793
- if (this.isProcessingChanges) {
6794
- return;
6795
- }
6796
- // Cuando cambia props o props.options
6797
- if (changes['props']) {
6798
- try {
6799
- this.isProcessingChanges = true;
6800
- // Desuscribirse del antiguo control si existe
6801
- if (this.valueChangesSubscription) {
6802
- this.valueChangesSubscription.unsubscribe();
6803
- }
6804
- if (this.props?.options) {
6805
- // Verificar si las opciones han cambiado realmente
6806
- const optionsChanged = !this.areOptionsEqual(this.previousOptions, this.props.options);
6807
- if (optionsChanged) {
6808
- this.previousOptions = [...this.props.options];
6809
- this.initializeItems();
6810
- }
6802
+ // Component methods
6803
+ toggleDropdown(event) {
6804
+ event.stopPropagation();
6805
+ this.isOpen.update(value => !value);
6806
+ if (this.isOpen()) {
6807
+ // Focus search bar when opening if available
6808
+ setTimeout(() => {
6809
+ const searchbar = this.dropdownRef?.nativeElement?.querySelector('ion-searchbar');
6810
+ if (searchbar) {
6811
+ searchbar.setFocus();
6811
6812
  }
6812
- // Sincronizar con el nuevo control si existe
6813
- this.syncControlValueWithSelectedItems();
6814
- this.updateDisplayValue();
6815
- // Suscribirse al nuevo control
6816
- this.subscribeToValueChanges();
6817
- }
6818
- finally {
6819
- this.isProcessingChanges = false;
6820
- }
6821
- }
6822
- }
6823
- ionViewWillEnter() {
6824
- if (this.isProcessingChanges) {
6825
- return;
6826
- }
6827
- try {
6828
- this.isProcessingChanges = true;
6829
- this.initializeItems();
6830
- this.syncControlValueWithSelectedItems();
6831
- this.updateDisplayValue();
6832
- this.subscribeToValueChanges();
6833
- }
6834
- finally {
6835
- this.isProcessingChanges = false;
6836
- }
6837
- }
6838
- // Suscribirse a cambios en el FormControl
6839
- subscribeToValueChanges() {
6840
- if (!this.props?.control)
6841
- return;
6842
- this.valueChangesSubscription = this.props.control.valueChanges.subscribe(value => {
6843
- if (this.isProcessingChanges)
6844
- return;
6845
- try {
6846
- this.isProcessingChanges = true;
6847
- this.syncControlValueWithSelectedItems();
6848
- this.updateDisplayValue();
6849
- }
6850
- finally {
6851
- this.isProcessingChanges = false;
6852
- }
6853
- });
6854
- }
6855
- // Compara si dos arrays de opciones son iguales
6856
- areOptionsEqual(prevOptions, newOptions) {
6857
- // PERF: Use reference equality first for fast path
6858
- if (prevOptions === newOptions)
6859
- return true;
6860
- if (!prevOptions || !newOptions)
6861
- return prevOptions === newOptions;
6862
- if (prevOptions.length !== newOptions.length)
6863
- return false;
6864
- // Only compare valueProperty for equality
6865
- for (let i = 0; i < prevOptions.length; i++) {
6866
- if (prevOptions[i][this.valueProperty] !== newOptions[i][this.valueProperty]) {
6867
- return false;
6868
- }
6869
- }
6870
- return true;
6871
- }
6872
- initializeItems() {
6873
- // PERF: Avoid unnecessary array copies
6874
- this.filteredItems = this.props?.options || [];
6875
- }
6876
- syncControlValueWithSelectedItems() {
6877
- if (!this.props?.control) {
6878
- this.selectedItems = [];
6879
- return;
6880
- }
6881
- const controlValue = this.props.control.value;
6882
- if (controlValue === null || controlValue === undefined) {
6883
- this.selectedItems = [];
6884
- return;
6885
- }
6886
- // PERF: Use a Map for faster lookup if options are large
6887
- if (this.props.options && this.props.options.length > 0) {
6888
- const map = new Map(this.props.options.map(opt => [opt[this.valueProperty], opt]));
6889
- const selectedOption = map.get(controlValue);
6890
- this.selectedItems = selectedOption ? [selectedOption] : [];
6891
- }
6892
- else {
6893
- this.selectedItems = [];
6894
- }
6895
- }
6896
- applyDefaultValue() {
6897
- applyDefaultValueToControl(this.props);
6898
- }
6899
- onFilter(event) {
6900
- // If no search term, show all options
6901
- if (!event || event.trim() === '') {
6902
- this.filteredItems = this.props?.options ? [...this.props.options] : [];
6903
- this.changeDetector.detectChanges();
6904
- return;
6905
- }
6906
- // If no options, nothing to filter
6907
- if (!this.props?.options || this.props.options.length === 0) {
6908
- this.filteredItems = [];
6909
- this.changeDetector.detectChanges();
6910
- return;
6813
+ }, 100);
6911
6814
  }
6912
- // PERF: Avoid repeated replaceSpecialChars and toLowerCase for each option
6913
- const search = replaceSpecialChars(event.toLowerCase());
6914
- this.filteredItems = this.props.options.filter(element => {
6915
- // Only use labelProperty and valueProperty for filtering (faster)
6916
- const label = element[this.labelProperty]
6917
- ? replaceSpecialChars(String(element[this.labelProperty]).toLowerCase())
6918
- : '';
6919
- const value = element[this.valueProperty]
6920
- ? replaceSpecialChars(String(element[this.valueProperty]).toLowerCase())
6921
- : '';
6922
- return label.includes(search) || value.includes(search);
6923
- });
6924
- this.changeDetector.detectChanges();
6925
6815
  }
6926
- onFocus() {
6927
- console.log('onFocus');
6928
- }
6929
- onBlur() {
6930
- console.log('onBlur');
6816
+ onSearch(event) {
6817
+ this.searchTerm.set(event.detail.value || '');
6931
6818
  }
6932
- openModal() {
6933
- if (this.modal) {
6934
- this.modal.present();
6819
+ selectOption(option) {
6820
+ const value = option[this.valueProperty];
6821
+ this.selectedValue.set(value);
6822
+ this.isOpen.set(false);
6823
+ this.searchTerm.set('');
6824
+ // Update form control
6825
+ if (this.props?.control) {
6826
+ this.props.control.setValue(value);
6827
+ this.props.control.markAsDirty();
6828
+ this.props.control.markAsTouched();
6935
6829
  }
6936
6830
  }
6937
- preventDefaultBehavior(event) {
6938
- event.preventDefault();
6939
- event.stopPropagation();
6940
- this.openModal();
6831
+ isSelected(option) {
6832
+ return this.selectedValue() === option[this.valueProperty];
6941
6833
  }
6942
- cancelModal() {
6943
- // Reset filter and show all options when closing modal
6944
- this.searchTerm = '';
6945
- this.filteredItems = this.props?.options ? [...this.props.options] : [];
6946
- this.changeDetector.detectChanges();
6947
- if (this.modal) {
6948
- this.modal.dismiss();
6949
- }
6834
+ trackByFn(_index, option) {
6835
+ return option[this.valueProperty];
6950
6836
  }
6951
- selectItem(item) {
6952
- if (this.multiple) {
6953
- const index = this.selectedItems.findIndex(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
6954
- if (index === -1) {
6955
- this.selectedItems.push(item);
6956
- }
6957
- else {
6958
- this.selectedItems.splice(index, 1);
6959
- }
6960
- }
6961
- else {
6962
- this.selectedItems = [item];
6963
- this.cancelModal();
6837
+ handleClickOutside(event) {
6838
+ if (this.isOpen() &&
6839
+ !this.mainInputRef?.nativeElement?.contains(event.target) &&
6840
+ !this.dropdownRef?.nativeElement?.contains(event.target)) {
6841
+ this.isOpen.set(false);
6842
+ this.searchTerm.set('');
6964
6843
  }
6965
- this.updateDisplayValue();
6966
- this.applyChanges();
6967
6844
  }
6968
- isItemSelected(item) {
6969
- return this.selectedItems.some(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
6970
- }
6971
- updateDisplayValue() {
6972
- if (this.selectedItems.length === 0) {
6973
- this.displayValue = '';
6974
- return;
6975
- }
6976
- if (this.multiple) {
6977
- if (this.selectedItems.length === 1) {
6978
- this.displayValue = this.selectedItems[0][this.labelProperty];
6979
- }
6980
- else {
6981
- this.displayValue = `${this.selectedItems.length} elementos seleccionados`;
6982
- }
6983
- }
6984
- else {
6985
- this.displayValue = this.selectedItems[0][this.labelProperty];
6986
- }
6845
+ getOptionByValue(value) {
6846
+ return this.props?.options?.find(option => option[this.valueProperty] === value);
6987
6847
  }
6988
- applyChanges() {
6989
- if (!this.props?.control) {
6990
- return;
6991
- }
6992
- try {
6993
- this.isProcessingChanges = true;
6994
- if (this.selectedItems.length > 0) {
6995
- this.props.control.setValue(this.selectedItems[0][this.valueProperty]);
6996
- }
6997
- else {
6998
- this.props.control.setValue(null);
6999
- }
7000
- this.props.control.markAsDirty();
7001
- this.props.control.updateValueAndValidity();
7002
- }
7003
- finally {
7004
- this.isProcessingChanges = false;
6848
+ applyDefaultValue() {
6849
+ if (this.props) {
6850
+ applyDefaultValueToControl(this.props);
7005
6851
  }
7006
6852
  }
7007
- // Método público para reiniciar el componente
7008
- reset() {
7009
- this.selectedItems = [];
7010
- this.displayValue = '';
7011
- if (this.props?.control) {
7012
- this.props.control.setValue(null);
6853
+ syncSelectedValue() {
6854
+ if (this.props?.control?.value) {
6855
+ this.selectedValue.set(this.props.control.value);
7013
6856
  }
7014
- this.changeDetector.detectChanges();
7015
6857
  }
7016
6858
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7017
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SelectSearchComponent, isStandalone: true, selector: "val-select-search", inputs: { label: "label", labelProperty: "labelProperty", valueProperty: "valueProperty", multiple: "multiple", placeholder: "placeholder", props: "props" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
7018
- <ion-input
7019
- type="text"
7020
- [value]="displayValue"
7021
- [placeholder]="props?.placeholder || placeholder"
7022
- readonly
7023
- (mousedown)="preventDefaultBehavior($event)"
7024
- />
7025
-
7026
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
6859
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SelectSearchComponent, isStandalone: true, selector: "val-select-search", inputs: { props: "props", labelProperty: "labelProperty", valueProperty: "valueProperty", placeholder: "placeholder" }, viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "mainInputRef", first: true, predicate: ["mainInput"], descendants: true }], ngImport: i0, template: `
6860
+ <div class="select-container" (click)="toggleDropdown($event)">
6861
+ <!-- Main input display -->
6862
+ <ion-input
6863
+ #mainInput
6864
+ type="text"
6865
+ [value]="displayValue()"
6866
+ [placeholder]="props?.placeholder || placeholder"
6867
+ readonly
6868
+ class="main-input"
6869
+ [class.is-open]="isOpen()"
6870
+ />
6871
+
6872
+ <!-- Dropdown icon -->
6873
+ <ion-icon
6874
+ name="chevron-down-outline"
6875
+ class="dropdown-icon"
6876
+ [class.rotated]="isOpen()"
6877
+ ></ion-icon>
6878
+
6879
+ <!-- Hidden input for form control -->
6880
+ <ion-input
6881
+ style="position: absolute; opacity: 0; pointer-events: none;"
6882
+ [formControl]="props?.control"
6883
+ type="hidden"
6884
+ />
6885
+ </div>
7027
6886
 
7028
- <ion-modal
7029
- #modal
7030
- [initialBreakpoint]="1"
7031
- [breakpoints]="[0, 0.5, 0.75, 1]"
7032
- (didDismiss)="cancelModal()"
6887
+ <!-- Dropdown overlay -->
6888
+ <div
6889
+ class="dropdown-overlay"
6890
+ [class.visible]="isOpen()"
6891
+ #dropdown
7033
6892
  >
7034
- <ng-template>
7035
- <ion-header>
7036
- <ion-toolbar>
7037
- <ion-title>{{ label }}</ion-title>
7038
- <ion-buttons slot="end">
7039
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
7040
- </ion-buttons>
7041
- </ion-toolbar>
7042
- <ion-toolbar>
7043
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
7044
- </ion-toolbar>
7045
- </ion-header>
7046
- <ion-content>
7047
- <ion-list>
7048
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
7049
- <ion-label>{{ item[labelProperty] }}</ion-label>
7050
- <ion-icon *ngIf="isItemSelected(item)" name="checkmark-outline" slot="end" color="primary"></ion-icon>
7051
- </ion-item>
7052
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
7053
- <ion-label color="dark">No se encontraron resultados</ion-label>
7054
- </ion-item>
7055
- </ion-list>
7056
- </ion-content>
7057
- </ng-template>
7058
- </ion-modal>
7059
- `, isInline: true, styles: ["ion-header{padding:8px 8px 0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: IonicModule }, { kind: "component", type: i2.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonInput, selector: "ion-input", inputs: ["autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i2.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2.IonModal, selector: "ion-modal" }, { kind: "directive", type: i2.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: SearchbarComponent, selector: "val-searchbar", inputs: ["disabled"], outputs: ["filterEvent", "focusEvent", "blurEvent"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
6893
+ <!-- Search bar -->
6894
+ <div class="search-container" *ngIf="props?.options && props.options.length > 5">
6895
+ <ion-searchbar
6896
+ #searchbar
6897
+ [placeholder]="'Buscar'"
6898
+ (ionInput)="onSearch($event)"
6899
+ [value]="searchTerm()"
6900
+ show-clear-button="focus"
6901
+ [debounce]="200"
6902
+ ></ion-searchbar>
6903
+ </div>
6904
+
6905
+ <!-- Options list -->
6906
+ <div class="options-container">
6907
+ <ion-list class="options-list">
6908
+ <ion-item
6909
+ *ngFor="let option of filteredOptions(); trackBy: trackByFn"
6910
+ button
6911
+ (click)="selectOption(option)"
6912
+ class="option-item"
6913
+ >
6914
+ <ion-label>{{ option[labelProperty] }}</ion-label>
6915
+ <ion-icon
6916
+ *ngIf="isSelected(option)"
6917
+ name="checkmark-outline"
6918
+ slot="end"
6919
+ color="primary"
6920
+ ></ion-icon>
6921
+ </ion-item>
6922
+
6923
+ <!-- No results message -->
6924
+ <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
6925
+ <ion-label color="medium">
6926
+ {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
6927
+ </ion-label>
6928
+ </ion-item>
6929
+ </ion-list>
6930
+ </div>
6931
+ </div>
6932
+ `, isInline: true, styles: [":host{display:block;position:relative;width:100%}.select-container{position:relative;display:flex;align-items:center;cursor:pointer}.select-container .main-input{flex:1;cursor:pointer}.select-container .main-input.is-open{--border-color: var(--ion-color-primary)}.select-container .dropdown-icon{position:absolute;right:12px;font-size:16px;color:var(--ion-color-medium);transition:transform .2s ease;pointer-events:none;z-index:2}.select-container .dropdown-icon.rotated{transform:rotate(180deg)}.dropdown-overlay{position:absolute;top:100%;left:0;right:0;background:var(--ion-background-color);border:1px solid var(--ion-color-light);border-radius:8px;box-shadow:0 4px 16px #0000001a;z-index:1000;max-height:300px;opacity:0;transform:translateY(-8px);pointer-events:none;transition:all .2s ease}.dropdown-overlay.visible{opacity:1;transform:translateY(4px);pointer-events:all}.search-container{padding:12px;border-bottom:1px solid var(--ion-color-light)}.search-container ion-searchbar{--background: var(--ion-color-light);--border-radius: 8px;--box-shadow: none;--padding-start: 12px;--padding-end: 12px;height:40px}.options-container{max-height:240px;overflow-y:auto}.options-container .options-list{padding:0}.options-container .option-item{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;cursor:pointer}.options-container .option-item:hover{--background: var(--ion-color-light)}.options-container .option-item ion-label{font-size:16px;line-height:1.4}.options-container .option-item ion-icon{font-size:20px}.options-container .no-results{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;text-align:center}.options-container .no-results ion-label{font-style:italic;font-size:14px}@media (max-width: 768px){.dropdown-overlay{max-height:250px}.options-container{max-height:200px}}@media (prefers-color-scheme: dark){.dropdown-overlay{box-shadow:0 4px 16px #0000004d}}.option-item:focus-within{--background: var(--ion-color-primary-tint);outline:2px solid var(--ion-color-primary);outline-offset:-2px}.option-item{transition:background-color .15s ease}.dropdown-icon{transition:transform .2s cubic-bezier(.4,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: IonicModule }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonInput, selector: "ion-input", inputs: ["autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i2.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }, { kind: "directive", type: i2.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
7060
6933
  }
7061
6934
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, decorators: [{
7062
6935
  type: Component,
7063
- args: [{ selector: 'val-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, SearchbarComponent, ReactiveFormsModule], template: `
7064
- <ion-input
7065
- type="text"
7066
- [value]="displayValue"
7067
- [placeholder]="props?.placeholder || placeholder"
7068
- readonly
7069
- (mousedown)="preventDefaultBehavior($event)"
7070
- />
7071
-
7072
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
6936
+ args: [{ selector: 'val-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, ReactiveFormsModule], template: `
6937
+ <div class="select-container" (click)="toggleDropdown($event)">
6938
+ <!-- Main input display -->
6939
+ <ion-input
6940
+ #mainInput
6941
+ type="text"
6942
+ [value]="displayValue()"
6943
+ [placeholder]="props?.placeholder || placeholder"
6944
+ readonly
6945
+ class="main-input"
6946
+ [class.is-open]="isOpen()"
6947
+ />
6948
+
6949
+ <!-- Dropdown icon -->
6950
+ <ion-icon
6951
+ name="chevron-down-outline"
6952
+ class="dropdown-icon"
6953
+ [class.rotated]="isOpen()"
6954
+ ></ion-icon>
6955
+
6956
+ <!-- Hidden input for form control -->
6957
+ <ion-input
6958
+ style="position: absolute; opacity: 0; pointer-events: none;"
6959
+ [formControl]="props?.control"
6960
+ type="hidden"
6961
+ />
6962
+ </div>
7073
6963
 
7074
- <ion-modal
7075
- #modal
7076
- [initialBreakpoint]="1"
7077
- [breakpoints]="[0, 0.5, 0.75, 1]"
7078
- (didDismiss)="cancelModal()"
6964
+ <!-- Dropdown overlay -->
6965
+ <div
6966
+ class="dropdown-overlay"
6967
+ [class.visible]="isOpen()"
6968
+ #dropdown
7079
6969
  >
7080
- <ng-template>
7081
- <ion-header>
7082
- <ion-toolbar>
7083
- <ion-title>{{ label }}</ion-title>
7084
- <ion-buttons slot="end">
7085
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
7086
- </ion-buttons>
7087
- </ion-toolbar>
7088
- <ion-toolbar>
7089
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
7090
- </ion-toolbar>
7091
- </ion-header>
7092
- <ion-content>
7093
- <ion-list>
7094
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
7095
- <ion-label>{{ item[labelProperty] }}</ion-label>
7096
- <ion-icon *ngIf="isItemSelected(item)" name="checkmark-outline" slot="end" color="primary"></ion-icon>
7097
- </ion-item>
7098
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
7099
- <ion-label color="dark">No se encontraron resultados</ion-label>
7100
- </ion-item>
7101
- </ion-list>
7102
- </ion-content>
7103
- </ng-template>
7104
- </ion-modal>
7105
- `, styles: ["ion-header{padding:8px 8px 0}\n"] }]
7106
- }], ctorParameters: () => [], propDecorators: { modal: [{
6970
+ <!-- Search bar -->
6971
+ <div class="search-container" *ngIf="props?.options && props.options.length > 5">
6972
+ <ion-searchbar
6973
+ #searchbar
6974
+ [placeholder]="'Buscar'"
6975
+ (ionInput)="onSearch($event)"
6976
+ [value]="searchTerm()"
6977
+ show-clear-button="focus"
6978
+ [debounce]="200"
6979
+ ></ion-searchbar>
6980
+ </div>
6981
+
6982
+ <!-- Options list -->
6983
+ <div class="options-container">
6984
+ <ion-list class="options-list">
6985
+ <ion-item
6986
+ *ngFor="let option of filteredOptions(); trackBy: trackByFn"
6987
+ button
6988
+ (click)="selectOption(option)"
6989
+ class="option-item"
6990
+ >
6991
+ <ion-label>{{ option[labelProperty] }}</ion-label>
6992
+ <ion-icon
6993
+ *ngIf="isSelected(option)"
6994
+ name="checkmark-outline"
6995
+ slot="end"
6996
+ color="primary"
6997
+ ></ion-icon>
6998
+ </ion-item>
6999
+
7000
+ <!-- No results message -->
7001
+ <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
7002
+ <ion-label color="medium">
7003
+ {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
7004
+ </ion-label>
7005
+ </ion-item>
7006
+ </ion-list>
7007
+ </div>
7008
+ </div>
7009
+ `, styles: [":host{display:block;position:relative;width:100%}.select-container{position:relative;display:flex;align-items:center;cursor:pointer}.select-container .main-input{flex:1;cursor:pointer}.select-container .main-input.is-open{--border-color: var(--ion-color-primary)}.select-container .dropdown-icon{position:absolute;right:12px;font-size:16px;color:var(--ion-color-medium);transition:transform .2s ease;pointer-events:none;z-index:2}.select-container .dropdown-icon.rotated{transform:rotate(180deg)}.dropdown-overlay{position:absolute;top:100%;left:0;right:0;background:var(--ion-background-color);border:1px solid var(--ion-color-light);border-radius:8px;box-shadow:0 4px 16px #0000001a;z-index:1000;max-height:300px;opacity:0;transform:translateY(-8px);pointer-events:none;transition:all .2s ease}.dropdown-overlay.visible{opacity:1;transform:translateY(4px);pointer-events:all}.search-container{padding:12px;border-bottom:1px solid var(--ion-color-light)}.search-container ion-searchbar{--background: var(--ion-color-light);--border-radius: 8px;--box-shadow: none;--padding-start: 12px;--padding-end: 12px;height:40px}.options-container{max-height:240px;overflow-y:auto}.options-container .options-list{padding:0}.options-container .option-item{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;cursor:pointer}.options-container .option-item:hover{--background: var(--ion-color-light)}.options-container .option-item ion-label{font-size:16px;line-height:1.4}.options-container .option-item ion-icon{font-size:20px}.options-container .no-results{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;text-align:center}.options-container .no-results ion-label{font-style:italic;font-size:14px}@media (max-width: 768px){.dropdown-overlay{max-height:250px}.options-container{max-height:200px}}@media (prefers-color-scheme: dark){.dropdown-overlay{box-shadow:0 4px 16px #0000004d}}.option-item:focus-within{--background: var(--ion-color-primary-tint);outline:2px solid var(--ion-color-primary);outline-offset:-2px}.option-item{transition:background-color .15s ease}.dropdown-icon{transition:transform .2s cubic-bezier(.4,0,.2,1)}\n"] }]
7010
+ }], ctorParameters: () => [], propDecorators: { dropdownRef: [{
7107
7011
  type: ViewChild,
7108
- args: ['modal']
7109
- }], label: [{
7012
+ args: ['dropdown']
7013
+ }], mainInputRef: [{
7014
+ type: ViewChild,
7015
+ args: ['mainInput']
7016
+ }], props: [{
7110
7017
  type: Input
7111
7018
  }], labelProperty: [{
7112
7019
  type: Input
7113
7020
  }], valueProperty: [{
7114
7021
  type: Input
7115
- }], multiple: [{
7116
- type: Input
7117
7022
  }], placeholder: [{
7118
7023
  type: Input
7119
- }], props: [{
7120
- type: Input
7121
7024
  }] } });
7122
7025
 
7123
7026
  /**
@@ -8287,6 +8190,7 @@ class FormComponent {
8287
8190
  this.onSelectChange = new EventEmitter();
8288
8191
  this.types = InputType;
8289
8192
  this.subscriptions = [];
8193
+ this.previousValues = new Map();
8290
8194
  }
8291
8195
  ngOnInit() {
8292
8196
  const formControls = {};
@@ -8317,8 +8221,15 @@ class FormComponent {
8317
8221
  }
8318
8222
  trackSelectChanges(fieldName) {
8319
8223
  const control = this.getControl(fieldName);
8320
- const subscription = control.valueChanges.subscribe(value => {
8321
- this.onSelectChange.emit({ field: fieldName, value });
8224
+ const subscription = control.valueChanges
8225
+ .pipe(distinctUntilChanged$1()) // Evitar valores duplicados
8226
+ .subscribe(value => {
8227
+ // Evitar loops - solo emitir si el valor realmente cambió
8228
+ const previousValue = this.previousValues.get(fieldName);
8229
+ if (previousValue !== value) {
8230
+ this.previousValues.set(fieldName, value);
8231
+ this.onSelectChange.emit({ field: fieldName, value });
8232
+ }
8322
8233
  });
8323
8234
  this.subscriptions.push(subscription);
8324
8235
  }
@@ -8470,7 +8381,7 @@ class FormComponent {
8470
8381
  ></val-button-group>
8471
8382
  </form>
8472
8383
  </div>
8473
- `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.section{margin-top:1rem}.input{margin:.5rem 0}@media (min-width: 768px){.input{margin:.75rem 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextInputComponent, selector: "val-text-input", inputs: ["props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input" }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: DividerComponent, selector: "val-divider", inputs: ["props"] }, { kind: "component", type: HintComponent, selector: "val-hint", inputs: ["props"] }, { kind: "component", type: CommentInputComponent, selector: "val-comment-input", inputs: ["props"] }, { kind: "component", type: DateInputComponent, selector: "val-date-input", inputs: ["props"] }, { kind: "component", type: FileInputComponent, selector: "val-file-input", inputs: ["props"] }, { kind: "component", type: HourInputComponent, selector: "val-hour-input", inputs: ["props"] }, { kind: "component", type: EmailInputComponent, selector: "val-email-input", inputs: ["props"] }, { kind: "component", type: NumberInputComponent, selector: "val-number-input", inputs: ["props"] }, { kind: "component", type: NumberFromToComponent, selector: "val-number-from-to", inputs: ["props"] }, { kind: "component", type: RadioInputComponent, selector: "val-radio-input", inputs: ["props"] }, { kind: "component", type: PasswordInputComponent, selector: "val-password-input", inputs: ["props"] }, { kind: "component", type: PinInputComponent, selector: "val-pin-input", inputs: ["props"] }, { kind: "component", type: SelectSearchComponent, selector: "val-select-search", inputs: ["label", "labelProperty", "valueProperty", "multiple", "placeholder", "props"] }, { kind: "component", type: MultiSelectSearchComponent, selector: "val-multi-select-search", inputs: ["label", "labelProperty", "valueProperty", "placeholder", "props"] }, { kind: "component", type: MultiSelectSimpleComponent, selector: "val-multi-select-simple", inputs: ["props", "labelProperty", "valueProperty", "placeholder"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["props"] }] }); }
8384
+ `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.section{margin-top:1rem}.input{margin:.5rem 0}@media (min-width: 768px){.input{margin:.75rem 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextInputComponent, selector: "val-text-input", inputs: ["props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input" }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: DividerComponent, selector: "val-divider", inputs: ["props"] }, { kind: "component", type: HintComponent, selector: "val-hint", inputs: ["props"] }, { kind: "component", type: CommentInputComponent, selector: "val-comment-input", inputs: ["props"] }, { kind: "component", type: DateInputComponent, selector: "val-date-input", inputs: ["props"] }, { kind: "component", type: FileInputComponent, selector: "val-file-input", inputs: ["props"] }, { kind: "component", type: HourInputComponent, selector: "val-hour-input", inputs: ["props"] }, { kind: "component", type: EmailInputComponent, selector: "val-email-input", inputs: ["props"] }, { kind: "component", type: NumberInputComponent, selector: "val-number-input", inputs: ["props"] }, { kind: "component", type: NumberFromToComponent, selector: "val-number-from-to", inputs: ["props"] }, { kind: "component", type: RadioInputComponent, selector: "val-radio-input", inputs: ["props"] }, { kind: "component", type: PasswordInputComponent, selector: "val-password-input", inputs: ["props"] }, { kind: "component", type: PinInputComponent, selector: "val-pin-input", inputs: ["props"] }, { kind: "component", type: SelectSearchComponent, selector: "val-select-search", inputs: ["props", "labelProperty", "valueProperty", "placeholder"] }, { kind: "component", type: MultiSelectSearchComponent, selector: "val-multi-select-search", inputs: ["label", "labelProperty", "valueProperty", "placeholder", "props"] }, { kind: "component", type: MultiSelectSimpleComponent, selector: "val-multi-select-simple", inputs: ["props", "labelProperty", "valueProperty", "placeholder"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["props"] }] }); }
8474
8385
  }
8475
8386
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormComponent, decorators: [{
8476
8387
  type: Component,