valtech-components 2.0.381 → 2.0.383

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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, Component, Input, Output, Injectable, inject, InjectionToken, Inject, ChangeDetectorRef, HostListener, Pipe, ChangeDetectionStrategy, ViewChild } from '@angular/core';
3
- import { IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonDatetimeButton, IonInput, IonSelect, IonSelectOption, IonLabel, IonRadioGroup, IonRadio, IonSearchbar, IonMenuButton, IonFooter, IonList, IonListHeader, IonNote, IonItem } from '@ionic/angular/standalone';
2
+ import { EventEmitter, Component, Input, Output, Injectable, inject, InjectionToken, Inject, ChangeDetectorRef, HostListener, Pipe, ChangeDetectionStrategy, ViewChild, signal, computed, forwardRef } from '@angular/core';
3
+ import { IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonDatetimeButton, IonInput, IonSelect, IonSelectOption, IonLabel, IonSearchbar, IonRadioGroup, IonRadio, IonMenuButton, IonFooter, IonList, IonListHeader, IonNote, IonItem } from '@ionic/angular/standalone';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule, NgStyle, Location, AsyncPipe, NgFor, NgClass } from '@angular/common';
6
6
  import { addIcons } from 'ionicons';
@@ -9,19 +9,19 @@ import { BehaviorSubject, distinctUntilChanged, shareReplay, map, Subscription,
9
9
  import { Router, RouterLink } from '@angular/router';
10
10
  import { Browser } from '@capacitor/browser';
11
11
  import * as i1$1 from '@angular/platform-browser';
12
- import * as i1$2 from '@angular/forms';
13
- import { ReactiveFormsModule, FormsModule, Validators } from '@angular/forms';
14
- import { map as map$1 } from 'rxjs/operators';
15
- import * as i1$3 from 'ng-otp-input';
16
- import { NgOtpInputComponent, NgOtpInputModule } from 'ng-otp-input';
17
- import * as i2 from '@ionic/angular';
18
- import { IonicModule, ToastController } from '@ionic/angular';
19
12
  import { Clipboard } from '@capacitor/clipboard';
13
+ import * as i2 from '@ionic/angular';
14
+ import { ToastController, IonicModule } from '@ionic/angular';
20
15
  import * as Prism from 'prismjs';
21
16
  import 'prismjs/components/prism-css';
22
17
  import 'prismjs/components/prism-javascript';
23
18
  import 'prismjs/components/prism-markup';
24
19
  import 'prismjs/components/prism-typescript';
20
+ import * as i1$2 from '@angular/forms';
21
+ import { ReactiveFormsModule, FormsModule, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
22
+ import { map as map$1 } from 'rxjs/operators';
23
+ import * as i1$3 from 'ng-otp-input';
24
+ import { NgOtpInputComponent, NgOtpInputModule } from 'ng-otp-input';
25
25
  import 'prismjs/components/prism-bash';
26
26
 
27
27
  /**
@@ -384,7 +384,8 @@ var InputType;
384
384
  InputType[InputType["SELECT"] = 11] = "SELECT";
385
385
  InputType[InputType["SEARCH_SELECT"] = 12] = "SEARCH_SELECT";
386
386
  InputType[InputType["MULTI_SELECT"] = 13] = "MULTI_SELECT";
387
- InputType[InputType["FILE"] = 14] = "FILE";
387
+ InputType[InputType["MULTI_SELECT_SIMPLE"] = 14] = "MULTI_SELECT_SIMPLE";
388
+ InputType[InputType["FILE"] = 15] = "FILE";
388
389
  })(InputType || (InputType = {}));
389
390
  /**
390
391
  * Possible action types for a toolbar.
@@ -3042,6 +3043,27 @@ function createTitleProps(styleConfig, contentConfig) {
3042
3043
  };
3043
3044
  }
3044
3045
 
3046
+ class ActionHeaderComponent {
3047
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3048
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ActionHeaderComponent, isStandalone: true, selector: "val-action-header", inputs: { props: "props" }, ngImport: i0, template: `
3049
+ <section class="header-content-container">
3050
+ <val-display [props]="props.title" />
3051
+ <val-button [props]="props.action" />
3052
+ </section>
3053
+ `, isInline: true, styles: [".header-content-container{width:100%;display:flex;align-items:center;justify-content:space-between}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["props"], outputs: ["onClick"] }] }); }
3054
+ }
3055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActionHeaderComponent, decorators: [{
3056
+ type: Component,
3057
+ args: [{ selector: 'val-action-header', standalone: true, imports: [CommonModule, DisplayComponent, ButtonComponent], template: `
3058
+ <section class="header-content-container">
3059
+ <val-display [props]="props.title" />
3060
+ <val-button [props]="props.action" />
3061
+ </section>
3062
+ `, styles: [".header-content-container{width:100%;display:flex;align-items:center;justify-content:space-between}\n"] }]
3063
+ }], propDecorators: { props: [{
3064
+ type: Input
3065
+ }] } });
3066
+
3045
3067
  /**
3046
3068
  * val-alert-box
3047
3069
  *
@@ -3591,6 +3613,150 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3591
3613
  args: [{ selector: 'val-check-input', standalone: true, imports: [CommonModule, IonCheckbox], template: ` <ion-checkbox>I agree to the terms and conditions</ion-checkbox> ` }]
3592
3614
  }], ctorParameters: () => [] });
3593
3615
 
3616
+ class CodeDisplayComponent {
3617
+ constructor(cdr) {
3618
+ this.cdr = cdr;
3619
+ this.toast = inject(ToastController);
3620
+ this.langService = inject(LangService);
3621
+ this.selectedTab = 0;
3622
+ }
3623
+ ngOnChanges(changes) {
3624
+ if (changes['code'] || changes['language'] || changes['tabs']) {
3625
+ this.cdr.detectChanges();
3626
+ setTimeout(() => this.highlightCode());
3627
+ }
3628
+ }
3629
+ ngAfterViewInit() {
3630
+ setTimeout(() => this.highlightCode());
3631
+ }
3632
+ selectTab(i) {
3633
+ this.selectedTab = i;
3634
+ this.cdr.detectChanges();
3635
+ setTimeout(() => this.highlightCode());
3636
+ }
3637
+ highlightCode() {
3638
+ if (this.codeElement) {
3639
+ const code = this.props.tabs.length > 0 ? this.props.tabs[this.selectedTab]?.code : this.props.code;
3640
+ this.codeElement.nativeElement.textContent = code || '';
3641
+ Prism.highlightElement(this.codeElement.nativeElement);
3642
+ }
3643
+ }
3644
+ async copyToClipboard() {
3645
+ try {
3646
+ const code = this.props.tabs.length > 0 ? this.props.tabs[this.selectedTab]?.code : this.props.code;
3647
+ await Clipboard.write({ string: code || '' });
3648
+ const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
3649
+ this.presentToast(copiedMessage);
3650
+ }
3651
+ catch (error) {
3652
+ console.error('Error al copiar al portapapeles:', error);
3653
+ }
3654
+ }
3655
+ async presentToast(message) {
3656
+ const toast = await this.toast.create({
3657
+ message: message,
3658
+ duration: 2000,
3659
+ position: 'bottom',
3660
+ color: 'dark',
3661
+ });
3662
+ toast.present();
3663
+ }
3664
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CodeDisplayComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
3665
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CodeDisplayComponent, isStandalone: true, selector: "val-code-display", inputs: { props: "props" }, viewQueries: [{ propertyName: "codeElement", first: true, predicate: ["codeElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
3666
+ <div class="code-viewer-container">
3667
+ <div class="tab-bar">
3668
+ <div
3669
+ class="tab"
3670
+ *ngFor="let tab of props.tabs; let i = index"
3671
+ [class.active]="i === selectedTab"
3672
+ (click)="selectTab(i)"
3673
+ >
3674
+ <span class="tab-label">{{ tab.label }}</span>
3675
+ </div>
3676
+ </div>
3677
+ <div class="code-content">
3678
+ <!-- <span class="language-badge">{{ props.tabs[selectedTab]?.language || props.language }}</span> -->
3679
+ <ion-button fill="clear" class="copy-button" (click)="copyToClipboard()">
3680
+ <ion-icon name="copy-outline"></ion-icon>
3681
+ </ion-button>
3682
+ <pre><code [class]="'language-' + (props.tabs[selectedTab]?.language || props.language)" #codeElement></code></pre>
3683
+ </div>
3684
+ </div>
3685
+ `, 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)}.code-viewer-container{background-color:#fff;border-radius:24px;overflow:hidden;box-shadow:0 2px 4px #0000000d;border:1px solid #f2f6f7;position:relative;min-width:320px;max-width:100%}.tab-bar{display:flex;background:#f6f9fa;border-bottom:1px solid #f2f6f7;gap:2px;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:#e0e0e0 #f6f9fa;-webkit-overflow-scrolling:touch;max-width:100%;font-size:12px}.tab-bar::-webkit-scrollbar{height:6px;background:#f6f9fa}.tab-bar::-webkit-scrollbar-thumb{background:#e0e0e0;border-radius:4px}.tab{padding:10px 18px 8px;font-family:Roboto Mono,monospace;font-size:.95em;color:#899396;cursor:pointer;border-radius:8px 8px 0 0;background:transparent;transition:background .2s,color .2s;margin-bottom:-1px;border:1px solid transparent;border-bottom:none}.tab:hover{background:#e8eef2}.tab.active{background:#fff;color:#19422d;border:1px solid #f2f6f7;border-bottom:1px solid #ffffff;z-index:2}.tab-label{font-weight:500}.code-content{overflow-x:auto;overflow-y:auto;max-height:30rem;min-height:5rem;background:#fff;position:relative}.language-badge{position:absolute;top:15px;left:15px;background:#f6f9fa;color:#899396;font-family:Roboto Mono,monospace;font-size:.8em;font-weight:500;border-radius:6px;padding:2px 8px;z-index:3;pointer-events:none;text-transform:uppercase}.copy-button{position:absolute;top:10px;right:15px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:var(--ion-color-primary);background:#ffffffb3;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease}.copy-button:hover{background:#ffffffe6}.copy-button ion-icon{font-size:1.2em;margin:0}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.5;display:block;white-space:inherit;word-break:normal}@media (max-width: 600px){.code-viewer-container{border-radius:24px}.tab-bar{font-size:11px}.language-badge{font-size:.7em;padding:1px 6px;top:10px;left:10px}.copy-button{top:10px;right:10px}.code-content{max-height:20rem}code{font-size:.7em}}@media (min-width: 600px){code{font-size:.8em}}@media (prefers-color-scheme: dark){.code-viewer-container{background-color:#21252b;box-shadow:0 4px 15px #0009;border:1px solid #3b4048}.tab-bar{background:#1a1a1a;border-bottom:1px solid #3b4048;scrollbar-color:#3b4048 #1a1a1a}.tab-bar::-webkit-scrollbar{background:#1a1a1a}.tab-bar::-webkit-scrollbar-thumb{background:#3b4048}.tab{color:#8b949e}.tab:hover{background:#21252b}.tab.active{background:#282c34;color:#c9d1d9;border:1px solid #3b4048;border-bottom:1px solid #282c34}.code-content{background:#161b22}.language-badge{background:#3e4451;color:#8b949e}.copy-button{background:#0006}.copy-button:hover{background:#0009}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] }); }
3686
+ }
3687
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CodeDisplayComponent, decorators: [{
3688
+ type: Component,
3689
+ args: [{ selector: 'val-code-display', standalone: true, imports: [CommonModule, IonIcon, IonButton], template: `
3690
+ <div class="code-viewer-container">
3691
+ <div class="tab-bar">
3692
+ <div
3693
+ class="tab"
3694
+ *ngFor="let tab of props.tabs; let i = index"
3695
+ [class.active]="i === selectedTab"
3696
+ (click)="selectTab(i)"
3697
+ >
3698
+ <span class="tab-label">{{ tab.label }}</span>
3699
+ </div>
3700
+ </div>
3701
+ <div class="code-content">
3702
+ <!-- <span class="language-badge">{{ props.tabs[selectedTab]?.language || props.language }}</span> -->
3703
+ <ion-button fill="clear" class="copy-button" (click)="copyToClipboard()">
3704
+ <ion-icon name="copy-outline"></ion-icon>
3705
+ </ion-button>
3706
+ <pre><code [class]="'language-' + (props.tabs[selectedTab]?.language || props.language)" #codeElement></code></pre>
3707
+ </div>
3708
+ </div>
3709
+ `, 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)}.code-viewer-container{background-color:#fff;border-radius:24px;overflow:hidden;box-shadow:0 2px 4px #0000000d;border:1px solid #f2f6f7;position:relative;min-width:320px;max-width:100%}.tab-bar{display:flex;background:#f6f9fa;border-bottom:1px solid #f2f6f7;gap:2px;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:#e0e0e0 #f6f9fa;-webkit-overflow-scrolling:touch;max-width:100%;font-size:12px}.tab-bar::-webkit-scrollbar{height:6px;background:#f6f9fa}.tab-bar::-webkit-scrollbar-thumb{background:#e0e0e0;border-radius:4px}.tab{padding:10px 18px 8px;font-family:Roboto Mono,monospace;font-size:.95em;color:#899396;cursor:pointer;border-radius:8px 8px 0 0;background:transparent;transition:background .2s,color .2s;margin-bottom:-1px;border:1px solid transparent;border-bottom:none}.tab:hover{background:#e8eef2}.tab.active{background:#fff;color:#19422d;border:1px solid #f2f6f7;border-bottom:1px solid #ffffff;z-index:2}.tab-label{font-weight:500}.code-content{overflow-x:auto;overflow-y:auto;max-height:30rem;min-height:5rem;background:#fff;position:relative}.language-badge{position:absolute;top:15px;left:15px;background:#f6f9fa;color:#899396;font-family:Roboto Mono,monospace;font-size:.8em;font-weight:500;border-radius:6px;padding:2px 8px;z-index:3;pointer-events:none;text-transform:uppercase}.copy-button{position:absolute;top:10px;right:15px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:var(--ion-color-primary);background:#ffffffb3;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease}.copy-button:hover{background:#ffffffe6}.copy-button ion-icon{font-size:1.2em;margin:0}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.5;display:block;white-space:inherit;word-break:normal}@media (max-width: 600px){.code-viewer-container{border-radius:24px}.tab-bar{font-size:11px}.language-badge{font-size:.7em;padding:1px 6px;top:10px;left:10px}.copy-button{top:10px;right:10px}.code-content{max-height:20rem}code{font-size:.7em}}@media (min-width: 600px){code{font-size:.8em}}@media (prefers-color-scheme: dark){.code-viewer-container{background-color:#21252b;box-shadow:0 4px 15px #0009;border:1px solid #3b4048}.tab-bar{background:#1a1a1a;border-bottom:1px solid #3b4048;scrollbar-color:#3b4048 #1a1a1a}.tab-bar::-webkit-scrollbar{background:#1a1a1a}.tab-bar::-webkit-scrollbar-thumb{background:#3b4048}.tab{color:#8b949e}.tab:hover{background:#21252b}.tab.active{background:#282c34;color:#c9d1d9;border:1px solid #3b4048;border-bottom:1px solid #282c34}.code-content{background:#161b22}.language-badge{background:#3e4451;color:#8b949e}.copy-button{background:#0006}.copy-button:hover{background:#0009}}\n"] }]
3710
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { codeElement: [{
3711
+ type: ViewChild,
3712
+ args: ['codeElement']
3713
+ }], props: [{
3714
+ type: Input
3715
+ }] } });
3716
+
3717
+ class CommandDisplayComponent {
3718
+ constructor() {
3719
+ this.toast = inject(ToastController);
3720
+ this.langService = inject(LangService);
3721
+ }
3722
+ async copyCommand() {
3723
+ if (this.props.text) {
3724
+ await Clipboard.write({
3725
+ string: this.props.text,
3726
+ });
3727
+ const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
3728
+ this.presentToast(copiedMessage);
3729
+ }
3730
+ }
3731
+ async presentToast(message) {
3732
+ const toast = await this.toast.create({
3733
+ message: message,
3734
+ duration: 2000,
3735
+ position: 'bottom',
3736
+ color: 'dark',
3737
+ });
3738
+ toast.present();
3739
+ }
3740
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CommandDisplayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3741
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CommandDisplayComponent, isStandalone: true, selector: "val-command-display", inputs: { props: "props" }, ngImport: i0, template: `
3742
+ <div class="command-container">
3743
+ <div class="command-text">$ {{ props.text }}</div>
3744
+ <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
3745
+ </div>
3746
+ `, isInline: true, styles: [".command-container{display:flex;align-items:center;justify-content:space-between;background-color:var(--ion-color-light, #f2f2f2);border-radius:24px;padding:12px 16px;box-shadow:0 2px 4px #0000001a}.command-text{flex-grow:1;font-family:monospace;font-size:.8rem;color:var(--ion-color-dark, #333);margin-right:10px}.copy-icon{font-size:1.3rem;color:var(--ion-color-medium, #92949c);cursor:pointer;transition:color .2s ease-in-out}.copy-icon:hover{color:var(--ion-color-primary, #3880ff)}@media (min-width: 600px){.command-text,.copy-icon{font-size:1.2rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
3747
+ }
3748
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CommandDisplayComponent, decorators: [{
3749
+ type: Component,
3750
+ args: [{ selector: 'val-command-display', standalone: true, imports: [CommonModule, IonIcon], template: `
3751
+ <div class="command-container">
3752
+ <div class="command-text">$ {{ props.text }}</div>
3753
+ <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
3754
+ </div>
3755
+ `, styles: [".command-container{display:flex;align-items:center;justify-content:space-between;background-color:var(--ion-color-light, #f2f2f2);border-radius:24px;padding:12px 16px;box-shadow:0 2px 4px #0000001a}.command-text{flex-grow:1;font-family:monospace;font-size:.8rem;color:var(--ion-color-dark, #333);margin-right:10px}.copy-icon{font-size:1.3rem;color:var(--ion-color-medium, #92949c);cursor:pointer;transition:color .2s ease-in-out}.copy-icon:hover{color:var(--ion-color-primary, #3880ff)}@media (min-width: 600px){.command-text,.copy-icon{font-size:1.2rem}}\n"] }]
3756
+ }], ctorParameters: () => [], propDecorators: { props: [{
3757
+ type: Input
3758
+ }] } });
3759
+
3594
3760
  /**
3595
3761
  * val-comment-input
3596
3762
  *
@@ -4149,72 +4315,267 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4149
4315
  }] } });
4150
4316
 
4151
4317
  /**
4152
- * val-popover-selector
4153
- *
4154
- * A generic reusable popover selector component that can be used for any type of selection.
4155
- * Provides a button trigger that opens a popover with selectable options.
4318
+ * val-link
4156
4319
  *
4157
- * @example
4158
- * // Basic usage
4159
- * <val-popover-selector
4160
- * [props]="selectorProps"
4161
- * (selectionChange)="onSelectionChange($event)">
4162
- * </val-popover-selector>
4320
+ * A stylized link button with navigation support for internal, in-app, or new tab links.
4163
4321
  *
4164
4322
  * @example
4165
- * // With icon and custom styling
4166
- * const selectorProps: PopoverSelectorMetadata = {
4167
- * options: [
4168
- * { value: 'option1', label: 'Option 1', icon: 'star' },
4169
- * { value: 'option2', label: 'Option 2', icon: 'heart' }
4170
- * ],
4171
- * selectedValue: 'option1',
4172
- * label: 'Choose option',
4173
- * icon: 'settings',
4174
- * color: 'primary',
4175
- * size: 'large',
4176
- * fill: 'solid'
4177
- * };
4323
+ * <val-link [props]="{ text: 'Go', color: 'primary', link: '/home', type: 'internal' }" (onClick)="handler($event)"></val-link>
4178
4324
  *
4179
- * @input props: PopoverSelectorMetadata - Configuration for the selector
4180
- * @output selectionChange: EventEmitter<string | string[]> - Emitted when selection changes
4325
+ * @input props: LinkMetadata - Configuration for the link (text, color, link, type, etc.)
4326
+ * @output onClick - Emits the token of the clicked link
4181
4327
  */
4182
- class PopoverSelectorComponent {
4328
+ class LinkComponent {
4183
4329
  constructor() {
4184
- /**
4185
- * Event emitted when the selection changes.
4186
- * Emits the selected value(s).
4187
- */
4188
- this.selectionChange = new EventEmitter();
4189
- this.langService = inject(LangService);
4190
- // Register required icons
4191
- addIcons({ chevronDown });
4192
- }
4193
- /**
4194
- * Get reactive placeholder text.
4195
- */
4196
- getPlaceholderText() {
4197
- return this.props.placeholder || this.langService.getText('_global', 'select', 'Seleccionar...');
4198
- }
4199
- /**
4200
- * Get reactive cancel text.
4201
- */
4202
- getCancelText() {
4203
- return this.props.cancelText || this.langService.getText('_global', 'cancel', 'Cancelar');
4330
+ this.onClick = new EventEmitter();
4331
+ this.service = inject(NavigationService);
4332
+ addIcons({ chevronForwardOutline });
4204
4333
  }
4205
- /**
4206
- * Get reactive ok text.
4207
- */
4208
- getOkText() {
4209
- return this.props.okText || this.langService.getText('_global', 'ok', 'Aceptar');
4334
+ ngOnInit() { }
4335
+ onClickHandler() {
4336
+ this.onClick.emit(this.props.token);
4337
+ switch (this.props.type) {
4338
+ case 'internal':
4339
+ this.service.navigateByUrl(this.props.link);
4340
+ break;
4341
+ case 'browse':
4342
+ this.service.navigateInApp(this.props.link);
4343
+ break;
4344
+ case 'tab':
4345
+ this.service.openInNewTab(this.props.link);
4346
+ break;
4347
+ }
4210
4348
  }
4211
- /**
4212
- * Handle selection change from the ion-select.
4213
- * @param event - The ion-select change event
4214
- */
4215
- onSelectionChange(event) {
4216
- const selectedValue = event.detail.value;
4217
- this.selectionChange.emit(selectedValue);
4349
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4350
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LinkComponent, isStandalone: true, selector: "val-link", inputs: { props: "props" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
4351
+ <div>
4352
+ <ion-button type="button" [color]="props.color" fill="clear" [size]="props.size" (click)="onClickHandler()">
4353
+ <ion-icon slot="end" name="chevron-forward-outline"></ion-icon>
4354
+ <ion-text>{{ props.text }}</ion-text>
4355
+ </ion-button>
4356
+ </div>
4357
+ `, 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)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;margin:0;--padding-bottom: 0;--padding-top: 0;--padding-start: 0;--padding-end: 0}\n"], dependencies: [{ kind: "component", type: 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
4358
+ }
4359
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkComponent, decorators: [{
4360
+ type: Component,
4361
+ args: [{ selector: 'val-link', standalone: true, imports: [IonButton, IonIcon, IonText], template: `
4362
+ <div>
4363
+ <ion-button type="button" [color]="props.color" fill="clear" [size]="props.size" (click)="onClickHandler()">
4364
+ <ion-icon slot="end" name="chevron-forward-outline"></ion-icon>
4365
+ <ion-text>{{ props.text }}</ion-text>
4366
+ </ion-button>
4367
+ </div>
4368
+ `, 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)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;margin:0;--padding-bottom: 0;--padding-top: 0;--padding-start: 0;--padding-end: 0}\n"] }]
4369
+ }], ctorParameters: () => [], propDecorators: { props: [{
4370
+ type: Input
4371
+ }], onClick: [{
4372
+ type: Output
4373
+ }] } });
4374
+
4375
+ /**
4376
+ * val-title-block
4377
+ *
4378
+ * Displays a block of titles (above, main, below) with configurable styles and positions.
4379
+ *
4380
+ * @example
4381
+ * <val-title-block [props]="{ title: {...}, aboveTitle: {...}, bellowTitle: {...}, position: 'center' }"></val-title-block>
4382
+ *
4383
+ * @input props: TitleBlockMetada - Configuration for the title block (title, aboveTitle, bellowTitle, position)
4384
+ */
4385
+ class TitleBlockComponent {
4386
+ constructor(cdr) {
4387
+ this.cdr = cdr;
4388
+ }
4389
+ ngOnInit() { }
4390
+ ngOnChanges(changes) {
4391
+ if (changes['props']) {
4392
+ // Forzar detección de cambios múltiple
4393
+ this.cdr.detectChanges();
4394
+ setTimeout(() => {
4395
+ this.cdr.detectChanges();
4396
+ }, 0);
4397
+ }
4398
+ }
4399
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TitleBlockComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
4400
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TitleBlockComponent, isStandalone: true, selector: "val-title-block", inputs: { props: "props" }, usesOnChanges: true, ngImport: i0, template: `
4401
+ <div [ngClass]="['titles-container', props.position]">
4402
+ <val-title
4403
+ *ngIf="props.aboveTitle"
4404
+ [props]="{
4405
+ content: props.aboveTitle.content | uppercase,
4406
+ color: props.aboveTitle.color,
4407
+ bold: false,
4408
+ size: props.aboveTitle.size,
4409
+ }"
4410
+ ></val-title>
4411
+ <val-display
4412
+ *ngIf="props.title"
4413
+ [props]="{
4414
+ content: props.title.content,
4415
+ color: props.title.color,
4416
+ size: props.title.size,
4417
+ }"
4418
+ ></val-display>
4419
+ <val-title
4420
+ style="margin-top: 16px;"
4421
+ *ngIf="props.bellowTitle"
4422
+ [props]="{
4423
+ content: props.bellowTitle.content,
4424
+ color: props.bellowTitle.color,
4425
+ bold: false,
4426
+ size: props.bellowTitle.size,
4427
+ thin: props.bellowTitle.thin,
4428
+ }"
4429
+ ></val-title>
4430
+ </div>
4431
+ `, 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)}val-button,val-title,val-display{display:inline-block}.titles-container{width:100%;display:flex;flex-direction:column;flex-wrap:wrap}.titles-container.left{align-content:flex-start;align-items:start;text-align:left}.titles-container.center{align-content:center;align-items:center;text-align:center}.titles-container.right{align-content:flex-end;align-items:end;text-align:end}.titles-container.leftocenter{align-content:flex-start;align-items:start;text-align:left}@media (min-width: 768px){.titles-container.leftocenter{align-content:center;align-items:center;text-align:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }] }); }
4432
+ }
4433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TitleBlockComponent, decorators: [{
4434
+ type: Component,
4435
+ args: [{ selector: 'val-title-block', standalone: true, imports: [CommonModule, TitleComponent, DisplayComponent], template: `
4436
+ <div [ngClass]="['titles-container', props.position]">
4437
+ <val-title
4438
+ *ngIf="props.aboveTitle"
4439
+ [props]="{
4440
+ content: props.aboveTitle.content | uppercase,
4441
+ color: props.aboveTitle.color,
4442
+ bold: false,
4443
+ size: props.aboveTitle.size,
4444
+ }"
4445
+ ></val-title>
4446
+ <val-display
4447
+ *ngIf="props.title"
4448
+ [props]="{
4449
+ content: props.title.content,
4450
+ color: props.title.color,
4451
+ size: props.title.size,
4452
+ }"
4453
+ ></val-display>
4454
+ <val-title
4455
+ style="margin-top: 16px;"
4456
+ *ngIf="props.bellowTitle"
4457
+ [props]="{
4458
+ content: props.bellowTitle.content,
4459
+ color: props.bellowTitle.color,
4460
+ bold: false,
4461
+ size: props.bellowTitle.size,
4462
+ thin: props.bellowTitle.thin,
4463
+ }"
4464
+ ></val-title>
4465
+ </div>
4466
+ `, 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)}val-button,val-title,val-display{display:inline-block}.titles-container{width:100%;display:flex;flex-direction:column;flex-wrap:wrap}.titles-container.left{align-content:flex-start;align-items:start;text-align:left}.titles-container.center{align-content:center;align-items:center;text-align:center}.titles-container.right{align-content:flex-end;align-items:end;text-align:end}.titles-container.leftocenter{align-content:flex-start;align-items:start;text-align:left}@media (min-width: 768px){.titles-container.leftocenter{align-content:center;align-items:center;text-align:center}}\n"] }]
4467
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { props: [{
4468
+ type: Input
4469
+ }] } });
4470
+
4471
+ // src/app/layout/layout.component.ts (solo la parte de styles)
4472
+ class InfoComponent {
4473
+ constructor() {
4474
+ this.icon = inject(IconService);
4475
+ }
4476
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4477
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: InfoComponent, isStandalone: true, selector: "val-info", inputs: { props: "props" }, ngImport: i0, template: `
4478
+ @if (props.image) {
4479
+ <val-image style="display: contents;" [props]="props.image" />
4480
+ }
4481
+ <val-title-block style="display: block;margin-top: 16px;" [props]="props.title" />
4482
+
4483
+ @if (props.link) {
4484
+ <val-link [props]="props.link" />
4485
+ }
4486
+
4487
+ @if (props.actions) {
4488
+ <val-button-group [props]="props.actions" />
4489
+ }
4490
+ `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LinkComponent, selector: "val-link", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TitleBlockComponent, selector: "val-title-block", inputs: ["props"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }] }); }
4491
+ }
4492
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoComponent, decorators: [{
4493
+ type: Component,
4494
+ args: [{ selector: 'val-info', standalone: true, imports: [CommonModule, LinkComponent, TitleBlockComponent, ImageComponent, ButtonGroupComponent], template: `
4495
+ @if (props.image) {
4496
+ <val-image style="display: contents;" [props]="props.image" />
4497
+ }
4498
+ <val-title-block style="display: block;margin-top: 16px;" [props]="props.title" />
4499
+
4500
+ @if (props.link) {
4501
+ <val-link [props]="props.link" />
4502
+ }
4503
+
4504
+ @if (props.actions) {
4505
+ <val-button-group [props]="props.actions" />
4506
+ }
4507
+ ` }]
4508
+ }], propDecorators: { props: [{
4509
+ type: Input
4510
+ }] } });
4511
+
4512
+ /**
4513
+ * val-popover-selector
4514
+ *
4515
+ * A generic reusable popover selector component that can be used for any type of selection.
4516
+ * Provides a button trigger that opens a popover with selectable options.
4517
+ *
4518
+ * @example
4519
+ * // Basic usage
4520
+ * <val-popover-selector
4521
+ * [props]="selectorProps"
4522
+ * (selectionChange)="onSelectionChange($event)">
4523
+ * </val-popover-selector>
4524
+ *
4525
+ * @example
4526
+ * // With icon and custom styling
4527
+ * const selectorProps: PopoverSelectorMetadata = {
4528
+ * options: [
4529
+ * { value: 'option1', label: 'Option 1', icon: 'star' },
4530
+ * { value: 'option2', label: 'Option 2', icon: 'heart' }
4531
+ * ],
4532
+ * selectedValue: 'option1',
4533
+ * label: 'Choose option',
4534
+ * icon: 'settings',
4535
+ * color: 'primary',
4536
+ * size: 'large',
4537
+ * fill: 'solid'
4538
+ * };
4539
+ *
4540
+ * @input props: PopoverSelectorMetadata - Configuration for the selector
4541
+ * @output selectionChange: EventEmitter<string | string[]> - Emitted when selection changes
4542
+ */
4543
+ class PopoverSelectorComponent {
4544
+ constructor() {
4545
+ /**
4546
+ * Event emitted when the selection changes.
4547
+ * Emits the selected value(s).
4548
+ */
4549
+ this.selectionChange = new EventEmitter();
4550
+ this.langService = inject(LangService);
4551
+ // Register required icons
4552
+ addIcons({ chevronDown });
4553
+ }
4554
+ /**
4555
+ * Get reactive placeholder text.
4556
+ */
4557
+ getPlaceholderText() {
4558
+ return this.props.placeholder || this.langService.getText('_global', 'select', 'Seleccionar...');
4559
+ }
4560
+ /**
4561
+ * Get reactive cancel text.
4562
+ */
4563
+ getCancelText() {
4564
+ return this.props.cancelText || this.langService.getText('_global', 'cancel', 'Cancelar');
4565
+ }
4566
+ /**
4567
+ * Get reactive ok text.
4568
+ */
4569
+ getOkText() {
4570
+ return this.props.okText || this.langService.getText('_global', 'ok', 'Aceptar');
4571
+ }
4572
+ /**
4573
+ * Handle selection change from the ion-select.
4574
+ * @param event - The ion-select change event
4575
+ */
4576
+ onSelectionChange(event) {
4577
+ const selectedValue = event.detail.value;
4578
+ this.selectionChange.emit(selectedValue);
4218
4579
  }
4219
4580
  /**
4220
4581
  * Get the display text for the trigger button.
@@ -4269,7 +4630,7 @@ class PopoverSelectorComponent {
4269
4630
 
4270
4631
  <span class="trigger-text">{{ getDisplayText() }}</span>
4271
4632
 
4272
- <ion-icon name="chevron-down" slot="end" class="chevron-icon"> </ion-icon>
4633
+ <ion-icon name="chevron-down-outline" slot="end" class="chevron-icon"> </ion-icon>
4273
4634
  </ion-button>
4274
4635
 
4275
4636
  <ion-select-option *ngFor="let option of props.options" [value]="option.value" [disabled]="option.disabled">
@@ -4311,7 +4672,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4311
4672
 
4312
4673
  <span class="trigger-text">{{ getDisplayText() }}</span>
4313
4674
 
4314
- <ion-icon name="chevron-down" slot="end" class="chevron-icon"> </ion-icon>
4675
+ <ion-icon name="chevron-down-outline" slot="end" class="chevron-icon"> </ion-icon>
4315
4676
  </ion-button>
4316
4677
 
4317
4678
  <ion-select-option *ngFor="let option of props.options" [value]="option.value" [disabled]="option.disabled">
@@ -4678,105 +5039,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4678
5039
  }]
4679
5040
  }], ctorParameters: () => [] });
4680
5041
 
4681
- /**
4682
- * val-title-block
4683
- *
4684
- * Displays a block of titles (above, main, below) with configurable styles and positions.
4685
- *
4686
- * @example
4687
- * <val-title-block [props]="{ title: {...}, aboveTitle: {...}, bellowTitle: {...}, position: 'center' }"></val-title-block>
4688
- *
4689
- * @input props: TitleBlockMetada - Configuration for the title block (title, aboveTitle, bellowTitle, position)
4690
- */
4691
- class TitleBlockComponent {
4692
- constructor(cdr) {
4693
- this.cdr = cdr;
4694
- }
4695
- ngOnInit() { }
4696
- ngOnChanges(changes) {
4697
- if (changes['props']) {
4698
- // Forzar detección de cambios múltiple
4699
- this.cdr.detectChanges();
4700
- setTimeout(() => {
4701
- this.cdr.detectChanges();
4702
- }, 0);
4703
- }
4704
- }
4705
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TitleBlockComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
4706
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TitleBlockComponent, isStandalone: true, selector: "val-title-block", inputs: { props: "props" }, usesOnChanges: true, ngImport: i0, template: `
4707
- <div [ngClass]="['titles-container', props.position]">
4708
- <val-title
4709
- *ngIf="props.aboveTitle"
4710
- [props]="{
4711
- content: props.aboveTitle.content | uppercase,
4712
- color: props.aboveTitle.color,
4713
- bold: false,
4714
- size: props.aboveTitle.size,
4715
- }"
4716
- ></val-title>
4717
- <val-display
4718
- *ngIf="props.title"
4719
- [props]="{
4720
- content: props.title.content,
4721
- color: props.title.color,
4722
- size: props.title.size,
4723
- }"
4724
- ></val-display>
4725
- <val-title
4726
- style="margin-top: 16px;"
4727
- *ngIf="props.bellowTitle"
4728
- [props]="{
4729
- content: props.bellowTitle.content,
4730
- color: props.bellowTitle.color,
4731
- bold: false,
4732
- size: props.bellowTitle.size,
4733
- thin: props.bellowTitle.thin,
4734
- }"
4735
- ></val-title>
4736
- </div>
4737
- `, 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)}val-button,val-title,val-display{display:inline-block}.titles-container{width:100%;display:flex;flex-direction:column;flex-wrap:wrap}.titles-container.left{align-content:flex-start;align-items:start;text-align:left}.titles-container.center{align-content:center;align-items:center;text-align:center}.titles-container.right{align-content:flex-end;align-items:end;text-align:end}.titles-container.leftocenter{align-content:flex-start;align-items:start;text-align:left}@media (min-width: 768px){.titles-container.leftocenter{align-content:center;align-items:center;text-align:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }] }); }
4738
- }
4739
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TitleBlockComponent, decorators: [{
4740
- type: Component,
4741
- args: [{ selector: 'val-title-block', standalone: true, imports: [CommonModule, TitleComponent, DisplayComponent], template: `
4742
- <div [ngClass]="['titles-container', props.position]">
4743
- <val-title
4744
- *ngIf="props.aboveTitle"
4745
- [props]="{
4746
- content: props.aboveTitle.content | uppercase,
4747
- color: props.aboveTitle.color,
4748
- bold: false,
4749
- size: props.aboveTitle.size,
4750
- }"
4751
- ></val-title>
4752
- <val-display
4753
- *ngIf="props.title"
4754
- [props]="{
4755
- content: props.title.content,
4756
- color: props.title.color,
4757
- size: props.title.size,
4758
- }"
4759
- ></val-display>
4760
- <val-title
4761
- style="margin-top: 16px;"
4762
- *ngIf="props.bellowTitle"
4763
- [props]="{
4764
- content: props.bellowTitle.content,
4765
- color: props.bellowTitle.color,
4766
- bold: false,
4767
- size: props.bellowTitle.size,
4768
- thin: props.bellowTitle.thin,
4769
- }"
4770
- ></val-title>
4771
- </div>
4772
- `, 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)}val-button,val-title,val-display{display:inline-block}.titles-container{width:100%;display:flex;flex-direction:column;flex-wrap:wrap}.titles-container.left{align-content:flex-start;align-items:start;text-align:left}.titles-container.center{align-content:center;align-items:center;text-align:center}.titles-container.right{align-content:flex-end;align-items:end;text-align:end}.titles-container.leftocenter{align-content:flex-start;align-items:start;text-align:left}@media (min-width: 768px){.titles-container.leftocenter{align-content:center;align-items:center;text-align:center}}\n"] }]
4773
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { props: [{
4774
- type: Input
4775
- }] } });
4776
-
4777
- class LayeredCardComponent {
4778
- constructor() {
4779
- this.theme = inject(ThemeService);
5042
+ class LayeredCardComponent {
5043
+ constructor() {
5044
+ this.theme = inject(ThemeService);
4780
5045
  }
4781
5046
  color(background) {
4782
5047
  if (!background) {
@@ -4870,64 +5135,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4870
5135
  type: Input
4871
5136
  }] } });
4872
5137
 
4873
- /**
4874
- * val-link
4875
- *
4876
- * A stylized link button with navigation support for internal, in-app, or new tab links.
4877
- *
4878
- * @example
4879
- * <val-link [props]="{ text: 'Go', color: 'primary', link: '/home', type: 'internal' }" (onClick)="handler($event)"></val-link>
4880
- *
4881
- * @input props: LinkMetadata - Configuration for the link (text, color, link, type, etc.)
4882
- * @output onClick - Emits the token of the clicked link
4883
- */
4884
- class LinkComponent {
4885
- constructor() {
4886
- this.onClick = new EventEmitter();
4887
- this.service = inject(NavigationService);
4888
- addIcons({ chevronForwardOutline });
4889
- }
4890
- ngOnInit() { }
4891
- onClickHandler() {
4892
- this.onClick.emit(this.props.token);
4893
- switch (this.props.type) {
4894
- case 'internal':
4895
- this.service.navigateByUrl(this.props.link);
4896
- break;
4897
- case 'browse':
4898
- this.service.navigateInApp(this.props.link);
4899
- break;
4900
- case 'tab':
4901
- this.service.openInNewTab(this.props.link);
4902
- break;
4903
- }
4904
- }
4905
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4906
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LinkComponent, isStandalone: true, selector: "val-link", inputs: { props: "props" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
4907
- <div>
4908
- <ion-button type="button" [color]="props.color" fill="clear" [size]="props.size" (click)="onClickHandler()">
4909
- <ion-icon slot="end" name="chevron-forward-outline"></ion-icon>
4910
- <ion-text>{{ props.text }}</ion-text>
4911
- </ion-button>
4912
- </div>
4913
- `, 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)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;margin:0;--padding-bottom: 0;--padding-top: 0;--padding-start: 0;--padding-end: 0}\n"], dependencies: [{ kind: "component", type: 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
4914
- }
4915
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkComponent, decorators: [{
4916
- type: Component,
4917
- args: [{ selector: 'val-link', standalone: true, imports: [IonButton, IonIcon, IonText], template: `
4918
- <div>
4919
- <ion-button type="button" [color]="props.color" fill="clear" [size]="props.size" (click)="onClickHandler()">
4920
- <ion-icon slot="end" name="chevron-forward-outline"></ion-icon>
4921
- <ion-text>{{ props.text }}</ion-text>
4922
- </ion-button>
4923
- </div>
4924
- `, 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)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;margin:0;--padding-bottom: 0;--padding-top: 0;--padding-start: 0;--padding-end: 0}\n"] }]
4925
- }], ctorParameters: () => [], propDecorators: { props: [{
4926
- type: Input
4927
- }], onClick: [{
4928
- type: Output
4929
- }] } });
4930
-
4931
5138
  /**
4932
5139
  * val-links-cake
4933
5140
  *
@@ -4974,240 +5181,1099 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4974
5181
  }] } });
4975
5182
 
4976
5183
  /**
4977
- * val-notes-box
5184
+ * Removes diacritical marks (accents) from a string using Unicode normalization.
5185
+ * Useful for text search and comparison.
4978
5186
  *
4979
- * Displays a styled notes/info box with optional prefix and configurable color, size, and padding.
5187
+ * @param text The input string
5188
+ * @returns The normalized string without diacritical marks
4980
5189
  *
4981
5190
  * @example
4982
- * <val-notes-box [props]="{ text: 'Note', prefix: 'Info', color: 'primary', textColor: 'dark', size: 'medium', rounded: true, padding: '8px' }"></val-notes-box>
4983
- *
4984
- * @input props: NotesBoxMetadata - Configuration for the notes box (text, prefix, color, textColor, size, rounded, padding)
5191
+ * replaceSpecialChars('canción') // returns 'cancion'
4985
5192
  */
4986
- class NotesBoxComponent {
4987
- constructor() { }
4988
- ngOnInit() { }
4989
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NotesBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4990
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NotesBoxComponent, isStandalone: true, selector: "val-notes-box", inputs: { props: "props" }, ngImport: i0, template: `
4991
- <val-box
4992
- [props]="{
4993
- icon: '',
4994
- bordered: false,
4995
- color: props.color,
4996
- leftBorder: true,
4997
- rounded: props.rounded,
4998
- padding: props.padding,
4999
- }"
5000
- >
5001
- <div [ngClass]="['content-container', props.size]" body>
5002
- @if (props.prefix) {
5003
- <val-text
5004
- [props]="{ content: props.prefix, color: props.textColor, bold: true, size: props.size }"
5005
- ></val-text>
5006
- }
5007
- <val-text [props]="{ content: props.text, color: props.textColor, bold: false, size: props.size }"></val-text>
5008
- </div>
5009
- </val-box>
5010
- `, 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)}.content-container{display:inline-grid}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: BoxComponent, selector: "val-box", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
5011
- }
5012
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NotesBoxComponent, decorators: [{
5013
- type: Component,
5014
- args: [{ selector: 'val-notes-box', standalone: true, imports: [CommonModule, BoxComponent, TextComponent], template: `
5015
- <val-box
5016
- [props]="{
5017
- icon: '',
5018
- bordered: false,
5019
- color: props.color,
5020
- leftBorder: true,
5021
- rounded: props.rounded,
5022
- padding: props.padding,
5023
- }"
5024
- >
5025
- <div [ngClass]="['content-container', props.size]" body>
5026
- @if (props.prefix) {
5027
- <val-text
5028
- [props]="{ content: props.prefix, color: props.textColor, bold: true, size: props.size }"
5029
- ></val-text>
5030
- }
5031
- <val-text [props]="{ content: props.text, color: props.textColor, bold: false, size: props.size }"></val-text>
5032
- </div>
5033
- </val-box>
5034
- `, 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)}.content-container{display:inline-grid}\n"] }]
5035
- }], ctorParameters: () => [], propDecorators: { props: [{
5036
- type: Input
5037
- }] } });
5193
+ const replaceSpecialChars = (text) => text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
5038
5194
 
5039
5195
  /**
5040
- * val-number-input
5196
+ * val-searchbar
5041
5197
  *
5042
- * A number input field integrated with Angular forms.
5198
+ * A search bar component with debounce and event emitters for filtering, focus, and blur.
5043
5199
  *
5044
5200
  * @example
5045
- * <val-number-input [props]="{ control: myControl, placeholder: 'Enter a number' }"></val-number-input>
5201
+ * <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()"></val-searchbar>
5046
5202
  *
5047
- * @input props: InputMetadata - Configuration for the input (form control, placeholder, etc.)
5203
+ * @input disabled - Whether the searchbar is disabled.
5204
+ * @output filterEvent - Emits the search term on input.
5205
+ * @output focusEvent - Emits when the searchbar gains focus.
5206
+ * @output blurEvent - Emits when the searchbar loses focus.
5048
5207
  */
5049
- class NumberInputComponent {
5050
- constructor() { }
5051
- ngOnInit() {
5052
- // Apply default values on initialization
5053
- if (this.props?.withDefault || this.props?.value) {
5054
- applyDefaultValueToControl(this.props);
5055
- }
5208
+ class SearchbarComponent {
5209
+ constructor() {
5210
+ /**
5211
+ * Emits the search term on input.
5212
+ */
5213
+ this.filterEvent = new EventEmitter();
5214
+ /**
5215
+ * Emits when the searchbar gains focus.
5216
+ */
5217
+ this.focusEvent = new EventEmitter();
5218
+ /**
5219
+ * Emits when the searchbar loses focus.
5220
+ */
5221
+ this.blurEvent = new EventEmitter();
5056
5222
  }
5057
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5058
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NumberInputComponent, isStandalone: true, selector: "val-number-input", inputs: { props: "props" }, ngImport: i0, template: ` <ion-input [formControl]="props.control" type="number" [placeholder]="props.placeholder"></ion-input> `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }] }); }
5059
- }
5060
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberInputComponent, decorators: [{
5061
- type: Component,
5062
- args: [{ selector: 'val-number-input', standalone: true, imports: [ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="props.control" type="number" [placeholder]="props.placeholder"></ion-input> ` }]
5063
- }], ctorParameters: () => [], propDecorators: { props: [{
5064
- type: Input
5065
- }] } });
5066
-
5067
- class NumberFromToComponent {
5068
- constructor() { }
5069
- ngOnInit() {
5070
- // Apply default values if configured
5071
- if (this.props?.withDefault || this.props?.value) {
5072
- this.applyDefaultValues();
5073
- }
5223
+ onSearch($event) {
5224
+ const searchTerm = $event.detail.value;
5225
+ this.filterEvent.emit(searchTerm);
5074
5226
  }
5075
- applyDefaultValues() {
5076
- const defaultValue = this.resolveDefaultValue();
5077
- if (defaultValue !== null) {
5078
- if (typeof defaultValue === 'object' && defaultValue.from !== undefined) {
5079
- this.fromControl?.setValue(defaultValue.from);
5080
- this.toControl?.setValue(defaultValue.to);
5081
- }
5082
- else {
5083
- // Si es un valor simple, aplicarlo a ambos controles
5084
- this.fromControl?.setValue(defaultValue);
5085
- this.toControl?.setValue(defaultValue);
5086
- }
5087
- this.fromControl?.markAsPristine();
5088
- this.toControl?.markAsPristine();
5089
- this.fromControl?.updateValueAndValidity();
5090
- this.toControl?.updateValueAndValidity();
5091
- }
5227
+ onFocus() {
5228
+ this.focusEvent.emit();
5092
5229
  }
5093
- resolveDefaultValue() {
5094
- // Explicit value takes precedence
5095
- if (this.props.value !== undefined && this.props.value !== null && this.props.value !== '') {
5096
- return this.parseValue(this.props.value);
5230
+ onBlur() {
5231
+ this.blurEvent.emit();
5232
+ }
5233
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SearchbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5234
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SearchbarComponent, isStandalone: true, selector: "val-searchbar", inputs: { disabled: "disabled" }, outputs: { filterEvent: "filterEvent", focusEvent: "focusEvent", blurEvent: "blurEvent" }, ngImport: i0, template: `
5235
+ <ion-searchbar
5236
+ mode="ios"
5237
+ debounce="500"
5238
+ placeholder="Búsqueda"
5239
+ [disabled]="disabled"
5240
+ showCancelButton="focus"
5241
+ cancelButtonText="Cancelar"
5242
+ (ionInput)="onSearch($event)"
5243
+ (ionBlur)="onBlur()"
5244
+ (ionFocus)="onFocus()"
5245
+ >
5246
+ </ion-searchbar>
5247
+ `, 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)}ion-searchbar{--cancel-button-color: var(--ion-color-dark);--background: var(--ion-color-light);font-family:var(--ion-default-font),Arial,sans-serif}\n"], dependencies: [{ kind: "component", type: IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }] }); }
5248
+ }
5249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SearchbarComponent, decorators: [{
5250
+ type: Component,
5251
+ args: [{ selector: 'val-searchbar', standalone: true, imports: [IonSearchbar], template: `
5252
+ <ion-searchbar
5253
+ mode="ios"
5254
+ debounce="500"
5255
+ placeholder="Búsqueda"
5256
+ [disabled]="disabled"
5257
+ showCancelButton="focus"
5258
+ cancelButtonText="Cancelar"
5259
+ (ionInput)="onSearch($event)"
5260
+ (ionBlur)="onBlur()"
5261
+ (ionFocus)="onFocus()"
5262
+ >
5263
+ </ion-searchbar>
5264
+ `, 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)}ion-searchbar{--cancel-button-color: var(--ion-color-dark);--background: var(--ion-color-light);font-family:var(--ion-default-font),Arial,sans-serif}\n"] }]
5265
+ }], ctorParameters: () => [], propDecorators: { disabled: [{
5266
+ type: Input
5267
+ }], filterEvent: [{
5268
+ type: Output
5269
+ }], focusEvent: [{
5270
+ type: Output
5271
+ }], blurEvent: [{
5272
+ type: Output
5273
+ }] } });
5274
+
5275
+ class MultiSelectSearchComponent {
5276
+ constructor() {
5277
+ this.labelProperty = 'name';
5278
+ this.valueProperty = 'id';
5279
+ this.langService = inject(LangService);
5280
+ this.icon = inject(IconService);
5281
+ this.changeDetector = inject(ChangeDetectorRef);
5282
+ this.searchTerm = '';
5283
+ this.filteredItems = [];
5284
+ this.selectedItems = [];
5285
+ this.tempSelectedItems = [];
5286
+ this.displayValue = '';
5287
+ this.previousOptions = [];
5288
+ this.isProcessingChanges = false;
5289
+ this.label = this.langService.getText('_global', 'selectMultiple', 'Seleccionar múltiples');
5290
+ this.placeholder = this.langService.getText('_global', 'selectOptions', 'Seleccione opciones');
5291
+ }
5292
+ ngOnInit() {
5293
+ this.applyDefaultValue();
5294
+ this.initializeItems();
5295
+ this.syncControlValueWithSelectedItems();
5296
+ this.updateDisplayValue();
5297
+ this.subscribeToValueChanges();
5298
+ }
5299
+ ngOnDestroy() {
5300
+ if (this.valueChangesSubscription) {
5301
+ this.valueChangesSubscription.unsubscribe();
5097
5302
  }
5098
- // No default configuration
5099
- if (!this.props.withDefault) {
5100
- return null;
5303
+ }
5304
+ ngOnChanges(changes) {
5305
+ if (this.isProcessingChanges) {
5306
+ return;
5101
5307
  }
5102
- // Custom default value
5103
- if (typeof this.props.withDefault === 'string') {
5104
- return this.parseValue(this.props.withDefault);
5308
+ if (changes['props']) {
5309
+ try {
5310
+ this.isProcessingChanges = true;
5311
+ if (this.valueChangesSubscription) {
5312
+ this.valueChangesSubscription.unsubscribe();
5313
+ }
5314
+ if (this.props?.options) {
5315
+ const optionsChanged = !this.areOptionsEqual(this.previousOptions, this.props.options);
5316
+ if (optionsChanged) {
5317
+ this.previousOptions = [...this.props.options];
5318
+ this.initializeItems();
5319
+ }
5320
+ }
5321
+ this.syncControlValueWithSelectedItems();
5322
+ this.updateDisplayValue();
5323
+ this.subscribeToValueChanges();
5324
+ }
5325
+ finally {
5326
+ this.isProcessingChanges = false;
5327
+ }
5105
5328
  }
5106
- // Auto default value (withDefault === true)
5107
- return { from: 0, to: 0 };
5108
5329
  }
5109
- parseValue(value) {
5330
+ ionViewWillEnter() {
5331
+ if (this.isProcessingChanges) {
5332
+ return;
5333
+ }
5110
5334
  try {
5111
- // Try to parse as JSON first (for object values)
5112
- return JSON.parse(value);
5335
+ this.isProcessingChanges = true;
5336
+ this.initializeItems();
5337
+ this.syncControlValueWithSelectedItems();
5338
+ this.updateDisplayValue();
5339
+ this.subscribeToValueChanges();
5113
5340
  }
5114
- catch {
5115
- // If not JSON, treat as number
5116
- const numValue = parseFloat(value) || 0;
5117
- return { from: numValue, to: numValue };
5341
+ finally {
5342
+ this.isProcessingChanges = false;
5118
5343
  }
5119
5344
  }
5120
- get fromControl() {
5121
- return this.props.fromControl;
5345
+ subscribeToValueChanges() {
5346
+ if (!this.props?.control)
5347
+ return;
5348
+ this.valueChangesSubscription = this.props.control.valueChanges.subscribe(() => {
5349
+ if (this.isProcessingChanges)
5350
+ return;
5351
+ try {
5352
+ this.isProcessingChanges = true;
5353
+ this.syncControlValueWithSelectedItems();
5354
+ this.updateDisplayValue();
5355
+ }
5356
+ finally {
5357
+ this.isProcessingChanges = false;
5358
+ }
5359
+ });
5122
5360
  }
5123
- get toControl() {
5124
- return this.props.toControl;
5361
+ areOptionsEqual(prevOptions, newOptions) {
5362
+ if (prevOptions === newOptions)
5363
+ return true;
5364
+ if (!prevOptions || !newOptions)
5365
+ return prevOptions === newOptions;
5366
+ if (prevOptions.length !== newOptions.length)
5367
+ return false;
5368
+ for (let i = 0; i < prevOptions.length; i++) {
5369
+ if (prevOptions[i][this.valueProperty] !== newOptions[i][this.valueProperty]) {
5370
+ return false;
5371
+ }
5372
+ }
5373
+ return true;
5125
5374
  }
5126
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberFromToComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5127
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NumberFromToComponent, isStandalone: true, selector: "val-number-from-to", inputs: { props: "props" }, ngImport: i0, template: `
5128
- <div class="number-from-to-container">
5129
- <ion-label position="stacked">{{ props.fromLabel || 'Inicial' }}</ion-label>
5130
- <ion-input
5131
- [formControl]="fromControl"
5132
- type="number"
5133
- [placeholder]="props.fromPlaceholder || props.placeholder"
5134
- [min]="props.range?.min"
5135
- [max]="props.range?.max"
5136
- >
5137
- </ion-input>
5138
-
5139
- <ion-label position="stacked">{{ props.toLabel || 'Final' }}</ion-label>
5140
- <ion-input
5141
- [formControl]="toControl"
5142
- type="number"
5143
- [placeholder]="props.toPlaceholder || props.placeholder"
5144
- [min]="props.range?.min"
5145
- [max]="props.range?.max"
5146
- >
5147
- </ion-input>
5148
- </div>
5149
- `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }] }); }
5150
- }
5151
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberFromToComponent, decorators: [{
5152
- type: Component,
5153
- args: [{ selector: 'val-number-from-to', standalone: true, imports: [ReactiveFormsModule, IonInput, IonLabel], template: `
5154
- <div class="number-from-to-container">
5155
- <ion-label position="stacked">{{ props.fromLabel || 'Inicial' }}</ion-label>
5156
- <ion-input
5157
- [formControl]="fromControl"
5158
- type="number"
5159
- [placeholder]="props.fromPlaceholder || props.placeholder"
5160
- [min]="props.range?.min"
5161
- [max]="props.range?.max"
5162
- >
5163
- </ion-input>
5164
-
5165
- <ion-label position="stacked">{{ props.toLabel || 'Final' }}</ion-label>
5166
- <ion-input
5167
- [formControl]="toControl"
5168
- type="number"
5169
- [placeholder]="props.toPlaceholder || props.placeholder"
5170
- [min]="props.range?.min"
5171
- [max]="props.range?.max"
5172
- >
5173
- </ion-input>
5174
- </div>
5175
- ` }]
5176
- }], ctorParameters: () => [], propDecorators: { props: [{
5177
- type: Input
5178
- }] } });
5179
-
5180
- /**
5181
- * val-password-input
5182
- *
5183
- * A password input field with show/hide toggle, integrated with Angular forms.
5184
- *
5185
- * @example
5186
- * <val-password-input [props]="{ control: myControl, placeholder: 'Enter password' }"></val-password-input>
5187
- *
5188
- * @input props: InputMetadata - Configuration for the input (form control, placeholder, etc.)
5189
- */
5190
- class PasswordInputComponent {
5191
- constructor(icon) {
5192
- this.hidePassword = true;
5375
+ initializeItems() {
5376
+ this.filteredItems = this.props?.options || [];
5193
5377
  }
5194
- ngOnInit() { }
5195
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PasswordInputComponent, deps: [{ token: IconService }], target: i0.ɵɵFactoryTarget.Component }); }
5196
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PasswordInputComponent, isStandalone: true, selector: "val-password-input", inputs: { props: "props" }, ngImport: i0, template: `
5197
- <div class="input-container">
5198
- <ion-input
5199
- class="sign-in__input-password"
5200
- [formControl]="props.control"
5201
- [type]="hidePassword ? 'password' : 'text'"
5202
- [placeholder]="props.placeholder"
5203
- ></ion-input>
5204
- <ion-button color="dark" fill="clear" (click)="hidePassword = !hidePassword" size="small">
5205
- <ion-icon slot="icon-only" [name]="hidePassword ? 'eye-off-outline' : 'eye-outline'"></ion-icon>
5206
- </ion-button>
5207
- </div>
5208
- `, 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}}.input-container{display:flex;align-items:center;flex-direction:row}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
5209
- }
5210
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PasswordInputComponent, decorators: [{
5378
+ syncControlValueWithSelectedItems() {
5379
+ if (!this.props?.control) {
5380
+ this.selectedItems = [];
5381
+ return;
5382
+ }
5383
+ const controlValue = this.props.control.value;
5384
+ if (!controlValue || controlValue === '') {
5385
+ this.selectedItems = [];
5386
+ return;
5387
+ }
5388
+ // Handle both array and string formats
5389
+ let valueArray = [];
5390
+ if (Array.isArray(controlValue)) {
5391
+ valueArray = controlValue;
5392
+ }
5393
+ else if (typeof controlValue === 'string') {
5394
+ valueArray = controlValue.split(',').filter(v => v.trim() !== '');
5395
+ }
5396
+ if (this.props.options && this.props.options.length > 0) {
5397
+ const map = new Map(this.props.options.map(opt => [opt[this.valueProperty], opt]));
5398
+ this.selectedItems = valueArray
5399
+ .map(value => map.get(value.toString().trim()))
5400
+ .filter(item => item !== undefined);
5401
+ }
5402
+ else {
5403
+ this.selectedItems = [];
5404
+ }
5405
+ }
5406
+ applyDefaultValue() {
5407
+ applyDefaultValueToControl(this.props);
5408
+ }
5409
+ onFilter(event) {
5410
+ if (!event || event.trim() === '') {
5411
+ this.filteredItems = this.props?.options ? [...this.props.options] : [];
5412
+ this.changeDetector.detectChanges();
5413
+ return;
5414
+ }
5415
+ if (!this.props?.options || this.props.options.length === 0) {
5416
+ this.filteredItems = [];
5417
+ this.changeDetector.detectChanges();
5418
+ return;
5419
+ }
5420
+ const search = replaceSpecialChars(event.toLowerCase());
5421
+ this.filteredItems = this.props.options.filter(element => {
5422
+ const label = element[this.labelProperty]
5423
+ ? replaceSpecialChars(String(element[this.labelProperty]).toLowerCase())
5424
+ : '';
5425
+ const value = element[this.valueProperty]
5426
+ ? replaceSpecialChars(String(element[this.valueProperty]).toLowerCase())
5427
+ : '';
5428
+ return label.includes(search) || value.includes(search);
5429
+ });
5430
+ this.changeDetector.detectChanges();
5431
+ }
5432
+ onFocus() {
5433
+ console.log('onFocus');
5434
+ }
5435
+ onBlur() {
5436
+ console.log('onBlur');
5437
+ }
5438
+ openModal() {
5439
+ this.syncControlValueWithSelectedItems();
5440
+ this.tempSelectedItems = [...this.selectedItems];
5441
+ this.updateDisplayValue();
5442
+ if (this.modal) {
5443
+ this.modal.present();
5444
+ }
5445
+ }
5446
+ preventDefaultBehavior(event) {
5447
+ event.preventDefault();
5448
+ event.stopPropagation();
5449
+ this.openModal();
5450
+ }
5451
+ cancelModal() {
5452
+ // Reset filter and show all options when closing modal
5453
+ this.searchTerm = '';
5454
+ this.filteredItems = this.props?.options ? [...this.props.options] : [];
5455
+ this.changeDetector.detectChanges();
5456
+ if (this.modal) {
5457
+ this.modal.dismiss();
5458
+ }
5459
+ }
5460
+ selectItem(item) {
5461
+ const index = this.tempSelectedItems.findIndex(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
5462
+ if (index === -1) {
5463
+ this.tempSelectedItems.push(item);
5464
+ }
5465
+ else {
5466
+ this.tempSelectedItems.splice(index, 1);
5467
+ }
5468
+ }
5469
+ isItemSelected(item) {
5470
+ return this.tempSelectedItems.some(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
5471
+ }
5472
+ clearSelection() {
5473
+ this.tempSelectedItems = [];
5474
+ }
5475
+ applySelection() {
5476
+ this.selectedItems = [...this.tempSelectedItems];
5477
+ this.updateDisplayValue();
5478
+ this.applyChanges();
5479
+ this.cancelModal();
5480
+ }
5481
+ updateDisplayValue() {
5482
+ if (this.selectedItems.length === 0) {
5483
+ this.displayValue = '';
5484
+ return;
5485
+ }
5486
+ if (this.selectedItems.length === 1) {
5487
+ this.displayValue = this.selectedItems[0][this.labelProperty];
5488
+ }
5489
+ else {
5490
+ this.displayValue = `${this.selectedItems.length} elementos seleccionados`;
5491
+ }
5492
+ }
5493
+ applyChanges() {
5494
+ if (!this.props?.control) {
5495
+ return;
5496
+ }
5497
+ try {
5498
+ this.isProcessingChanges = true;
5499
+ const values = this.selectedItems.map(item => item[this.valueProperty]);
5500
+ const stringValue = values.join(',');
5501
+ this.props.control.setValue(stringValue);
5502
+ this.props.control.markAsDirty();
5503
+ this.props.control.markAsTouched();
5504
+ this.props.control.updateValueAndValidity();
5505
+ // Debug validators if still having issues
5506
+ if (this.props.control.invalid) {
5507
+ console.warn('Control is invalid after setValue:', {
5508
+ value: this.props.control.value,
5509
+ errors: this.props.control.errors,
5510
+ validators: this.props.control.validator
5511
+ });
5512
+ }
5513
+ }
5514
+ finally {
5515
+ this.isProcessingChanges = false;
5516
+ }
5517
+ }
5518
+ reset() {
5519
+ this.selectedItems = [];
5520
+ this.displayValue = '';
5521
+ if (this.props?.control) {
5522
+ this.props.control.setValue('');
5523
+ }
5524
+ this.changeDetector.detectChanges();
5525
+ }
5526
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5527
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MultiSelectSearchComponent, isStandalone: true, selector: "val-multi-select-search", inputs: { label: "label", labelProperty: "labelProperty", valueProperty: "valueProperty", placeholder: "placeholder", props: "props" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
5528
+ <ion-input
5529
+ type="text"
5530
+ [value]="displayValue"
5531
+ [placeholder]="props?.placeholder || placeholder"
5532
+ readonly
5533
+ (mousedown)="preventDefaultBehavior($event)"
5534
+ />
5535
+
5536
+ <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
5537
+
5538
+ <ion-modal
5539
+ #modal
5540
+ [initialBreakpoint]="1"
5541
+ [breakpoints]="[0, 0.5, 0.75, 1]"
5542
+ (didDismiss)="cancelModal()"
5543
+ >
5544
+ <ng-template>
5545
+ <ion-header>
5546
+ <ion-toolbar>
5547
+ <ion-title>{{ label }}</ion-title>
5548
+ <ion-buttons slot="end">
5549
+ <ion-button (click)="cancelModal()">Cerrar</ion-button>
5550
+ </ion-buttons>
5551
+ </ion-toolbar>
5552
+ <ion-toolbar>
5553
+ <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
5554
+ </ion-toolbar>
5555
+ </ion-header>
5556
+ <ion-content>
5557
+ <ion-item *ngIf="tempSelectedItems.length > 0" lines="none" color="light">
5558
+ <ion-icon name="checkmark-circle-outline" slot="start" color="success"></ion-icon>
5559
+ <ion-label>
5560
+ <h3>{{ tempSelectedItems.length }} item{{ tempSelectedItems.length === 1 ? '' : 's' }} seleccionado{{ tempSelectedItems.length === 1 ? '' : 's' }}</h3>
5561
+ </ion-label>
5562
+ </ion-item>
5563
+ <ion-list>
5564
+ <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
5565
+ <ion-checkbox
5566
+ [checked]="isItemSelected(item)"
5567
+ slot="start"
5568
+ [disabled]="true"
5569
+ ></ion-checkbox>
5570
+ <ion-label>{{ item[labelProperty] }}</ion-label>
5571
+ </ion-item>
5572
+ <ion-item *ngIf="filteredItems.length === 0" lines="none">
5573
+ <ion-label color="dark">No se encontraron resultados</ion-label>
5574
+ </ion-item>
5575
+ </ion-list>
5576
+ </ion-content>
5577
+ <ion-footer *ngIf="tempSelectedItems.length > 0">
5578
+ <ion-toolbar>
5579
+ <ion-buttons slot="end">
5580
+ <ion-button (click)="clearSelection()">Limpiar</ion-button>
5581
+ <ion-button fill="solid" (click)="applySelection()">Aplicar ({{ tempSelectedItems.length }})</ion-button>
5582
+ </ion-buttons>
5583
+ </ion-toolbar>
5584
+ </ion-footer>
5585
+ </ng-template>
5586
+ </ion-modal>
5587
+ `, 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.IonCheckbox, selector: "ion-checkbox", inputs: ["alignment", "checked", "color", "disabled", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: i2.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { 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.BooleanValueAccessor, selector: "ion-checkbox,ion-toggle" }, { 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"] }] }); }
5588
+ }
5589
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSearchComponent, decorators: [{
5590
+ type: Component,
5591
+ args: [{ selector: 'val-multi-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, SearchbarComponent, ReactiveFormsModule], template: `
5592
+ <ion-input
5593
+ type="text"
5594
+ [value]="displayValue"
5595
+ [placeholder]="props?.placeholder || placeholder"
5596
+ readonly
5597
+ (mousedown)="preventDefaultBehavior($event)"
5598
+ />
5599
+
5600
+ <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
5601
+
5602
+ <ion-modal
5603
+ #modal
5604
+ [initialBreakpoint]="1"
5605
+ [breakpoints]="[0, 0.5, 0.75, 1]"
5606
+ (didDismiss)="cancelModal()"
5607
+ >
5608
+ <ng-template>
5609
+ <ion-header>
5610
+ <ion-toolbar>
5611
+ <ion-title>{{ label }}</ion-title>
5612
+ <ion-buttons slot="end">
5613
+ <ion-button (click)="cancelModal()">Cerrar</ion-button>
5614
+ </ion-buttons>
5615
+ </ion-toolbar>
5616
+ <ion-toolbar>
5617
+ <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
5618
+ </ion-toolbar>
5619
+ </ion-header>
5620
+ <ion-content>
5621
+ <ion-item *ngIf="tempSelectedItems.length > 0" lines="none" color="light">
5622
+ <ion-icon name="checkmark-circle-outline" slot="start" color="success"></ion-icon>
5623
+ <ion-label>
5624
+ <h3>{{ tempSelectedItems.length }} item{{ tempSelectedItems.length === 1 ? '' : 's' }} seleccionado{{ tempSelectedItems.length === 1 ? '' : 's' }}</h3>
5625
+ </ion-label>
5626
+ </ion-item>
5627
+ <ion-list>
5628
+ <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
5629
+ <ion-checkbox
5630
+ [checked]="isItemSelected(item)"
5631
+ slot="start"
5632
+ [disabled]="true"
5633
+ ></ion-checkbox>
5634
+ <ion-label>{{ item[labelProperty] }}</ion-label>
5635
+ </ion-item>
5636
+ <ion-item *ngIf="filteredItems.length === 0" lines="none">
5637
+ <ion-label color="dark">No se encontraron resultados</ion-label>
5638
+ </ion-item>
5639
+ </ion-list>
5640
+ </ion-content>
5641
+ <ion-footer *ngIf="tempSelectedItems.length > 0">
5642
+ <ion-toolbar>
5643
+ <ion-buttons slot="end">
5644
+ <ion-button (click)="clearSelection()">Limpiar</ion-button>
5645
+ <ion-button fill="solid" (click)="applySelection()">Aplicar ({{ tempSelectedItems.length }})</ion-button>
5646
+ </ion-buttons>
5647
+ </ion-toolbar>
5648
+ </ion-footer>
5649
+ </ng-template>
5650
+ </ion-modal>
5651
+ `, styles: ["ion-header{padding:8px 8px 0}\n"] }]
5652
+ }], ctorParameters: () => [], propDecorators: { modal: [{
5653
+ type: ViewChild,
5654
+ args: ['modal']
5655
+ }], label: [{
5656
+ type: Input
5657
+ }], labelProperty: [{
5658
+ type: Input
5659
+ }], valueProperty: [{
5660
+ type: Input
5661
+ }], placeholder: [{
5662
+ type: Input
5663
+ }], props: [{
5664
+ type: Input
5665
+ }] } });
5666
+
5667
+ class MultiSelectSimpleComponent {
5668
+ constructor() {
5669
+ this.labelProperty = 'name';
5670
+ this.valueProperty = 'id';
5671
+ this.placeholder = '';
5672
+ this.langService = inject(LangService);
5673
+ // Signals for reactive state management
5674
+ this.isOpen = signal(false);
5675
+ this.searchTerm = signal('');
5676
+ this.selectedValues = signal([]);
5677
+ // Computed signals
5678
+ this.displayValue = computed(() => {
5679
+ const selected = this.selectedValues();
5680
+ if (selected.length === 0) {
5681
+ return '';
5682
+ }
5683
+ if (selected.length === 1) {
5684
+ const option = this.getOptionByValue(selected[0]);
5685
+ return option ? option[this.labelProperty] : '';
5686
+ }
5687
+ return `${selected.length} elementos seleccionados`;
5688
+ });
5689
+ this.filteredOptions = computed(() => {
5690
+ const options = this.props?.options || [];
5691
+ const search = this.searchTerm().toLowerCase();
5692
+ if (!search) {
5693
+ return options;
5694
+ }
5695
+ return options.filter(option => {
5696
+ const label = option[this.labelProperty]
5697
+ ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
5698
+ : '';
5699
+ const value = option[this.valueProperty]
5700
+ ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
5701
+ : '';
5702
+ const searchTerm = replaceSpecialChars(search);
5703
+ return label.includes(searchTerm) || value.includes(searchTerm);
5704
+ });
5705
+ });
5706
+ this.searchPlaceholder = '';
5707
+ // ControlValueAccessor
5708
+ this.onChange = (value) => { };
5709
+ this.onTouched = () => { };
5710
+ this.placeholder = this.langService.getText('_global', 'selectOptions', 'Seleccione opciones');
5711
+ this.searchPlaceholder = this.langService.getText('_global', 'search', 'Buscar');
5712
+ // Close dropdown when clicking outside
5713
+ document.addEventListener('click', this.handleClickOutside.bind(this));
5714
+ }
5715
+ ngOnInit() {
5716
+ this.applyDefaultValue();
5717
+ this.syncSelectedValues();
5718
+ }
5719
+ ngOnDestroy() {
5720
+ document.removeEventListener('click', this.handleClickOutside.bind(this));
5721
+ }
5722
+ // ControlValueAccessor implementation
5723
+ writeValue(value) {
5724
+ const valueArray = this.parseValue(value);
5725
+ this.selectedValues.set(valueArray);
5726
+ }
5727
+ registerOnChange(fn) {
5728
+ this.onChange = fn;
5729
+ }
5730
+ registerOnTouched(fn) {
5731
+ this.onTouched = fn;
5732
+ }
5733
+ setDisabledState(isDisabled) {
5734
+ // Handle disabled state if needed
5735
+ }
5736
+ // Component methods
5737
+ toggleDropdown(event) {
5738
+ event.stopPropagation();
5739
+ this.isOpen.update(value => !value);
5740
+ if (this.isOpen()) {
5741
+ this.onTouched();
5742
+ // Focus search bar when opening
5743
+ setTimeout(() => {
5744
+ const searchbar = this.dropdownRef?.nativeElement?.querySelector('ion-searchbar');
5745
+ if (searchbar) {
5746
+ searchbar.setFocus();
5747
+ }
5748
+ }, 100);
5749
+ }
5750
+ }
5751
+ onSearch(event) {
5752
+ this.searchTerm.set(event.detail.value || '');
5753
+ }
5754
+ toggleOption(option) {
5755
+ const value = option[this.valueProperty];
5756
+ const currentSelected = this.selectedValues();
5757
+ if (this.isSelected(option)) {
5758
+ // Remove from selection
5759
+ this.selectedValues.set(currentSelected.filter(v => v !== value));
5760
+ }
5761
+ else {
5762
+ // Add to selection
5763
+ this.selectedValues.set([...currentSelected, value]);
5764
+ }
5765
+ this.emitValue();
5766
+ }
5767
+ selectAll() {
5768
+ const allValues = this.filteredOptions().map(option => option[this.valueProperty]);
5769
+ const currentSelected = this.selectedValues();
5770
+ // Add only new values to avoid duplicates
5771
+ const newValues = allValues.filter(value => !currentSelected.includes(value));
5772
+ this.selectedValues.set([...currentSelected, ...newValues]);
5773
+ this.emitValue();
5774
+ }
5775
+ clearAll() {
5776
+ this.selectedValues.set([]);
5777
+ this.emitValue();
5778
+ }
5779
+ isSelected(option) {
5780
+ return this.selectedValues().includes(option[this.valueProperty]);
5781
+ }
5782
+ trackByFn(index, option) {
5783
+ return option[this.valueProperty];
5784
+ }
5785
+ handleClickOutside(event) {
5786
+ if (this.isOpen() &&
5787
+ !this.mainInputRef?.nativeElement?.contains(event.target) &&
5788
+ !this.dropdownRef?.nativeElement?.contains(event.target)) {
5789
+ this.isOpen.set(false);
5790
+ this.searchTerm.set('');
5791
+ }
5792
+ }
5793
+ parseValue(value) {
5794
+ if (!value)
5795
+ return [];
5796
+ if (Array.isArray(value))
5797
+ return value.map(v => String(v));
5798
+ if (typeof value === 'string') {
5799
+ return value.split(',').map(v => v.trim()).filter(v => v !== '');
5800
+ }
5801
+ return [String(value)];
5802
+ }
5803
+ emitValue() {
5804
+ const value = this.selectedValues().join(',');
5805
+ this.onChange(value);
5806
+ if (this.props?.control) {
5807
+ this.props.control.setValue(value);
5808
+ this.props.control.markAsDirty();
5809
+ this.props.control.markAsTouched();
5810
+ }
5811
+ }
5812
+ getOptionByValue(value) {
5813
+ return this.props?.options?.find(option => option[this.valueProperty] === value);
5814
+ }
5815
+ applyDefaultValue() {
5816
+ if (this.props) {
5817
+ applyDefaultValueToControl(this.props);
5818
+ }
5819
+ }
5820
+ syncSelectedValues() {
5821
+ if (this.props?.control?.value) {
5822
+ const valueArray = this.parseValue(this.props.control.value);
5823
+ this.selectedValues.set(valueArray);
5824
+ }
5825
+ }
5826
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5827
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MultiSelectSimpleComponent, isStandalone: true, selector: "val-multi-select-simple", inputs: { props: "props", labelProperty: "labelProperty", valueProperty: "valueProperty", placeholder: "placeholder" }, providers: [
5828
+ {
5829
+ provide: NG_VALUE_ACCESSOR,
5830
+ useExisting: forwardRef(() => MultiSelectSimpleComponent),
5831
+ multi: true
5832
+ }
5833
+ ], viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "mainInputRef", first: true, predicate: ["mainInput"], descendants: true }], ngImport: i0, template: `
5834
+ <div class="multi-select-container" (click)="toggleDropdown($event)">
5835
+ <!-- Main input display -->
5836
+ <ion-input
5837
+ #mainInput
5838
+ type="text"
5839
+ [value]="displayValue()"
5840
+ [placeholder]="props?.placeholder || placeholder"
5841
+ readonly
5842
+ class="main-input"
5843
+ [class.is-open]="isOpen()"
5844
+ />
5845
+
5846
+ <!-- Dropdown icon -->
5847
+ <ion-icon
5848
+ name="chevron-down-outline"
5849
+ class="dropdown-icon"
5850
+ [class.rotated]="isOpen()"
5851
+ ></ion-icon>
5852
+
5853
+ <!-- Hidden input for form control -->
5854
+ <ion-input
5855
+ style="position: absolute; opacity: 0; pointer-events: none;"
5856
+ [formControl]="props?.control"
5857
+ type="hidden"
5858
+ />
5859
+ </div>
5860
+
5861
+ <!-- Dropdown overlay -->
5862
+ <div
5863
+ class="dropdown-overlay"
5864
+ [class.visible]="isOpen()"
5865
+ #dropdown
5866
+ >
5867
+ <!-- Search bar -->
5868
+ <div class="search-container">
5869
+ <ion-searchbar
5870
+ #searchbar
5871
+ [placeholder]="searchPlaceholder"
5872
+ (ionInput)="onSearch($event)"
5873
+ [value]="searchTerm()"
5874
+ show-clear-button="focus"
5875
+ ></ion-searchbar>
5876
+ </div>
5877
+
5878
+ <!-- Action buttons -->
5879
+ <div class="actions-container">
5880
+ <ion-button
5881
+ fill="clear"
5882
+ size="small"
5883
+ (click)="selectAll()"
5884
+ [disabled]="filteredOptions().length === 0"
5885
+ >
5886
+ Seleccionar todos
5887
+ </ion-button>
5888
+ <ion-button
5889
+ fill="clear"
5890
+ size="small"
5891
+ color="medium"
5892
+ (click)="clearAll()"
5893
+ [disabled]="selectedValues().length === 0"
5894
+ >
5895
+ Limpiar
5896
+ </ion-button>
5897
+ </div>
5898
+
5899
+ <!-- Options list -->
5900
+ <div class="options-container">
5901
+ <ion-list class="options-list">
5902
+ <ion-item
5903
+ *ngFor="let option of filteredOptions(); trackBy: trackByFn"
5904
+ button
5905
+ (click)="toggleOption(option)"
5906
+ class="option-item"
5907
+ >
5908
+ <ion-checkbox
5909
+ slot="start"
5910
+ [checked]="isSelected(option)"
5911
+ ></ion-checkbox>
5912
+ <ion-label>{{ option[labelProperty] }}</ion-label>
5913
+ </ion-item>
5914
+
5915
+ <!-- No results message -->
5916
+ <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
5917
+ <ion-label color="medium">
5918
+ {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
5919
+ </ion-label>
5920
+ </ion-item>
5921
+ </ion-list>
5922
+ </div>
5923
+ </div>
5924
+ `, isInline: true, styles: [":host{display:block;position:relative;width:100%}.multi-select-container{position:relative;display:flex;align-items:center;cursor:pointer}.multi-select-container .main-input{flex:1;cursor:pointer}.multi-select-container .main-input.is-open{--border-color: var(--ion-color-primary)}.multi-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}.multi-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:400px;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}.actions-container{display:flex;justify-content:space-between;padding:8px 12px;border-bottom:1px solid var(--ion-color-light)}.actions-container ion-button{--padding-start: 8px;--padding-end: 8px;height:32px;font-size:14px}.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-checkbox{--size: 20px;margin-right:12px}.options-container .option-item ion-label{font-size:16px;line-height:1.4}.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:300px}.options-container{max-height:200px}.actions-container ion-button{font-size:12px;--padding-start: 6px;--padding-end: 6px}}@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.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.IonCheckbox, selector: "ion-checkbox", inputs: ["alignment", "checked", "color", "disabled", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { 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.BooleanValueAccessor, selector: "ion-checkbox,ion-toggle" }, { 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"] }] }); }
5925
+ }
5926
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSimpleComponent, decorators: [{
5927
+ type: Component,
5928
+ args: [{ selector: 'val-multi-select-simple', standalone: true, imports: [CommonModule, IonicModule, FormsModule, ReactiveFormsModule], providers: [
5929
+ {
5930
+ provide: NG_VALUE_ACCESSOR,
5931
+ useExisting: forwardRef(() => MultiSelectSimpleComponent),
5932
+ multi: true
5933
+ }
5934
+ ], template: `
5935
+ <div class="multi-select-container" (click)="toggleDropdown($event)">
5936
+ <!-- Main input display -->
5937
+ <ion-input
5938
+ #mainInput
5939
+ type="text"
5940
+ [value]="displayValue()"
5941
+ [placeholder]="props?.placeholder || placeholder"
5942
+ readonly
5943
+ class="main-input"
5944
+ [class.is-open]="isOpen()"
5945
+ />
5946
+
5947
+ <!-- Dropdown icon -->
5948
+ <ion-icon
5949
+ name="chevron-down-outline"
5950
+ class="dropdown-icon"
5951
+ [class.rotated]="isOpen()"
5952
+ ></ion-icon>
5953
+
5954
+ <!-- Hidden input for form control -->
5955
+ <ion-input
5956
+ style="position: absolute; opacity: 0; pointer-events: none;"
5957
+ [formControl]="props?.control"
5958
+ type="hidden"
5959
+ />
5960
+ </div>
5961
+
5962
+ <!-- Dropdown overlay -->
5963
+ <div
5964
+ class="dropdown-overlay"
5965
+ [class.visible]="isOpen()"
5966
+ #dropdown
5967
+ >
5968
+ <!-- Search bar -->
5969
+ <div class="search-container">
5970
+ <ion-searchbar
5971
+ #searchbar
5972
+ [placeholder]="searchPlaceholder"
5973
+ (ionInput)="onSearch($event)"
5974
+ [value]="searchTerm()"
5975
+ show-clear-button="focus"
5976
+ ></ion-searchbar>
5977
+ </div>
5978
+
5979
+ <!-- Action buttons -->
5980
+ <div class="actions-container">
5981
+ <ion-button
5982
+ fill="clear"
5983
+ size="small"
5984
+ (click)="selectAll()"
5985
+ [disabled]="filteredOptions().length === 0"
5986
+ >
5987
+ Seleccionar todos
5988
+ </ion-button>
5989
+ <ion-button
5990
+ fill="clear"
5991
+ size="small"
5992
+ color="medium"
5993
+ (click)="clearAll()"
5994
+ [disabled]="selectedValues().length === 0"
5995
+ >
5996
+ Limpiar
5997
+ </ion-button>
5998
+ </div>
5999
+
6000
+ <!-- Options list -->
6001
+ <div class="options-container">
6002
+ <ion-list class="options-list">
6003
+ <ion-item
6004
+ *ngFor="let option of filteredOptions(); trackBy: trackByFn"
6005
+ button
6006
+ (click)="toggleOption(option)"
6007
+ class="option-item"
6008
+ >
6009
+ <ion-checkbox
6010
+ slot="start"
6011
+ [checked]="isSelected(option)"
6012
+ ></ion-checkbox>
6013
+ <ion-label>{{ option[labelProperty] }}</ion-label>
6014
+ </ion-item>
6015
+
6016
+ <!-- No results message -->
6017
+ <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
6018
+ <ion-label color="medium">
6019
+ {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
6020
+ </ion-label>
6021
+ </ion-item>
6022
+ </ion-list>
6023
+ </div>
6024
+ </div>
6025
+ `, styles: [":host{display:block;position:relative;width:100%}.multi-select-container{position:relative;display:flex;align-items:center;cursor:pointer}.multi-select-container .main-input{flex:1;cursor:pointer}.multi-select-container .main-input.is-open{--border-color: var(--ion-color-primary)}.multi-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}.multi-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:400px;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}.actions-container{display:flex;justify-content:space-between;padding:8px 12px;border-bottom:1px solid var(--ion-color-light)}.actions-container ion-button{--padding-start: 8px;--padding-end: 8px;height:32px;font-size:14px}.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-checkbox{--size: 20px;margin-right:12px}.options-container .option-item ion-label{font-size:16px;line-height:1.4}.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:300px}.options-container{max-height:200px}.actions-container ion-button{font-size:12px;--padding-start: 6px;--padding-end: 6px}}@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"] }]
6026
+ }], ctorParameters: () => [], propDecorators: { dropdownRef: [{
6027
+ type: ViewChild,
6028
+ args: ['dropdown']
6029
+ }], mainInputRef: [{
6030
+ type: ViewChild,
6031
+ args: ['mainInput']
6032
+ }], props: [{
6033
+ type: Input
6034
+ }], labelProperty: [{
6035
+ type: Input
6036
+ }], valueProperty: [{
6037
+ type: Input
6038
+ }], placeholder: [{
6039
+ type: Input
6040
+ }] } });
6041
+
6042
+ /**
6043
+ * val-notes-box
6044
+ *
6045
+ * Displays a styled notes/info box with optional prefix and configurable color, size, and padding.
6046
+ *
6047
+ * @example
6048
+ * <val-notes-box [props]="{ text: 'Note', prefix: 'Info', color: 'primary', textColor: 'dark', size: 'medium', rounded: true, padding: '8px' }"></val-notes-box>
6049
+ *
6050
+ * @input props: NotesBoxMetadata - Configuration for the notes box (text, prefix, color, textColor, size, rounded, padding)
6051
+ */
6052
+ class NotesBoxComponent {
6053
+ constructor() { }
6054
+ ngOnInit() { }
6055
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NotesBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6056
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NotesBoxComponent, isStandalone: true, selector: "val-notes-box", inputs: { props: "props" }, ngImport: i0, template: `
6057
+ <val-box
6058
+ [props]="{
6059
+ icon: '',
6060
+ bordered: false,
6061
+ color: props.color,
6062
+ leftBorder: true,
6063
+ rounded: props.rounded,
6064
+ padding: props.padding,
6065
+ }"
6066
+ >
6067
+ <div [ngClass]="['content-container', props.size]" body>
6068
+ @if (props.prefix) {
6069
+ <val-text
6070
+ [props]="{ content: props.prefix, color: props.textColor, bold: true, size: props.size }"
6071
+ ></val-text>
6072
+ }
6073
+ <val-text [props]="{ content: props.text, color: props.textColor, bold: false, size: props.size }"></val-text>
6074
+ </div>
6075
+ </val-box>
6076
+ `, 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)}.content-container{display:inline-grid}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: BoxComponent, selector: "val-box", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
6077
+ }
6078
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NotesBoxComponent, decorators: [{
6079
+ type: Component,
6080
+ args: [{ selector: 'val-notes-box', standalone: true, imports: [CommonModule, BoxComponent, TextComponent], template: `
6081
+ <val-box
6082
+ [props]="{
6083
+ icon: '',
6084
+ bordered: false,
6085
+ color: props.color,
6086
+ leftBorder: true,
6087
+ rounded: props.rounded,
6088
+ padding: props.padding,
6089
+ }"
6090
+ >
6091
+ <div [ngClass]="['content-container', props.size]" body>
6092
+ @if (props.prefix) {
6093
+ <val-text
6094
+ [props]="{ content: props.prefix, color: props.textColor, bold: true, size: props.size }"
6095
+ ></val-text>
6096
+ }
6097
+ <val-text [props]="{ content: props.text, color: props.textColor, bold: false, size: props.size }"></val-text>
6098
+ </div>
6099
+ </val-box>
6100
+ `, 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)}.content-container{display:inline-grid}\n"] }]
6101
+ }], ctorParameters: () => [], propDecorators: { props: [{
6102
+ type: Input
6103
+ }] } });
6104
+
6105
+ class NumberFromToComponent {
6106
+ constructor() { }
6107
+ ngOnInit() {
6108
+ // Apply default values if configured
6109
+ if (this.props?.withDefault || this.props?.value) {
6110
+ this.applyDefaultValues();
6111
+ }
6112
+ }
6113
+ applyDefaultValues() {
6114
+ const defaultValue = this.resolveDefaultValue();
6115
+ if (defaultValue !== null) {
6116
+ if (typeof defaultValue === 'object' && defaultValue.from !== undefined) {
6117
+ this.fromControl?.setValue(defaultValue.from);
6118
+ this.toControl?.setValue(defaultValue.to);
6119
+ }
6120
+ else {
6121
+ // Si es un valor simple, aplicarlo a ambos controles
6122
+ this.fromControl?.setValue(defaultValue);
6123
+ this.toControl?.setValue(defaultValue);
6124
+ }
6125
+ this.fromControl?.markAsPristine();
6126
+ this.toControl?.markAsPristine();
6127
+ this.fromControl?.updateValueAndValidity();
6128
+ this.toControl?.updateValueAndValidity();
6129
+ }
6130
+ }
6131
+ resolveDefaultValue() {
6132
+ // Explicit value takes precedence
6133
+ if (this.props.value !== undefined && this.props.value !== null && this.props.value !== '') {
6134
+ return this.parseValue(this.props.value);
6135
+ }
6136
+ // No default configuration
6137
+ if (!this.props.withDefault) {
6138
+ return null;
6139
+ }
6140
+ // Custom default value
6141
+ if (typeof this.props.withDefault === 'string') {
6142
+ return this.parseValue(this.props.withDefault);
6143
+ }
6144
+ // Auto default value (withDefault === true)
6145
+ return { from: 0, to: 0 };
6146
+ }
6147
+ parseValue(value) {
6148
+ try {
6149
+ // Try to parse as JSON first (for object values)
6150
+ return JSON.parse(value);
6151
+ }
6152
+ catch {
6153
+ // If not JSON, treat as number
6154
+ const numValue = parseFloat(value) || 0;
6155
+ return { from: numValue, to: numValue };
6156
+ }
6157
+ }
6158
+ get fromControl() {
6159
+ return this.props.fromControl;
6160
+ }
6161
+ get toControl() {
6162
+ return this.props.toControl;
6163
+ }
6164
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberFromToComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6165
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NumberFromToComponent, isStandalone: true, selector: "val-number-from-to", inputs: { props: "props" }, ngImport: i0, template: `
6166
+ <div class="number-from-to-container">
6167
+ <ion-label position="stacked">{{ props.fromLabel || 'Inicial' }}</ion-label>
6168
+ <ion-input
6169
+ [formControl]="fromControl"
6170
+ type="number"
6171
+ [placeholder]="props.fromPlaceholder || props.placeholder"
6172
+ [min]="props.range?.min"
6173
+ [max]="props.range?.max"
6174
+ >
6175
+ </ion-input>
6176
+
6177
+ <ion-label position="stacked">{{ props.toLabel || 'Final' }}</ion-label>
6178
+ <ion-input
6179
+ [formControl]="toControl"
6180
+ type="number"
6181
+ [placeholder]="props.toPlaceholder || props.placeholder"
6182
+ [min]="props.range?.min"
6183
+ [max]="props.range?.max"
6184
+ >
6185
+ </ion-input>
6186
+ </div>
6187
+ `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }] }); }
6188
+ }
6189
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberFromToComponent, decorators: [{
6190
+ type: Component,
6191
+ args: [{ selector: 'val-number-from-to', standalone: true, imports: [ReactiveFormsModule, IonInput, IonLabel], template: `
6192
+ <div class="number-from-to-container">
6193
+ <ion-label position="stacked">{{ props.fromLabel || 'Inicial' }}</ion-label>
6194
+ <ion-input
6195
+ [formControl]="fromControl"
6196
+ type="number"
6197
+ [placeholder]="props.fromPlaceholder || props.placeholder"
6198
+ [min]="props.range?.min"
6199
+ [max]="props.range?.max"
6200
+ >
6201
+ </ion-input>
6202
+
6203
+ <ion-label position="stacked">{{ props.toLabel || 'Final' }}</ion-label>
6204
+ <ion-input
6205
+ [formControl]="toControl"
6206
+ type="number"
6207
+ [placeholder]="props.toPlaceholder || props.placeholder"
6208
+ [min]="props.range?.min"
6209
+ [max]="props.range?.max"
6210
+ >
6211
+ </ion-input>
6212
+ </div>
6213
+ ` }]
6214
+ }], ctorParameters: () => [], propDecorators: { props: [{
6215
+ type: Input
6216
+ }] } });
6217
+
6218
+ /**
6219
+ * val-number-input
6220
+ *
6221
+ * A number input field integrated with Angular forms.
6222
+ *
6223
+ * @example
6224
+ * <val-number-input [props]="{ control: myControl, placeholder: 'Enter a number' }"></val-number-input>
6225
+ *
6226
+ * @input props: InputMetadata - Configuration for the input (form control, placeholder, etc.)
6227
+ */
6228
+ class NumberInputComponent {
6229
+ constructor() { }
6230
+ ngOnInit() {
6231
+ // Apply default values on initialization
6232
+ if (this.props?.withDefault || this.props?.value) {
6233
+ applyDefaultValueToControl(this.props);
6234
+ }
6235
+ }
6236
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6237
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NumberInputComponent, isStandalone: true, selector: "val-number-input", inputs: { props: "props" }, ngImport: i0, template: ` <ion-input [formControl]="props.control" type="number" [placeholder]="props.placeholder"></ion-input> `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }] }); }
6238
+ }
6239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberInputComponent, decorators: [{
6240
+ type: Component,
6241
+ args: [{ selector: 'val-number-input', standalone: true, imports: [ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="props.control" type="number" [placeholder]="props.placeholder"></ion-input> ` }]
6242
+ }], ctorParameters: () => [], propDecorators: { props: [{
6243
+ type: Input
6244
+ }] } });
6245
+
6246
+ /**
6247
+ * val-password-input
6248
+ *
6249
+ * A password input field with show/hide toggle, integrated with Angular forms.
6250
+ *
6251
+ * @example
6252
+ * <val-password-input [props]="{ control: myControl, placeholder: 'Enter password' }"></val-password-input>
6253
+ *
6254
+ * @input props: InputMetadata - Configuration for the input (form control, placeholder, etc.)
6255
+ */
6256
+ class PasswordInputComponent {
6257
+ constructor(icon) {
6258
+ this.hidePassword = true;
6259
+ }
6260
+ ngOnInit() { }
6261
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PasswordInputComponent, deps: [{ token: IconService }], target: i0.ɵɵFactoryTarget.Component }); }
6262
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PasswordInputComponent, isStandalone: true, selector: "val-password-input", inputs: { props: "props" }, ngImport: i0, template: `
6263
+ <div class="input-container">
6264
+ <ion-input
6265
+ class="sign-in__input-password"
6266
+ [formControl]="props.control"
6267
+ [type]="hidePassword ? 'password' : 'text'"
6268
+ [placeholder]="props.placeholder"
6269
+ ></ion-input>
6270
+ <ion-button color="dark" fill="clear" (click)="hidePassword = !hidePassword" size="small">
6271
+ <ion-icon slot="icon-only" [name]="hidePassword ? 'eye-off-outline' : 'eye-outline'"></ion-icon>
6272
+ </ion-button>
6273
+ </div>
6274
+ `, 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}}.input-container{display:flex;align-items:center;flex-direction:row}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
6275
+ }
6276
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PasswordInputComponent, decorators: [{
5211
6277
  type: Component,
5212
6278
  args: [{ selector: 'val-password-input', standalone: true, imports: [ReactiveFormsModule, IonInput, IonButton, IonIcon], template: `
5213
6279
  <div class="input-container">
@@ -5226,6 +6292,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
5226
6292
  type: Input
5227
6293
  }] } });
5228
6294
 
6295
+ class PillComponent {
6296
+ constructor() {
6297
+ this.theme = inject(ThemeService);
6298
+ }
6299
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PillComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6300
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PillComponent, isStandalone: true, selector: "val-pill", inputs: { props: "props" }, ngImport: i0, template: `
6301
+ <div
6302
+ [id]="props.token"
6303
+ class="fun-card"
6304
+ [class.bordered]="props.bordered"
6305
+ [class.hoverable]="props.hoverable"
6306
+ [ngStyle]="{
6307
+ background: theme.IsDark ? 'var(--ion-background-color)' : props.background,
6308
+ }"
6309
+ >
6310
+ <val-action-header style="width: 100%;" [props]="props.content" />
6311
+ </div>
6312
+ `, 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)}.fun-card{z-index:0;position:relative;margin-bottom:8px;cursor:pointer;background:var(--ion-card-background, var(--ion-item-background, var(--ion-background-color, #fff)));display:flex;border-radius:48px;align-items:start;padding:8px 8px 8px 24px;flex-direction:column;box-shadow:0 .25rem .75rem #12195412}.fun-card.hoverable{transition:transform .3s ease,box-shadow .3s ease}.fun-card.hoverable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.bordered{border:.0625rem solid var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ActionHeaderComponent, selector: "val-action-header", inputs: ["props"] }] }); }
6313
+ }
6314
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PillComponent, decorators: [{
6315
+ type: Component,
6316
+ args: [{ selector: 'val-pill', standalone: true, imports: [CommonModule, ActionHeaderComponent], template: `
6317
+ <div
6318
+ [id]="props.token"
6319
+ class="fun-card"
6320
+ [class.bordered]="props.bordered"
6321
+ [class.hoverable]="props.hoverable"
6322
+ [ngStyle]="{
6323
+ background: theme.IsDark ? 'var(--ion-background-color)' : props.background,
6324
+ }"
6325
+ >
6326
+ <val-action-header style="width: 100%;" [props]="props.content" />
6327
+ </div>
6328
+ `, 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)}.fun-card{z-index:0;position:relative;margin-bottom:8px;cursor:pointer;background:var(--ion-card-background, var(--ion-item-background, var(--ion-background-color, #fff)));display:flex;border-radius:48px;align-items:start;padding:8px 8px 8px 24px;flex-direction:column;box-shadow:0 .25rem .75rem #12195412}.fun-card.hoverable{transition:transform .3s ease,box-shadow .3s ease}.fun-card.hoverable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.bordered{border:.0625rem solid var(--ion-color-medium)}\n"] }]
6329
+ }], propDecorators: { props: [{
6330
+ type: Input
6331
+ }] } });
6332
+
5229
6333
  /**
5230
6334
  * val-pin-input
5231
6335
  *
@@ -5277,6 +6381,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
5277
6381
  type: Input
5278
6382
  }] } });
5279
6383
 
6384
+ class PlainCodeBoxComponent {
6385
+ constructor() {
6386
+ this.toast = inject(ToastController);
6387
+ this.cdr = inject(ChangeDetectorRef);
6388
+ this.langService = inject(LangService);
6389
+ this.props = { lines: [] };
6390
+ }
6391
+ ngOnChanges(changes) {
6392
+ if (changes['props'] && !changes['props'].firstChange) {
6393
+ this.cdr.detectChanges();
6394
+ setTimeout(() => this.highlightCode());
6395
+ }
6396
+ }
6397
+ ngAfterViewInit() {
6398
+ setTimeout(() => this.highlightCode());
6399
+ }
6400
+ highlightCode() {
6401
+ if (this.codeBlock && this.props.lines && this.props.lines.length > 0) {
6402
+ Prism.highlightElement(this.codeBlock.nativeElement);
6403
+ }
6404
+ }
6405
+ async copyCode() {
6406
+ const fullCode = this.props.lines.map(line => line.text).join('\n');
6407
+ if (fullCode) {
6408
+ await Clipboard.write({
6409
+ string: fullCode,
6410
+ });
6411
+ const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
6412
+ this.presentToast(copiedMessage);
6413
+ }
6414
+ }
6415
+ async presentToast(message) {
6416
+ const toast = await this.toast.create({
6417
+ message: message,
6418
+ duration: 2000,
6419
+ position: 'bottom',
6420
+ color: 'dark',
6421
+ });
6422
+ toast.present();
6423
+ }
6424
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlainCodeBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6425
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PlainCodeBoxComponent, isStandalone: true, selector: "val-plain-code-box", inputs: { props: "props" }, viewQueries: [{ propertyName: "codeBlock", first: true, predicate: ["codeBlock"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
6426
+ <div class="code-box-container">
6427
+ <ion-button *ngIf="props.showCopyButton !== false" fill="clear" class="copy-button" (click)="copyCode()">
6428
+ <ion-icon name="copy-outline"></ion-icon>
6429
+ </ion-button>
6430
+ <pre><code [class]="'language-' + (props.language || 'bash')" #codeBlock><ng-container *ngFor="let line of props.lines; let i = index"><span [class]="line.type ? 'line-' + line.type : 'line-normal'">{{ line.text }}</span><br *ngIf="i < props.lines.length - 1">
6431
+ </ng-container></code></pre>
6432
+ </div>
6433
+ `, isInline: true, styles: [".code-box-container{position:relative;background-color:#282c34;border-radius:16px;overflow:hidden;box-shadow:0 4px 15px #0009;margin:0}@media (prefers-color-scheme: light){.code-box-container{background-color:#fff;box-shadow:0 2px 4px #0000001a}}.copy-button{position:absolute;top:8px;right:8px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:#61afef;background:#0006;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease,color .2s ease}.copy-button:hover{background:#00000080;color:#8cc4ff}.copy-button ion-icon{font-size:1.2em;margin:0}@media (prefers-color-scheme: light){.copy-button{color:var(--ion-color-primary, #007bff);background:#ffffffb3}.copy-button:hover{background:#ffffffe6;color:var(--ion-color-primary-tint, #3880ff)}}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre-wrap;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.6;display:block;white-space:inherit;word-break:inherit;color:#abb2bf;margin:0}@media (prefers-color-scheme: light){code{color:#333}}code .line-normal{color:#abb2bf}@media (prefers-color-scheme: light){code .line-normal{color:#333}}code .line-command{color:#c678dd}@media (prefers-color-scheme: light){code .line-command{color:var(--ion-color-primary, #3880ff)}}code .line-error{color:#e06c75}@media (prefers-color-scheme: light){code .line-error{color:var(--ion-color-danger, #eb445a)}}code .line-success{color:#98c379}@media (prefers-color-scheme: light){code .line-success{color:var(--ion-color-success, #2dd36f)}}code .token.comment{color:#5c6370}code .token.selector,code .token.string{color:#98c379}code .token.punctuation{color:#abb2bf}code .token.operator{color:#c678dd}code .token.boolean,code .token.number{color:#d19a66}code .token.function{color:#61afef}code .token.keyword{color:#c678dd}code .token.class-name{color:#e6c07b}code .token.tag{color:#e06c75}code .token.attr-name{color:#d19a66}code .token.attr-value{color:#98c379}code .token.property{color:#56b6c2}code .token.variable{color:#e06c75}@media (max-width: 600px){.code-box-container{border-radius:16px}.copy-button{top:6px;right:6px;min-width:24px;min-height:24px;height:24px;width:24px}.copy-button ion-icon{font-size:1em}pre{padding:0;margin:0}code{font-size:.8em;line-height:1.5;margin:0}}@media (min-width: 601px) and (max-width: 1024px){code{font-size:.9em}}@media (min-width: 1025px){code{font-size:1em}}\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: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] }); }
6434
+ }
6435
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlainCodeBoxComponent, decorators: [{
6436
+ type: Component,
6437
+ args: [{ selector: 'val-plain-code-box', standalone: true, imports: [CommonModule, IonIcon, IonButton], template: `
6438
+ <div class="code-box-container">
6439
+ <ion-button *ngIf="props.showCopyButton !== false" fill="clear" class="copy-button" (click)="copyCode()">
6440
+ <ion-icon name="copy-outline"></ion-icon>
6441
+ </ion-button>
6442
+ <pre><code [class]="'language-' + (props.language || 'bash')" #codeBlock><ng-container *ngFor="let line of props.lines; let i = index"><span [class]="line.type ? 'line-' + line.type : 'line-normal'">{{ line.text }}</span><br *ngIf="i < props.lines.length - 1">
6443
+ </ng-container></code></pre>
6444
+ </div>
6445
+ `, styles: [".code-box-container{position:relative;background-color:#282c34;border-radius:16px;overflow:hidden;box-shadow:0 4px 15px #0009;margin:0}@media (prefers-color-scheme: light){.code-box-container{background-color:#fff;box-shadow:0 2px 4px #0000001a}}.copy-button{position:absolute;top:8px;right:8px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:#61afef;background:#0006;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease,color .2s ease}.copy-button:hover{background:#00000080;color:#8cc4ff}.copy-button ion-icon{font-size:1.2em;margin:0}@media (prefers-color-scheme: light){.copy-button{color:var(--ion-color-primary, #007bff);background:#ffffffb3}.copy-button:hover{background:#ffffffe6;color:var(--ion-color-primary-tint, #3880ff)}}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre-wrap;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.6;display:block;white-space:inherit;word-break:inherit;color:#abb2bf;margin:0}@media (prefers-color-scheme: light){code{color:#333}}code .line-normal{color:#abb2bf}@media (prefers-color-scheme: light){code .line-normal{color:#333}}code .line-command{color:#c678dd}@media (prefers-color-scheme: light){code .line-command{color:var(--ion-color-primary, #3880ff)}}code .line-error{color:#e06c75}@media (prefers-color-scheme: light){code .line-error{color:var(--ion-color-danger, #eb445a)}}code .line-success{color:#98c379}@media (prefers-color-scheme: light){code .line-success{color:var(--ion-color-success, #2dd36f)}}code .token.comment{color:#5c6370}code .token.selector,code .token.string{color:#98c379}code .token.punctuation{color:#abb2bf}code .token.operator{color:#c678dd}code .token.boolean,code .token.number{color:#d19a66}code .token.function{color:#61afef}code .token.keyword{color:#c678dd}code .token.class-name{color:#e6c07b}code .token.tag{color:#e06c75}code .token.attr-name{color:#d19a66}code .token.attr-value{color:#98c379}code .token.property{color:#56b6c2}code .token.variable{color:#e06c75}@media (max-width: 600px){.code-box-container{border-radius:16px}.copy-button{top:6px;right:6px;min-width:24px;min-height:24px;height:24px;width:24px}.copy-button ion-icon{font-size:1em}pre{padding:0;margin:0}code{font-size:.8em;line-height:1.5;margin:0}}@media (min-width: 601px) and (max-width: 1024px){code{font-size:.9em}}@media (min-width: 1025px){code{font-size:1em}}\n"] }]
6446
+ }], ctorParameters: () => [], propDecorators: { props: [{
6447
+ type: Input
6448
+ }], codeBlock: [{
6449
+ type: ViewChild,
6450
+ args: ['codeBlock']
6451
+ }] } });
6452
+
5280
6453
  //TODO: support automatic or manual interval for messages. Include the interval number as a parameter.
5281
6454
  /**
5282
6455
  * val-progress-status
@@ -5482,115 +6655,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
5482
6655
  * A radio group input for selecting one option, integrated with Angular forms.
5483
6656
  *
5484
6657
  * @example
5485
- * <val-radio-input [props]="{ control: myControl, options: [{ id: '1', name: 'Option 1' }] }"></val-radio-input>
5486
- *
5487
- * @input props: InputMetadata - Configuration for the radio input (form control, options, etc.)
5488
- */
5489
- class RadioInputComponent {
5490
- constructor() { }
5491
- ngOnInit() { }
5492
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5493
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: RadioInputComponent, isStandalone: true, selector: "val-radio-input", inputs: { props: "props" }, ngImport: i0, template: `
5494
- <ion-radio-group [allowEmptySelection]="true" [formControl]="props.control">
5495
- <ng-container *ngFor="let o of props.options">
5496
- <ion-radio [value]="o.id">{{ o.name }}</ion-radio>
5497
- <br />
5498
- </ng-container>
5499
- </ion-radio-group>
5500
- `, isInline: true, styles: [""], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }] }); }
5501
- }
5502
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioInputComponent, decorators: [{
5503
- type: Component,
5504
- args: [{ selector: 'val-radio-input', standalone: true, imports: [NgFor, ReactiveFormsModule, IonRadioGroup, IonRadio], template: `
5505
- <ion-radio-group [allowEmptySelection]="true" [formControl]="props.control">
5506
- <ng-container *ngFor="let o of props.options">
5507
- <ion-radio [value]="o.id">{{ o.name }}</ion-radio>
5508
- <br />
5509
- </ng-container>
5510
- </ion-radio-group>
5511
- ` }]
5512
- }], ctorParameters: () => [], propDecorators: { props: [{
5513
- type: Input
5514
- }] } });
5515
-
5516
- /**
5517
- * val-searchbar
5518
- *
5519
- * A search bar component with debounce and event emitters for filtering, focus, and blur.
5520
- *
5521
- * @example
5522
- * <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()"></val-searchbar>
5523
- *
5524
- * @input disabled - Whether the searchbar is disabled.
5525
- * @output filterEvent - Emits the search term on input.
5526
- * @output focusEvent - Emits when the searchbar gains focus.
5527
- * @output blurEvent - Emits when the searchbar loses focus.
5528
- */
5529
- class SearchbarComponent {
5530
- constructor() {
5531
- /**
5532
- * Emits the search term on input.
5533
- */
5534
- this.filterEvent = new EventEmitter();
5535
- /**
5536
- * Emits when the searchbar gains focus.
5537
- */
5538
- this.focusEvent = new EventEmitter();
5539
- /**
5540
- * Emits when the searchbar loses focus.
5541
- */
5542
- this.blurEvent = new EventEmitter();
5543
- }
5544
- onSearch($event) {
5545
- const searchTerm = $event.detail.value;
5546
- this.filterEvent.emit(searchTerm);
5547
- }
5548
- onFocus() {
5549
- this.focusEvent.emit();
5550
- }
5551
- onBlur() {
5552
- this.blurEvent.emit();
5553
- }
5554
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SearchbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5555
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SearchbarComponent, isStandalone: true, selector: "val-searchbar", inputs: { disabled: "disabled" }, outputs: { filterEvent: "filterEvent", focusEvent: "focusEvent", blurEvent: "blurEvent" }, ngImport: i0, template: `
5556
- <ion-searchbar
5557
- mode="ios"
5558
- debounce="500"
5559
- placeholder="Búsqueda"
5560
- [disabled]="disabled"
5561
- showCancelButton="focus"
5562
- cancelButtonText="Cancelar"
5563
- (ionInput)="onSearch($event)"
5564
- (ionBlur)="onBlur()"
5565
- (ionFocus)="onFocus()"
5566
- >
5567
- </ion-searchbar>
5568
- `, 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)}ion-searchbar{--cancel-button-color: var(--ion-color-dark);--background: var(--ion-color-light);font-family:var(--ion-default-font),Arial,sans-serif}\n"], dependencies: [{ kind: "component", type: IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }] }); }
6658
+ * <val-radio-input [props]="{ control: myControl, options: [{ id: '1', name: 'Option 1' }] }"></val-radio-input>
6659
+ *
6660
+ * @input props: InputMetadata - Configuration for the radio input (form control, options, etc.)
6661
+ */
6662
+ class RadioInputComponent {
6663
+ constructor() { }
6664
+ ngOnInit() { }
6665
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6666
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: RadioInputComponent, isStandalone: true, selector: "val-radio-input", inputs: { props: "props" }, ngImport: i0, template: `
6667
+ <ion-radio-group [allowEmptySelection]="true" [formControl]="props.control">
6668
+ <ng-container *ngFor="let o of props.options">
6669
+ <ion-radio [value]="o.id">{{ o.name }}</ion-radio>
6670
+ <br />
6671
+ </ng-container>
6672
+ </ion-radio-group>
6673
+ `, isInline: true, styles: [""], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }] }); }
5569
6674
  }
5570
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SearchbarComponent, decorators: [{
6675
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioInputComponent, decorators: [{
5571
6676
  type: Component,
5572
- args: [{ selector: 'val-searchbar', standalone: true, imports: [IonSearchbar], template: `
5573
- <ion-searchbar
5574
- mode="ios"
5575
- debounce="500"
5576
- placeholder="Búsqueda"
5577
- [disabled]="disabled"
5578
- showCancelButton="focus"
5579
- cancelButtonText="Cancelar"
5580
- (ionInput)="onSearch($event)"
5581
- (ionBlur)="onBlur()"
5582
- (ionFocus)="onFocus()"
5583
- >
5584
- </ion-searchbar>
5585
- `, 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)}ion-searchbar{--cancel-button-color: var(--ion-color-dark);--background: var(--ion-color-light);font-family:var(--ion-default-font),Arial,sans-serif}\n"] }]
5586
- }], ctorParameters: () => [], propDecorators: { disabled: [{
6677
+ args: [{ selector: 'val-radio-input', standalone: true, imports: [NgFor, ReactiveFormsModule, IonRadioGroup, IonRadio], template: `
6678
+ <ion-radio-group [allowEmptySelection]="true" [formControl]="props.control">
6679
+ <ng-container *ngFor="let o of props.options">
6680
+ <ion-radio [value]="o.id">{{ o.name }}</ion-radio>
6681
+ <br />
6682
+ </ng-container>
6683
+ </ion-radio-group>
6684
+ ` }]
6685
+ }], ctorParameters: () => [], propDecorators: { props: [{
5587
6686
  type: Input
5588
- }], filterEvent: [{
5589
- type: Output
5590
- }], focusEvent: [{
5591
- type: Output
5592
- }], blurEvent: [{
5593
- type: Output
5594
6687
  }] } });
5595
6688
 
5596
6689
  /**
@@ -5655,18 +6748,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
5655
6748
  type: Input
5656
6749
  }] } });
5657
6750
 
5658
- /**
5659
- * Removes diacritical marks (accents) from a string using Unicode normalization.
5660
- * Useful for text search and comparison.
5661
- *
5662
- * @param text The input string
5663
- * @returns The normalized string without diacritical marks
5664
- *
5665
- * @example
5666
- * replaceSpecialChars('canción') // returns 'cancion'
5667
- */
5668
- const replaceSpecialChars = (text) => text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
5669
-
5670
6751
  /**
5671
6752
  * val-select-search
5672
6753
  *
@@ -5900,486 +6981,173 @@ class SelectSearchComponent {
5900
6981
  this.displayValue = `${this.selectedItems.length} elementos seleccionados`;
5901
6982
  }
5902
6983
  }
5903
- else {
5904
- this.displayValue = this.selectedItems[0][this.labelProperty];
5905
- }
5906
- }
5907
- applyChanges() {
5908
- if (!this.props?.control) {
5909
- return;
5910
- }
5911
- try {
5912
- this.isProcessingChanges = true;
5913
- if (this.selectedItems.length > 0) {
5914
- this.props.control.setValue(this.selectedItems[0][this.valueProperty]);
5915
- }
5916
- else {
5917
- this.props.control.setValue(null);
5918
- }
5919
- this.props.control.markAsDirty();
5920
- this.props.control.updateValueAndValidity();
5921
- }
5922
- finally {
5923
- this.isProcessingChanges = false;
5924
- }
5925
- }
5926
- // Método público para reiniciar el componente
5927
- reset() {
5928
- this.selectedItems = [];
5929
- this.displayValue = '';
5930
- if (this.props?.control) {
5931
- this.props.control.setValue(null);
5932
- }
5933
- this.changeDetector.detectChanges();
5934
- }
5935
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5936
- 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: `
5937
- <ion-input
5938
- type="text"
5939
- [value]="displayValue"
5940
- [placeholder]="props?.placeholder || placeholder"
5941
- readonly
5942
- (mousedown)="preventDefaultBehavior($event)"
5943
- />
5944
-
5945
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
5946
-
5947
- <ion-modal
5948
- #modal
5949
- [initialBreakpoint]="1"
5950
- [breakpoints]="[0, 0.5, 0.75, 1]"
5951
- (didDismiss)="cancelModal()"
5952
- >
5953
- <ng-template>
5954
- <ion-header>
5955
- <ion-toolbar>
5956
- <ion-title>{{ label }}</ion-title>
5957
- <ion-buttons slot="end">
5958
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
5959
- </ion-buttons>
5960
- </ion-toolbar>
5961
- <ion-toolbar>
5962
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
5963
- </ion-toolbar>
5964
- </ion-header>
5965
- <ion-content>
5966
- <ion-list>
5967
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
5968
- <ion-label>{{ item[labelProperty] }}</ion-label>
5969
- <ion-icon *ngIf="isItemSelected(item)" name="checkmark-outline" slot="end" color="primary"></ion-icon>
5970
- </ion-item>
5971
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
5972
- <ion-label color="dark">No se encontraron resultados</ion-label>
5973
- </ion-item>
5974
- </ion-list>
5975
- </ion-content>
5976
- </ng-template>
5977
- </ion-modal>
5978
- `, 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"] }] }); }
5979
- }
5980
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, decorators: [{
5981
- type: Component,
5982
- args: [{ selector: 'val-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, SearchbarComponent, ReactiveFormsModule], template: `
5983
- <ion-input
5984
- type="text"
5985
- [value]="displayValue"
5986
- [placeholder]="props?.placeholder || placeholder"
5987
- readonly
5988
- (mousedown)="preventDefaultBehavior($event)"
5989
- />
5990
-
5991
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
5992
-
5993
- <ion-modal
5994
- #modal
5995
- [initialBreakpoint]="1"
5996
- [breakpoints]="[0, 0.5, 0.75, 1]"
5997
- (didDismiss)="cancelModal()"
5998
- >
5999
- <ng-template>
6000
- <ion-header>
6001
- <ion-toolbar>
6002
- <ion-title>{{ label }}</ion-title>
6003
- <ion-buttons slot="end">
6004
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
6005
- </ion-buttons>
6006
- </ion-toolbar>
6007
- <ion-toolbar>
6008
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
6009
- </ion-toolbar>
6010
- </ion-header>
6011
- <ion-content>
6012
- <ion-list>
6013
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
6014
- <ion-label>{{ item[labelProperty] }}</ion-label>
6015
- <ion-icon *ngIf="isItemSelected(item)" name="checkmark-outline" slot="end" color="primary"></ion-icon>
6016
- </ion-item>
6017
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
6018
- <ion-label color="dark">No se encontraron resultados</ion-label>
6019
- </ion-item>
6020
- </ion-list>
6021
- </ion-content>
6022
- </ng-template>
6023
- </ion-modal>
6024
- `, styles: ["ion-header{padding:8px 8px 0}\n"] }]
6025
- }], ctorParameters: () => [], propDecorators: { modal: [{
6026
- type: ViewChild,
6027
- args: ['modal']
6028
- }], label: [{
6029
- type: Input
6030
- }], labelProperty: [{
6031
- type: Input
6032
- }], valueProperty: [{
6033
- type: Input
6034
- }], multiple: [{
6035
- type: Input
6036
- }], placeholder: [{
6037
- type: Input
6038
- }], props: [{
6039
- type: Input
6040
- }] } });
6041
-
6042
- /**
6043
- * val-text-input
6044
- *
6045
- * A text input field integrated with Angular forms.
6046
- *
6047
- * @example
6048
- * <val-text-input [props]="{ control: myControl, placeholder: 'Enter text', ... }"></val-text-input>
6049
- *
6050
- * @input props: InputMetadata - Configuration for the input (form control, placeholder, label, etc.)
6051
- */
6052
- class TextInputComponent {
6053
- constructor() {
6054
- this.states = ComponentStates;
6055
- }
6056
- ngOnInit() {
6057
- // Apply default values on initialization
6058
- if (this.props?.withDefault || this.props?.value) {
6059
- applyDefaultValueToControl(this.props);
6060
- }
6061
- }
6062
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6063
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TextInputComponent, isStandalone: true, selector: "val-text-input", inputs: { props: "props" }, ngImport: i0, template: ` <ion-input [formControl]="props.control" type="text" [placeholder]="props.placeholder" /> `, 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: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }] }); }
6064
- }
6065
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextInputComponent, decorators: [{
6066
- type: Component,
6067
- args: [{ selector: 'val-text-input', standalone: true, imports: [ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="props.control" type="text" [placeholder]="props.placeholder" /> `, 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"] }]
6068
- }], ctorParameters: () => [], propDecorators: { props: [{
6069
- type: Input
6070
- }] } });
6071
-
6072
- class CodeDisplayComponent {
6073
- constructor(cdr) {
6074
- this.cdr = cdr;
6075
- this.toast = inject(ToastController);
6076
- this.langService = inject(LangService);
6077
- this.selectedTab = 0;
6078
- }
6079
- ngOnChanges(changes) {
6080
- if (changes['code'] || changes['language'] || changes['tabs']) {
6081
- this.cdr.detectChanges();
6082
- setTimeout(() => this.highlightCode());
6083
- }
6084
- }
6085
- ngAfterViewInit() {
6086
- setTimeout(() => this.highlightCode());
6087
- }
6088
- selectTab(i) {
6089
- this.selectedTab = i;
6090
- this.cdr.detectChanges();
6091
- setTimeout(() => this.highlightCode());
6092
- }
6093
- highlightCode() {
6094
- if (this.codeElement) {
6095
- const code = this.props.tabs.length > 0 ? this.props.tabs[this.selectedTab]?.code : this.props.code;
6096
- this.codeElement.nativeElement.textContent = code || '';
6097
- Prism.highlightElement(this.codeElement.nativeElement);
6098
- }
6984
+ else {
6985
+ this.displayValue = this.selectedItems[0][this.labelProperty];
6986
+ }
6099
6987
  }
6100
- async copyToClipboard() {
6988
+ applyChanges() {
6989
+ if (!this.props?.control) {
6990
+ return;
6991
+ }
6101
6992
  try {
6102
- const code = this.props.tabs.length > 0 ? this.props.tabs[this.selectedTab]?.code : this.props.code;
6103
- await Clipboard.write({ string: code || '' });
6104
- const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
6105
- this.presentToast(copiedMessage);
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();
6106
7002
  }
6107
- catch (error) {
6108
- console.error('Error al copiar al portapapeles:', error);
7003
+ finally {
7004
+ this.isProcessingChanges = false;
6109
7005
  }
6110
7006
  }
6111
- async presentToast(message) {
6112
- const toast = await this.toast.create({
6113
- message: message,
6114
- duration: 2000,
6115
- position: 'bottom',
6116
- color: 'dark',
6117
- });
6118
- toast.present();
6119
- }
6120
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CodeDisplayComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
6121
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CodeDisplayComponent, isStandalone: true, selector: "val-code-display", inputs: { props: "props" }, viewQueries: [{ propertyName: "codeElement", first: true, predicate: ["codeElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
6122
- <div class="code-viewer-container">
6123
- <div class="tab-bar">
6124
- <div
6125
- class="tab"
6126
- *ngFor="let tab of props.tabs; let i = index"
6127
- [class.active]="i === selectedTab"
6128
- (click)="selectTab(i)"
6129
- >
6130
- <span class="tab-label">{{ tab.label }}</span>
6131
- </div>
6132
- </div>
6133
- <div class="code-content">
6134
- <!-- <span class="language-badge">{{ props.tabs[selectedTab]?.language || props.language }}</span> -->
6135
- <ion-button fill="clear" class="copy-button" (click)="copyToClipboard()">
6136
- <ion-icon name="copy-outline"></ion-icon>
6137
- </ion-button>
6138
- <pre><code [class]="'language-' + (props.tabs[selectedTab]?.language || props.language)" #codeElement></code></pre>
6139
- </div>
6140
- </div>
6141
- `, 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)}.code-viewer-container{background-color:#fff;border-radius:24px;overflow:hidden;box-shadow:0 2px 4px #0000000d;border:1px solid #f2f6f7;position:relative;min-width:320px;max-width:100%}.tab-bar{display:flex;background:#f6f9fa;border-bottom:1px solid #f2f6f7;gap:2px;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:#e0e0e0 #f6f9fa;-webkit-overflow-scrolling:touch;max-width:100%;font-size:12px}.tab-bar::-webkit-scrollbar{height:6px;background:#f6f9fa}.tab-bar::-webkit-scrollbar-thumb{background:#e0e0e0;border-radius:4px}.tab{padding:10px 18px 8px;font-family:Roboto Mono,monospace;font-size:.95em;color:#899396;cursor:pointer;border-radius:8px 8px 0 0;background:transparent;transition:background .2s,color .2s;margin-bottom:-1px;border:1px solid transparent;border-bottom:none}.tab:hover{background:#e8eef2}.tab.active{background:#fff;color:#19422d;border:1px solid #f2f6f7;border-bottom:1px solid #ffffff;z-index:2}.tab-label{font-weight:500}.code-content{overflow-x:auto;overflow-y:auto;max-height:30rem;min-height:5rem;background:#fff;position:relative}.language-badge{position:absolute;top:15px;left:15px;background:#f6f9fa;color:#899396;font-family:Roboto Mono,monospace;font-size:.8em;font-weight:500;border-radius:6px;padding:2px 8px;z-index:3;pointer-events:none;text-transform:uppercase}.copy-button{position:absolute;top:10px;right:15px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:var(--ion-color-primary);background:#ffffffb3;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease}.copy-button:hover{background:#ffffffe6}.copy-button ion-icon{font-size:1.2em;margin:0}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.5;display:block;white-space:inherit;word-break:normal}@media (max-width: 600px){.code-viewer-container{border-radius:24px}.tab-bar{font-size:11px}.language-badge{font-size:.7em;padding:1px 6px;top:10px;left:10px}.copy-button{top:10px;right:10px}.code-content{max-height:20rem}code{font-size:.7em}}@media (min-width: 600px){code{font-size:.8em}}@media (prefers-color-scheme: dark){.code-viewer-container{background-color:#21252b;box-shadow:0 4px 15px #0009;border:1px solid #3b4048}.tab-bar{background:#1a1a1a;border-bottom:1px solid #3b4048;scrollbar-color:#3b4048 #1a1a1a}.tab-bar::-webkit-scrollbar{background:#1a1a1a}.tab-bar::-webkit-scrollbar-thumb{background:#3b4048}.tab{color:#8b949e}.tab:hover{background:#21252b}.tab.active{background:#282c34;color:#c9d1d9;border:1px solid #3b4048;border-bottom:1px solid #282c34}.code-content{background:#161b22}.language-badge{background:#3e4451;color:#8b949e}.copy-button{background:#0006}.copy-button:hover{background:#0009}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] }); }
6142
- }
6143
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CodeDisplayComponent, decorators: [{
6144
- type: Component,
6145
- args: [{ selector: 'val-code-display', standalone: true, imports: [CommonModule, IonIcon, IonButton], template: `
6146
- <div class="code-viewer-container">
6147
- <div class="tab-bar">
6148
- <div
6149
- class="tab"
6150
- *ngFor="let tab of props.tabs; let i = index"
6151
- [class.active]="i === selectedTab"
6152
- (click)="selectTab(i)"
6153
- >
6154
- <span class="tab-label">{{ tab.label }}</span>
6155
- </div>
6156
- </div>
6157
- <div class="code-content">
6158
- <!-- <span class="language-badge">{{ props.tabs[selectedTab]?.language || props.language }}</span> -->
6159
- <ion-button fill="clear" class="copy-button" (click)="copyToClipboard()">
6160
- <ion-icon name="copy-outline"></ion-icon>
6161
- </ion-button>
6162
- <pre><code [class]="'language-' + (props.tabs[selectedTab]?.language || props.language)" #codeElement></code></pre>
6163
- </div>
6164
- </div>
6165
- `, 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)}.code-viewer-container{background-color:#fff;border-radius:24px;overflow:hidden;box-shadow:0 2px 4px #0000000d;border:1px solid #f2f6f7;position:relative;min-width:320px;max-width:100%}.tab-bar{display:flex;background:#f6f9fa;border-bottom:1px solid #f2f6f7;gap:2px;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:#e0e0e0 #f6f9fa;-webkit-overflow-scrolling:touch;max-width:100%;font-size:12px}.tab-bar::-webkit-scrollbar{height:6px;background:#f6f9fa}.tab-bar::-webkit-scrollbar-thumb{background:#e0e0e0;border-radius:4px}.tab{padding:10px 18px 8px;font-family:Roboto Mono,monospace;font-size:.95em;color:#899396;cursor:pointer;border-radius:8px 8px 0 0;background:transparent;transition:background .2s,color .2s;margin-bottom:-1px;border:1px solid transparent;border-bottom:none}.tab:hover{background:#e8eef2}.tab.active{background:#fff;color:#19422d;border:1px solid #f2f6f7;border-bottom:1px solid #ffffff;z-index:2}.tab-label{font-weight:500}.code-content{overflow-x:auto;overflow-y:auto;max-height:30rem;min-height:5rem;background:#fff;position:relative}.language-badge{position:absolute;top:15px;left:15px;background:#f6f9fa;color:#899396;font-family:Roboto Mono,monospace;font-size:.8em;font-weight:500;border-radius:6px;padding:2px 8px;z-index:3;pointer-events:none;text-transform:uppercase}.copy-button{position:absolute;top:10px;right:15px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:var(--ion-color-primary);background:#ffffffb3;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease}.copy-button:hover{background:#ffffffe6}.copy-button ion-icon{font-size:1.2em;margin:0}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.5;display:block;white-space:inherit;word-break:normal}@media (max-width: 600px){.code-viewer-container{border-radius:24px}.tab-bar{font-size:11px}.language-badge{font-size:.7em;padding:1px 6px;top:10px;left:10px}.copy-button{top:10px;right:10px}.code-content{max-height:20rem}code{font-size:.7em}}@media (min-width: 600px){code{font-size:.8em}}@media (prefers-color-scheme: dark){.code-viewer-container{background-color:#21252b;box-shadow:0 4px 15px #0009;border:1px solid #3b4048}.tab-bar{background:#1a1a1a;border-bottom:1px solid #3b4048;scrollbar-color:#3b4048 #1a1a1a}.tab-bar::-webkit-scrollbar{background:#1a1a1a}.tab-bar::-webkit-scrollbar-thumb{background:#3b4048}.tab{color:#8b949e}.tab:hover{background:#21252b}.tab.active{background:#282c34;color:#c9d1d9;border:1px solid #3b4048;border-bottom:1px solid #282c34}.code-content{background:#161b22}.language-badge{background:#3e4451;color:#8b949e}.copy-button{background:#0006}.copy-button:hover{background:#0009}}\n"] }]
6166
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { codeElement: [{
6167
- type: ViewChild,
6168
- args: ['codeElement']
6169
- }], props: [{
6170
- type: Input
6171
- }] } });
6172
-
6173
- class ActionHeaderComponent {
6174
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6175
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ActionHeaderComponent, isStandalone: true, selector: "val-action-header", inputs: { props: "props" }, ngImport: i0, template: `
6176
- <section class="header-content-container">
6177
- <val-display [props]="props.title" />
6178
- <val-button [props]="props.action" />
6179
- </section>
6180
- `, isInline: true, styles: [".header-content-container{width:100%;display:flex;align-items:center;justify-content:space-between}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["props"], outputs: ["onClick"] }] }); }
6181
- }
6182
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActionHeaderComponent, decorators: [{
6183
- type: Component,
6184
- args: [{ selector: 'val-action-header', standalone: true, imports: [CommonModule, DisplayComponent, ButtonComponent], template: `
6185
- <section class="header-content-container">
6186
- <val-display [props]="props.title" />
6187
- <val-button [props]="props.action" />
6188
- </section>
6189
- `, styles: [".header-content-container{width:100%;display:flex;align-items:center;justify-content:space-between}\n"] }]
6190
- }], propDecorators: { props: [{
6191
- type: Input
6192
- }] } });
6193
-
6194
- class PillComponent {
6195
- constructor() {
6196
- this.theme = inject(ThemeService);
6197
- }
6198
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PillComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6199
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PillComponent, isStandalone: true, selector: "val-pill", inputs: { props: "props" }, ngImport: i0, template: `
6200
- <div
6201
- [id]="props.token"
6202
- class="fun-card"
6203
- [class.bordered]="props.bordered"
6204
- [class.hoverable]="props.hoverable"
6205
- [ngStyle]="{
6206
- background: theme.IsDark ? 'var(--ion-background-color)' : props.background,
6207
- }"
6208
- >
6209
- <val-action-header style="width: 100%;" [props]="props.content" />
6210
- </div>
6211
- `, 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)}.fun-card{z-index:0;position:relative;margin-bottom:8px;cursor:pointer;background:var(--ion-card-background, var(--ion-item-background, var(--ion-background-color, #fff)));display:flex;border-radius:48px;align-items:start;padding:8px 8px 8px 24px;flex-direction:column;box-shadow:0 .25rem .75rem #12195412}.fun-card.hoverable{transition:transform .3s ease,box-shadow .3s ease}.fun-card.hoverable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.bordered{border:.0625rem solid var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ActionHeaderComponent, selector: "val-action-header", inputs: ["props"] }] }); }
6212
- }
6213
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PillComponent, decorators: [{
6214
- type: Component,
6215
- args: [{ selector: 'val-pill', standalone: true, imports: [CommonModule, ActionHeaderComponent], template: `
6216
- <div
6217
- [id]="props.token"
6218
- class="fun-card"
6219
- [class.bordered]="props.bordered"
6220
- [class.hoverable]="props.hoverable"
6221
- [ngStyle]="{
6222
- background: theme.IsDark ? 'var(--ion-background-color)' : props.background,
6223
- }"
6224
- >
6225
- <val-action-header style="width: 100%;" [props]="props.content" />
6226
- </div>
6227
- `, 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)}.fun-card{z-index:0;position:relative;margin-bottom:8px;cursor:pointer;background:var(--ion-card-background, var(--ion-item-background, var(--ion-background-color, #fff)));display:flex;border-radius:48px;align-items:start;padding:8px 8px 8px 24px;flex-direction:column;box-shadow:0 .25rem .75rem #12195412}.fun-card.hoverable{transition:transform .3s ease,box-shadow .3s ease}.fun-card.hoverable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.bordered{border:.0625rem solid var(--ion-color-medium)}\n"] }]
6228
- }], propDecorators: { props: [{
6229
- type: Input
6230
- }] } });
6231
-
6232
- class CommandDisplayComponent {
6233
- constructor() {
6234
- this.toast = inject(ToastController);
6235
- this.langService = inject(LangService);
6236
- }
6237
- async copyCommand() {
6238
- if (this.props.text) {
6239
- await Clipboard.write({
6240
- string: this.props.text,
6241
- });
6242
- const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
6243
- this.presentToast(copiedMessage);
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);
6244
7013
  }
7014
+ this.changeDetector.detectChanges();
6245
7015
  }
6246
- async presentToast(message) {
6247
- const toast = await this.toast.create({
6248
- message: message,
6249
- duration: 2000,
6250
- position: 'bottom',
6251
- color: 'dark',
6252
- });
6253
- toast.present();
6254
- }
6255
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CommandDisplayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6256
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CommandDisplayComponent, isStandalone: true, selector: "val-command-display", inputs: { props: "props" }, ngImport: i0, template: `
6257
- <div class="command-container">
6258
- <div class="command-text">$ {{ props.text }}</div>
6259
- <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
6260
- </div>
6261
- `, isInline: true, styles: [".command-container{display:flex;align-items:center;justify-content:space-between;background-color:var(--ion-color-light, #f2f2f2);border-radius:24px;padding:12px 16px;box-shadow:0 2px 4px #0000001a}.command-text{flex-grow:1;font-family:monospace;font-size:.8rem;color:var(--ion-color-dark, #333);margin-right:10px}.copy-icon{font-size:1.3rem;color:var(--ion-color-medium, #92949c);cursor:pointer;transition:color .2s ease-in-out}.copy-icon:hover{color:var(--ion-color-primary, #3880ff)}@media (min-width: 600px){.command-text,.copy-icon{font-size:1.2rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
6262
- }
6263
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CommandDisplayComponent, decorators: [{
6264
- type: Component,
6265
- args: [{ selector: 'val-command-display', standalone: true, imports: [CommonModule, IonIcon], template: `
6266
- <div class="command-container">
6267
- <div class="command-text">$ {{ props.text }}</div>
6268
- <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
6269
- </div>
6270
- `, styles: [".command-container{display:flex;align-items:center;justify-content:space-between;background-color:var(--ion-color-light, #f2f2f2);border-radius:24px;padding:12px 16px;box-shadow:0 2px 4px #0000001a}.command-text{flex-grow:1;font-family:monospace;font-size:.8rem;color:var(--ion-color-dark, #333);margin-right:10px}.copy-icon{font-size:1.3rem;color:var(--ion-color-medium, #92949c);cursor:pointer;transition:color .2s ease-in-out}.copy-icon:hover{color:var(--ion-color-primary, #3880ff)}@media (min-width: 600px){.command-text,.copy-icon{font-size:1.2rem}}\n"] }]
6271
- }], ctorParameters: () => [], propDecorators: { props: [{
6272
- type: Input
6273
- }] } });
6274
-
6275
- // src/app/layout/layout.component.ts (solo la parte de styles)
6276
- class InfoComponent {
6277
- constructor() {
6278
- this.icon = inject(IconService);
6279
- }
6280
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6281
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: InfoComponent, isStandalone: true, selector: "val-info", inputs: { props: "props" }, ngImport: i0, template: `
6282
- @if (props.image) {
6283
- <val-image style="display: contents;" [props]="props.image" />
6284
- }
6285
- <val-title-block style="display: block;margin-top: 16px;" [props]="props.title" />
7016
+ 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
+ />
6286
7025
 
6287
- @if (props.link) {
6288
- <val-link [props]="props.link" />
6289
- }
7026
+ <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
6290
7027
 
6291
- @if (props.actions) {
6292
- <val-button-group [props]="props.actions" />
6293
- }
6294
- `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LinkComponent, selector: "val-link", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TitleBlockComponent, selector: "val-title-block", inputs: ["props"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }] }); }
7028
+ <ion-modal
7029
+ #modal
7030
+ [initialBreakpoint]="1"
7031
+ [breakpoints]="[0, 0.5, 0.75, 1]"
7032
+ (didDismiss)="cancelModal()"
7033
+ >
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"] }] }); }
6295
7060
  }
6296
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InfoComponent, decorators: [{
7061
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, decorators: [{
6297
7062
  type: Component,
6298
- args: [{ selector: 'val-info', standalone: true, imports: [CommonModule, LinkComponent, TitleBlockComponent, ImageComponent, ButtonGroupComponent], template: `
6299
- @if (props.image) {
6300
- <val-image style="display: contents;" [props]="props.image" />
6301
- }
6302
- <val-title-block style="display: block;margin-top: 16px;" [props]="props.title" />
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
+ />
6303
7071
 
6304
- @if (props.link) {
6305
- <val-link [props]="props.link" />
6306
- }
7072
+ <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
6307
7073
 
6308
- @if (props.actions) {
6309
- <val-button-group [props]="props.actions" />
6310
- }
6311
- ` }]
6312
- }], propDecorators: { props: [{
7074
+ <ion-modal
7075
+ #modal
7076
+ [initialBreakpoint]="1"
7077
+ [breakpoints]="[0, 0.5, 0.75, 1]"
7078
+ (didDismiss)="cancelModal()"
7079
+ >
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: [{
7107
+ type: ViewChild,
7108
+ args: ['modal']
7109
+ }], label: [{
7110
+ type: Input
7111
+ }], labelProperty: [{
7112
+ type: Input
7113
+ }], valueProperty: [{
7114
+ type: Input
7115
+ }], multiple: [{
7116
+ type: Input
7117
+ }], placeholder: [{
7118
+ type: Input
7119
+ }], props: [{
6313
7120
  type: Input
6314
7121
  }] } });
6315
7122
 
6316
- class PlainCodeBoxComponent {
7123
+ /**
7124
+ * val-text-input
7125
+ *
7126
+ * A text input field integrated with Angular forms.
7127
+ *
7128
+ * @example
7129
+ * <val-text-input [props]="{ control: myControl, placeholder: 'Enter text', ... }"></val-text-input>
7130
+ *
7131
+ * @input props: InputMetadata - Configuration for the input (form control, placeholder, label, etc.)
7132
+ */
7133
+ class TextInputComponent {
6317
7134
  constructor() {
6318
- this.toast = inject(ToastController);
6319
- this.cdr = inject(ChangeDetectorRef);
6320
- this.langService = inject(LangService);
6321
- this.props = { lines: [] };
6322
- }
6323
- ngOnChanges(changes) {
6324
- if (changes['props'] && !changes['props'].firstChange) {
6325
- this.cdr.detectChanges();
6326
- setTimeout(() => this.highlightCode());
6327
- }
6328
- }
6329
- ngAfterViewInit() {
6330
- setTimeout(() => this.highlightCode());
6331
- }
6332
- highlightCode() {
6333
- if (this.codeBlock && this.props.lines && this.props.lines.length > 0) {
6334
- Prism.highlightElement(this.codeBlock.nativeElement);
6335
- }
7135
+ this.states = ComponentStates;
6336
7136
  }
6337
- async copyCode() {
6338
- const fullCode = this.props.lines.map(line => line.text).join('\n');
6339
- if (fullCode) {
6340
- await Clipboard.write({
6341
- string: fullCode,
6342
- });
6343
- const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
6344
- this.presentToast(copiedMessage);
7137
+ ngOnInit() {
7138
+ // Apply default values on initialization
7139
+ if (this.props?.withDefault || this.props?.value) {
7140
+ applyDefaultValueToControl(this.props);
6345
7141
  }
6346
7142
  }
6347
- async presentToast(message) {
6348
- const toast = await this.toast.create({
6349
- message: message,
6350
- duration: 2000,
6351
- position: 'bottom',
6352
- color: 'dark',
6353
- });
6354
- toast.present();
6355
- }
6356
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlainCodeBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6357
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PlainCodeBoxComponent, isStandalone: true, selector: "val-plain-code-box", inputs: { props: "props" }, viewQueries: [{ propertyName: "codeBlock", first: true, predicate: ["codeBlock"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
6358
- <div class="code-box-container">
6359
- <ion-button *ngIf="props.showCopyButton !== false" fill="clear" class="copy-button" (click)="copyCode()">
6360
- <ion-icon name="copy-outline"></ion-icon>
6361
- </ion-button>
6362
- <pre><code [class]="'language-' + (props.language || 'bash')" #codeBlock><ng-container *ngFor="let line of props.lines; let i = index"><span [class]="line.type ? 'line-' + line.type : 'line-normal'">{{ line.text }}</span><br *ngIf="i < props.lines.length - 1">
6363
- </ng-container></code></pre>
6364
- </div>
6365
- `, isInline: true, styles: [".code-box-container{position:relative;background-color:#282c34;border-radius:16px;overflow:hidden;box-shadow:0 4px 15px #0009;margin:0}@media (prefers-color-scheme: light){.code-box-container{background-color:#fff;box-shadow:0 2px 4px #0000001a}}.copy-button{position:absolute;top:8px;right:8px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:#61afef;background:#0006;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease,color .2s ease}.copy-button:hover{background:#00000080;color:#8cc4ff}.copy-button ion-icon{font-size:1.2em;margin:0}@media (prefers-color-scheme: light){.copy-button{color:var(--ion-color-primary, #007bff);background:#ffffffb3}.copy-button:hover{background:#ffffffe6;color:var(--ion-color-primary-tint, #3880ff)}}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre-wrap;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.6;display:block;white-space:inherit;word-break:inherit;color:#abb2bf;margin:0}@media (prefers-color-scheme: light){code{color:#333}}code .line-normal{color:#abb2bf}@media (prefers-color-scheme: light){code .line-normal{color:#333}}code .line-command{color:#c678dd}@media (prefers-color-scheme: light){code .line-command{color:var(--ion-color-primary, #3880ff)}}code .line-error{color:#e06c75}@media (prefers-color-scheme: light){code .line-error{color:var(--ion-color-danger, #eb445a)}}code .line-success{color:#98c379}@media (prefers-color-scheme: light){code .line-success{color:var(--ion-color-success, #2dd36f)}}code .token.comment{color:#5c6370}code .token.selector,code .token.string{color:#98c379}code .token.punctuation{color:#abb2bf}code .token.operator{color:#c678dd}code .token.boolean,code .token.number{color:#d19a66}code .token.function{color:#61afef}code .token.keyword{color:#c678dd}code .token.class-name{color:#e6c07b}code .token.tag{color:#e06c75}code .token.attr-name{color:#d19a66}code .token.attr-value{color:#98c379}code .token.property{color:#56b6c2}code .token.variable{color:#e06c75}@media (max-width: 600px){.code-box-container{border-radius:16px}.copy-button{top:6px;right:6px;min-width:24px;min-height:24px;height:24px;width:24px}.copy-button ion-icon{font-size:1em}pre{padding:0;margin:0}code{font-size:.8em;line-height:1.5;margin:0}}@media (min-width: 601px) and (max-width: 1024px){code{font-size:.9em}}@media (min-width: 1025px){code{font-size:1em}}\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: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] }); }
7143
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7144
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TextInputComponent, isStandalone: true, selector: "val-text-input", inputs: { props: "props" }, ngImport: i0, template: ` <ion-input [formControl]="props.control" type="text" [placeholder]="props.placeholder" /> `, 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: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "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", "size", "spellcheck", "step", "type", "value"] }] }); }
6366
7145
  }
6367
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlainCodeBoxComponent, decorators: [{
7146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextInputComponent, decorators: [{
6368
7147
  type: Component,
6369
- args: [{ selector: 'val-plain-code-box', standalone: true, imports: [CommonModule, IonIcon, IonButton], template: `
6370
- <div class="code-box-container">
6371
- <ion-button *ngIf="props.showCopyButton !== false" fill="clear" class="copy-button" (click)="copyCode()">
6372
- <ion-icon name="copy-outline"></ion-icon>
6373
- </ion-button>
6374
- <pre><code [class]="'language-' + (props.language || 'bash')" #codeBlock><ng-container *ngFor="let line of props.lines; let i = index"><span [class]="line.type ? 'line-' + line.type : 'line-normal'">{{ line.text }}</span><br *ngIf="i < props.lines.length - 1">
6375
- </ng-container></code></pre>
6376
- </div>
6377
- `, styles: [".code-box-container{position:relative;background-color:#282c34;border-radius:16px;overflow:hidden;box-shadow:0 4px 15px #0009;margin:0}@media (prefers-color-scheme: light){.code-box-container{background-color:#fff;box-shadow:0 2px 4px #0000001a}}.copy-button{position:absolute;top:8px;right:8px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:#61afef;background:#0006;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease,color .2s ease}.copy-button:hover{background:#00000080;color:#8cc4ff}.copy-button ion-icon{font-size:1.2em;margin:0}@media (prefers-color-scheme: light){.copy-button{color:var(--ion-color-primary, #007bff);background:#ffffffb3}.copy-button:hover{background:#ffffffe6;color:var(--ion-color-primary-tint, #3880ff)}}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre-wrap;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.6;display:block;white-space:inherit;word-break:inherit;color:#abb2bf;margin:0}@media (prefers-color-scheme: light){code{color:#333}}code .line-normal{color:#abb2bf}@media (prefers-color-scheme: light){code .line-normal{color:#333}}code .line-command{color:#c678dd}@media (prefers-color-scheme: light){code .line-command{color:var(--ion-color-primary, #3880ff)}}code .line-error{color:#e06c75}@media (prefers-color-scheme: light){code .line-error{color:var(--ion-color-danger, #eb445a)}}code .line-success{color:#98c379}@media (prefers-color-scheme: light){code .line-success{color:var(--ion-color-success, #2dd36f)}}code .token.comment{color:#5c6370}code .token.selector,code .token.string{color:#98c379}code .token.punctuation{color:#abb2bf}code .token.operator{color:#c678dd}code .token.boolean,code .token.number{color:#d19a66}code .token.function{color:#61afef}code .token.keyword{color:#c678dd}code .token.class-name{color:#e6c07b}code .token.tag{color:#e06c75}code .token.attr-name{color:#d19a66}code .token.attr-value{color:#98c379}code .token.property{color:#56b6c2}code .token.variable{color:#e06c75}@media (max-width: 600px){.code-box-container{border-radius:16px}.copy-button{top:6px;right:6px;min-width:24px;min-height:24px;height:24px;width:24px}.copy-button ion-icon{font-size:1em}pre{padding:0;margin:0}code{font-size:.8em;line-height:1.5;margin:0}}@media (min-width: 601px) and (max-width: 1024px){code{font-size:.9em}}@media (min-width: 1025px){code{font-size:1em}}\n"] }]
7148
+ args: [{ selector: 'val-text-input', standalone: true, imports: [ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="props.control" type="text" [placeholder]="props.placeholder" /> `, 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"] }]
6378
7149
  }], ctorParameters: () => [], propDecorators: { props: [{
6379
7150
  type: Input
6380
- }], codeBlock: [{
6381
- type: ViewChild,
6382
- args: ['codeBlock']
6383
7151
  }] } });
6384
7152
 
6385
7153
  /**
@@ -7360,539 +8128,156 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7360
8128
  type: Component,
7361
8129
  args: [{ selector: 'val-footer', standalone: true, imports: [CommonModule, IonFooter, ToolbarComponent], template: `
7362
8130
  <ion-footer
7363
- [class.ion-no-border]="!props.bordered"
7364
- [translucent]="props.translucent"
7365
- [class.background]="props.toolbar.color === 'background'"
7366
- >
7367
- <val-toolbar
7368
- *ngIf="props.toolbar.title || props.toolbar.withActions || props.toolbar.withBack"
7369
- [props]="props.toolbar"
7370
- (onClick)="clickHandler($event)"
7371
- ></val-toolbar>
7372
- <ng-content select="[extra]"></ng-content>
7373
- </ion-footer>
7374
- `, styles: [".background{background:var(--ion-background-color)}\n"] }]
7375
- }], ctorParameters: () => [], propDecorators: { props: [{
7376
- type: Input
7377
- }], onClick: [{
7378
- type: Output
7379
- }] } });
7380
-
7381
- const maxLength = (field, max) => {
7382
- return {
7383
- validator: Validators.maxLength(max),
7384
- error: `El campo ${field} no debe superar los ${max} caracteres.`,
7385
- };
7386
- };
7387
- const createNumberFromToField = (name, label, fromLabel, toLabel, options) => {
7388
- return {
7389
- control: null, // Will be set by form component
7390
- token: `number-from-to-${name}`,
7391
- label,
7392
- name,
7393
- hint: options?.hint || '',
7394
- placeholder: '',
7395
- type: InputType.NUMBER_FROM_TO,
7396
- order: options?.order || 0,
7397
- validators: options?.validators || [],
7398
- range: options?.range,
7399
- errors: {},
7400
- state: ComponentStates.ENABLED,
7401
- fromLabel,
7402
- toLabel,
7403
- fromPlaceholder: options?.fromPlaceholder,
7404
- toPlaceholder: options?.toPlaceholder,
7405
- };
7406
- };
7407
-
7408
- class FormFooterComponent {
7409
- constructor() {
7410
- this.onSubmit = new EventEmitter();
7411
- }
7412
- ngOnInit() { }
7413
- async submitHandler(token) {
7414
- this.onSubmit.emit({ fields: this.props.form.value, token });
7415
- }
7416
- get actions() {
7417
- if (!this.props.form) {
7418
- return [];
7419
- }
7420
- if (this.props.form.valid) {
7421
- this.props.data.actions.state = ComponentStates.ENABLED;
7422
- }
7423
- if (this.props.data.state === ComponentStates.WORKING) {
7424
- this.props.data.actions.state = ComponentStates.WORKING;
7425
- }
7426
- if (this.props.data.state === ComponentStates.ENABLED) {
7427
- this.props.data.actions.state = ComponentStates.ENABLED;
7428
- }
7429
- if (this.props.data.state === ComponentStates.DISABLED) {
7430
- this.props.data.actions.state = ComponentStates.DISABLED;
7431
- }
7432
- return [this.props.data.actions];
7433
- }
7434
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7435
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FormFooterComponent, isStandalone: true, selector: "val-form-footer", inputs: { props: "props" }, outputs: { onSubmit: "onSubmit" }, ngImport: i0, template: `
7436
- <val-footer
7437
- [props]="{
7438
- bordered: false,
7439
- translucent: false,
7440
- toolbar: {
7441
- title: '',
7442
- actions: [],
7443
- color: 'background',
7444
- withBack: false,
7445
- withActions: false,
7446
- },
7447
- }"
7448
- >
7449
- <val-button-group
7450
- extra
7451
- [props]="{ buttons: actions, position: 'center', columned: false }"
7452
- (onClick)="submitHandler($event)"
7453
- ></val-button-group>
7454
- </val-footer>
7455
- `, isInline: true, styles: [""], dependencies: [{ kind: "component", type: FooterComponent, selector: "val-footer", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }] }); }
7456
- }
7457
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormFooterComponent, decorators: [{
7458
- type: Component,
7459
- args: [{ selector: 'val-form-footer', standalone: true, imports: [FooterComponent, ButtonGroupComponent], template: `
7460
- <val-footer
7461
- [props]="{
7462
- bordered: false,
7463
- translucent: false,
7464
- toolbar: {
7465
- title: '',
7466
- actions: [],
7467
- color: 'background',
7468
- withBack: false,
7469
- withActions: false,
7470
- },
7471
- }"
8131
+ [class.ion-no-border]="!props.bordered"
8132
+ [translucent]="props.translucent"
8133
+ [class.background]="props.toolbar.color === 'background'"
7472
8134
  >
7473
- <val-button-group
7474
- extra
7475
- [props]="{ buttons: actions, position: 'center', columned: false }"
7476
- (onClick)="submitHandler($event)"
7477
- ></val-button-group>
7478
- </val-footer>
7479
- ` }]
8135
+ <val-toolbar
8136
+ *ngIf="props.toolbar.title || props.toolbar.withActions || props.toolbar.withBack"
8137
+ [props]="props.toolbar"
8138
+ (onClick)="clickHandler($event)"
8139
+ ></val-toolbar>
8140
+ <ng-content select="[extra]"></ng-content>
8141
+ </ion-footer>
8142
+ `, styles: [".background{background:var(--ion-background-color)}\n"] }]
7480
8143
  }], ctorParameters: () => [], propDecorators: { props: [{
7481
8144
  type: Input
7482
- }], onSubmit: [{
8145
+ }], onClick: [{
7483
8146
  type: Output
7484
8147
  }] } });
7485
8148
 
7486
- /**
7487
- * Scrolls smoothly to the top of the element with the given id.
7488
- * @param id The id of the element to scroll to
7489
- */
7490
- const goToTop = (id) => {
7491
- const element = document.getElementById(id);
7492
- if (element) {
7493
- element.scrollIntoView({
7494
- block: 'start',
7495
- inline: 'nearest',
7496
- behavior: 'smooth',
7497
- });
7498
- }
8149
+ const maxLength = (field, max) => {
8150
+ return {
8151
+ validator: Validators.maxLength(max),
8152
+ error: `El campo ${field} no debe superar los ${max} caracteres.`,
8153
+ };
7499
8154
  };
7500
- /**
7501
- * Checks if the bottom of the given ElementRef is within the viewport.
7502
- * Useful for determining if a form or element is fully visible.
7503
- * @param elementRef The Angular ElementRef to check
7504
- * @returns True if the element's bottom is at or above the window's bottom
7505
- */
7506
- const isAtEnd = (elementRef) => {
7507
- const formElement = elementRef.nativeElement;
7508
- const rect = formElement.getBoundingClientRect();
7509
- const windowHeight = window.innerHeight;
7510
- return rect.bottom <= windowHeight;
8155
+ const createNumberFromToField = (name, label, fromLabel, toLabel, options) => {
8156
+ return {
8157
+ control: null, // Will be set by form component
8158
+ token: `number-from-to-${name}`,
8159
+ label,
8160
+ name,
8161
+ hint: options?.hint || '',
8162
+ placeholder: '',
8163
+ type: InputType.NUMBER_FROM_TO,
8164
+ order: options?.order || 0,
8165
+ validators: options?.validators || [],
8166
+ range: options?.range,
8167
+ errors: {},
8168
+ state: ComponentStates.ENABLED,
8169
+ fromLabel,
8170
+ toLabel,
8171
+ fromPlaceholder: options?.fromPlaceholder,
8172
+ toPlaceholder: options?.toPlaceholder,
8173
+ };
7511
8174
  };
7512
8175
 
7513
- class MultiSelectSearchComponent {
8176
+ class FormFooterComponent {
7514
8177
  constructor() {
7515
- this.labelProperty = 'name';
7516
- this.valueProperty = 'id';
7517
- this.langService = inject(LangService);
7518
- this.icon = inject(IconService);
7519
- this.changeDetector = inject(ChangeDetectorRef);
7520
- this.searchTerm = '';
7521
- this.filteredItems = [];
7522
- this.selectedItems = [];
7523
- this.tempSelectedItems = [];
7524
- this.displayValue = '';
7525
- this.previousOptions = [];
7526
- this.isProcessingChanges = false;
7527
- this.label = this.langService.getText('_global', 'selectMultiple', 'Seleccionar múltiples');
7528
- this.placeholder = this.langService.getText('_global', 'selectOptions', 'Seleccione opciones');
7529
- }
7530
- ngOnInit() {
7531
- this.applyDefaultValue();
7532
- this.initializeItems();
7533
- this.syncControlValueWithSelectedItems();
7534
- this.updateDisplayValue();
7535
- this.subscribeToValueChanges();
7536
- }
7537
- ngOnDestroy() {
7538
- if (this.valueChangesSubscription) {
7539
- this.valueChangesSubscription.unsubscribe();
7540
- }
7541
- }
7542
- ngOnChanges(changes) {
7543
- if (this.isProcessingChanges) {
7544
- return;
7545
- }
7546
- if (changes['props']) {
7547
- try {
7548
- this.isProcessingChanges = true;
7549
- if (this.valueChangesSubscription) {
7550
- this.valueChangesSubscription.unsubscribe();
7551
- }
7552
- if (this.props?.options) {
7553
- const optionsChanged = !this.areOptionsEqual(this.previousOptions, this.props.options);
7554
- if (optionsChanged) {
7555
- this.previousOptions = [...this.props.options];
7556
- this.initializeItems();
7557
- }
7558
- }
7559
- this.syncControlValueWithSelectedItems();
7560
- this.updateDisplayValue();
7561
- this.subscribeToValueChanges();
7562
- }
7563
- finally {
7564
- this.isProcessingChanges = false;
7565
- }
7566
- }
7567
- }
7568
- ionViewWillEnter() {
7569
- if (this.isProcessingChanges) {
7570
- return;
7571
- }
7572
- try {
7573
- this.isProcessingChanges = true;
7574
- this.initializeItems();
7575
- this.syncControlValueWithSelectedItems();
7576
- this.updateDisplayValue();
7577
- this.subscribeToValueChanges();
7578
- }
7579
- finally {
7580
- this.isProcessingChanges = false;
7581
- }
7582
- }
7583
- subscribeToValueChanges() {
7584
- if (!this.props?.control)
7585
- return;
7586
- this.valueChangesSubscription = this.props.control.valueChanges.subscribe(() => {
7587
- if (this.isProcessingChanges)
7588
- return;
7589
- try {
7590
- this.isProcessingChanges = true;
7591
- this.syncControlValueWithSelectedItems();
7592
- this.updateDisplayValue();
7593
- }
7594
- finally {
7595
- this.isProcessingChanges = false;
7596
- }
7597
- });
7598
- }
7599
- areOptionsEqual(prevOptions, newOptions) {
7600
- if (prevOptions === newOptions)
7601
- return true;
7602
- if (!prevOptions || !newOptions)
7603
- return prevOptions === newOptions;
7604
- if (prevOptions.length !== newOptions.length)
7605
- return false;
7606
- for (let i = 0; i < prevOptions.length; i++) {
7607
- if (prevOptions[i][this.valueProperty] !== newOptions[i][this.valueProperty]) {
7608
- return false;
7609
- }
7610
- }
7611
- return true;
7612
- }
7613
- initializeItems() {
7614
- this.filteredItems = this.props?.options || [];
7615
- }
7616
- syncControlValueWithSelectedItems() {
7617
- if (!this.props?.control) {
7618
- this.selectedItems = [];
7619
- return;
7620
- }
7621
- const controlValue = this.props.control.value;
7622
- if (!Array.isArray(controlValue) || controlValue.length === 0) {
7623
- this.selectedItems = [];
7624
- return;
7625
- }
7626
- if (this.props.options && this.props.options.length > 0) {
7627
- const map = new Map(this.props.options.map(opt => [opt[this.valueProperty], opt]));
7628
- this.selectedItems = controlValue
7629
- .map(value => map.get(value))
7630
- .filter(item => item !== undefined);
7631
- }
7632
- else {
7633
- this.selectedItems = [];
7634
- }
7635
- }
7636
- applyDefaultValue() {
7637
- applyDefaultValueToControl(this.props);
7638
- }
7639
- onFilter(event) {
7640
- if (!event || event.trim() === '') {
7641
- this.filteredItems = this.props?.options ? [...this.props.options] : [];
7642
- this.changeDetector.detectChanges();
7643
- return;
7644
- }
7645
- if (!this.props?.options || this.props.options.length === 0) {
7646
- this.filteredItems = [];
7647
- this.changeDetector.detectChanges();
7648
- return;
7649
- }
7650
- const search = replaceSpecialChars(event.toLowerCase());
7651
- this.filteredItems = this.props.options.filter(element => {
7652
- const label = element[this.labelProperty]
7653
- ? replaceSpecialChars(String(element[this.labelProperty]).toLowerCase())
7654
- : '';
7655
- const value = element[this.valueProperty]
7656
- ? replaceSpecialChars(String(element[this.valueProperty]).toLowerCase())
7657
- : '';
7658
- return label.includes(search) || value.includes(search);
7659
- });
7660
- this.changeDetector.detectChanges();
7661
- }
7662
- onFocus() {
7663
- console.log('onFocus');
7664
- }
7665
- onBlur() {
7666
- console.log('onBlur');
7667
- }
7668
- openModal() {
7669
- this.syncControlValueWithSelectedItems();
7670
- this.tempSelectedItems = [...this.selectedItems];
7671
- this.updateDisplayValue();
7672
- if (this.modal) {
7673
- this.modal.present();
7674
- }
7675
- }
7676
- preventDefaultBehavior(event) {
7677
- event.preventDefault();
7678
- event.stopPropagation();
7679
- this.openModal();
7680
- }
7681
- cancelModal() {
7682
- // Reset filter and show all options when closing modal
7683
- this.searchTerm = '';
7684
- this.filteredItems = this.props?.options ? [...this.props.options] : [];
7685
- this.changeDetector.detectChanges();
7686
- if (this.modal) {
7687
- this.modal.dismiss();
7688
- }
7689
- }
7690
- selectItem(item) {
7691
- console.log('selectItem called with:', item);
7692
- const index = this.tempSelectedItems.findIndex(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
7693
- if (index === -1) {
7694
- this.tempSelectedItems.push(item);
7695
- console.log('Item added, tempSelectedItems:', this.tempSelectedItems);
7696
- }
7697
- else {
7698
- this.tempSelectedItems.splice(index, 1);
7699
- console.log('Item removed, tempSelectedItems:', this.tempSelectedItems);
7700
- }
7701
- }
7702
- isItemSelected(item) {
7703
- return this.tempSelectedItems.some(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
7704
- }
7705
- clearSelection() {
7706
- this.tempSelectedItems = [];
8178
+ this.onSubmit = new EventEmitter();
7707
8179
  }
7708
- applySelection() {
7709
- console.log('applySelection called, tempSelectedItems:', this.tempSelectedItems);
7710
- this.selectedItems = [...this.tempSelectedItems];
7711
- this.updateDisplayValue();
7712
- console.log('About to call applyChanges with selectedItems:', this.selectedItems);
7713
- this.applyChanges();
7714
- this.cancelModal();
8180
+ ngOnInit() { }
8181
+ async submitHandler(token) {
8182
+ this.onSubmit.emit({ fields: this.props.form.value, token });
7715
8183
  }
7716
- updateDisplayValue() {
7717
- if (this.selectedItems.length === 0) {
7718
- this.displayValue = '';
7719
- return;
7720
- }
7721
- if (this.selectedItems.length === 1) {
7722
- this.displayValue = this.selectedItems[0][this.labelProperty];
7723
- }
7724
- else {
7725
- this.displayValue = `${this.selectedItems.length} elementos seleccionados`;
8184
+ get actions() {
8185
+ if (!this.props.form) {
8186
+ return [];
7726
8187
  }
7727
- }
7728
- applyChanges() {
7729
- console.log('applyChanges called, props.control exists:', !!this.props?.control);
7730
- if (!this.props?.control) {
7731
- console.log('No control found, exiting applyChanges');
7732
- return;
8188
+ if (this.props.form.valid) {
8189
+ this.props.data.actions.state = ComponentStates.ENABLED;
7733
8190
  }
7734
- try {
7735
- this.isProcessingChanges = true;
7736
- const values = this.selectedItems.map(item => item[this.valueProperty]);
7737
- console.log('Setting control value to:', values);
7738
- this.props.control.setValue(values);
7739
- this.props.control.markAsDirty();
7740
- this.props.control.updateValueAndValidity();
7741
- console.log('Control value after setValue:', this.props.control.value);
8191
+ if (this.props.data.state === ComponentStates.WORKING) {
8192
+ this.props.data.actions.state = ComponentStates.WORKING;
7742
8193
  }
7743
- finally {
7744
- this.isProcessingChanges = false;
8194
+ if (this.props.data.state === ComponentStates.ENABLED) {
8195
+ this.props.data.actions.state = ComponentStates.ENABLED;
7745
8196
  }
7746
- }
7747
- reset() {
7748
- this.selectedItems = [];
7749
- this.displayValue = '';
7750
- if (this.props?.control) {
7751
- this.props.control.setValue([]);
8197
+ if (this.props.data.state === ComponentStates.DISABLED) {
8198
+ this.props.data.actions.state = ComponentStates.DISABLED;
7752
8199
  }
7753
- this.changeDetector.detectChanges();
8200
+ return [this.props.data.actions];
7754
8201
  }
7755
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7756
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MultiSelectSearchComponent, isStandalone: true, selector: "val-multi-select-search", inputs: { label: "label", labelProperty: "labelProperty", valueProperty: "valueProperty", placeholder: "placeholder", props: "props" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
7757
- <ion-input
7758
- type="text"
7759
- [value]="displayValue"
7760
- [placeholder]="props?.placeholder || placeholder"
7761
- readonly
7762
- (mousedown)="preventDefaultBehavior($event)"
7763
- />
7764
-
7765
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
7766
-
7767
- <ion-modal
7768
- #modal
7769
- [initialBreakpoint]="1"
7770
- [breakpoints]="[0, 0.5, 0.75, 1]"
7771
- (didDismiss)="cancelModal()"
8202
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8203
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FormFooterComponent, isStandalone: true, selector: "val-form-footer", inputs: { props: "props" }, outputs: { onSubmit: "onSubmit" }, ngImport: i0, template: `
8204
+ <val-footer
8205
+ [props]="{
8206
+ bordered: false,
8207
+ translucent: false,
8208
+ toolbar: {
8209
+ title: '',
8210
+ actions: [],
8211
+ color: 'background',
8212
+ withBack: false,
8213
+ withActions: false,
8214
+ },
8215
+ }"
7772
8216
  >
7773
- <ng-template>
7774
- <ion-header>
7775
- <ion-toolbar>
7776
- <ion-title>{{ label }}</ion-title>
7777
- <ion-buttons slot="end">
7778
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
7779
- </ion-buttons>
7780
- </ion-toolbar>
7781
- <ion-toolbar>
7782
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
7783
- </ion-toolbar>
7784
- </ion-header>
7785
- <ion-content>
7786
- <ion-item *ngIf="tempSelectedItems.length > 0" lines="none" color="light">
7787
- <ion-icon name="checkmark-circle-outline" slot="start" color="success"></ion-icon>
7788
- <ion-label>
7789
- <h3>{{ tempSelectedItems.length }} item{{ tempSelectedItems.length === 1 ? '' : 's' }} seleccionado{{ tempSelectedItems.length === 1 ? '' : 's' }}</h3>
7790
- </ion-label>
7791
- </ion-item>
7792
- <ion-list>
7793
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
7794
- <ion-checkbox
7795
- [checked]="isItemSelected(item)"
7796
- slot="start"
7797
- [disabled]="true"
7798
- ></ion-checkbox>
7799
- <ion-label>{{ item[labelProperty] }}</ion-label>
7800
- </ion-item>
7801
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
7802
- <ion-label color="dark">No se encontraron resultados</ion-label>
7803
- </ion-item>
7804
- </ion-list>
7805
- </ion-content>
7806
- <ion-footer *ngIf="tempSelectedItems.length > 0">
7807
- <ion-toolbar>
7808
- <ion-buttons slot="end">
7809
- <ion-button (click)="clearSelection()">Limpiar</ion-button>
7810
- <ion-button fill="solid" (click)="applySelection()">Aplicar ({{ tempSelectedItems.length }})</ion-button>
7811
- </ion-buttons>
7812
- </ion-toolbar>
7813
- </ion-footer>
7814
- </ng-template>
7815
- </ion-modal>
7816
- `, 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.IonCheckbox, selector: "ion-checkbox", inputs: ["alignment", "checked", "color", "disabled", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: i2.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { 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.BooleanValueAccessor, selector: "ion-checkbox,ion-toggle" }, { 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"] }] }); }
8217
+ <val-button-group
8218
+ extra
8219
+ [props]="{ buttons: actions, position: 'center', columned: false }"
8220
+ (onClick)="submitHandler($event)"
8221
+ ></val-button-group>
8222
+ </val-footer>
8223
+ `, isInline: true, styles: [""], dependencies: [{ kind: "component", type: FooterComponent, selector: "val-footer", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: ButtonGroupComponent, selector: "val-button-group", inputs: ["props"], outputs: ["onClick"] }] }); }
7817
8224
  }
7818
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectSearchComponent, decorators: [{
8225
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormFooterComponent, decorators: [{
7819
8226
  type: Component,
7820
- args: [{ selector: 'val-multi-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, SearchbarComponent, ReactiveFormsModule], template: `
7821
- <ion-input
7822
- type="text"
7823
- [value]="displayValue"
7824
- [placeholder]="props?.placeholder || placeholder"
7825
- readonly
7826
- (mousedown)="preventDefaultBehavior($event)"
7827
- />
7828
-
7829
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
7830
-
7831
- <ion-modal
7832
- #modal
7833
- [initialBreakpoint]="1"
7834
- [breakpoints]="[0, 0.5, 0.75, 1]"
7835
- (didDismiss)="cancelModal()"
8227
+ args: [{ selector: 'val-form-footer', standalone: true, imports: [FooterComponent, ButtonGroupComponent], template: `
8228
+ <val-footer
8229
+ [props]="{
8230
+ bordered: false,
8231
+ translucent: false,
8232
+ toolbar: {
8233
+ title: '',
8234
+ actions: [],
8235
+ color: 'background',
8236
+ withBack: false,
8237
+ withActions: false,
8238
+ },
8239
+ }"
7836
8240
  >
7837
- <ng-template>
7838
- <ion-header>
7839
- <ion-toolbar>
7840
- <ion-title>{{ label }}</ion-title>
7841
- <ion-buttons slot="end">
7842
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
7843
- </ion-buttons>
7844
- </ion-toolbar>
7845
- <ion-toolbar>
7846
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
7847
- </ion-toolbar>
7848
- </ion-header>
7849
- <ion-content>
7850
- <ion-item *ngIf="tempSelectedItems.length > 0" lines="none" color="light">
7851
- <ion-icon name="checkmark-circle-outline" slot="start" color="success"></ion-icon>
7852
- <ion-label>
7853
- <h3>{{ tempSelectedItems.length }} item{{ tempSelectedItems.length === 1 ? '' : 's' }} seleccionado{{ tempSelectedItems.length === 1 ? '' : 's' }}</h3>
7854
- </ion-label>
7855
- </ion-item>
7856
- <ion-list>
7857
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
7858
- <ion-checkbox
7859
- [checked]="isItemSelected(item)"
7860
- slot="start"
7861
- [disabled]="true"
7862
- ></ion-checkbox>
7863
- <ion-label>{{ item[labelProperty] }}</ion-label>
7864
- </ion-item>
7865
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
7866
- <ion-label color="dark">No se encontraron resultados</ion-label>
7867
- </ion-item>
7868
- </ion-list>
7869
- </ion-content>
7870
- <ion-footer *ngIf="tempSelectedItems.length > 0">
7871
- <ion-toolbar>
7872
- <ion-buttons slot="end">
7873
- <ion-button (click)="clearSelection()">Limpiar</ion-button>
7874
- <ion-button fill="solid" (click)="applySelection()">Aplicar ({{ tempSelectedItems.length }})</ion-button>
7875
- </ion-buttons>
7876
- </ion-toolbar>
7877
- </ion-footer>
7878
- </ng-template>
7879
- </ion-modal>
7880
- `, styles: ["ion-header{padding:8px 8px 0}\n"] }]
7881
- }], ctorParameters: () => [], propDecorators: { modal: [{
7882
- type: ViewChild,
7883
- args: ['modal']
7884
- }], label: [{
7885
- type: Input
7886
- }], labelProperty: [{
7887
- type: Input
7888
- }], valueProperty: [{
7889
- type: Input
7890
- }], placeholder: [{
7891
- type: Input
7892
- }], props: [{
8241
+ <val-button-group
8242
+ extra
8243
+ [props]="{ buttons: actions, position: 'center', columned: false }"
8244
+ (onClick)="submitHandler($event)"
8245
+ ></val-button-group>
8246
+ </val-footer>
8247
+ ` }]
8248
+ }], ctorParameters: () => [], propDecorators: { props: [{
7893
8249
  type: Input
8250
+ }], onSubmit: [{
8251
+ type: Output
7894
8252
  }] } });
7895
8253
 
8254
+ /**
8255
+ * Scrolls smoothly to the top of the element with the given id.
8256
+ * @param id The id of the element to scroll to
8257
+ */
8258
+ const goToTop = (id) => {
8259
+ const element = document.getElementById(id);
8260
+ if (element) {
8261
+ element.scrollIntoView({
8262
+ block: 'start',
8263
+ inline: 'nearest',
8264
+ behavior: 'smooth',
8265
+ });
8266
+ }
8267
+ };
8268
+ /**
8269
+ * Checks if the bottom of the given ElementRef is within the viewport.
8270
+ * Useful for determining if a form or element is fully visible.
8271
+ * @param elementRef The Angular ElementRef to check
8272
+ * @returns True if the element's bottom is at or above the window's bottom
8273
+ */
8274
+ const isAtEnd = (elementRef) => {
8275
+ const formElement = elementRef.nativeElement;
8276
+ const rect = formElement.getBoundingClientRect();
8277
+ const windowHeight = window.innerHeight;
8278
+ return rect.bottom <= windowHeight;
8279
+ };
8280
+
7896
8281
  class FormComponent {
7897
8282
  constructor(fb, elementRef) {
7898
8283
  this.fb = fb;
@@ -7920,7 +8305,7 @@ class FormComponent {
7920
8305
  this.form = this.fb.group(formControls);
7921
8306
  this.props.sections.forEach(section => {
7922
8307
  section.fields
7923
- .filter(x => x.type === this.types.SELECT || x.type === this.types.TEXT || x.type === this.types.SEARCH_SELECT || x.type === this.types.MULTI_SELECT)
8308
+ .filter(x => x.type === this.types.SELECT || x.type === this.types.TEXT || x.type === this.types.SEARCH_SELECT || x.type === this.types.MULTI_SELECT || x.type === this.types.MULTI_SELECT_SIMPLE)
7924
8309
  .forEach(field => {
7925
8310
  this.trackSelectChanges(field.name);
7926
8311
  });
@@ -8071,6 +8456,9 @@ class FormComponent {
8071
8456
  <ng-container *ngIf="f.type === types.MULTI_SELECT">
8072
8457
  <val-multi-select-search [props]="getFieldProp(f)"></val-multi-select-search>
8073
8458
  </ng-container>
8459
+ <ng-container *ngIf="f.type === types.MULTI_SELECT_SIMPLE">
8460
+ <val-multi-select-simple [props]="getFieldProp(f)"></val-multi-select-simple>
8461
+ </ng-container>
8074
8462
  <val-hint [props]="getFieldProp(f)"></val-hint>
8075
8463
  </div>
8076
8464
  <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
@@ -8082,7 +8470,7 @@ class FormComponent {
8082
8470
  ></val-button-group>
8083
8471
  </form>
8084
8472
  </div>
8085
- `, 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: SearchSelectorComponent, selector: "val-select-input", inputs: ["props"] }] }); }
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"] }] }); }
8086
8474
  }
8087
8475
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormComponent, decorators: [{
8088
8476
  type: Component,
@@ -8108,6 +8496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
8108
8496
  PinInputComponent,
8109
8497
  SelectSearchComponent,
8110
8498
  MultiSelectSearchComponent,
8499
+ MultiSelectSimpleComponent,
8111
8500
  SearchSelectorComponent,
8112
8501
  ], template: `
8113
8502
  <div class="container">
@@ -8169,6 +8558,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
8169
8558
  <ng-container *ngIf="f.type === types.MULTI_SELECT">
8170
8559
  <val-multi-select-search [props]="getFieldProp(f)"></val-multi-select-search>
8171
8560
  </ng-container>
8561
+ <ng-container *ngIf="f.type === types.MULTI_SELECT_SIMPLE">
8562
+ <val-multi-select-simple [props]="getFieldProp(f)"></val-multi-select-simple>
8563
+ </ng-container>
8172
8564
  <val-hint [props]="getFieldProp(f)"></val-hint>
8173
8565
  </div>
8174
8566
  <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
@@ -9509,5 +9901,5 @@ function createContentHelper(langService, className) {
9509
9901
  * Generated bundle index. Do not edit.
9510
9902
  */
9511
9903
 
9512
- export { ARTICLE_SPACING, ActionHeaderComponent, ActionType, AlertBoxComponent, ArticleBuilder, ArticleComponent, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, ButtonComponent, ButtonGroupComponent, CardComponent, CardSection, CardType, CheckInputComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentInputComponent, ComponentStates, ContentLoaderComponent, DateInputComponent, DisplayComponent, DividerComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FileInputComponent, FooterComponent, FormComponent, FormFooterComponent, GlobalContent, HeaderComponent, HintComponent, HourInputComponent, HrefComponent, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InfoComponent, InputType, ItemListComponent, LANGUAGES, LangService, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksCakeComponent, LocalStorageService, MOTION, NavigationService, NoContentComponent, NotesBoxComponent, NumberFromToComponent, NumberInputComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PasswordInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProgressBarComponent, ProgressStatusComponent, PrompterComponent, RadioInputComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SelectSearchComponent, SimpleComponent, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, TextComponent, TextContent, TextInputComponent, ThemeOption, ThemeService, TitleBlockComponent, TitleComponent, ToastService, ToolbarActionType, ToolbarComponent, ValtechConfigService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, content, createButtonProps, createContentHelper, createDisplayProps, createNumberFromToField, createReactiveContentMetadata, createTextProps, createTitleProps, extractContentConfig, extractContentConfigWithInterpolation, fromContent, fromContentWithInterpolation, fromMultipleContent, globalContentData, goToTop, interpolateContent, interpolateStaticContent, isAtEnd, maxLength, replaceSpecialChars, resolveColor, resolveInputDefaultValue, shouldUseReactiveContent, shouldUseReactiveContentWithInterpolation };
9904
+ export { ARTICLE_SPACING, ActionHeaderComponent, ActionType, AlertBoxComponent, ArticleBuilder, ArticleComponent, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, ButtonComponent, ButtonGroupComponent, CardComponent, CardSection, CardType, CheckInputComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentInputComponent, ComponentStates, ContentLoaderComponent, DateInputComponent, DisplayComponent, DividerComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FileInputComponent, FooterComponent, FormComponent, FormFooterComponent, GlobalContent, HeaderComponent, HintComponent, HourInputComponent, HrefComponent, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InfoComponent, InputType, ItemListComponent, LANGUAGES, LangService, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksCakeComponent, LocalStorageService, MOTION, MultiSelectSearchComponent, MultiSelectSimpleComponent, NavigationService, NoContentComponent, NotesBoxComponent, NumberFromToComponent, NumberInputComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PasswordInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProgressBarComponent, ProgressStatusComponent, PrompterComponent, RadioInputComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SelectSearchComponent, SimpleComponent, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, TextComponent, TextContent, TextInputComponent, ThemeOption, ThemeService, TitleBlockComponent, TitleComponent, ToastService, ToolbarActionType, ToolbarComponent, ValtechConfigService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, content, createButtonProps, createContentHelper, createDisplayProps, createNumberFromToField, createReactiveContentMetadata, createTextProps, createTitleProps, extractContentConfig, extractContentConfigWithInterpolation, fromContent, fromContentWithInterpolation, fromMultipleContent, globalContentData, goToTop, interpolateContent, interpolateStaticContent, isAtEnd, maxLength, replaceSpecialChars, resolveColor, resolveInputDefaultValue, shouldUseReactiveContent, shouldUseReactiveContentWithInterpolation };
9513
9905
  //# sourceMappingURL=valtech-components.mjs.map