valtech-components 2.0.1035 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/esm2022/lib/components/atoms/box/box.component.mjs +6 -8
  2. package/esm2022/lib/components/atoms/button/factory.mjs +24 -217
  3. package/esm2022/lib/components/atoms/divider/divider.component.mjs +2 -4
  4. package/esm2022/lib/components/atoms/href/href.component.mjs +1 -2
  5. package/esm2022/lib/components/atoms/image/image.component.mjs +36 -3
  6. package/esm2022/lib/components/molecules/action-card/action-card.component.mjs +4 -9
  7. package/esm2022/lib/components/molecules/breadcrumb/breadcrumb.component.mjs +4 -4
  8. package/esm2022/lib/components/molecules/card/card.component.mjs +53 -10
  9. package/esm2022/lib/components/molecules/checkbox-radio-input/checkbox-radio-input.component.mjs +27 -36
  10. package/esm2022/lib/components/molecules/chip-group/chip-group.component.mjs +44 -6
  11. package/esm2022/lib/components/molecules/command-display/command-display.component.mjs +32 -7
  12. package/esm2022/lib/components/molecules/comment/comment.component.mjs +28 -12
  13. package/esm2022/lib/components/molecules/cta-card/cta-card.component.mjs +4 -9
  14. package/esm2022/lib/components/molecules/expandable-text/expandable-text.component.mjs +7 -7
  15. package/esm2022/lib/components/molecules/features-list/features-list.component.mjs +159 -71
  16. package/esm2022/lib/components/molecules/file-input/file-input.component.mjs +7 -3
  17. package/esm2022/lib/components/molecules/hint/hint.component.mjs +30 -5
  18. package/esm2022/lib/components/molecules/pagination/pagination.component.mjs +75 -19
  19. package/esm2022/lib/components/molecules/password-input/password-input.component.mjs +42 -9
  20. package/esm2022/lib/components/molecules/permission-selector/types.mjs +1 -1
  21. package/esm2022/lib/components/molecules/rating/rating.component.mjs +88 -12
  22. package/esm2022/lib/components/molecules/stepper/stepper.component.mjs +15 -7
  23. package/esm2022/lib/components/molecules/text-input/text-input.component.mjs +93 -7
  24. package/esm2022/lib/components/organisms/change-email-modal/change-email-modal.component.mjs +5 -5
  25. package/esm2022/lib/components/organisms/change-password-modal/change-password-modal.component.mjs +4 -4
  26. package/esm2022/lib/components/organisms/form/form.component.mjs +62 -20
  27. package/esm2022/lib/components/organisms/login/login.component.mjs +8 -8
  28. package/esm2022/lib/components/organisms/mfa-modal/mfa-modal.component.mjs +3 -3
  29. package/esm2022/lib/components/types.mjs +1 -1
  30. package/esm2022/lib/services/presets/default-presets.mjs +45 -0
  31. package/esm2022/lib/services/presets/index.mjs +3 -1
  32. package/esm2022/lib/services/presets/preset.service.mjs +17 -4
  33. package/esm2022/lib/services/requests/request-form-builder.service.mjs +8 -3
  34. package/esm2022/lib/shared/utils/ionic-color.mjs +36 -0
  35. package/esm2022/lib/version.mjs +2 -2
  36. package/esm2022/public-api.mjs +2 -8
  37. package/fesm2022/valtech-components.mjs +1138 -1022
  38. package/fesm2022/valtech-components.mjs.map +1 -1
  39. package/lib/components/atoms/box/box.component.d.ts +2 -5
  40. package/lib/components/atoms/button/factory.d.ts +15 -69
  41. package/lib/components/atoms/divider/divider.component.d.ts +1 -4
  42. package/lib/components/atoms/href/href.component.d.ts +2 -3
  43. package/lib/components/atoms/image/image.component.d.ts +5 -0
  44. package/lib/components/molecules/action-card/action-card.component.d.ts +1 -1
  45. package/lib/components/molecules/card/card.component.d.ts +2 -1
  46. package/lib/components/molecules/checkbox-radio-input/checkbox-radio-input.component.d.ts +2 -3
  47. package/lib/components/molecules/chip-group/chip-group.component.d.ts +5 -0
  48. package/lib/components/molecules/command-display/command-display.component.d.ts +4 -0
  49. package/lib/components/molecules/comment/comment.component.d.ts +3 -0
  50. package/lib/components/molecules/cta-card/cta-card.component.d.ts +0 -1
  51. package/lib/components/molecules/hint/hint.component.d.ts +11 -1
  52. package/lib/components/molecules/pagination/pagination.component.d.ts +5 -0
  53. package/lib/components/molecules/password-input/password-input.component.d.ts +4 -2
  54. package/lib/components/molecules/permission-selector/types.d.ts +1 -0
  55. package/lib/components/molecules/rating/rating.component.d.ts +11 -0
  56. package/lib/components/molecules/text-input/text-input.component.d.ts +21 -0
  57. package/lib/components/organisms/form/form.component.d.ts +19 -0
  58. package/lib/components/types.d.ts +21 -1
  59. package/lib/services/presets/default-presets.d.ts +22 -0
  60. package/lib/services/presets/index.d.ts +1 -0
  61. package/lib/services/presets/preset.service.d.ts +4 -0
  62. package/lib/shared/utils/ionic-color.d.ts +20 -0
  63. package/lib/version.d.ts +1 -1
  64. package/package.json +1 -1
  65. package/public-api.d.ts +1 -7
  66. package/src/lib/components/styles/mixins.scss +16 -0
  67. package/esm2022/lib/components/molecules/content-card/content-card.component.mjs +0 -86
  68. package/esm2022/lib/components/molecules/content-card/types.mjs +0 -11
  69. package/esm2022/lib/components/molecules/email-input/email-input.component.mjs +0 -68
  70. package/esm2022/lib/components/molecules/hour-input/hour-input.component.mjs +0 -28
  71. package/esm2022/lib/components/molecules/info-card/info-card.component.mjs +0 -126
  72. package/esm2022/lib/components/molecules/info-card/types.mjs +0 -11
  73. package/esm2022/lib/components/molecules/number-input/number-input.component.mjs +0 -34
  74. package/lib/components/molecules/content-card/content-card.component.d.ts +0 -26
  75. package/lib/components/molecules/content-card/types.d.ts +0 -30
  76. package/lib/components/molecules/email-input/email-input.component.d.ts +0 -34
  77. package/lib/components/molecules/hour-input/hour-input.component.d.ts +0 -15
  78. package/lib/components/molecules/info-card/info-card.component.d.ts +0 -37
  79. package/lib/components/molecules/info-card/types.d.ts +0 -44
  80. package/lib/components/molecules/number-input/number-input.component.d.ts +0 -16
@@ -23,7 +23,7 @@ import { IonicModule, ToastController, NavController } from '@ionic/angular';
23
23
  import { isSupported, getMessaging as getMessaging$1 } from 'firebase/messaging';
24
24
  import { getApps, getApp, initializeApp as initializeApp$1 } from 'firebase/app';
25
25
  import * as i2$1 from '@ionic/angular/standalone';
26
- import { AlertController, IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonInput, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonRippleEffect, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, IonDatetimeButton, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
26
+ import { AlertController, IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonRadio, IonRadioGroup, IonTextarea, IonDatetime, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonInput, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonRippleEffect, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, IonDatetimeButton, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
27
27
  import { addIcons } from 'ionicons';
28
28
  import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, cloudUploadOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline, shareSocialOutline, helpCircleOutline, menuOutline, stopCircleOutline, videocamOffOutline } from 'ionicons/icons';
29
29
  import { Browser } from '@capacitor/browser';
@@ -56,7 +56,7 @@ import { BrowserMultiFormatReader } from '@zxing/browser';
56
56
  * Current version of valtech-components.
57
57
  * This is automatically updated during the publish process.
58
58
  */
59
- const VERSION = '2.0.1035';
59
+ const VERSION = '4.0.0';
60
60
 
61
61
  // Control de estado de refresco (singleton a nivel de módulo)
62
62
  let isRefreshing = false;
@@ -9442,6 +9442,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9442
9442
  }]
9443
9443
  }], ctorParameters: () => [] });
9444
9444
 
9445
+ /**
9446
+ * Presets de botón por defecto provistos por la librería.
9447
+ *
9448
+ * Son el reemplazo recomendado de las factories deprecadas de
9449
+ * `atoms/button/factory.ts`: en vez de construir el `ButtonMetadata` a mano,
9450
+ * el consumer usa `<val-button preset="primary-round" [props]="{ text }">`.
9451
+ *
9452
+ * Cada preset define solo el ESTILO reutilizable (color/fill/shape/expand/size).
9453
+ * El `text`, `type`, `state`, `icon` y `href` se pasan por `[props]` en cada uso.
9454
+ *
9455
+ * Disponibles sin configuración: `PresetService` los siembra de fábrica y
9456
+ * `provideValtechPresets` los preserva (las apps EXTIENDEN estos defaults en
9457
+ * vez de pisarlos). Una app puede sobrescribir un preset declarando la misma
9458
+ * clave bajo `button` en su `APP_PRESETS`.
9459
+ */
9460
+ const DEFAULT_BUTTON_PRESETS = {
9461
+ // Primary
9462
+ primary: { color: 'primary', fill: 'solid' },
9463
+ 'primary-round': { color: 'primary', fill: 'solid', shape: 'round' },
9464
+ 'primary-block': { color: 'primary', fill: 'solid', expand: 'block' },
9465
+ 'primary-full': { color: 'primary', fill: 'solid', expand: 'full' },
9466
+ // Secondary
9467
+ secondary: { color: 'secondary', fill: 'solid' },
9468
+ 'secondary-round': { color: 'secondary', fill: 'solid', shape: 'round' },
9469
+ // Generic solid (color-agnostic — color comes from val-button default / props)
9470
+ solid: { fill: 'solid' },
9471
+ 'solid-round': { fill: 'solid', shape: 'round' },
9472
+ 'solid-block': { color: 'primary', fill: 'solid', expand: 'block' },
9473
+ // Outline / Clear
9474
+ outline: { fill: 'outline' },
9475
+ 'outline-round': { fill: 'outline', shape: 'round' },
9476
+ clear: { fill: 'clear' },
9477
+ 'clear-round': { fill: 'clear', shape: 'round' },
9478
+ // Intent
9479
+ danger: { color: 'danger', fill: 'solid' },
9480
+ 'danger-round': { color: 'danger', fill: 'solid', shape: 'round' },
9481
+ };
9482
+ /**
9483
+ * Presets que la librería siembra de fábrica en `PresetService`.
9484
+ * Hoy solo botón; agregar otros componentes acá a medida que se definan.
9485
+ */
9486
+ const DEFAULT_PRESETS = {
9487
+ button: DEFAULT_BUTTON_PRESETS,
9488
+ };
9489
+
9445
9490
  /**
9446
9491
  * Servicio para gestionar presets de componentes.
9447
9492
  *
@@ -9459,7 +9504,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9459
9504
  */
9460
9505
  class PresetService {
9461
9506
  constructor() {
9462
- this._presets = signal({});
9507
+ // Seeded with library defaults (e.g. button presets). Apps EXTEND these via
9508
+ // registerPresets (merge), so the defaults survive app-level registration.
9509
+ this._presets = signal(structuredClone(DEFAULT_PRESETS));
9463
9510
  }
9464
9511
  /**
9465
9512
  * Obtiene un preset específico para un componente
@@ -9499,6 +9546,10 @@ class PresetService {
9499
9546
  *
9500
9547
  * @param presets Configuración de presets
9501
9548
  *
9549
+ * Hace MERGE por componente sobre lo ya registrado (incluidos los defaults
9550
+ * de la librería), así que las apps EXTIENDEN los presets existentes en vez
9551
+ * de reemplazarlos. Para sobrescribir un preset, declarar la misma clave.
9552
+ *
9502
9553
  * @example
9503
9554
  * presets.registerPresets({
9504
9555
  * button: {
@@ -9510,13 +9561,19 @@ class PresetService {
9510
9561
  * });
9511
9562
  */
9512
9563
  registerPresets(presets) {
9513
- this._presets.set(presets);
9564
+ this._presets.update(current => {
9565
+ const merged = { ...current };
9566
+ for (const [component, componentPresets] of Object.entries(presets)) {
9567
+ merged[component] = { ...(current[component] ?? {}), ...componentPresets };
9568
+ }
9569
+ return merged;
9570
+ });
9514
9571
  }
9515
9572
  /**
9516
9573
  * Agrega presets para un componente específico (merge con existentes)
9517
9574
  */
9518
9575
  registerComponentPresets(component, presets) {
9519
- this._presets.update((current) => ({
9576
+ this._presets.update(current => ({
9520
9577
  ...current,
9521
9578
  [component]: {
9522
9579
  ...current[component],
@@ -9680,95 +9737,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9680
9737
  type: Output
9681
9738
  }] } });
9682
9739
 
9683
- /* eslint-disable no-underscore-dangle */
9684
- /**
9685
- * Service for registering and managing custom Ionicons icons in the application.
9686
- * Automatically registers a set of commonly used icons on initialization.
9687
- */
9688
- class IconService {
9689
- /**
9690
- * Registers a set of Ionicons icons for use throughout the app.
9691
- */
9692
- constructor() {
9693
- addIcons({
9694
- addOutline,
9695
- addCircleOutline,
9696
- alertOutline,
9697
- alertCircleOutline,
9698
- arrowBackOutline,
9699
- arrowForwardOutline,
9700
- arrowDownOutline,
9701
- settings,
9702
- settingsOutline,
9703
- checkmarkCircleOutline,
9704
- ellipsisHorizontalOutline,
9705
- notifications,
9706
- notificationsOutline,
9707
- openOutline,
9708
- closeOutline,
9709
- chatbubblesOutline,
9710
- shareOutline,
9711
- heart,
9712
- heartOutline,
9713
- home,
9714
- homeOutline,
9715
- eyeOffOutline,
9716
- eyeOutline,
9717
- scanOutline,
9718
- chevronDownOutline,
9719
- chevronForwardOutline,
9720
- checkmarkOutline,
9721
- clipboardOutline,
9722
- copyOutline,
9723
- filterOutline,
9724
- locationOutline,
9725
- calendarOutline,
9726
- businessOutline,
9727
- logoTwitter,
9728
- logoInstagram,
9729
- logoLinkedin,
9730
- logoYoutube,
9731
- logoTiktok,
9732
- logoFacebook,
9733
- logoGoogle,
9734
- createOutline,
9735
- trashOutline,
9736
- playOutline,
9737
- peopleOutline,
9738
- phonePortraitOutline,
9739
- refreshOutline,
9740
- documentTextOutline,
9741
- lockClosedOutline,
9742
- informationCircleOutline,
9743
- logoNpm,
9744
- removeOutline,
9745
- optionsOutline,
9746
- personOutline,
9747
- shieldCheckmarkOutline,
9748
- keyOutline,
9749
- desktopOutline,
9750
- logOutOutline,
9751
- cloudDownloadOutline,
9752
- cloudOutline,
9753
- gitBranchOutline,
9754
- layersOutline,
9755
- serverOutline,
9756
- warningOutline,
9757
- bulbOutline,
9758
- lockOpenOutline,
9759
- diamondOutline,
9760
- });
9761
- }
9762
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: IconService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9763
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: IconService, providedIn: 'root' }); }
9764
- }
9765
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: IconService, decorators: [{
9766
- type: Injectable,
9767
- args: [{
9768
- providedIn: 'root',
9769
- }]
9770
- }], ctorParameters: () => [] });
9771
-
9772
9740
  /**
9773
9741
  * val-box
9774
9742
  *
@@ -9783,17 +9751,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9783
9751
  * @output onClick - Emits when the box or its icon is clicked
9784
9752
  */
9785
9753
  class BoxComponent {
9786
- constructor(icon) {
9754
+ constructor() {
9787
9755
  /**
9788
9756
  * Event emitted when the box or its icon is clicked.
9789
9757
  */
9790
9758
  this.onClick = new EventEmitter();
9791
9759
  }
9792
- ngOnInit() { }
9793
9760
  clickHandler() {
9794
9761
  this.onClick.emit();
9795
9762
  }
9796
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BoxComponent, deps: [{ token: IconService }], target: i0.ɵɵFactoryTarget.Component }); }
9763
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9797
9764
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: BoxComponent, isStandalone: true, selector: "val-box", inputs: { props: "props" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
9798
9765
  <ion-card
9799
9766
  class="box"
@@ -9845,7 +9812,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9845
9812
  </div>
9846
9813
  </ion-card>
9847
9814
  `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}.bordered{border:.0625rem solid var(--ion-color-medium)}.box{width:100%;margin:0rem;border-radius:0rem;box-shadow:none;padding:0rem}.box.rounded{border-radius:1.125rem}.icon{cursor:pointer;margin:0rem;padding:0rem;position:absolute;right:.25rem;top:.25rem;font-size:1.5rem}@media (min-width: 768px){.icon{right:.5rem;top:.5rem;font-size:2rem}}.left-border{border-left:.1875rem solid #dde3ed}.left-border.small{border-width:.1875rem}.left-border.medium{border-width:.375rem}.left-border.large{border-width:.4375rem}.left-border.xlarge{border-width:.5rem}.transparent{--background: transparent}\n"] }]
9848
- }], ctorParameters: () => [{ type: IconService }], propDecorators: { props: [{
9815
+ }], propDecorators: { props: [{
9849
9816
  type: Input
9850
9817
  }], onClick: [{
9851
9818
  type: Output
@@ -10133,6 +10100,95 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10133
10100
  }]
10134
10101
  }] });
10135
10102
 
10103
+ /* eslint-disable no-underscore-dangle */
10104
+ /**
10105
+ * Service for registering and managing custom Ionicons icons in the application.
10106
+ * Automatically registers a set of commonly used icons on initialization.
10107
+ */
10108
+ class IconService {
10109
+ /**
10110
+ * Registers a set of Ionicons icons for use throughout the app.
10111
+ */
10112
+ constructor() {
10113
+ addIcons({
10114
+ addOutline,
10115
+ addCircleOutline,
10116
+ alertOutline,
10117
+ alertCircleOutline,
10118
+ arrowBackOutline,
10119
+ arrowForwardOutline,
10120
+ arrowDownOutline,
10121
+ settings,
10122
+ settingsOutline,
10123
+ checkmarkCircleOutline,
10124
+ ellipsisHorizontalOutline,
10125
+ notifications,
10126
+ notificationsOutline,
10127
+ openOutline,
10128
+ closeOutline,
10129
+ chatbubblesOutline,
10130
+ shareOutline,
10131
+ heart,
10132
+ heartOutline,
10133
+ home,
10134
+ homeOutline,
10135
+ eyeOffOutline,
10136
+ eyeOutline,
10137
+ scanOutline,
10138
+ chevronDownOutline,
10139
+ chevronForwardOutline,
10140
+ checkmarkOutline,
10141
+ clipboardOutline,
10142
+ copyOutline,
10143
+ filterOutline,
10144
+ locationOutline,
10145
+ calendarOutline,
10146
+ businessOutline,
10147
+ logoTwitter,
10148
+ logoInstagram,
10149
+ logoLinkedin,
10150
+ logoYoutube,
10151
+ logoTiktok,
10152
+ logoFacebook,
10153
+ logoGoogle,
10154
+ createOutline,
10155
+ trashOutline,
10156
+ playOutline,
10157
+ peopleOutline,
10158
+ phonePortraitOutline,
10159
+ refreshOutline,
10160
+ documentTextOutline,
10161
+ lockClosedOutline,
10162
+ informationCircleOutline,
10163
+ logoNpm,
10164
+ removeOutline,
10165
+ optionsOutline,
10166
+ personOutline,
10167
+ shieldCheckmarkOutline,
10168
+ keyOutline,
10169
+ desktopOutline,
10170
+ logOutOutline,
10171
+ cloudDownloadOutline,
10172
+ cloudOutline,
10173
+ gitBranchOutline,
10174
+ layersOutline,
10175
+ serverOutline,
10176
+ warningOutline,
10177
+ bulbOutline,
10178
+ lockOpenOutline,
10179
+ diamondOutline,
10180
+ });
10181
+ }
10182
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: IconService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
10183
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: IconService, providedIn: 'root' }); }
10184
+ }
10185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: IconService, decorators: [{
10186
+ type: Injectable,
10187
+ args: [{
10188
+ providedIn: 'root',
10189
+ }]
10190
+ }], ctorParameters: () => [] });
10191
+
10136
10192
  /**
10137
10193
  * Configuracion por defecto para header tipo 'home'
10138
10194
  */
@@ -10556,222 +10612,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10556
10612
  type: Output
10557
10613
  }] } });
10558
10614
 
10559
- const Icon = (name, slot) => {
10560
- return {
10561
- name,
10562
- slot,
10563
- };
10564
- };
10565
- /* name convention: COLOR FILL SIZE [optionals: SHAPE EXPAND ICON HREF/DOWNLOAD] TYPE */
10566
- const BaseDefault = (text, type) => {
10567
- return {
10568
- color: 'primary',
10569
- state: 'ENABLED',
10570
- text,
10571
- size: 'default',
10572
- type,
10573
- };
10574
- };
10575
- const ClearDefault = (text, type) => {
10576
- return { ...BaseDefault(text, type), fill: 'clear' };
10577
- };
10578
- const ClearDefaultRound = (text, type) => {
10579
- return { ...ClearDefault(text, type), shape: 'round' };
10580
- };
10581
- const SolidDefault = (text, type) => {
10582
- return { ...BaseDefault(text, type), fill: 'solid' };
10583
- };
10584
- const SolidDefaultRound = (text, type) => {
10585
- return { ...SolidDefault(text, type), shape: 'round' };
10586
- };
10587
- const OutlineDefault = (text, type) => {
10588
- return { ...BaseDefault(text, type), fill: 'outline' };
10589
- };
10590
- const OutlineDefaultRound = (text, type) => {
10591
- return { ...OutlineDefault(text, type), shape: 'round' };
10592
- };
10593
- const ClearDefaultFull = (text, type) => {
10594
- return { ...ClearDefault(text, type), expand: 'full' };
10595
- };
10596
- const ClearDefaultRoundFull = (text, type) => {
10597
- return { ...ClearDefaultRound(text, type), expand: 'full' };
10598
- };
10599
- const ClearDefaultBlock = (text, type) => {
10600
- return { ...ClearDefault(text, type), expand: 'block' };
10601
- };
10602
- const ClearDefaultRoundBlock = (text, type) => {
10603
- return { ...ClearDefaultRound(text, type), expand: 'block' };
10604
- };
10605
- const SolidDefaultFull = (text, type) => {
10606
- return { ...SolidDefault(text, type), expand: 'full' };
10607
- };
10608
- const SolidDefaultRoundFull = (text, type) => {
10609
- return { ...SolidDefaultRound(text, type), expand: 'full' };
10610
- };
10611
- const SolidDefaultBlock = (text, type) => {
10612
- return { ...SolidDefault(text, type), expand: 'block' };
10613
- };
10614
- const SolidDefaultRoundBlock = (text, type) => {
10615
- return { ...SolidDefaultRound(text, type), expand: 'block' };
10616
- };
10617
- const OutlineDefaultFull = (text, type) => {
10618
- return { ...OutlineDefault(text, type), expand: 'full' };
10619
- };
10620
- const OutlineDefaultRoundFull = (text, type) => {
10621
- return { ...OutlineDefaultRound(text, type), expand: 'full' };
10622
- };
10623
- const OutlineDefaultBlock = (text, type) => {
10624
- return { ...OutlineDefault(text, type), expand: 'block' };
10625
- };
10626
- const OutlineDefaultRoundBlock = (text, type) => {
10627
- return { ...OutlineDefaultRound(text, type), expand: 'block' };
10628
- };
10629
- const SolidDefaultButton = (text) => {
10630
- return SolidDefault(text, 'button');
10631
- };
10632
- const SolidSmallButton = (text) => {
10633
- return { ...SolidDefault(text, 'button'), size: 'small' };
10634
- };
10635
- const SolidLargeButton = (text) => {
10636
- return { ...SolidDefault(text, 'button'), size: 'large' };
10637
- };
10638
- const SolidDefaultRoundButton = (text) => {
10639
- return SolidDefaultRound(text, 'button');
10640
- };
10641
- const SolidSmallRoundButton = (text) => {
10642
- return { ...SolidDefaultRound(text, 'button'), size: 'small' };
10643
- };
10644
- const SolidLargeRoundButton = (text) => {
10645
- return { ...SolidDefaultRound(text, 'button'), size: 'large' };
10646
- };
10647
- const SolidFullButton = (text) => {
10648
- return SolidDefaultFull(text, 'button');
10649
- };
10650
- const SolidBlockButton = (text) => {
10651
- return SolidDefaultBlock(text, 'button');
10652
- };
10653
- /** PRIMARY */
10654
- const PrimarySolidDefaultRoundButton = (text) => {
10655
- return { ...SolidDefaultRoundButton(text), color: 'primary' };
10656
- };
10657
- const PrimarySolidDefaultRoundIconButton = (text, icon) => {
10658
- return { ...PrimarySolidDefaultRoundButton(text), icon };
10659
- };
10660
- const PrimarySolidDefaultRoundHrefButton = (text, href, target) => {
10661
- return { ...PrimarySolidDefaultRoundButton(text), href, target };
10662
- };
10663
- const PrimarySolidDefaultRoundIconHrefButton = (text, icon, href, target) => {
10664
- return { ...PrimarySolidDefaultRoundIconButton(text, icon), href, target };
10665
- };
10666
- const PrimarySolidSmallRoundButton = (text) => {
10667
- return { ...SolidSmallRoundButton(text), color: 'primary' };
10668
- };
10669
- const PrimarySolidSmallRoundIconButton = (text, icon) => {
10670
- return { ...PrimarySolidSmallRoundButton(text), icon };
10671
- };
10672
- const PrimarySolidSmallRoundHrefButton = (text, href, target) => {
10673
- return { ...PrimarySolidSmallRoundButton(text), href, target };
10674
- };
10675
- const PrimarySolidSmallRoundIconHrefButton = (text, icon, href, target) => {
10676
- return { ...PrimarySolidSmallRoundIconButton(text, icon), href, target };
10677
- };
10678
- const PrimarySolidLargeRoundButton = (text) => {
10679
- return { ...SolidLargeRoundButton(text), color: 'primary' };
10680
- };
10681
- const PrimarySolidLargeRoundIconButton = (text, icon) => {
10682
- return { ...PrimarySolidLargeRoundButton(text), icon };
10683
- };
10684
- const PrimarySolidLargeRoundHrefButton = (text, href, target) => {
10685
- return { ...PrimarySolidLargeRoundButton(text), href, target };
10686
- };
10687
- const PrimarySolidLargeRoundIconHrefButton = (text, icon, href, target) => {
10688
- return { ...PrimarySolidLargeRoundIconButton(text, icon), href, target };
10689
- };
10690
- const PrimarySolidBlockButton = (text) => {
10691
- return { ...SolidBlockButton(text), color: 'primary' };
10692
- };
10693
- const PrimarySolidBlockIconButton = (text, icon) => {
10694
- return { ...PrimarySolidBlockButton(text), icon };
10695
- };
10696
- const PrimarySolidBlockHrefButton = (text, href, target) => {
10697
- return { ...PrimarySolidBlockButton(text), href, target };
10698
- };
10699
- const PrimarySolidBlockIconHrefButton = (text, icon, href, target) => {
10700
- return { ...PrimarySolidBlockIconButton(text, icon), href, target };
10701
- };
10702
- const PrimarySolidFullButton = (text) => {
10703
- return { ...SolidFullButton(text), color: 'primary' };
10704
- };
10705
- const PrimarySolidFullIconButton = (text, icon) => {
10706
- return { ...PrimarySolidFullButton(text), icon };
10707
- };
10708
- const PrimarySolidFullHrefButton = (text, href, target) => {
10709
- return { ...PrimarySolidFullButton(text), href, target };
10710
- };
10711
- const PrimarySolidFullIconHrefButton = (text, icon, href, target) => {
10712
- return { ...PrimarySolidFullIconButton(text, icon), href, target };
10713
- };
10714
- /** SECONDARY */
10715
- const SecondarySolidDefaultRoundButton = (text) => {
10716
- return { ...SolidDefaultRoundButton(text), color: 'secondary' };
10717
- };
10718
- const SecondarySolidDefaultRoundIconButton = (text, icon) => {
10719
- return { ...SecondarySolidDefaultRoundButton(text), icon };
10720
- };
10721
- const SecondarySolidDefaultRoundHrefButton = (text, href, target) => {
10722
- return { ...SecondarySolidDefaultRoundButton(text), href, target };
10723
- };
10724
- const SecondarySolidDefaultRoundIconHrefButton = (text, icon, href, target) => {
10725
- return { ...SecondarySolidDefaultRoundIconButton(text, icon), href, target };
10726
- };
10727
- const SecondarySolidSmallRoundButton = (text) => {
10728
- return { ...SolidSmallRoundButton(text), color: 'secondary' };
10729
- };
10730
- const SecondarySolidSmallRoundIconButton = (text, icon) => {
10731
- return { ...SecondarySolidSmallRoundButton(text), icon };
10732
- };
10733
- const SecondarySolidSmallRoundHrefButton = (text, href, target) => {
10734
- return { ...SecondarySolidSmallRoundButton(text), href, target };
10735
- };
10736
- const SecondarySolidSmallRoundIconHrefButton = (text, icon, href, target) => {
10737
- return { ...SecondarySolidSmallRoundIconButton(text, icon), href, target };
10738
- };
10739
- const SecondarySolidLargeRoundButton = (text) => {
10740
- return { ...SolidLargeRoundButton(text), color: 'secondary' };
10741
- };
10742
- const SecondarySolidLargeRoundIconButton = (text, icon) => {
10743
- return { ...SecondarySolidLargeRoundButton(text), icon };
10744
- };
10745
- const SecondarySolidLargeRoundHrefButton = (text, href, target) => {
10746
- return { ...SecondarySolidLargeRoundButton(text), href, target };
10747
- };
10748
- const SecondarySolidLargeRoundIconHrefButton = (text, icon, href, target) => {
10749
- return { ...SecondarySolidLargeRoundIconButton(text, icon), href, target };
10750
- };
10751
- const SecondarySolidFullButton = (text) => {
10752
- return { ...SolidFullButton(text), color: 'secondary' };
10753
- };
10754
- const SecondarySolidFullIconButton = (text, icon) => {
10755
- return { ...SecondarySolidFullButton(text), icon };
10756
- };
10757
- const SecondarySolidFullHrefButton = (text, href, target) => {
10758
- return { ...SecondarySolidFullButton(text), href, target };
10759
- };
10760
- const SecondarySolidFullIconHrefButton = (text, icon, href, target) => {
10761
- return { ...SecondarySolidFullIconButton(text, icon), href, target };
10762
- };
10763
- const SecondarySolidBlockButton = (text) => {
10764
- return { ...SolidBlockButton(text), color: 'secondary' };
10765
- };
10766
- const SecondarySolidBlockIconButton = (text, icon) => {
10767
- return { ...SecondarySolidBlockButton(text), icon };
10768
- };
10769
- const SecondarySolidBlockHrefButton = (text, href, target) => {
10770
- return { ...SecondarySolidBlockButton(text), href, target };
10771
- };
10772
- const SecondarySolidBlockIconHrefButton = (text, icon, href, target) => {
10773
- return { ...SecondarySolidBlockIconButton(text, icon), href, target };
10774
- };
10615
+ const Icon = (name, slot) => ({ name, slot });
10616
+ /**
10617
+ * Single source of truth for building a `ButtonMetadata`.
10618
+ *
10619
+ * Applies the shared defaults (`primary` color, `ENABLED` state, `default`
10620
+ * size, `button` type) and merges any overrides. This builder (and
10621
+ * `iconButton`) is the canonical way to construct a button in code; for
10622
+ * templates prefer a registered `<val-button preset="...">` (channel `button`
10623
+ * of the PresetService).
10624
+ *
10625
+ * @example
10626
+ * button({ text: 'Save', fill: 'solid', shape: 'round', expand: 'full' })
10627
+ */
10628
+ const button = (overrides = {}) => ({
10629
+ color: 'primary',
10630
+ state: 'ENABLED',
10631
+ size: 'default',
10632
+ type: 'button',
10633
+ text: '',
10634
+ ...overrides,
10635
+ });
10636
+ /** Convenience builder for a button with a leading/trailing icon. */
10637
+ const iconButton = (text, icon, overrides = {}) => button({ text, icon, ...overrides });
10775
10638
 
10776
10639
  /**
10777
10640
  * val-display
@@ -10831,15 +10694,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10831
10694
  * @input props: DividerMetadata - Configuration for the divider (size, color, fill)
10832
10695
  */
10833
10696
  class DividerComponent {
10834
- constructor() { }
10835
- ngOnInit() { }
10836
10697
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10837
10698
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DividerComponent, isStandalone: true, selector: "val-divider", inputs: { props: "props" }, ngImport: i0, template: ` <div [ngClass]="['divider', props.size, props.color, props.fill]"></div> `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}.solid{border-top:.0625rem solid #878ca0}.gradient{height:.125rem}.gradient.primary{background:linear-gradient(to right,var(--ion-color-primary),var(--ion-color-light))}.gradient.secondary{background:linear-gradient(to right,var(--ion-color-secondary),var(--ion-color-light))}.gradient.dark{background:linear-gradient(to right,var(--ion-color-dark),var(--ion-color-light))}.gradient.light{background:linear-gradient(to right,var(--ion-color-light),#ffffff)}.gradient.medium{background:linear-gradient(to right,var(--ion-color-medium),#ffffff)}.small{margin:1rem}.medium{margin:1.5rem 1rem}.large{margin:2.25rem 1rem}.primary{border-color:var(--ion-color-primary)}.secondary{border-color:var(--ion-color-secondary)}.dark{border-color:var(--ion-color-dark)}.light{border-color:var(--ion-color-light)}.medium{border-color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
10838
10699
  }
10839
10700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DividerComponent, decorators: [{
10840
10701
  type: Component,
10841
10702
  args: [{ selector: 'val-divider', standalone: true, imports: [CommonModule], template: ` <div [ngClass]="['divider', props.size, props.color, props.fill]"></div> `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}.solid{border-top:.0625rem solid #878ca0}.gradient{height:.125rem}.gradient.primary{background:linear-gradient(to right,var(--ion-color-primary),var(--ion-color-light))}.gradient.secondary{background:linear-gradient(to right,var(--ion-color-secondary),var(--ion-color-light))}.gradient.dark{background:linear-gradient(to right,var(--ion-color-dark),var(--ion-color-light))}.gradient.light{background:linear-gradient(to right,var(--ion-color-light),#ffffff)}.gradient.medium{background:linear-gradient(to right,var(--ion-color-medium),#ffffff)}.small{margin:1rem}.medium{margin:1.5rem 1rem}.large{margin:2.25rem 1rem}.primary{border-color:var(--ion-color-primary)}.secondary{border-color:var(--ion-color-secondary)}.dark{border-color:var(--ion-color-dark)}.light{border-color:var(--ion-color-light)}.medium{border-color:var(--ion-color-medium)}\n"] }]
10842
- }], ctorParameters: () => [], propDecorators: { props: [{
10703
+ }], propDecorators: { props: [{
10843
10704
  type: Input
10844
10705
  }] } });
10845
10706
 
@@ -10859,7 +10720,6 @@ class HrefComponent {
10859
10720
  this.downloadService = downloadService;
10860
10721
  this.onClick = new EventEmitter();
10861
10722
  }
10862
- ngOnInit() { }
10863
10723
  getFileName() {
10864
10724
  return this.downloadService.getFileNameFromUrl(this.props.url);
10865
10725
  }
@@ -11007,6 +10867,19 @@ class ImageComponent {
11007
10867
  this.isPreviewOpen = true;
11008
10868
  this.resetZoom();
11009
10869
  }
10870
+ /**
10871
+ * Keyboard activation of the preview trigger. Space must preventDefault to
10872
+ * avoid scrolling the page when the focused image is activated.
10873
+ */
10874
+ onPreviewKeydown(event) {
10875
+ if (!this.props.previewMode)
10876
+ return;
10877
+ const key = event.key;
10878
+ if (key === ' ' || key === 'Spacebar') {
10879
+ event.preventDefault();
10880
+ }
10881
+ this.openPreview();
10882
+ }
11010
10883
  closePreview() {
11011
10884
  this.isPreviewOpen = false;
11012
10885
  }
@@ -11170,6 +11043,11 @@ class ImageComponent {
11170
11043
  [style.max-width.rem]="props.width"
11171
11044
  [style.height.px]="props.height"
11172
11045
  (click)="props.previewMode ? openPreview() : null"
11046
+ (keydown.enter)="props.previewMode ? openPreview() : null"
11047
+ (keydown.space)="onPreviewKeydown($event)"
11048
+ [attr.role]="props.previewMode ? 'button' : null"
11049
+ [attr.tabindex]="props.previewMode ? 0 : null"
11050
+ [attr.aria-haspopup]="props.previewMode ? 'dialog' : null"
11173
11051
  />
11174
11052
  } @else {
11175
11053
  <img
@@ -11190,6 +11068,11 @@ class ImageComponent {
11190
11068
  [style.max-width.rem]="props.width"
11191
11069
  [style.height.px]="props.height"
11192
11070
  (click)="props.previewMode ? openPreview() : null"
11071
+ (keydown.enter)="props.previewMode ? openPreview() : null"
11072
+ (keydown.space)="onPreviewKeydown($event)"
11073
+ [attr.role]="props.previewMode ? 'button' : null"
11074
+ [attr.tabindex]="props.previewMode ? 0 : null"
11075
+ [attr.aria-haspopup]="props.previewMode ? 'dialog' : null"
11193
11076
  />
11194
11077
  }
11195
11078
  </div>
@@ -11274,7 +11157,7 @@ class ImageComponent {
11274
11157
  </ion-content>
11275
11158
  </ng-template>
11276
11159
  </ion-modal>
11277
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-image-container{margin:0;padding:0;max-width:100%}.val-image-container--left{margin-right:auto;text-align:left}.val-image-container--center{margin-left:auto;margin-right:auto;text-align:center}.val-image-container--right{margin-left:auto;text-align:right}.val-image-wrapper{display:inline-block;position:relative}.val-image{width:100%;height:auto;display:block;opacity:1;max-width:100%}.val-image.center{margin:0 auto}.val-image.rounded{border-radius:.5rem}.val-image.circular{border-radius:50%;aspect-ratio:1;object-fit:cover}.val-image.box{border-radius:0}.val-image.bordered{border:.0625rem solid var(--ion-color-medium)}.val-image.shaded{box-shadow:.1875rem .625rem .5rem #1219541a}body.dark .val-image.dark,html.ion-palette-dark .val-image.dark,body[data-theme=dark] .val-image.dark{filter:invert(1)}.val-image.limited{max-width:100%}@media (max-width: 768px){.val-image .val-image-wrapper.small{width:40%}.val-image .val-image-wrapper.medium{width:60%}.val-image .val-image-wrapper.large{width:80%}.val-image .val-image-wrapper.xlarge{width:100%}}.val-image.small{width:30%}.val-image.medium{width:50%}.val-image.large{width:70%}.val-image.xlarge{width:100%}.val-image-caption{margin-top:.5rem;color:var(--ion-color-medium-shade, #666);font-style:italic;line-height:1.4}.val-image-caption--small{font-size:.75rem}.val-image-caption--medium{font-size:.875rem}.val-image-caption--large{font-size:1rem}.val-image.visible{animation:appearance ease-in 1s forwards}@keyframes appearance{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.val-image-container{flex-shrink:0;align-self:flex-start}.flexbox-container .val-image-container--left{align-self:flex-start}.flexbox-container .val-image-container--center{align-self:center}.flexbox-container .val-image-container--right{align-self:flex-end}.val-image--preview-enabled{cursor:pointer;transition:opacity .2s ease,transform .2s ease}.val-image--preview-enabled:hover{opacity:.9;transform:scale(1.02)}ion-modal ion-content{position:relative;--padding-start: 0;--padding-end: 0;--padding-top: 0;--padding-bottom: 0}.val-image-preview-controls{position:absolute;bottom:20px;left:50%;transform:translate(-50%);z-index:1000;display:flex;align-items:center;gap:15px;background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.9);padding:4px 8px;border-radius:25px;backdrop-filter:blur(10px);box-shadow:0 4px 20px #00000026}.val-image-preview-zoom-level{font-size:.875rem;font-weight:600;min-width:50px;text-align:center;color:var(--ion-text-color)}.val-image-preview-viewport{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;align-items:center;justify-content:center;touch-action:none}.val-image-preview-img{max-width:90vw;max-height:90vh;object-fit:contain;transition:transform .1s ease-out;transform-origin:center center;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}@media (max-width: 768px){.val-image-preview-controls{bottom:10px;padding:8px 16px;gap:10px}.val-image-preview-zoom-level{font-size:.75rem;min-width:40px}.val-image-preview-img{max-width:95vw;max-height:85vh}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { 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: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }] }); }
11160
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-image-container{margin:0;padding:0;max-width:100%}.val-image-container--left{margin-right:auto;text-align:left}.val-image-container--center{margin-left:auto;margin-right:auto;text-align:center}.val-image-container--right{margin-left:auto;text-align:right}.val-image-wrapper{display:inline-block;position:relative}.val-image{width:100%;height:auto;display:block;opacity:1;max-width:100%}.val-image.center{margin:0 auto}.val-image.rounded{border-radius:.5rem}.val-image.circular{border-radius:50%;aspect-ratio:1;object-fit:cover}.val-image.box{border-radius:0}.val-image.bordered{border:.0625rem solid var(--ion-color-medium)}.val-image.shaded{box-shadow:.1875rem .625rem .5rem #1219541a}body.dark .val-image.dark,html.ion-palette-dark .val-image.dark,body[data-theme=dark] .val-image.dark{filter:invert(1)}.val-image.limited{max-width:100%}@media (max-width: 768px){.val-image .val-image-wrapper.small{width:40%}.val-image .val-image-wrapper.medium{width:60%}.val-image .val-image-wrapper.large{width:80%}.val-image .val-image-wrapper.xlarge{width:100%}}.val-image.small{width:30%}.val-image.medium{width:50%}.val-image.large{width:70%}.val-image.xlarge{width:100%}.val-image-caption{margin-top:.5rem;color:var(--ion-color-medium-shade, #666);font-style:italic;line-height:1.4}.val-image-caption--small{font-size:.75rem}.val-image-caption--medium{font-size:.875rem}.val-image-caption--large{font-size:1rem}.val-image.visible{animation:appearance ease-in 1s forwards}@keyframes appearance{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.val-image-container{flex-shrink:0;align-self:flex-start}.flexbox-container .val-image-container--left{align-self:flex-start}.flexbox-container .val-image-container--center{align-self:center}.flexbox-container .val-image-container--right{align-self:flex-end}.val-image--preview-enabled{cursor:pointer;transition:opacity .2s ease,transform .2s ease}.val-image--preview-enabled:hover{opacity:.9;transform:scale(1.02)}.val-image--preview-enabled:focus-visible:focus{outline:none}.val-image--preview-enabled:focus-visible:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}ion-modal ion-content{position:relative;--padding-start: 0;--padding-end: 0;--padding-top: 0;--padding-bottom: 0}.val-image-preview-controls{position:absolute;bottom:20px;left:50%;transform:translate(-50%);z-index:1000;display:flex;align-items:center;gap:15px;background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.9);padding:4px 8px;border-radius:25px;backdrop-filter:blur(10px);box-shadow:0 4px 20px #00000026}.val-image-preview-zoom-level{font-size:.875rem;font-weight:600;min-width:50px;text-align:center;color:var(--ion-text-color)}.val-image-preview-viewport{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;align-items:center;justify-content:center;touch-action:none}.val-image-preview-img{max-width:90vw;max-height:90vh;object-fit:contain;transition:transform .1s ease-out;transform-origin:center center;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}@media (max-width: 768px){.val-image-preview-controls{bottom:10px;padding:8px 16px;gap:10px}.val-image-preview-zoom-level{font-size:.75rem;min-width:40px}.val-image-preview-img{max-width:95vw;max-height:85vh}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { 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: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }] }); }
11278
11161
  }
11279
11162
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ImageComponent, decorators: [{
11280
11163
  type: Component,
@@ -11313,6 +11196,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11313
11196
  [style.max-width.rem]="props.width"
11314
11197
  [style.height.px]="props.height"
11315
11198
  (click)="props.previewMode ? openPreview() : null"
11199
+ (keydown.enter)="props.previewMode ? openPreview() : null"
11200
+ (keydown.space)="onPreviewKeydown($event)"
11201
+ [attr.role]="props.previewMode ? 'button' : null"
11202
+ [attr.tabindex]="props.previewMode ? 0 : null"
11203
+ [attr.aria-haspopup]="props.previewMode ? 'dialog' : null"
11316
11204
  />
11317
11205
  } @else {
11318
11206
  <img
@@ -11333,6 +11221,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11333
11221
  [style.max-width.rem]="props.width"
11334
11222
  [style.height.px]="props.height"
11335
11223
  (click)="props.previewMode ? openPreview() : null"
11224
+ (keydown.enter)="props.previewMode ? openPreview() : null"
11225
+ (keydown.space)="onPreviewKeydown($event)"
11226
+ [attr.role]="props.previewMode ? 'button' : null"
11227
+ [attr.tabindex]="props.previewMode ? 0 : null"
11228
+ [attr.aria-haspopup]="props.previewMode ? 'dialog' : null"
11336
11229
  />
11337
11230
  }
11338
11231
  </div>
@@ -11417,7 +11310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11417
11310
  </ion-content>
11418
11311
  </ng-template>
11419
11312
  </ion-modal>
11420
- `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-image-container{margin:0;padding:0;max-width:100%}.val-image-container--left{margin-right:auto;text-align:left}.val-image-container--center{margin-left:auto;margin-right:auto;text-align:center}.val-image-container--right{margin-left:auto;text-align:right}.val-image-wrapper{display:inline-block;position:relative}.val-image{width:100%;height:auto;display:block;opacity:1;max-width:100%}.val-image.center{margin:0 auto}.val-image.rounded{border-radius:.5rem}.val-image.circular{border-radius:50%;aspect-ratio:1;object-fit:cover}.val-image.box{border-radius:0}.val-image.bordered{border:.0625rem solid var(--ion-color-medium)}.val-image.shaded{box-shadow:.1875rem .625rem .5rem #1219541a}body.dark .val-image.dark,html.ion-palette-dark .val-image.dark,body[data-theme=dark] .val-image.dark{filter:invert(1)}.val-image.limited{max-width:100%}@media (max-width: 768px){.val-image .val-image-wrapper.small{width:40%}.val-image .val-image-wrapper.medium{width:60%}.val-image .val-image-wrapper.large{width:80%}.val-image .val-image-wrapper.xlarge{width:100%}}.val-image.small{width:30%}.val-image.medium{width:50%}.val-image.large{width:70%}.val-image.xlarge{width:100%}.val-image-caption{margin-top:.5rem;color:var(--ion-color-medium-shade, #666);font-style:italic;line-height:1.4}.val-image-caption--small{font-size:.75rem}.val-image-caption--medium{font-size:.875rem}.val-image-caption--large{font-size:1rem}.val-image.visible{animation:appearance ease-in 1s forwards}@keyframes appearance{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.val-image-container{flex-shrink:0;align-self:flex-start}.flexbox-container .val-image-container--left{align-self:flex-start}.flexbox-container .val-image-container--center{align-self:center}.flexbox-container .val-image-container--right{align-self:flex-end}.val-image--preview-enabled{cursor:pointer;transition:opacity .2s ease,transform .2s ease}.val-image--preview-enabled:hover{opacity:.9;transform:scale(1.02)}ion-modal ion-content{position:relative;--padding-start: 0;--padding-end: 0;--padding-top: 0;--padding-bottom: 0}.val-image-preview-controls{position:absolute;bottom:20px;left:50%;transform:translate(-50%);z-index:1000;display:flex;align-items:center;gap:15px;background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.9);padding:4px 8px;border-radius:25px;backdrop-filter:blur(10px);box-shadow:0 4px 20px #00000026}.val-image-preview-zoom-level{font-size:.875rem;font-weight:600;min-width:50px;text-align:center;color:var(--ion-text-color)}.val-image-preview-viewport{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;align-items:center;justify-content:center;touch-action:none}.val-image-preview-img{max-width:90vw;max-height:90vh;object-fit:contain;transition:transform .1s ease-out;transform-origin:center center;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}@media (max-width: 768px){.val-image-preview-controls{bottom:10px;padding:8px 16px;gap:10px}.val-image-preview-zoom-level{font-size:.75rem;min-width:40px}.val-image-preview-img{max-width:95vw;max-height:85vh}}\n"] }]
11313
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-image-container{margin:0;padding:0;max-width:100%}.val-image-container--left{margin-right:auto;text-align:left}.val-image-container--center{margin-left:auto;margin-right:auto;text-align:center}.val-image-container--right{margin-left:auto;text-align:right}.val-image-wrapper{display:inline-block;position:relative}.val-image{width:100%;height:auto;display:block;opacity:1;max-width:100%}.val-image.center{margin:0 auto}.val-image.rounded{border-radius:.5rem}.val-image.circular{border-radius:50%;aspect-ratio:1;object-fit:cover}.val-image.box{border-radius:0}.val-image.bordered{border:.0625rem solid var(--ion-color-medium)}.val-image.shaded{box-shadow:.1875rem .625rem .5rem #1219541a}body.dark .val-image.dark,html.ion-palette-dark .val-image.dark,body[data-theme=dark] .val-image.dark{filter:invert(1)}.val-image.limited{max-width:100%}@media (max-width: 768px){.val-image .val-image-wrapper.small{width:40%}.val-image .val-image-wrapper.medium{width:60%}.val-image .val-image-wrapper.large{width:80%}.val-image .val-image-wrapper.xlarge{width:100%}}.val-image.small{width:30%}.val-image.medium{width:50%}.val-image.large{width:70%}.val-image.xlarge{width:100%}.val-image-caption{margin-top:.5rem;color:var(--ion-color-medium-shade, #666);font-style:italic;line-height:1.4}.val-image-caption--small{font-size:.75rem}.val-image-caption--medium{font-size:.875rem}.val-image-caption--large{font-size:1rem}.val-image.visible{animation:appearance ease-in 1s forwards}@keyframes appearance{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.val-image-container{flex-shrink:0;align-self:flex-start}.flexbox-container .val-image-container--left{align-self:flex-start}.flexbox-container .val-image-container--center{align-self:center}.flexbox-container .val-image-container--right{align-self:flex-end}.val-image--preview-enabled{cursor:pointer;transition:opacity .2s ease,transform .2s ease}.val-image--preview-enabled:hover{opacity:.9;transform:scale(1.02)}.val-image--preview-enabled:focus-visible:focus{outline:none}.val-image--preview-enabled:focus-visible:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}ion-modal ion-content{position:relative;--padding-start: 0;--padding-end: 0;--padding-top: 0;--padding-bottom: 0}.val-image-preview-controls{position:absolute;bottom:20px;left:50%;transform:translate(-50%);z-index:1000;display:flex;align-items:center;gap:15px;background:rgba(var(--ion-background-color-rgb, 255, 255, 255),.9);padding:4px 8px;border-radius:25px;backdrop-filter:blur(10px);box-shadow:0 4px 20px #00000026}.val-image-preview-zoom-level{font-size:.875rem;font-weight:600;min-width:50px;text-align:center;color:var(--ion-text-color)}.val-image-preview-viewport{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;align-items:center;justify-content:center;touch-action:none}.val-image-preview-img{max-width:90vw;max-height:90vh;object-fit:contain;transition:transform .1s ease-out;transform-origin:center center;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}@media (max-width: 768px){.val-image-preview-controls{bottom:10px;padding:8px 16px;gap:10px}.val-image-preview-zoom-level{font-size:.75rem;min-width:40px}.val-image-preview-img{max-width:95vw;max-height:85vh}}\n"] }]
11421
11314
  }], ctorParameters: () => [], propDecorators: { props: [{
11422
11315
  type: Input
11423
11316
  }], onKeyDown: [{
@@ -15220,6 +15113,11 @@ class CardComponent {
15220
15113
  clickHandler(section, token) {
15221
15114
  this.onClick.emit({ section, token });
15222
15115
  }
15116
+ /** Activación por teclado con Space — previene el scroll de la página. */
15117
+ onKeyActivate(event, section, token) {
15118
+ event.preventDefault();
15119
+ this.clickHandler(section, token);
15120
+ }
15223
15121
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15224
15122
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CardComponent, isStandalone: true, selector: "val-card", inputs: { preset: "preset", props: "props" }, outputs: { onClick: "onClick" }, usesOnChanges: true, ngImport: i0, template: `
15225
15123
  <ion-card *ngIf="resolvedProps.type === types.native">
@@ -15246,8 +15144,13 @@ class CardComponent {
15246
15144
 
15247
15145
  <ion-card
15248
15146
  *ngIf="resolvedProps.type === types.tappable"
15249
- (click)="clickHandler(sections.content, resolvedProps.token)"
15250
15147
  class="tapable"
15148
+ role="button"
15149
+ tabindex="0"
15150
+ [attr.aria-label]="resolvedProps.title || resolvedProps.overtitle || null"
15151
+ (click)="clickHandler(sections.content, resolvedProps.token)"
15152
+ (keydown.enter)="clickHandler(sections.content, resolvedProps.token)"
15153
+ (keydown.space)="onKeyActivate($event, sections.content, resolvedProps.token)"
15251
15154
  >
15252
15155
  @if (resolvedProps.image) {
15253
15156
  <img [alt]="resolvedProps.title || 'Card image'" [src]="resolvedProps.image" />
@@ -15262,8 +15165,14 @@ class CardComponent {
15262
15165
 
15263
15166
  <ion-card
15264
15167
  *ngIf="resolvedProps.type === types.checker"
15265
- (click)="clickHandler(sections.content, resolvedProps.token)"
15266
15168
  class="tapable"
15169
+ role="button"
15170
+ tabindex="0"
15171
+ [attr.aria-pressed]="!!resolvedProps.selected"
15172
+ [attr.aria-label]="resolvedProps.title || resolvedProps.overtitle || null"
15173
+ (click)="clickHandler(sections.content, resolvedProps.token)"
15174
+ (keydown.enter)="clickHandler(sections.content, resolvedProps.token)"
15175
+ (keydown.space)="onKeyActivate($event, sections.content, resolvedProps.token)"
15267
15176
  >
15268
15177
  <ion-card-header *ngIf="resolvedProps.title || resolvedProps.overtitle" class="checker">
15269
15178
  <div>
@@ -15339,7 +15248,15 @@ class CardComponent {
15339
15248
  </ion-buttons>
15340
15249
  </ion-card-header>
15341
15250
 
15342
- <div class="tapable" (click)="clickHandler(sections.content, resolvedProps.token)">
15251
+ <div
15252
+ class="tapable"
15253
+ role="button"
15254
+ tabindex="0"
15255
+ [attr.aria-label]="resolvedProps.title || resolvedProps.overtitle || null"
15256
+ (click)="clickHandler(sections.content, resolvedProps.token)"
15257
+ (keydown.enter)="clickHandler(sections.content, resolvedProps.token)"
15258
+ (keydown.space)="onKeyActivate($event, sections.content, resolvedProps.token)"
15259
+ >
15343
15260
  <ion-card-header *ngIf="resolvedProps.title || resolvedProps.overtitle" class="complex-header">
15344
15261
  <div>
15345
15262
  <ion-card-subtitle *ngIf="resolvedProps.overtitle">{{ resolvedProps.overtitle }}</ion-card-subtitle>
@@ -15393,7 +15310,7 @@ class CardComponent {
15393
15310
  </ng-container>
15394
15311
  </ion-buttons>
15395
15312
  </ion-card>
15396
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-card.tapable{transition:transform .3s ease,box-shadow .3s ease}ion-card.tapable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.tapable{cursor:pointer}.checker{display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-header{padding:10px;display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-content{padding-left:10px;padding-top:4px;padding-bottom:10px}.complex{border-radius:16px}img{width:100%;height:auto;max-height:250px;object-fit:cover;display:block;border-radius:24px}.card-actions{display:flex;gap:.5rem;padding:0 16px 16px;flex-wrap:wrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { 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"] }] }); }
15313
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-card.tapable{transition:transform .3s ease,box-shadow .3s ease}ion-card.tapable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.tapable{cursor:pointer}.tapable:focus{outline:none}.tapable:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.checker{display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-header{padding:10px;display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-content{padding-left:10px;padding-top:4px;padding-bottom:10px}.complex{border-radius:16px}img{width:100%;height:auto;max-height:250px;object-fit:cover;display:block;border-radius:24px}.card-actions{display:flex;gap:.5rem;padding:0 16px 16px;flex-wrap:wrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { 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"] }] }); }
15397
15314
  }
15398
15315
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CardComponent, decorators: [{
15399
15316
  type: Component,
@@ -15437,8 +15354,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15437
15354
 
15438
15355
  <ion-card
15439
15356
  *ngIf="resolvedProps.type === types.tappable"
15440
- (click)="clickHandler(sections.content, resolvedProps.token)"
15441
15357
  class="tapable"
15358
+ role="button"
15359
+ tabindex="0"
15360
+ [attr.aria-label]="resolvedProps.title || resolvedProps.overtitle || null"
15361
+ (click)="clickHandler(sections.content, resolvedProps.token)"
15362
+ (keydown.enter)="clickHandler(sections.content, resolvedProps.token)"
15363
+ (keydown.space)="onKeyActivate($event, sections.content, resolvedProps.token)"
15442
15364
  >
15443
15365
  @if (resolvedProps.image) {
15444
15366
  <img [alt]="resolvedProps.title || 'Card image'" [src]="resolvedProps.image" />
@@ -15453,8 +15375,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15453
15375
 
15454
15376
  <ion-card
15455
15377
  *ngIf="resolvedProps.type === types.checker"
15456
- (click)="clickHandler(sections.content, resolvedProps.token)"
15457
15378
  class="tapable"
15379
+ role="button"
15380
+ tabindex="0"
15381
+ [attr.aria-pressed]="!!resolvedProps.selected"
15382
+ [attr.aria-label]="resolvedProps.title || resolvedProps.overtitle || null"
15383
+ (click)="clickHandler(sections.content, resolvedProps.token)"
15384
+ (keydown.enter)="clickHandler(sections.content, resolvedProps.token)"
15385
+ (keydown.space)="onKeyActivate($event, sections.content, resolvedProps.token)"
15458
15386
  >
15459
15387
  <ion-card-header *ngIf="resolvedProps.title || resolvedProps.overtitle" class="checker">
15460
15388
  <div>
@@ -15530,7 +15458,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15530
15458
  </ion-buttons>
15531
15459
  </ion-card-header>
15532
15460
 
15533
- <div class="tapable" (click)="clickHandler(sections.content, resolvedProps.token)">
15461
+ <div
15462
+ class="tapable"
15463
+ role="button"
15464
+ tabindex="0"
15465
+ [attr.aria-label]="resolvedProps.title || resolvedProps.overtitle || null"
15466
+ (click)="clickHandler(sections.content, resolvedProps.token)"
15467
+ (keydown.enter)="clickHandler(sections.content, resolvedProps.token)"
15468
+ (keydown.space)="onKeyActivate($event, sections.content, resolvedProps.token)"
15469
+ >
15534
15470
  <ion-card-header *ngIf="resolvedProps.title || resolvedProps.overtitle" class="complex-header">
15535
15471
  <div>
15536
15472
  <ion-card-subtitle *ngIf="resolvedProps.overtitle">{{ resolvedProps.overtitle }}</ion-card-subtitle>
@@ -15584,8 +15520,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15584
15520
  </ng-container>
15585
15521
  </ion-buttons>
15586
15522
  </ion-card>
15587
- `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-card.tapable{transition:transform .3s ease,box-shadow .3s ease}ion-card.tapable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.tapable{cursor:pointer}.checker{display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-header{padding:10px;display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-content{padding-left:10px;padding-top:4px;padding-bottom:10px}.complex{border-radius:16px}img{width:100%;height:auto;max-height:250px;object-fit:cover;display:block;border-radius:24px}.card-actions{display:flex;gap:.5rem;padding:0 16px 16px;flex-wrap:wrap}\n"] }]
15588
- }], ctorParameters: () => [], propDecorators: { preset: [{
15523
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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-card.tapable{transition:transform .3s ease,box-shadow .3s ease}ion-card.tapable:hover{transform:scale(1.01);box-shadow:.1875rem .625rem .5rem #1219541a}.tapable{cursor:pointer}.tapable:focus{outline:none}.tapable:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.checker{display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-header{padding:10px;display:flex;flex-direction:row;justify-content:space-between;align-items:center}.complex-content{padding-left:10px;padding-top:4px;padding-bottom:10px}.complex{border-radius:16px}img{width:100%;height:auto;max-height:250px;object-fit:cover;display:block;border-radius:24px}.card-actions{display:flex;gap:.5rem;padding:0 16px 16px;flex-wrap:wrap}\n"] }]
15524
+ }], propDecorators: { preset: [{
15589
15525
  type: Input
15590
15526
  }], props: [{
15591
15527
  type: Input
@@ -15690,52 +15626,43 @@ class CheckboxRadioInputComponent {
15690
15626
  this.states = ComponentStates;
15691
15627
  }
15692
15628
  ngOnInit() { }
15693
- isSelected(option) {
15694
- return this.props.control?.value === option.id;
15695
- }
15696
- onOptionSelect(option, event) {
15697
- if (event.detail.checked) {
15698
- // Seleccionar esta opción
15699
- this.props.control?.setValue(option.id);
15700
- }
15701
- else {
15702
- // Si se deselecciona la opción actual, limpiar
15703
- if (this.props.control?.value === option.id) {
15704
- this.props.control?.setValue(null);
15705
- }
15706
- }
15629
+ onSelectionChange(event) {
15630
+ // ion-radio-group con allowEmptySelection: re-clickear la opción activa la
15631
+ // deselecciona (value === undefined) → mapear a null para limpiar el control.
15632
+ const value = event.detail.value;
15633
+ this.props.control?.setValue(value ?? null);
15707
15634
  }
15708
15635
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CheckboxRadioInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15709
15636
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CheckboxRadioInputComponent, isStandalone: true, selector: "val-checkbox-radio-input", inputs: { props: "props" }, ngImport: i0, template: `
15710
- <div class="checkbox-radio-group">
15637
+ <ion-radio-group
15638
+ class="checkbox-radio-group"
15639
+ [value]="props.control?.value"
15640
+ [allowEmptySelection]="true"
15641
+ (ionChange)="onSelectionChange($event)"
15642
+ >
15711
15643
  @for (option of props.options; track option.id) {
15712
- <ion-checkbox
15713
- [checked]="isSelected(option)"
15714
- [disabled]="props.state === states.DISABLED"
15715
- [labelPlacement]="'end'"
15716
- (ionChange)="onOptionSelect(option, $event)"
15717
- >
15644
+ <ion-radio [value]="option.id" [disabled]="props.state === states.DISABLED" labelPlacement="end">
15718
15645
  {{ option.name }}
15719
- </ion-checkbox>
15646
+ </ion-radio>
15720
15647
  }
15721
- </div>
15722
- `, isInline: true, styles: [".checkbox-radio-group{display:flex;flex-direction:row;gap:12px;margin-top:.5rem}.checkbox-radio-group ion-checkbox{--size: 24px;--checkbox-background-checked: var(--ion-color-primary);--checkmark-color: var(--ion-color-primary-contrast)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }] }); }
15648
+ </ion-radio-group>
15649
+ `, isInline: true, styles: [".checkbox-radio-group{display:flex;flex-direction:row;gap:12px;margin-top:.5rem}.checkbox-radio-group ion-checkbox{--size: 24px;--checkbox-background-checked: var(--ion-color-primary);--checkmark-color: var(--ion-color-primary-contrast)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }] }); }
15723
15650
  }
15724
15651
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CheckboxRadioInputComponent, decorators: [{
15725
15652
  type: Component,
15726
- args: [{ selector: 'val-checkbox-radio-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, IonCheckbox], template: `
15727
- <div class="checkbox-radio-group">
15653
+ args: [{ selector: 'val-checkbox-radio-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, IonRadio, IonRadioGroup], template: `
15654
+ <ion-radio-group
15655
+ class="checkbox-radio-group"
15656
+ [value]="props.control?.value"
15657
+ [allowEmptySelection]="true"
15658
+ (ionChange)="onSelectionChange($event)"
15659
+ >
15728
15660
  @for (option of props.options; track option.id) {
15729
- <ion-checkbox
15730
- [checked]="isSelected(option)"
15731
- [disabled]="props.state === states.DISABLED"
15732
- [labelPlacement]="'end'"
15733
- (ionChange)="onOptionSelect(option, $event)"
15734
- >
15661
+ <ion-radio [value]="option.id" [disabled]="props.state === states.DISABLED" labelPlacement="end">
15735
15662
  {{ option.name }}
15736
- </ion-checkbox>
15663
+ </ion-radio>
15737
15664
  }
15738
- </div>
15665
+ </ion-radio-group>
15739
15666
  `, styles: [".checkbox-radio-group{display:flex;flex-direction:row;gap:12px;margin-top:.5rem}.checkbox-radio-group ion-checkbox{--size: 24px;--checkbox-background-checked: var(--ion-color-primary);--checkmark-color: var(--ion-color-primary-contrast)}\n"] }]
15740
15667
  }], propDecorators: { props: [{
15741
15668
  type: Input
@@ -16062,67 +15989,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16062
15989
  type: Input
16063
15990
  }] } });
16064
15991
 
16065
- /**
16066
- * val-email-input
16067
- *
16068
- * An email input field integrated with Angular forms.
16069
- * Supports presets for reusable configurations.
16070
- *
16071
- * @example With preset (recommended):
16072
- * <val-email-input preset="form-field" [props]="{ control: myControl, placeholder: 'Email' }"></val-email-input>
16073
- *
16074
- * @example Static (backwards compatible):
16075
- * <val-email-input [props]="{ control: myControl, placeholder: 'Enter your email' }"></val-email-input>
16076
- *
16077
- * @input preset: string - Name of preset to apply (e.g., 'form-field')
16078
- * @input props: InputMetadata - Configuration for the input (overrides preset values)
16079
- */
16080
- class EmailInputComponent {
16081
- constructor() {
16082
- this.presets = inject(PresetService);
16083
- /**
16084
- * Input configuration object. Values here override preset values.
16085
- * @type {InputMetadata}
16086
- * @property control - The Angular FormControl for the input.
16087
- * @property placeholder - The placeholder text.
16088
- */
16089
- this.props = {};
16090
- /**
16091
- * Resolved props after merging preset + explicit props.
16092
- */
16093
- this.resolvedProps = {};
16094
- }
16095
- ngOnInit() {
16096
- this.resolveProps();
16097
- }
16098
- ngOnChanges(changes) {
16099
- if (changes['preset'] || changes['props']) {
16100
- this.resolveProps();
16101
- }
16102
- }
16103
- /**
16104
- * Merge preset configuration with explicit props.
16105
- * Explicit props take precedence over preset values.
16106
- */
16107
- resolveProps() {
16108
- const presetProps = this.preset ? this.presets.get('emailInput', this.preset) : {};
16109
- this.resolvedProps = {
16110
- ...presetProps,
16111
- ...this.props,
16112
- };
16113
- }
16114
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EmailInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16115
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: EmailInputComponent, isStandalone: true, selector: "val-email-input", inputs: { preset: "preset", props: "props" }, usesOnChanges: true, ngImport: i0, template: ` <ion-input [formControl]="resolvedProps.control" type="email" [placeholder]="resolvedProps.placeholder"></ion-input> `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.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"] }] }); }
16116
- }
16117
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EmailInputComponent, decorators: [{
16118
- type: Component,
16119
- args: [{ selector: 'val-email-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="resolvedProps.control" type="email" [placeholder]="resolvedProps.placeholder"></ion-input> ` }]
16120
- }], propDecorators: { preset: [{
16121
- type: Input
16122
- }], props: [{
16123
- type: Input
16124
- }] } });
16125
-
16126
15992
  /**
16127
15993
  * Resolves a color string to a valid CSS value for use in styles.
16128
15994
  * Supports Ionic color names, CSS variables, and custom colors.
@@ -16135,7 +16001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16135
16001
  * resolveColor('--my-custom-color'); // returns 'var(--my-custom-color)'
16136
16002
  * resolveColor('#ff0000'); // returns '#ff0000'
16137
16003
  */
16138
- function resolveColor$1(color) {
16004
+ function resolveColor(color) {
16139
16005
  // Si el color empieza con "--", se asume que es una variable CSS válida
16140
16006
  if (color.startsWith('--')) {
16141
16007
  return `var(${color})`;
@@ -16190,7 +16056,7 @@ class ExpandableTextComponent {
16190
16056
  this.expanded = !this.expanded;
16191
16057
  }
16192
16058
  color() {
16193
- return resolveColor$1(this.props.color || this.defaultColor);
16059
+ return resolveColor(this.props.color || this.defaultColor);
16194
16060
  }
16195
16061
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ExpandableTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16196
16062
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ExpandableTextComponent, isStandalone: true, selector: "val-expandable-text", inputs: { props: "props" }, ngImport: i0, template: `
@@ -16203,12 +16069,12 @@ class ExpandableTextComponent {
16203
16069
  </ion-text>
16204
16070
  </div>
16205
16071
  @if (!expanded && isTruncated) {
16206
- <span class="see-more" [style.color]="this.color()" (click)="toggleExpand()">
16072
+ <button type="button" class="see-more" [style.color]="this.color()" [attr.aria-expanded]="expanded" (click)="toggleExpand()">
16207
16073
  {{ getExpandText() }}
16208
- </span>
16074
+ </button>
16209
16075
  }
16210
16076
  </div>
16211
- `, isInline: true, styles: [".description-container{position:relative;overflow:hidden;transition:max-height .3s ease-in-out}.description-container:not(.expanded){max-height:10rem}.description-container.expanded{max-height:none}.content-wrapper{overflow:hidden}.description-container:not(.expanded).has-gradient .content-wrapper{-webkit-mask-image:linear-gradient(to bottom,black 50%,transparent 100%);mask-image:linear-gradient(to bottom,black 50%,transparent 100%)}.description{margin:0}.see-more{display:block;font-weight:700;cursor:pointer;margin-top:.25rem}\n"], dependencies: [{ kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
16077
+ `, isInline: true, styles: [".description-container{position:relative;overflow:hidden;transition:max-height .3s ease-in-out}.description-container:not(.expanded){max-height:10rem}.description-container.expanded{max-height:none}.content-wrapper{overflow:hidden}.description-container:not(.expanded).has-gradient .content-wrapper{-webkit-mask-image:linear-gradient(to bottom,black 50%,transparent 100%);mask-image:linear-gradient(to bottom,black 50%,transparent 100%)}.description{margin:0}.see-more{display:block;cursor:pointer;margin-top:.25rem;padding:0;border:none;background:none;font:inherit;font-weight:700;text-align:left}.see-more:focus{outline:none}.see-more:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:4px}\n"], dependencies: [{ kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
16212
16078
  }
16213
16079
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ExpandableTextComponent, decorators: [{
16214
16080
  type: Component,
@@ -16222,12 +16088,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16222
16088
  </ion-text>
16223
16089
  </div>
16224
16090
  @if (!expanded && isTruncated) {
16225
- <span class="see-more" [style.color]="this.color()" (click)="toggleExpand()">
16091
+ <button type="button" class="see-more" [style.color]="this.color()" [attr.aria-expanded]="expanded" (click)="toggleExpand()">
16226
16092
  {{ getExpandText() }}
16227
- </span>
16093
+ </button>
16228
16094
  }
16229
16095
  </div>
16230
- `, styles: [".description-container{position:relative;overflow:hidden;transition:max-height .3s ease-in-out}.description-container:not(.expanded){max-height:10rem}.description-container.expanded{max-height:none}.content-wrapper{overflow:hidden}.description-container:not(.expanded).has-gradient .content-wrapper{-webkit-mask-image:linear-gradient(to bottom,black 50%,transparent 100%);mask-image:linear-gradient(to bottom,black 50%,transparent 100%)}.description{margin:0}.see-more{display:block;font-weight:700;cursor:pointer;margin-top:.25rem}\n"] }]
16096
+ `, styles: [".description-container{position:relative;overflow:hidden;transition:max-height .3s ease-in-out}.description-container:not(.expanded){max-height:10rem}.description-container.expanded{max-height:none}.content-wrapper{overflow:hidden}.description-container:not(.expanded).has-gradient .content-wrapper{-webkit-mask-image:linear-gradient(to bottom,black 50%,transparent 100%);mask-image:linear-gradient(to bottom,black 50%,transparent 100%)}.description{margin:0}.see-more{display:block;cursor:pointer;margin-top:.25rem;padding:0;border:none;background:none;font:inherit;font-weight:700;text-align:left}.see-more:focus{outline:none}.see-more:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:4px}\n"] }]
16231
16097
  }], propDecorators: { props: [{
16232
16098
  type: Input
16233
16099
  }] } });
@@ -16249,7 +16115,11 @@ class FileInputComponent {
16249
16115
  ngOnInit() {
16250
16116
  // Initialize button with i18n text
16251
16117
  this.contrastButton = {
16252
- ...PrimarySolidDefaultRoundButton(this.props?.buttonText || this.i18n.t('uploadFile')),
16118
+ ...button({
16119
+ text: this.props?.buttonText || this.i18n.t('uploadFile'),
16120
+ fill: 'solid',
16121
+ shape: 'round',
16122
+ }),
16253
16123
  color: 'light',
16254
16124
  };
16255
16125
  }
@@ -16319,14 +16189,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16319
16189
  * val-hint
16320
16190
  *
16321
16191
  * Displays validation error messages for a form input, using Angular forms.
16192
+ * Cuando muestra un error, el contenedor se anuncia a tecnologías asistivas
16193
+ * (`role="alert"` + `aria-live="assertive"`). Acepta un `id` para que el input
16194
+ * asociado lo referencie vía `aria-describedby`.
16322
16195
  *
16323
16196
  * @example
16324
- * <val-hint [props]="{ control: myControl, errors: { required: 'Required field' } }"></val-hint>
16197
+ * <val-hint [props]="{ control: myControl, errors: { required: 'Required field' } }" id="email-error"></val-hint>
16325
16198
  *
16326
16199
  * @input props: InputMetadata - Configuration for the input (form control, errors, etc.)
16200
+ * @input id: string - Id del contenedor, para enlace `aria-describedby` desde el input.
16327
16201
  */
16328
16202
  class HintComponent {
16329
16203
  constructor() {
16204
+ /**
16205
+ * Si el hint representa un error (vs un hint informativo). Hoy `val-hint`
16206
+ * siempre muestra errores de validación, así que por defecto es `true`.
16207
+ */
16208
+ this.isError = true;
16330
16209
  this.i18n = inject(I18nService);
16331
16210
  }
16332
16211
  ngOnInit() { }
@@ -16366,8 +16245,14 @@ class HintComponent {
16366
16245
  return errors;
16367
16246
  }
16368
16247
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16369
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: HintComponent, isStandalone: true, selector: "val-hint", inputs: { props: "props" }, ngImport: i0, template: `
16370
- <div class="hint-container" *ngIf="shouldShowErrors">
16248
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: HintComponent, isStandalone: true, selector: "val-hint", inputs: { props: "props", id: "id", isError: "isError" }, ngImport: i0, template: `
16249
+ <div
16250
+ class="hint-container"
16251
+ *ngIf="shouldShowErrors"
16252
+ [attr.id]="id"
16253
+ [attr.role]="isError ? 'alert' : 'status'"
16254
+ [attr.aria-live]="isError ? 'assertive' : 'polite'"
16255
+ >
16371
16256
  <val-text
16372
16257
  *ngFor="let e of Errors"
16373
16258
  [props]="{
@@ -16383,7 +16268,13 @@ class HintComponent {
16383
16268
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HintComponent, decorators: [{
16384
16269
  type: Component,
16385
16270
  args: [{ selector: 'val-hint', standalone: true, imports: [CommonModule, TextComponent], template: `
16386
- <div class="hint-container" *ngIf="shouldShowErrors">
16271
+ <div
16272
+ class="hint-container"
16273
+ *ngIf="shouldShowErrors"
16274
+ [attr.id]="id"
16275
+ [attr.role]="isError ? 'alert' : 'status'"
16276
+ [attr.aria-live]="isError ? 'assertive' : 'polite'"
16277
+ >
16387
16278
  <val-text
16388
16279
  *ngFor="let e of Errors"
16389
16280
  [props]="{
@@ -16397,28 +16288,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16397
16288
  `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}.hint-container{margin-top:.25rem}\n"] }]
16398
16289
  }], ctorParameters: () => [], propDecorators: { props: [{
16399
16290
  type: Input
16400
- }] } });
16401
-
16402
- /**
16403
- * val-hour-input
16404
- *
16405
- * A time picker input integrated with Angular forms, using Ionic's datetime component.
16406
- *
16407
- * @example
16408
- * <val-hour-input [props]="{ control: myControl }"></val-hour-input>
16409
- *
16410
- * @input props: InputMetadata - Configuration for the time input (form control, etc.)
16411
- */
16412
- class HourInputComponent {
16413
- constructor() { }
16414
- ngOnInit() { }
16415
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HourInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16416
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: HourInputComponent, isStandalone: true, selector: "val-hour-input", inputs: { props: "props" }, ngImport: i0, template: ` <ion-datetime [formControl]="props.control" presentation="time"></ion-datetime>`, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }] }); }
16417
- }
16418
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HourInputComponent, decorators: [{
16419
- type: Component,
16420
- args: [{ selector: 'val-hour-input', standalone: true, imports: [ReactiveFormsModule, IonDatetime], template: ` <ion-datetime [formControl]="props.control" presentation="time"></ion-datetime>` }]
16421
- }], ctorParameters: () => [], propDecorators: { props: [{
16291
+ }], id: [{
16292
+ type: Input
16293
+ }], isError: [{
16422
16294
  type: Input
16423
16295
  }] } });
16424
16296
 
@@ -17114,7 +16986,7 @@ class LayeredCardComponent {
17114
16986
  if (!background) {
17115
16987
  return '';
17116
16988
  }
17117
- return resolveColor$1(background);
16989
+ return resolveColor(background);
17118
16990
  }
17119
16991
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LayeredCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17120
16992
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LayeredCardComponent, isStandalone: true, selector: "layered-card", inputs: { props: "props" }, ngImport: i0, template: `
@@ -17538,145 +17410,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
17538
17410
  args: [{ required: true }]
17539
17411
  }] } });
17540
17412
 
17541
- /**
17542
- * Utilities for handling default values in form inputs based on InputMetadata configuration.
17543
- */
17544
- /**
17545
- * Resolves the initial value for a form input based on its configuration.
17546
- *
17547
- * @param input - The input metadata configuration
17548
- * @returns The resolved initial value
17549
- *
17550
- * @example
17551
- * // Custom default value
17552
- * const customValue = resolveInputDefaultValue({ withDefault: '2025-06-24', type: InputType.DATE });
17553
- *
17554
- * // Auto default value
17555
- * const autoValue = resolveInputDefaultValue({ withDefault: true, type: InputType.NUMBER });
17556
- *
17557
- * // Explicit value (takes precedence)
17558
- * const explicitValue = resolveInputDefaultValue({ value: 'explicit', withDefault: true, type: InputType.TEXT });
17559
- */
17560
- function resolveInputDefaultValue(input) {
17561
- // Explicit value takes precedence
17562
- if (input.value !== undefined && input.value !== null && input.value !== '') {
17563
- return parseValueByType(input.value, input.type);
17564
- }
17565
- // No default configuration
17566
- if (!input.withDefault) {
17567
- return null;
17568
- }
17569
- // Custom default value
17570
- if (typeof input.withDefault === 'string') {
17571
- return parseValueByType(input.withDefault, input.type);
17572
- }
17573
- // Auto default value (withDefault === true)
17574
- return getAutoDefaultValue(input.type);
17575
- }
17576
- /**
17577
- * Parses a string value to the appropriate type based on the input type.
17578
- *
17579
- * @param value - The string value to parse
17580
- * @param type - The input type
17581
- * @returns The parsed value
17582
- */
17583
- function parseValueByType(value, type) {
17584
- switch (type) {
17585
- case InputType.DATE:
17586
- return new Date(value).toISOString();
17587
- case InputType.NUMBER:
17588
- return parseFloat(value) || 0;
17589
- case InputType.CHECK:
17590
- return value === 'true' || value === '1';
17591
- case InputType.TEXT:
17592
- case InputType.EMAIL:
17593
- case InputType.PASSWORD:
17594
- case InputType.COMMENT:
17595
- case InputType.PIN_CODE:
17596
- case InputType.HOUR:
17597
- case InputType.RADIO:
17598
- case InputType.SELECT:
17599
- case InputType.SEARCH_SELECT:
17600
- case InputType.FILE:
17601
- default:
17602
- return value;
17603
- }
17604
- }
17605
- /**
17606
- * Gets the automatic default value for a given input type.
17607
- *
17608
- * @param type - The input type
17609
- * @returns The auto default value
17610
- */
17611
- function getAutoDefaultValue(type) {
17612
- switch (type) {
17613
- case InputType.DATE:
17614
- return new Date().toISOString();
17615
- case InputType.NUMBER:
17616
- return 0;
17617
- case InputType.CHECK:
17618
- return false;
17619
- case InputType.TEXT:
17620
- case InputType.EMAIL:
17621
- case InputType.PASSWORD:
17622
- case InputType.COMMENT:
17623
- case InputType.PIN_CODE:
17624
- case InputType.HOUR:
17625
- case InputType.RADIO:
17626
- case InputType.SELECT:
17627
- case InputType.SEARCH_SELECT:
17628
- case InputType.FILE:
17629
- default:
17630
- return '';
17631
- }
17632
- }
17633
- /**
17634
- * Applies the resolved default value to a FormControl.
17635
- *
17636
- * @param input - The input metadata configuration
17637
- * @example
17638
- * const input = { control: myFormControl, type: InputType.DATE, withDefault: true };
17639
- * applyDefaultValueToControl(input);
17640
- */
17641
- function applyDefaultValueToControl(input) {
17642
- if (!input.control)
17643
- return;
17644
- const defaultValue = resolveInputDefaultValue(input);
17645
- if (defaultValue !== null) {
17646
- input.control.setValue(defaultValue);
17647
- input.control.markAsPristine();
17648
- input.control.updateValueAndValidity();
17649
- }
17650
- }
17651
-
17652
- /**
17653
- * val-number-input
17654
- *
17655
- * A number input field integrated with Angular forms.
17656
- *
17657
- * @example
17658
- * <val-number-input [props]="{ control: myControl, placeholder: 'Enter a number' }"></val-number-input>
17659
- *
17660
- * @input props: InputMetadata - Configuration for the input (form control, placeholder, etc.)
17661
- */
17662
- class NumberInputComponent {
17663
- constructor() { }
17664
- ngOnInit() {
17665
- // Apply default values on initialization
17666
- if (this.props?.withDefault || this.props?.value) {
17667
- applyDefaultValueToControl(this.props);
17668
- }
17669
- }
17670
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17671
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", 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$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.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"] }] }); }
17672
- }
17673
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NumberInputComponent, decorators: [{
17674
- type: Component,
17675
- args: [{ selector: 'val-number-input', standalone: true, imports: [ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="props.control" type="number" [placeholder]="props.placeholder"></ion-input> ` }]
17676
- }], ctorParameters: () => [], propDecorators: { props: [{
17677
- type: Input
17678
- }] } });
17679
-
17680
17413
  /**
17681
17414
  * val-number-from-to
17682
17415
  *
@@ -17814,6 +17547,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
17814
17547
  type: Input
17815
17548
  }] } });
17816
17549
 
17550
+ /**
17551
+ * Defaults i18n (es/en) — auto-registrados si el consumer no proveyó el
17552
+ * namespace `PasswordInput`. Cubre el aria-label del toggle mostrar/ocultar.
17553
+ */
17554
+ const PASSWORD_INPUT_I18N = {
17555
+ es: { showPassword: 'Mostrar contraseña', hidePassword: 'Ocultar contraseña' },
17556
+ en: { showPassword: 'Show password', hidePassword: 'Hide password' },
17557
+ };
17817
17558
  /**
17818
17559
  * val-password-input
17819
17560
  *
@@ -17830,8 +17571,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
17830
17571
  * @input props: InputMetadata - Configuration for the input (overrides preset values)
17831
17572
  */
17832
17573
  class PasswordInputComponent {
17833
- constructor(icon) {
17574
+ constructor() {
17834
17575
  this.presets = inject(PresetService);
17576
+ this.i18n = inject(I18nService);
17835
17577
  /**
17836
17578
  * Input configuration object. Values here override preset values.
17837
17579
  * @type {InputMetadata}
@@ -17844,6 +17586,16 @@ class PasswordInputComponent {
17844
17586
  */
17845
17587
  this.resolvedProps = {};
17846
17588
  this.hidePassword = true;
17589
+ if (!this.i18n.hasNamespace('PasswordInput')) {
17590
+ this.i18n.registerContent('PasswordInput', PASSWORD_INPUT_I18N);
17591
+ }
17592
+ }
17593
+ /** Aria-label del botón mostrar/ocultar según el estado de visibilidad. */
17594
+ toggleLabel() {
17595
+ this.i18n.lang();
17596
+ return this.hidePassword
17597
+ ? this.i18n.t('showPassword', 'PasswordInput')
17598
+ : this.i18n.t('hidePassword', 'PasswordInput');
17847
17599
  }
17848
17600
  ngOnInit() {
17849
17601
  this.resolveProps();
@@ -17864,7 +17616,7 @@ class PasswordInputComponent {
17864
17616
  ...this.props,
17865
17617
  };
17866
17618
  }
17867
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PasswordInputComponent, deps: [{ token: IconService }], target: i0.ɵɵFactoryTarget.Component }); }
17619
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PasswordInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17868
17620
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: PasswordInputComponent, isStandalone: true, selector: "val-password-input", inputs: { preset: "preset", props: "props" }, usesOnChanges: true, ngImport: i0, template: `
17869
17621
  <div class="input-container">
17870
17622
  <ion-input
@@ -17873,7 +17625,14 @@ class PasswordInputComponent {
17873
17625
  [type]="hidePassword ? 'password' : 'text'"
17874
17626
  [placeholder]="resolvedProps.placeholder"
17875
17627
  ></ion-input>
17876
- <ion-button color="dark" fill="clear" (click)="hidePassword = !hidePassword" size="small">
17628
+ <ion-button
17629
+ color="dark"
17630
+ fill="clear"
17631
+ (click)="hidePassword = !hidePassword"
17632
+ size="small"
17633
+ [attr.aria-label]="toggleLabel()"
17634
+ [attr.aria-pressed]="!hidePassword"
17635
+ >
17877
17636
  <ion-icon slot="icon-only" [name]="hidePassword ? 'eye-off-outline' : 'eye-outline'"></ion-icon>
17878
17637
  </ion-button>
17879
17638
  </div>
@@ -17889,12 +17648,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
17889
17648
  [type]="hidePassword ? 'password' : 'text'"
17890
17649
  [placeholder]="resolvedProps.placeholder"
17891
17650
  ></ion-input>
17892
- <ion-button color="dark" fill="clear" (click)="hidePassword = !hidePassword" size="small">
17651
+ <ion-button
17652
+ color="dark"
17653
+ fill="clear"
17654
+ (click)="hidePassword = !hidePassword"
17655
+ size="small"
17656
+ [attr.aria-label]="toggleLabel()"
17657
+ [attr.aria-pressed]="!hidePassword"
17658
+ >
17893
17659
  <ion-icon slot="icon-only" [name]="hidePassword ? 'eye-off-outline' : 'eye-outline'"></ion-icon>
17894
17660
  </ion-button>
17895
17661
  </div>
17896
17662
  `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}.input-container{display:flex;align-items:center;flex-direction:row}\n"] }]
17897
- }], ctorParameters: () => [{ type: IconService }], propDecorators: { preset: [{
17663
+ }], ctorParameters: () => [], propDecorators: { preset: [{
17898
17664
  type: Input
17899
17665
  }], props: [{
17900
17666
  type: Input
@@ -18447,6 +18213,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
18447
18213
  type: Output
18448
18214
  }] } });
18449
18215
 
18216
+ /**
18217
+ * Utilities for handling default values in form inputs based on InputMetadata configuration.
18218
+ */
18219
+ /**
18220
+ * Resolves the initial value for a form input based on its configuration.
18221
+ *
18222
+ * @param input - The input metadata configuration
18223
+ * @returns The resolved initial value
18224
+ *
18225
+ * @example
18226
+ * // Custom default value
18227
+ * const customValue = resolveInputDefaultValue({ withDefault: '2025-06-24', type: InputType.DATE });
18228
+ *
18229
+ * // Auto default value
18230
+ * const autoValue = resolveInputDefaultValue({ withDefault: true, type: InputType.NUMBER });
18231
+ *
18232
+ * // Explicit value (takes precedence)
18233
+ * const explicitValue = resolveInputDefaultValue({ value: 'explicit', withDefault: true, type: InputType.TEXT });
18234
+ */
18235
+ function resolveInputDefaultValue(input) {
18236
+ // Explicit value takes precedence
18237
+ if (input.value !== undefined && input.value !== null && input.value !== '') {
18238
+ return parseValueByType(input.value, input.type);
18239
+ }
18240
+ // No default configuration
18241
+ if (!input.withDefault) {
18242
+ return null;
18243
+ }
18244
+ // Custom default value
18245
+ if (typeof input.withDefault === 'string') {
18246
+ return parseValueByType(input.withDefault, input.type);
18247
+ }
18248
+ // Auto default value (withDefault === true)
18249
+ return getAutoDefaultValue(input.type);
18250
+ }
18251
+ /**
18252
+ * Parses a string value to the appropriate type based on the input type.
18253
+ *
18254
+ * @param value - The string value to parse
18255
+ * @param type - The input type
18256
+ * @returns The parsed value
18257
+ */
18258
+ function parseValueByType(value, type) {
18259
+ switch (type) {
18260
+ case InputType.DATE:
18261
+ return new Date(value).toISOString();
18262
+ case InputType.NUMBER:
18263
+ return parseFloat(value) || 0;
18264
+ case InputType.CHECK:
18265
+ return value === 'true' || value === '1';
18266
+ case InputType.TEXT:
18267
+ case InputType.EMAIL:
18268
+ case InputType.PASSWORD:
18269
+ case InputType.COMMENT:
18270
+ case InputType.PIN_CODE:
18271
+ case InputType.HOUR:
18272
+ case InputType.RADIO:
18273
+ case InputType.SELECT:
18274
+ case InputType.SEARCH_SELECT:
18275
+ case InputType.FILE:
18276
+ default:
18277
+ return value;
18278
+ }
18279
+ }
18280
+ /**
18281
+ * Gets the automatic default value for a given input type.
18282
+ *
18283
+ * @param type - The input type
18284
+ * @returns The auto default value
18285
+ */
18286
+ function getAutoDefaultValue(type) {
18287
+ switch (type) {
18288
+ case InputType.DATE:
18289
+ return new Date().toISOString();
18290
+ case InputType.NUMBER:
18291
+ return 0;
18292
+ case InputType.CHECK:
18293
+ return false;
18294
+ case InputType.TEXT:
18295
+ case InputType.EMAIL:
18296
+ case InputType.PASSWORD:
18297
+ case InputType.COMMENT:
18298
+ case InputType.PIN_CODE:
18299
+ case InputType.HOUR:
18300
+ case InputType.RADIO:
18301
+ case InputType.SELECT:
18302
+ case InputType.SEARCH_SELECT:
18303
+ case InputType.FILE:
18304
+ default:
18305
+ return '';
18306
+ }
18307
+ }
18308
+ /**
18309
+ * Applies the resolved default value to a FormControl.
18310
+ *
18311
+ * @param input - The input metadata configuration
18312
+ * @example
18313
+ * const input = { control: myFormControl, type: InputType.DATE, withDefault: true };
18314
+ * applyDefaultValueToControl(input);
18315
+ */
18316
+ function applyDefaultValueToControl(input) {
18317
+ if (!input.control)
18318
+ return;
18319
+ const defaultValue = resolveInputDefaultValue(input);
18320
+ if (defaultValue !== null) {
18321
+ input.control.setValue(defaultValue);
18322
+ input.control.markAsPristine();
18323
+ input.control.updateValueAndValidity();
18324
+ }
18325
+ }
18326
+
18450
18327
  /**
18451
18328
  * val-select-input
18452
18329
  *
@@ -19129,17 +19006,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19129
19006
  type: Output
19130
19007
  }] } });
19131
19008
 
19009
+ /** Contador estático para generar ids únicos por instancia. */
19010
+ let textInputUid = 0;
19132
19011
  /**
19133
19012
  * val-text-input
19134
19013
  *
19135
- * A text input field integrated with Angular forms.
19014
+ * A text input field integrated with Angular forms. Renders the native HTML
19015
+ * input type from `props.inputType` (default 'text'). Collapses the former
19016
+ * `val-email-input` / `val-number-input` / `val-hour-input` molecules:
19017
+ * - `inputType: 'email' | 'number' | 'tel' | 'password' | ...` → `<ion-input [type]>`
19018
+ * - `inputType: 'time'` → `<ion-datetime presentation="time">` (ex `val-hour-input`)
19019
+ *
19136
19020
  * Supports presets for reusable configurations.
19137
19021
  *
19138
19022
  * @example With preset (recommended):
19139
19023
  * <val-text-input preset="form-field" [props]="{ control: myControl, placeholder: 'Enter text' }"></val-text-input>
19140
19024
  *
19141
- * @example Static (backwards compatible):
19142
- * <val-text-input [props]="{ control: myControl, placeholder: 'Enter text' }"></val-text-input>
19025
+ * @example Email:
19026
+ * <val-text-input [props]="{ control: emailControl, inputType: 'email' }"></val-text-input>
19027
+ *
19028
+ * @example Time picker (ex val-hour-input):
19029
+ * <val-text-input [props]="{ control: timeControl, inputType: 'time' }"></val-text-input>
19143
19030
  *
19144
19031
  * @input preset: string - Name of preset to apply (e.g., 'form-field', 'search')
19145
19032
  * @input props: InputMetadata - Configuration for the input (overrides preset values)
@@ -19152,6 +19039,7 @@ class TextInputComponent {
19152
19039
  * @type {InputMetadata}
19153
19040
  * @property control - The Angular FormControl for the input.
19154
19041
  * @property placeholder - The placeholder text.
19042
+ * @property inputType - Native HTML input type ('text' | 'email' | 'number' | 'tel' | 'password' | 'time' | ...).
19155
19043
  * @property label, name, hint, type, validators, etc. - See InputMetadata for all options.
19156
19044
  */
19157
19045
  this.props = {};
@@ -19161,6 +19049,23 @@ class TextInputComponent {
19161
19049
  */
19162
19050
  this.resolvedProps = {};
19163
19051
  this.states = ComponentStates;
19052
+ /** Ids únicos por instancia para el wiring de accesibilidad label↔input↔error. */
19053
+ this.uid = `val-text-input-${textInputUid++}`;
19054
+ this.inputId = `${this.uid}-control`;
19055
+ }
19056
+ /**
19057
+ * Id del label visible. Si `val-form` orquesta el campo, pasa el id del
19058
+ * `<val-title>` externo vía `props.labelId`; si no, se usa el id interno.
19059
+ */
19060
+ get labelId() {
19061
+ return this.resolvedProps?.labelId ?? `${this.uid}-label`;
19062
+ }
19063
+ /**
19064
+ * Id del contenedor de error. Si `val-form` orquesta el campo, pasa el id del
19065
+ * `<val-hint>` externo vía `props.errorId`; si no, se usa el id interno.
19066
+ */
19067
+ get errorId() {
19068
+ return this.resolvedProps?.errorId ?? `${this.uid}-error`;
19164
19069
  }
19165
19070
  ngOnInit() {
19166
19071
  this.resolveProps();
@@ -19174,6 +19079,18 @@ class TextInputComponent {
19174
19079
  this.resolveProps();
19175
19080
  }
19176
19081
  }
19082
+ /**
19083
+ * Native HTML input type, defaulting to 'text'. Drives both the `[type]` of the
19084
+ * `<ion-input>` and the branch between `<ion-input>` and `<ion-datetime>`.
19085
+ */
19086
+ get resolvedType() {
19087
+ return this.resolvedProps?.inputType ?? 'text';
19088
+ }
19089
+ /** Para `aria-invalid` / `aria-describedby`: error visible solo si tocado. */
19090
+ get isInvalid() {
19091
+ const control = this.resolvedProps?.control;
19092
+ return !!(control && control.invalid && control.touched);
19093
+ }
19177
19094
  /**
19178
19095
  * Merge preset configuration with explicit props.
19179
19096
  * Explicit props take precedence over preset values.
@@ -19187,11 +19104,57 @@ class TextInputComponent {
19187
19104
  };
19188
19105
  }
19189
19106
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
19190
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TextInputComponent, isStandalone: true, selector: "val-text-input", inputs: { preset: "preset", props: "props" }, usesOnChanges: true, ngImport: i0, template: ` <ion-input [formControl]="resolvedProps.control" type="text" [placeholder]="resolvedProps.placeholder" /> `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.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"] }] }); }
19107
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TextInputComponent, isStandalone: true, selector: "val-text-input", inputs: { preset: "preset", props: "props" }, usesOnChanges: true, ngImport: i0, template: `
19108
+ @if (resolvedType === 'time') {
19109
+ <ion-datetime
19110
+ [formControl]="resolvedProps.control"
19111
+ presentation="time"
19112
+ [attr.id]="inputId"
19113
+ [attr.aria-label]="resolvedProps.label || null"
19114
+ [attr.aria-labelledby]="resolvedProps.label ? labelId : null"
19115
+ [attr.aria-invalid]="isInvalid"
19116
+ [attr.aria-describedby]="isInvalid ? errorId : null"
19117
+ ></ion-datetime>
19118
+ } @else {
19119
+ <ion-input
19120
+ [formControl]="resolvedProps.control"
19121
+ [type]="resolvedType"
19122
+ [placeholder]="resolvedProps.placeholder"
19123
+ [attr.id]="inputId"
19124
+ [attr.aria-label]="resolvedProps.label || null"
19125
+ [attr.aria-labelledby]="resolvedProps.label ? labelId : null"
19126
+ [attr.aria-invalid]="isInvalid"
19127
+ [attr.aria-describedby]="isInvalid ? errorId : null"
19128
+ />
19129
+ }
19130
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.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: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }] }); }
19191
19131
  }
19192
19132
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextInputComponent, decorators: [{
19193
19133
  type: Component,
19194
- args: [{ selector: 'val-text-input', standalone: true, imports: [ReactiveFormsModule, IonInput], template: ` <ion-input [formControl]="resolvedProps.control" type="text" [placeholder]="resolvedProps.placeholder" /> `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}\n"] }]
19134
+ args: [{ selector: 'val-text-input', standalone: true, imports: [ReactiveFormsModule, IonInput, IonDatetime], template: `
19135
+ @if (resolvedType === 'time') {
19136
+ <ion-datetime
19137
+ [formControl]="resolvedProps.control"
19138
+ presentation="time"
19139
+ [attr.id]="inputId"
19140
+ [attr.aria-label]="resolvedProps.label || null"
19141
+ [attr.aria-labelledby]="resolvedProps.label ? labelId : null"
19142
+ [attr.aria-invalid]="isInvalid"
19143
+ [attr.aria-describedby]="isInvalid ? errorId : null"
19144
+ ></ion-datetime>
19145
+ } @else {
19146
+ <ion-input
19147
+ [formControl]="resolvedProps.control"
19148
+ [type]="resolvedType"
19149
+ [placeholder]="resolvedProps.placeholder"
19150
+ [attr.id]="inputId"
19151
+ [attr.aria-label]="resolvedProps.label || null"
19152
+ [attr.aria-labelledby]="resolvedProps.label ? labelId : null"
19153
+ [attr.aria-invalid]="isInvalid"
19154
+ [attr.aria-describedby]="isInvalid ? errorId : null"
19155
+ />
19156
+ }
19157
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}\n"] }]
19195
19158
  }], propDecorators: { preset: [{
19196
19159
  type: Input
19197
19160
  }], props: [{
@@ -19434,7 +19397,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19434
19397
  type: Input
19435
19398
  }] } });
19436
19399
 
19437
- const IONIC_COLORS$9 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
19400
+ const IONIC_COLORS$6 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
19438
19401
  class PillComponent {
19439
19402
  constructor() {
19440
19403
  this.presets = inject(PresetService);
@@ -19474,7 +19437,7 @@ class PillComponent {
19474
19437
  }
19475
19438
  getIconColor() {
19476
19439
  const c = this.resolvedProps.notification?.iconColor || 'warning';
19477
- return IONIC_COLORS$9.includes(c) ? `var(--ion-color-${c})` : c;
19440
+ return IONIC_COLORS$6.includes(c) ? `var(--ion-color-${c})` : c;
19478
19441
  }
19479
19442
  onPillClick(event) {
19480
19443
  if (!this.resolvedProps.clickable)
@@ -19626,17 +19589,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
19626
19589
  type: Output
19627
19590
  }] } });
19628
19591
 
19592
+ /**
19593
+ * Defaults i18n (es/en) — auto-registrados si el consumer no proveyó el
19594
+ * namespace `CommandDisplay`. Cubre el aria-label del botón copiar.
19595
+ */
19596
+ const COMMAND_DISPLAY_I18N = {
19597
+ es: { copy: 'Copiar comando' },
19598
+ en: { copy: 'Copy command' },
19599
+ };
19629
19600
  class CommandDisplayComponent {
19630
19601
  constructor() {
19631
19602
  this.toast = inject(ToastController);
19632
19603
  this.i18n = inject(I18nService);
19604
+ /** Mensaje anunciado por el lector de pantalla al copiar. */
19605
+ this.copiedMessage = '';
19606
+ if (!this.i18n.hasNamespace('CommandDisplay')) {
19607
+ this.i18n.registerContent('CommandDisplay', COMMAND_DISPLAY_I18N);
19608
+ }
19609
+ }
19610
+ copyLabel() {
19611
+ this.i18n.lang();
19612
+ return this.i18n.t('copy', 'CommandDisplay');
19633
19613
  }
19634
19614
  async copyCommand() {
19635
19615
  if (this.props.text) {
19636
19616
  await Clipboard.write({
19637
19617
  string: this.props.text,
19638
19618
  });
19639
- this.presentToast(this.i18n.t('copiedToClipboard'));
19619
+ const message = this.i18n.t('copiedToClipboard');
19620
+ this.copiedMessage = message;
19621
+ this.presentToast(message);
19640
19622
  }
19641
19623
  }
19642
19624
  async presentToast(message) {
@@ -19652,19 +19634,25 @@ class CommandDisplayComponent {
19652
19634
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CommandDisplayComponent, isStandalone: true, selector: "val-command-display", inputs: { props: "props" }, ngImport: i0, template: `
19653
19635
  <div class="command-container">
19654
19636
  <div class="command-text">$ {{ props.text }}</div>
19655
- <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
19637
+ <button type="button" class="copy-button" [attr.aria-label]="copyLabel()" (click)="copyCommand()">
19638
+ <ion-icon name="copy-outline" class="copy-icon" aria-hidden="true"></ion-icon>
19639
+ </button>
19656
19640
  </div>
19657
- `, 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"] }] }); }
19641
+ <span class="sr-only" role="status" aria-live="polite">{{ copiedMessage }}</span>
19642
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}.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-button{display:inline-flex;align-items:center;justify-content:center;padding:4px;margin:0;border:none;background:none;line-height:0;cursor:pointer;border-radius:8px}.copy-button:focus{outline:none}.copy-button:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.copy-button:hover .copy-icon{color:var(--ion-color-primary, #3880ff)}.copy-icon{font-size:1.3rem;color:var(--ion-color-medium, #92949c);transition:color .2s ease-in-out}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@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"] }] }); }
19658
19643
  }
19659
19644
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommandDisplayComponent, decorators: [{
19660
19645
  type: Component,
19661
19646
  args: [{ selector: 'val-command-display', standalone: true, imports: [CommonModule, IonIcon], template: `
19662
19647
  <div class="command-container">
19663
19648
  <div class="command-text">$ {{ props.text }}</div>
19664
- <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
19649
+ <button type="button" class="copy-button" [attr.aria-label]="copyLabel()" (click)="copyCommand()">
19650
+ <ion-icon name="copy-outline" class="copy-icon" aria-hidden="true"></ion-icon>
19651
+ </button>
19665
19652
  </div>
19666
- `, 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"] }]
19667
- }], propDecorators: { props: [{
19653
+ <span class="sr-only" role="status" aria-live="polite">{{ copiedMessage }}</span>
19654
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}.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-button{display:inline-flex;align-items:center;justify-content:center;padding:4px;margin:0;border:none;background:none;line-height:0;cursor:pointer;border-radius:8px}.copy-button:focus{outline:none}.copy-button:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.copy-button:hover .copy-icon{color:var(--ion-color-primary, #3880ff)}.copy-icon{font-size:1.3rem;color:var(--ion-color-medium, #92949c);transition:color .2s ease-in-out}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media (min-width: 600px){.command-text,.copy-icon{font-size:1.2rem}}\n"] }]
19655
+ }], ctorParameters: () => [], propDecorators: { props: [{
19668
19656
  type: Input
19669
19657
  }] } });
19670
19658
 
@@ -20062,9 +20050,7 @@ class BreadcrumbComponent {
20062
20050
  }
20063
20051
  }
20064
20052
  resolveProps() {
20065
- const presetProps = this.preset
20066
- ? this.presets.get('breadcrumb', this.preset)
20067
- : {};
20053
+ const presetProps = this.preset ? this.presets.get('breadcrumb', this.preset) : {};
20068
20054
  this.resolvedProps = {
20069
20055
  ...presetProps,
20070
20056
  ...this.props,
@@ -20094,6 +20080,7 @@ class BreadcrumbComponent {
20094
20080
  [active]="item.active || isLast"
20095
20081
  [disabled]="item.disabled"
20096
20082
  [separator]="!isLast"
20083
+ [attr.aria-current]="item.active || isLast ? 'page' : null"
20097
20084
  (click)="onBreadcrumbClick($event, item, $index)"
20098
20085
  >
20099
20086
  @if (item.icon) {
@@ -20122,6 +20109,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20122
20109
  [active]="item.active || isLast"
20123
20110
  [disabled]="item.disabled"
20124
20111
  [separator]="!isLast"
20112
+ [attr.aria-current]="item.active || isLast ? 'page' : null"
20125
20113
  (click)="onBreadcrumbClick($event, item, $index)"
20126
20114
  >
20127
20115
  @if (item.icon) {
@@ -20146,6 +20134,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20146
20134
  }] } });
20147
20135
 
20148
20136
  addIcons({ chevronBack, chevronForward, playBack, playForward });
20137
+ /**
20138
+ * Defaults i18n (es/en) — auto-registrados si el consumer no proveyó el
20139
+ * namespace `Pagination`. Cubre los aria-label de la navegación y sus botones.
20140
+ */
20141
+ const PAGINATION_I18N = {
20142
+ es: {
20143
+ nav: 'Paginación',
20144
+ first: 'Primera página',
20145
+ previous: 'Página anterior',
20146
+ next: 'Página siguiente',
20147
+ last: 'Última página',
20148
+ page: 'Página {page}',
20149
+ pageInfo: 'Página {current} de {total}',
20150
+ },
20151
+ en: {
20152
+ nav: 'Pagination',
20153
+ first: 'First page',
20154
+ previous: 'Previous page',
20155
+ next: 'Next page',
20156
+ last: 'Last page',
20157
+ page: 'Page {page}',
20158
+ pageInfo: 'Page {current} of {total}',
20159
+ },
20160
+ };
20149
20161
  /**
20150
20162
  * val-pagination
20151
20163
  *
@@ -20171,9 +20183,28 @@ addIcons({ chevronBack, chevronForward, playBack, playForward });
20171
20183
  */
20172
20184
  class PaginationComponent {
20173
20185
  constructor() {
20186
+ this.i18n = inject(I18nService);
20174
20187
  this.pageChange = new EventEmitter();
20175
20188
  this.visiblePages = [];
20176
20189
  this.totalPages = 1;
20190
+ if (!this.i18n.hasNamespace('Pagination')) {
20191
+ this.i18n.registerContent('Pagination', PAGINATION_I18N);
20192
+ }
20193
+ }
20194
+ t(key) {
20195
+ this.i18n.lang();
20196
+ return this.i18n.t(key, 'Pagination');
20197
+ }
20198
+ pageLabel(page) {
20199
+ this.i18n.lang();
20200
+ return this.i18n.t('page', 'Pagination', { page: page.toString() });
20201
+ }
20202
+ pageInfo() {
20203
+ this.i18n.lang();
20204
+ return this.i18n.t('pageInfo', 'Pagination', {
20205
+ current: this.props.currentPage.toString(),
20206
+ total: this.totalPages.toString(),
20207
+ });
20177
20208
  }
20178
20209
  ngOnChanges(changes) {
20179
20210
  if (changes['props']) {
@@ -20242,16 +20273,17 @@ class PaginationComponent {
20242
20273
  }
20243
20274
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
20244
20275
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: PaginationComponent, isStandalone: true, selector: "val-pagination", inputs: { props: "props" }, outputs: { pageChange: "pageChange" }, usesOnChanges: true, ngImport: i0, template: `
20245
- <div class="pagination-container" [class.disabled]="props.disabled">
20276
+ <nav class="pagination-container" [class.disabled]="props.disabled" [attr.aria-label]="t('nav')">
20246
20277
  @if (props.showFirstLast !== false) {
20247
20278
  <ion-button
20248
20279
  fill="clear"
20249
20280
  [size]="props.size || 'default'"
20250
20281
  [color]="props.color || 'primary'"
20251
20282
  [disabled]="props.disabled || props.currentPage <= 1"
20283
+ [attr.aria-label]="t('first')"
20252
20284
  (click)="goToPage(1)"
20253
20285
  >
20254
- <ion-icon slot="icon-only" name="play-back"></ion-icon>
20286
+ <ion-icon slot="icon-only" name="play-back" aria-hidden="true"></ion-icon>
20255
20287
  </ion-button>
20256
20288
  }
20257
20289
 
@@ -20261,21 +20293,24 @@ class PaginationComponent {
20261
20293
  [size]="props.size || 'default'"
20262
20294
  [color]="props.color || 'primary'"
20263
20295
  [disabled]="props.disabled || props.currentPage <= 1"
20296
+ [attr.aria-label]="t('previous')"
20264
20297
  (click)="goToPage(props.currentPage - 1)"
20265
20298
  >
20266
- <ion-icon slot="icon-only" name="chevron-back"></ion-icon>
20299
+ <ion-icon slot="icon-only" name="chevron-back" aria-hidden="true"></ion-icon>
20267
20300
  </ion-button>
20268
20301
  }
20269
20302
 
20270
20303
  @for (page of visiblePages; track page) {
20271
20304
  @if (page === -1) {
20272
- <span class="ellipsis">...</span>
20305
+ <span class="ellipsis" aria-hidden="true">...</span>
20273
20306
  } @else {
20274
20307
  <ion-button
20275
20308
  [fill]="page === props.currentPage ? 'solid' : 'clear'"
20276
20309
  [size]="props.size || 'default'"
20277
20310
  [color]="props.color || 'primary'"
20278
20311
  [disabled]="props.disabled"
20312
+ [attr.aria-label]="pageLabel(page)"
20313
+ [attr.aria-current]="page === props.currentPage ? 'page' : null"
20279
20314
  (click)="goToPage(page)"
20280
20315
  >
20281
20316
  {{ page }}
@@ -20289,9 +20324,10 @@ class PaginationComponent {
20289
20324
  [size]="props.size || 'default'"
20290
20325
  [color]="props.color || 'primary'"
20291
20326
  [disabled]="props.disabled || props.currentPage >= totalPages"
20327
+ [attr.aria-label]="t('next')"
20292
20328
  (click)="goToPage(props.currentPage + 1)"
20293
20329
  >
20294
- <ion-icon slot="icon-only" name="chevron-forward"></ion-icon>
20330
+ <ion-icon slot="icon-only" name="chevron-forward" aria-hidden="true"></ion-icon>
20295
20331
  </ion-button>
20296
20332
  }
20297
20333
 
@@ -20301,31 +20337,33 @@ class PaginationComponent {
20301
20337
  [size]="props.size || 'default'"
20302
20338
  [color]="props.color || 'primary'"
20303
20339
  [disabled]="props.disabled || props.currentPage >= totalPages"
20340
+ [attr.aria-label]="t('last')"
20304
20341
  (click)="goToPage(totalPages)"
20305
20342
  >
20306
- <ion-icon slot="icon-only" name="play-forward"></ion-icon>
20343
+ <ion-icon slot="icon-only" name="play-forward" aria-hidden="true"></ion-icon>
20307
20344
  </ion-button>
20308
20345
  }
20309
20346
 
20310
20347
  @if (props.showPageInfo) {
20311
- <span class="page-info">Page {{ props.currentPage }} of {{ totalPages }}</span>
20348
+ <span class="page-info">{{ pageInfo() }}</span>
20312
20349
  }
20313
- </div>
20350
+ </nav>
20314
20351
  `, isInline: true, styles: [":host{display:block}.pagination-container{display:flex;align-items:center;justify-content:center;gap:4px;flex-wrap:wrap}.pagination-container.disabled{opacity:.5;pointer-events:none}ion-button{--padding-start: 8px;--padding-end: 8px;min-width:36px;font-weight:500}ion-button[size=small]{--padding-start: 6px;--padding-end: 6px;min-width:28px;font-size:.75rem}ion-button[size=large]{--padding-start: 12px;--padding-end: 12px;min-width:44px;font-size:1rem}.ellipsis{padding:0 8px;color:var(--ion-color-medium);font-size:.875rem}.page-info{margin-left:16px;color:var(--ion-color-medium);font-size:.875rem;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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"] }] }); }
20315
20352
  }
20316
20353
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, decorators: [{
20317
20354
  type: Component,
20318
20355
  args: [{ selector: 'val-pagination', standalone: true, imports: [CommonModule, IonButton, IonIcon], template: `
20319
- <div class="pagination-container" [class.disabled]="props.disabled">
20356
+ <nav class="pagination-container" [class.disabled]="props.disabled" [attr.aria-label]="t('nav')">
20320
20357
  @if (props.showFirstLast !== false) {
20321
20358
  <ion-button
20322
20359
  fill="clear"
20323
20360
  [size]="props.size || 'default'"
20324
20361
  [color]="props.color || 'primary'"
20325
20362
  [disabled]="props.disabled || props.currentPage <= 1"
20363
+ [attr.aria-label]="t('first')"
20326
20364
  (click)="goToPage(1)"
20327
20365
  >
20328
- <ion-icon slot="icon-only" name="play-back"></ion-icon>
20366
+ <ion-icon slot="icon-only" name="play-back" aria-hidden="true"></ion-icon>
20329
20367
  </ion-button>
20330
20368
  }
20331
20369
 
@@ -20335,21 +20373,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20335
20373
  [size]="props.size || 'default'"
20336
20374
  [color]="props.color || 'primary'"
20337
20375
  [disabled]="props.disabled || props.currentPage <= 1"
20376
+ [attr.aria-label]="t('previous')"
20338
20377
  (click)="goToPage(props.currentPage - 1)"
20339
20378
  >
20340
- <ion-icon slot="icon-only" name="chevron-back"></ion-icon>
20379
+ <ion-icon slot="icon-only" name="chevron-back" aria-hidden="true"></ion-icon>
20341
20380
  </ion-button>
20342
20381
  }
20343
20382
 
20344
20383
  @for (page of visiblePages; track page) {
20345
20384
  @if (page === -1) {
20346
- <span class="ellipsis">...</span>
20385
+ <span class="ellipsis" aria-hidden="true">...</span>
20347
20386
  } @else {
20348
20387
  <ion-button
20349
20388
  [fill]="page === props.currentPage ? 'solid' : 'clear'"
20350
20389
  [size]="props.size || 'default'"
20351
20390
  [color]="props.color || 'primary'"
20352
20391
  [disabled]="props.disabled"
20392
+ [attr.aria-label]="pageLabel(page)"
20393
+ [attr.aria-current]="page === props.currentPage ? 'page' : null"
20353
20394
  (click)="goToPage(page)"
20354
20395
  >
20355
20396
  {{ page }}
@@ -20363,9 +20404,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20363
20404
  [size]="props.size || 'default'"
20364
20405
  [color]="props.color || 'primary'"
20365
20406
  [disabled]="props.disabled || props.currentPage >= totalPages"
20407
+ [attr.aria-label]="t('next')"
20366
20408
  (click)="goToPage(props.currentPage + 1)"
20367
20409
  >
20368
- <ion-icon slot="icon-only" name="chevron-forward"></ion-icon>
20410
+ <ion-icon slot="icon-only" name="chevron-forward" aria-hidden="true"></ion-icon>
20369
20411
  </ion-button>
20370
20412
  }
20371
20413
 
@@ -20375,18 +20417,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20375
20417
  [size]="props.size || 'default'"
20376
20418
  [color]="props.color || 'primary'"
20377
20419
  [disabled]="props.disabled || props.currentPage >= totalPages"
20420
+ [attr.aria-label]="t('last')"
20378
20421
  (click)="goToPage(totalPages)"
20379
20422
  >
20380
- <ion-icon slot="icon-only" name="play-forward"></ion-icon>
20423
+ <ion-icon slot="icon-only" name="play-forward" aria-hidden="true"></ion-icon>
20381
20424
  </ion-button>
20382
20425
  }
20383
20426
 
20384
20427
  @if (props.showPageInfo) {
20385
- <span class="page-info">Page {{ props.currentPage }} of {{ totalPages }}</span>
20428
+ <span class="page-info">{{ pageInfo() }}</span>
20386
20429
  }
20387
- </div>
20430
+ </nav>
20388
20431
  `, styles: [":host{display:block}.pagination-container{display:flex;align-items:center;justify-content:center;gap:4px;flex-wrap:wrap}.pagination-container.disabled{opacity:.5;pointer-events:none}ion-button{--padding-start: 8px;--padding-end: 8px;min-width:36px;font-weight:500}ion-button[size=small]{--padding-start: 6px;--padding-end: 6px;min-width:28px;font-size:.75rem}ion-button[size=large]{--padding-start: 12px;--padding-end: 12px;min-width:44px;font-size:1rem}.ellipsis{padding:0 8px;color:var(--ion-color-medium);font-size:.875rem}.page-info{margin-left:16px;color:var(--ion-color-medium);font-size:.875rem;white-space:nowrap}\n"] }]
20389
- }], propDecorators: { props: [{
20432
+ }], ctorParameters: () => [], propDecorators: { props: [{
20390
20433
  type: Input
20391
20434
  }], pageChange: [{
20392
20435
  type: Output
@@ -20517,13 +20560,17 @@ class StepperComponent {
20517
20560
  [class.vertical]="resolvedProps.orientation === 'vertical'"
20518
20561
  >
20519
20562
  @for (step of resolvedProps.steps; track step.value; let i = $index; let isLast = $last) {
20520
- <div
20563
+ <button
20564
+ type="button"
20521
20565
  class="step"
20522
20566
  [class.current]="getStepStatus(step, i) === 'current'"
20523
20567
  [class.completed]="getStepStatus(step, i) === 'completed'"
20524
20568
  [class.error]="getStepStatus(step, i) === 'error'"
20525
20569
  [class.disabled]="step.disabled"
20526
20570
  [class.clickable]="isStepClickable(step, i)"
20571
+ [disabled]="!isStepClickable(step, i)"
20572
+ [attr.aria-current]="getStepStatus(step, i) === 'current' ? 'step' : null"
20573
+ [attr.aria-label]="getStepLabel(step)"
20527
20574
  (click)="onStepClick(step, i)"
20528
20575
  >
20529
20576
  <div class="step-indicator">
@@ -20559,10 +20606,10 @@ class StepperComponent {
20559
20606
  <div class="step-description">{{ step.description }}</div>
20560
20607
  }
20561
20608
  </div>
20562
- </div>
20609
+ </button>
20563
20610
  }
20564
20611
  </div>
20565
- `, isInline: true, styles: [":host{display:block}.stepper-container{display:flex}.stepper-container.horizontal{flex-direction:row;align-items:flex-start}.stepper-container.horizontal .step{flex:1;flex-direction:column;align-items:center;text-align:center}.stepper-container.horizontal .step .step-indicator{flex-direction:row;width:100%;justify-content:center}.stepper-container.horizontal .step .step-connector{flex:1;height:2px;margin:0 8px;align-self:center}.stepper-container.vertical{flex-direction:column}.stepper-container.vertical .step{flex-direction:row;align-items:flex-start}.stepper-container.vertical .step .step-indicator{flex-direction:column;align-items:center}.stepper-container.vertical .step .step-connector{width:2px;flex:1;min-height:24px;margin:8px 0}.stepper-container.vertical .step .step-content{margin-left:12px;padding-bottom:24px}.step{display:flex;cursor:default}.step.clickable{cursor:pointer}.step.clickable:hover .step-circle{transform:scale(1.1)}.step.disabled{opacity:.5;pointer-events:none}.step.current .step-circle{box-shadow:0 0 0 4px rgba(var(--ion-color-primary-rgb),.2)}.step-indicator{display:flex;position:relative}.step-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;background-color:var(--step-color, var(--ion-color-medium));color:#fff;font-weight:600;font-size:.875rem;transition:transform .2s,box-shadow .2s;flex-shrink:0}.step-circle ion-icon{font-size:1.125rem}.step-connector{background-color:var(--ion-color-light-shade);transition:background-color .3s}.step-connector.completed{background-color:var(--ion-color-primary)}.step-connector.dashed{background:repeating-linear-gradient(90deg,var(--ion-color-light-shade),var(--ion-color-light-shade) 4px,transparent 4px,transparent 8px)}.step-connector.dashed.completed{background:repeating-linear-gradient(90deg,var(--ion-color-primary),var(--ion-color-primary) 4px,transparent 4px,transparent 8px)}.step-content{margin-top:8px}.step-label{font-weight:500;font-size:.875rem;color:var(--ion-text-color)}.step-label .optional-text{font-weight:400;font-size:.75rem;color:var(--ion-color-medium);margin-left:4px}.step-description{font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}\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"] }] }); }
20612
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.stepper-container{display:flex}.stepper-container.horizontal{flex-direction:row;align-items:flex-start}.stepper-container.horizontal .step{flex:1;flex-direction:column;align-items:center;text-align:center}.stepper-container.horizontal .step .step-indicator{flex-direction:row;width:100%;justify-content:center}.stepper-container.horizontal .step .step-connector{flex:1;height:2px;margin:0 8px;align-self:center}.stepper-container.vertical{flex-direction:column}.stepper-container.vertical .step{flex-direction:row;align-items:flex-start}.stepper-container.vertical .step .step-indicator{flex-direction:column;align-items:center}.stepper-container.vertical .step .step-connector{width:2px;flex:1;min-height:24px;margin:8px 0}.stepper-container.vertical .step .step-content{margin-left:12px;padding-bottom:24px}.step{display:flex;cursor:default;padding:0;border:none;background:none;font:inherit;text-align:inherit;color:inherit}.step:focus{outline:none}.step:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.step.clickable{cursor:pointer}.step.clickable:hover .step-circle{transform:scale(1.1)}.step.disabled{opacity:.5}.step:disabled{cursor:default}.step.current .step-circle{box-shadow:0 0 0 4px rgba(var(--ion-color-primary-rgb),.2)}.step-indicator{display:flex;position:relative}.step-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;background-color:var(--step-color, var(--ion-color-medium));color:#fff;font-weight:600;font-size:.875rem;transition:transform .2s,box-shadow .2s;flex-shrink:0}.step-circle ion-icon{font-size:1.125rem}.step-connector{background-color:var(--ion-color-light-shade);transition:background-color .3s}.step-connector.completed{background-color:var(--ion-color-primary)}.step-connector.dashed{background:repeating-linear-gradient(90deg,var(--ion-color-light-shade),var(--ion-color-light-shade) 4px,transparent 4px,transparent 8px)}.step-connector.dashed.completed{background:repeating-linear-gradient(90deg,var(--ion-color-primary),var(--ion-color-primary) 4px,transparent 4px,transparent 8px)}.step-content{margin-top:8px}.step-label{font-weight:500;font-size:.875rem;color:var(--ion-text-color)}.step-label .optional-text{font-weight:400;font-size:.75rem;color:var(--ion-color-medium);margin-left:4px}.step-description{font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}\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"] }] }); }
20566
20613
  }
20567
20614
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StepperComponent, decorators: [{
20568
20615
  type: Component,
@@ -20573,13 +20620,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20573
20620
  [class.vertical]="resolvedProps.orientation === 'vertical'"
20574
20621
  >
20575
20622
  @for (step of resolvedProps.steps; track step.value; let i = $index; let isLast = $last) {
20576
- <div
20623
+ <button
20624
+ type="button"
20577
20625
  class="step"
20578
20626
  [class.current]="getStepStatus(step, i) === 'current'"
20579
20627
  [class.completed]="getStepStatus(step, i) === 'completed'"
20580
20628
  [class.error]="getStepStatus(step, i) === 'error'"
20581
20629
  [class.disabled]="step.disabled"
20582
20630
  [class.clickable]="isStepClickable(step, i)"
20631
+ [disabled]="!isStepClickable(step, i)"
20632
+ [attr.aria-current]="getStepStatus(step, i) === 'current' ? 'step' : null"
20633
+ [attr.aria-label]="getStepLabel(step)"
20583
20634
  (click)="onStepClick(step, i)"
20584
20635
  >
20585
20636
  <div class="step-indicator">
@@ -20615,10 +20666,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20615
20666
  <div class="step-description">{{ step.description }}</div>
20616
20667
  }
20617
20668
  </div>
20618
- </div>
20669
+ </button>
20619
20670
  }
20620
20671
  </div>
20621
- `, styles: [":host{display:block}.stepper-container{display:flex}.stepper-container.horizontal{flex-direction:row;align-items:flex-start}.stepper-container.horizontal .step{flex:1;flex-direction:column;align-items:center;text-align:center}.stepper-container.horizontal .step .step-indicator{flex-direction:row;width:100%;justify-content:center}.stepper-container.horizontal .step .step-connector{flex:1;height:2px;margin:0 8px;align-self:center}.stepper-container.vertical{flex-direction:column}.stepper-container.vertical .step{flex-direction:row;align-items:flex-start}.stepper-container.vertical .step .step-indicator{flex-direction:column;align-items:center}.stepper-container.vertical .step .step-connector{width:2px;flex:1;min-height:24px;margin:8px 0}.stepper-container.vertical .step .step-content{margin-left:12px;padding-bottom:24px}.step{display:flex;cursor:default}.step.clickable{cursor:pointer}.step.clickable:hover .step-circle{transform:scale(1.1)}.step.disabled{opacity:.5;pointer-events:none}.step.current .step-circle{box-shadow:0 0 0 4px rgba(var(--ion-color-primary-rgb),.2)}.step-indicator{display:flex;position:relative}.step-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;background-color:var(--step-color, var(--ion-color-medium));color:#fff;font-weight:600;font-size:.875rem;transition:transform .2s,box-shadow .2s;flex-shrink:0}.step-circle ion-icon{font-size:1.125rem}.step-connector{background-color:var(--ion-color-light-shade);transition:background-color .3s}.step-connector.completed{background-color:var(--ion-color-primary)}.step-connector.dashed{background:repeating-linear-gradient(90deg,var(--ion-color-light-shade),var(--ion-color-light-shade) 4px,transparent 4px,transparent 8px)}.step-connector.dashed.completed{background:repeating-linear-gradient(90deg,var(--ion-color-primary),var(--ion-color-primary) 4px,transparent 4px,transparent 8px)}.step-content{margin-top:8px}.step-label{font-weight:500;font-size:.875rem;color:var(--ion-text-color)}.step-label .optional-text{font-weight:400;font-size:.75rem;color:var(--ion-color-medium);margin-left:4px}.step-description{font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}\n"] }]
20672
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.stepper-container{display:flex}.stepper-container.horizontal{flex-direction:row;align-items:flex-start}.stepper-container.horizontal .step{flex:1;flex-direction:column;align-items:center;text-align:center}.stepper-container.horizontal .step .step-indicator{flex-direction:row;width:100%;justify-content:center}.stepper-container.horizontal .step .step-connector{flex:1;height:2px;margin:0 8px;align-self:center}.stepper-container.vertical{flex-direction:column}.stepper-container.vertical .step{flex-direction:row;align-items:flex-start}.stepper-container.vertical .step .step-indicator{flex-direction:column;align-items:center}.stepper-container.vertical .step .step-connector{width:2px;flex:1;min-height:24px;margin:8px 0}.stepper-container.vertical .step .step-content{margin-left:12px;padding-bottom:24px}.step{display:flex;cursor:default;padding:0;border:none;background:none;font:inherit;text-align:inherit;color:inherit}.step:focus{outline:none}.step:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.step.clickable{cursor:pointer}.step.clickable:hover .step-circle{transform:scale(1.1)}.step.disabled{opacity:.5}.step:disabled{cursor:default}.step.current .step-circle{box-shadow:0 0 0 4px rgba(var(--ion-color-primary-rgb),.2)}.step-indicator{display:flex;position:relative}.step-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;background-color:var(--step-color, var(--ion-color-medium));color:#fff;font-weight:600;font-size:.875rem;transition:transform .2s,box-shadow .2s;flex-shrink:0}.step-circle ion-icon{font-size:1.125rem}.step-connector{background-color:var(--ion-color-light-shade);transition:background-color .3s}.step-connector.completed{background-color:var(--ion-color-primary)}.step-connector.dashed{background:repeating-linear-gradient(90deg,var(--ion-color-light-shade),var(--ion-color-light-shade) 4px,transparent 4px,transparent 8px)}.step-connector.dashed.completed{background:repeating-linear-gradient(90deg,var(--ion-color-primary),var(--ion-color-primary) 4px,transparent 4px,transparent 8px)}.step-content{margin-top:8px}.step-label{font-weight:500;font-size:.875rem;color:var(--ion-text-color)}.step-label .optional-text{font-weight:400;font-size:.75rem;color:var(--ion-color-medium);margin-left:4px}.step-description{font-size:.75rem;color:var(--ion-color-medium);margin-top:4px}\n"] }]
20622
20673
  }], propDecorators: { preset: [{
20623
20674
  type: Input
20624
20675
  }], props: [{
@@ -20628,6 +20679,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20628
20679
  }] } });
20629
20680
 
20630
20681
  addIcons({ close, checkmark });
20682
+ /**
20683
+ * Defaults i18n (es/en) — auto-registrados si el consumer no proveyó el
20684
+ * namespace `ChipGroup`. Cubre el aria-label del botón eliminar.
20685
+ */
20686
+ const CHIP_GROUP_I18N = {
20687
+ es: { remove: 'Eliminar {label}' },
20688
+ en: { remove: 'Remove {label}' },
20689
+ };
20631
20690
  /**
20632
20691
  * val-chip-group
20633
20692
  *
@@ -20656,15 +20715,30 @@ addIcons({ close, checkmark });
20656
20715
  class ChipGroupComponent {
20657
20716
  constructor() {
20658
20717
  this.presets = inject(PresetService);
20718
+ this.i18n = inject(I18nService);
20659
20719
  this.props = {};
20660
20720
  this.resolvedProps = {};
20661
20721
  this.selectionChange = new EventEmitter();
20662
20722
  this.chipRemove = new EventEmitter();
20663
20723
  this.chipClick = new EventEmitter();
20724
+ if (!this.i18n.hasNamespace('ChipGroup')) {
20725
+ this.i18n.registerContent('ChipGroup', CHIP_GROUP_I18N);
20726
+ }
20664
20727
  }
20665
20728
  ngOnInit() {
20666
20729
  this.resolveProps();
20667
20730
  }
20731
+ removeLabel(chip) {
20732
+ this.i18n.lang();
20733
+ return this.i18n.t('remove', 'ChipGroup', { label: this.getChipLabel(chip) });
20734
+ }
20735
+ /** Activación de chip selectable por teclado (Enter/Space). */
20736
+ onChipKey(event, chip) {
20737
+ if (!this.resolvedProps.selectable)
20738
+ return;
20739
+ event.preventDefault();
20740
+ this.onChipClick(chip);
20741
+ }
20668
20742
  ngOnChanges(changes) {
20669
20743
  if (changes['preset'] || changes['props']) {
20670
20744
  this.resolveProps();
@@ -20732,7 +20806,12 @@ class ChipGroupComponent {
20732
20806
  [color]="getChipColor(chip)"
20733
20807
  [outline]="resolvedProps.outline && !chip.selected"
20734
20808
  [disabled]="chip.disabled"
20809
+ [attr.role]="resolvedProps.selectable ? 'button' : null"
20810
+ [attr.tabindex]="resolvedProps.selectable && !chip.disabled ? 0 : null"
20811
+ [attr.aria-pressed]="resolvedProps.selectable ? !!chip.selected : null"
20735
20812
  (click)="onChipClick(chip)"
20813
+ (keydown.enter)="onChipKey($event, chip)"
20814
+ (keydown.space)="onChipKey($event, chip)"
20736
20815
  >
20737
20816
  @if (chip.icon) {
20738
20817
  <ion-icon [name]="chip.icon"></ion-icon>
@@ -20742,12 +20821,14 @@ class ChipGroupComponent {
20742
20821
  }
20743
20822
  <ion-label>{{ getChipLabel(chip) }}</ion-label>
20744
20823
  @if (resolvedProps.removable && !chip.disabled) {
20745
- <ion-icon name="close" class="remove-icon" (click)="onRemoveChip($event, chip)"></ion-icon>
20824
+ <button type="button" class="remove-button" [attr.aria-label]="removeLabel(chip)" (click)="onRemoveChip($event, chip)">
20825
+ <ion-icon name="close" class="remove-icon" aria-hidden="true"></ion-icon>
20826
+ </button>
20746
20827
  }
20747
20828
  </ion-chip>
20748
20829
  }
20749
20830
  </div>
20750
- `, isInline: true, styles: [":host{display:block}.chip-group{display:flex;gap:8px}.chip-group.wrap{flex-wrap:wrap}.chip-group:not(.wrap){overflow-x:auto;padding-bottom:4px}.chip-group:not(.wrap)::-webkit-scrollbar{height:4px}.chip-group:not(.wrap)::-webkit-scrollbar-thumb{background:var(--ion-color-light-shade);border-radius:2px}ion-chip{margin:0;cursor:pointer;transition:transform .2s,box-shadow .2s}ion-chip:hover:not([disabled]){transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}ion-chip:active:not([disabled]){transform:translateY(0)}ion-chip[disabled]{opacity:.5;cursor:not-allowed}ion-chip ion-icon{font-size:1rem}ion-chip .selected-icon{margin-right:4px}ion-chip .remove-icon{margin-left:4px;cursor:pointer;opacity:.7;transition:opacity .2s}ion-chip .remove-icon:hover{opacity:1}ion-chip ion-label{font-size:.875rem;font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonChip, selector: "ion-chip", inputs: ["color", "disabled", "mode", "outline"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }] }); }
20831
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.chip-group{display:flex;gap:8px}.chip-group.wrap{flex-wrap:wrap}.chip-group:not(.wrap){overflow-x:auto;padding-bottom:4px}.chip-group:not(.wrap)::-webkit-scrollbar{height:4px}.chip-group:not(.wrap)::-webkit-scrollbar-thumb{background:var(--ion-color-light-shade);border-radius:2px}ion-chip{margin:0;cursor:pointer;transition:transform .2s,box-shadow .2s}ion-chip:focus{outline:none}ion-chip:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}ion-chip:hover:not([disabled]){transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}ion-chip:active:not([disabled]){transform:translateY(0)}ion-chip[disabled]{opacity:.5;cursor:not-allowed}ion-chip ion-icon{font-size:1rem}ion-chip .selected-icon{margin-right:4px}ion-chip .remove-button{display:inline-flex;align-items:center;justify-content:center;margin-left:4px;padding:0;border:none;background:none;line-height:0;cursor:pointer;border-radius:50%}ion-chip .remove-button:focus{outline:none}ion-chip .remove-button:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}ion-chip .remove-icon{opacity:.7;transition:opacity .2s}.remove-button:hover ion-chip .remove-icon{opacity:1}ion-chip ion-label{font-size:.875rem;font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonChip, selector: "ion-chip", inputs: ["color", "disabled", "mode", "outline"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }] }); }
20751
20832
  }
20752
20833
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChipGroupComponent, decorators: [{
20753
20834
  type: Component,
@@ -20758,7 +20839,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20758
20839
  [color]="getChipColor(chip)"
20759
20840
  [outline]="resolvedProps.outline && !chip.selected"
20760
20841
  [disabled]="chip.disabled"
20842
+ [attr.role]="resolvedProps.selectable ? 'button' : null"
20843
+ [attr.tabindex]="resolvedProps.selectable && !chip.disabled ? 0 : null"
20844
+ [attr.aria-pressed]="resolvedProps.selectable ? !!chip.selected : null"
20761
20845
  (click)="onChipClick(chip)"
20846
+ (keydown.enter)="onChipKey($event, chip)"
20847
+ (keydown.space)="onChipKey($event, chip)"
20762
20848
  >
20763
20849
  @if (chip.icon) {
20764
20850
  <ion-icon [name]="chip.icon"></ion-icon>
@@ -20768,13 +20854,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20768
20854
  }
20769
20855
  <ion-label>{{ getChipLabel(chip) }}</ion-label>
20770
20856
  @if (resolvedProps.removable && !chip.disabled) {
20771
- <ion-icon name="close" class="remove-icon" (click)="onRemoveChip($event, chip)"></ion-icon>
20857
+ <button type="button" class="remove-button" [attr.aria-label]="removeLabel(chip)" (click)="onRemoveChip($event, chip)">
20858
+ <ion-icon name="close" class="remove-icon" aria-hidden="true"></ion-icon>
20859
+ </button>
20772
20860
  }
20773
20861
  </ion-chip>
20774
20862
  }
20775
20863
  </div>
20776
- `, styles: [":host{display:block}.chip-group{display:flex;gap:8px}.chip-group.wrap{flex-wrap:wrap}.chip-group:not(.wrap){overflow-x:auto;padding-bottom:4px}.chip-group:not(.wrap)::-webkit-scrollbar{height:4px}.chip-group:not(.wrap)::-webkit-scrollbar-thumb{background:var(--ion-color-light-shade);border-radius:2px}ion-chip{margin:0;cursor:pointer;transition:transform .2s,box-shadow .2s}ion-chip:hover:not([disabled]){transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}ion-chip:active:not([disabled]){transform:translateY(0)}ion-chip[disabled]{opacity:.5;cursor:not-allowed}ion-chip ion-icon{font-size:1rem}ion-chip .selected-icon{margin-right:4px}ion-chip .remove-icon{margin-left:4px;cursor:pointer;opacity:.7;transition:opacity .2s}ion-chip .remove-icon:hover{opacity:1}ion-chip ion-label{font-size:.875rem;font-weight:500}\n"] }]
20777
- }], propDecorators: { preset: [{
20864
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.chip-group{display:flex;gap:8px}.chip-group.wrap{flex-wrap:wrap}.chip-group:not(.wrap){overflow-x:auto;padding-bottom:4px}.chip-group:not(.wrap)::-webkit-scrollbar{height:4px}.chip-group:not(.wrap)::-webkit-scrollbar-thumb{background:var(--ion-color-light-shade);border-radius:2px}ion-chip{margin:0;cursor:pointer;transition:transform .2s,box-shadow .2s}ion-chip:focus{outline:none}ion-chip:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}ion-chip:hover:not([disabled]){transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}ion-chip:active:not([disabled]){transform:translateY(0)}ion-chip[disabled]{opacity:.5;cursor:not-allowed}ion-chip ion-icon{font-size:1rem}ion-chip .selected-icon{margin-right:4px}ion-chip .remove-button{display:inline-flex;align-items:center;justify-content:center;margin-left:4px;padding:0;border:none;background:none;line-height:0;cursor:pointer;border-radius:50%}ion-chip .remove-button:focus{outline:none}ion-chip .remove-button:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}ion-chip .remove-icon{opacity:.7;transition:opacity .2s}.remove-button:hover ion-chip .remove-icon{opacity:1}ion-chip ion-label{font-size:.875rem;font-weight:500}\n"] }]
20865
+ }], ctorParameters: () => [], propDecorators: { preset: [{
20778
20866
  type: Input
20779
20867
  }], props: [{
20780
20868
  type: Input
@@ -20787,6 +20875,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
20787
20875
  }] } });
20788
20876
 
20789
20877
  addIcons({ star, starOutline, starHalf, heart, heartOutline, heartHalf });
20878
+ /**
20879
+ * Defaults i18n (es/en) — auto-registrados si el consumer no proveyó el
20880
+ * namespace `Rating`. Cubre el aria-label del grupo y de cada estrella.
20881
+ */
20882
+ const RATING_I18N = {
20883
+ es: { groupLabel: 'Valoración', starLabel: '{value} de {max}' },
20884
+ en: { groupLabel: 'Rating', starLabel: '{value} of {max}' },
20885
+ };
20790
20886
  /**
20791
20887
  * val-rating
20792
20888
  *
@@ -20810,10 +20906,14 @@ addIcons({ star, starOutline, starHalf, heart, heartOutline, heartHalf });
20810
20906
  class RatingComponent {
20811
20907
  constructor() {
20812
20908
  this.presets = inject(PresetService);
20909
+ this.i18n = inject(I18nService);
20813
20910
  this.props = {};
20814
20911
  this.resolvedProps = {};
20815
20912
  this.ratingChange = new EventEmitter();
20816
20913
  this.hoverValue = null;
20914
+ if (!this.i18n.hasNamespace('Rating')) {
20915
+ this.i18n.registerContent('Rating', RATING_I18N);
20916
+ }
20817
20917
  }
20818
20918
  ngOnInit() {
20819
20919
  this.resolveProps();
@@ -20839,6 +20939,43 @@ class RatingComponent {
20839
20939
  const max = this.resolvedProps.max || 5;
20840
20940
  return Array.from({ length: max }, (_, i) => i + 1);
20841
20941
  }
20942
+ groupLabel() {
20943
+ this.i18n.lang();
20944
+ return this.i18n.t('groupLabel', 'Rating');
20945
+ }
20946
+ starLabel(position) {
20947
+ this.i18n.lang();
20948
+ return this.i18n.t('starLabel', 'Rating', {
20949
+ value: position.toString(),
20950
+ max: (this.resolvedProps.max || 5).toString(),
20951
+ });
20952
+ }
20953
+ /**
20954
+ * Roving tabindex: solo una estrella es tabbable. La estrella del valor
20955
+ * actual (o la primera si no hay valor) recibe `0`, el resto `-1`.
20956
+ */
20957
+ getStarTabindex(position) {
20958
+ if (this.resolvedProps.readonly || this.resolvedProps.disabled)
20959
+ return -1;
20960
+ const value = this.resolvedProps.value || 0;
20961
+ const focusIndex = value >= 1 ? Math.ceil(value) : 1;
20962
+ return position === focusIndex ? 0 : -1;
20963
+ }
20964
+ /** Navegación con flechas: mueve el foco y selecciona la estrella vecina. */
20965
+ onArrow(event, delta) {
20966
+ if (this.resolvedProps.readonly || this.resolvedProps.disabled)
20967
+ return;
20968
+ event.preventDefault();
20969
+ const max = this.resolvedProps.max || 5;
20970
+ const current = this.resolvedProps.value >= 1 ? Math.ceil(this.resolvedProps.value) : 1;
20971
+ const next = Math.min(max, Math.max(1, current + delta));
20972
+ if (next === this.resolvedProps.value)
20973
+ return;
20974
+ this.ratingChange.emit({ value: next, previousValue: this.resolvedProps.value });
20975
+ const target = event.target;
20976
+ const buttons = target.closest('.rating-container')?.querySelectorAll('.rating-star');
20977
+ buttons?.[next - 1]?.focus();
20978
+ }
20842
20979
  getStarIcon(position) {
20843
20980
  const value = this.hoverValue !== null ? this.hoverValue : this.resolvedProps.value;
20844
20981
  const baseIcon = this.resolvedProps.icon || 'star';
@@ -20893,51 +21030,77 @@ class RatingComponent {
20893
21030
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RatingComponent, isStandalone: true, selector: "val-rating", inputs: { preset: "preset", props: "props" }, outputs: { ratingChange: "ratingChange" }, usesOnChanges: true, ngImport: i0, template: `
20894
21031
  <div
20895
21032
  class="rating-container"
21033
+ role="radiogroup"
21034
+ [attr.aria-label]="groupLabel()"
20896
21035
  [class.readonly]="resolvedProps.readonly"
20897
21036
  [class.disabled]="resolvedProps.disabled"
20898
21037
  [class]="'size-' + (resolvedProps.size || 'medium')"
20899
21038
  >
20900
21039
  @for (i of getStars(); track i) {
20901
- <ion-icon
20902
- [name]="getStarIcon(i)"
20903
- [color]="getStarColor(i)"
21040
+ <button
21041
+ type="button"
21042
+ class="rating-star"
21043
+ role="radio"
20904
21044
  [class.clickable]="!resolvedProps.readonly && !resolvedProps.disabled"
21045
+ [attr.aria-checked]="i <= resolvedProps.value"
21046
+ [attr.aria-label]="starLabel(i)"
21047
+ [attr.tabindex]="getStarTabindex(i)"
21048
+ [disabled]="resolvedProps.disabled"
20905
21049
  (click)="onStarClick(i)"
21050
+ (keydown.arrowright)="onArrow($event, 1)"
21051
+ (keydown.arrowup)="onArrow($event, 1)"
21052
+ (keydown.arrowleft)="onArrow($event, -1)"
21053
+ (keydown.arrowdown)="onArrow($event, -1)"
20906
21054
  (mouseenter)="onStarHover(i)"
20907
21055
  (mouseleave)="onStarLeave()"
20908
- ></ion-icon>
21056
+ >
21057
+ <ion-icon [name]="getStarIcon(i)" [color]="getStarColor(i)" aria-hidden="true"></ion-icon>
21058
+ </button>
20909
21059
  }
20910
21060
  @if (resolvedProps.showValue) {
20911
21061
  <span class="rating-value">{{ displayValue }}</span>
20912
21062
  }
20913
21063
  </div>
20914
- `, isInline: true, styles: [":host{display:inline-block}.rating-container{display:inline-flex;align-items:center;gap:4px}.rating-container.readonly{pointer-events:none}.rating-container.disabled{opacity:.5;pointer-events:none}.rating-container.size-small ion-icon{font-size:1rem}.rating-container.size-medium ion-icon{font-size:1.5rem}.rating-container.size-large ion-icon{font-size:2rem}ion-icon{transition:transform .15s ease,color .15s ease}ion-icon.clickable{cursor:pointer}ion-icon.clickable:hover{transform:scale(1.2)}.rating-value{margin-left:8px;font-weight:600;color:var(--ion-color-dark)}.size-small .rating-value{font-size:.75rem}.size-medium .rating-value{font-size:.875rem}.size-large .rating-value{font-size:1.125rem}\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"] }] }); }
21064
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:inline-block}.rating-container{display:inline-flex;align-items:center;gap:4px}.rating-container.readonly{pointer-events:none}.rating-container.disabled{opacity:.5;pointer-events:none}.rating-container.size-small ion-icon{font-size:1rem}.rating-container.size-medium ion-icon{font-size:1.5rem}.rating-container.size-large ion-icon{font-size:2rem}.rating-star{display:inline-flex;align-items:center;justify-content:center;padding:0;margin:0;border:none;background:none;color:inherit;line-height:0;cursor:default}.rating-star:focus{outline:none}.rating-star:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.rating-star.clickable{cursor:pointer}.rating-star.clickable:hover ion-icon{transform:scale(1.2)}.rating-star:disabled{cursor:default}ion-icon{transition:transform .15s ease,color .15s ease}.rating-value{margin-left:8px;font-weight:600;color:var(--ion-color-dark)}.size-small .rating-value{font-size:.75rem}.size-medium .rating-value{font-size:.875rem}.size-large .rating-value{font-size:1.125rem}\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"] }] }); }
20915
21065
  }
20916
21066
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RatingComponent, decorators: [{
20917
21067
  type: Component,
20918
21068
  args: [{ selector: 'val-rating', standalone: true, imports: [CommonModule, IonIcon], template: `
20919
21069
  <div
20920
21070
  class="rating-container"
21071
+ role="radiogroup"
21072
+ [attr.aria-label]="groupLabel()"
20921
21073
  [class.readonly]="resolvedProps.readonly"
20922
21074
  [class.disabled]="resolvedProps.disabled"
20923
21075
  [class]="'size-' + (resolvedProps.size || 'medium')"
20924
21076
  >
20925
21077
  @for (i of getStars(); track i) {
20926
- <ion-icon
20927
- [name]="getStarIcon(i)"
20928
- [color]="getStarColor(i)"
21078
+ <button
21079
+ type="button"
21080
+ class="rating-star"
21081
+ role="radio"
20929
21082
  [class.clickable]="!resolvedProps.readonly && !resolvedProps.disabled"
21083
+ [attr.aria-checked]="i <= resolvedProps.value"
21084
+ [attr.aria-label]="starLabel(i)"
21085
+ [attr.tabindex]="getStarTabindex(i)"
21086
+ [disabled]="resolvedProps.disabled"
20930
21087
  (click)="onStarClick(i)"
21088
+ (keydown.arrowright)="onArrow($event, 1)"
21089
+ (keydown.arrowup)="onArrow($event, 1)"
21090
+ (keydown.arrowleft)="onArrow($event, -1)"
21091
+ (keydown.arrowdown)="onArrow($event, -1)"
20931
21092
  (mouseenter)="onStarHover(i)"
20932
21093
  (mouseleave)="onStarLeave()"
20933
- ></ion-icon>
21094
+ >
21095
+ <ion-icon [name]="getStarIcon(i)" [color]="getStarColor(i)" aria-hidden="true"></ion-icon>
21096
+ </button>
20934
21097
  }
20935
21098
  @if (resolvedProps.showValue) {
20936
21099
  <span class="rating-value">{{ displayValue }}</span>
20937
21100
  }
20938
21101
  </div>
20939
- `, styles: [":host{display:inline-block}.rating-container{display:inline-flex;align-items:center;gap:4px}.rating-container.readonly{pointer-events:none}.rating-container.disabled{opacity:.5;pointer-events:none}.rating-container.size-small ion-icon{font-size:1rem}.rating-container.size-medium ion-icon{font-size:1.5rem}.rating-container.size-large ion-icon{font-size:2rem}ion-icon{transition:transform .15s ease,color .15s ease}ion-icon.clickable{cursor:pointer}ion-icon.clickable:hover{transform:scale(1.2)}.rating-value{margin-left:8px;font-weight:600;color:var(--ion-color-dark)}.size-small .rating-value{font-size:.75rem}.size-medium .rating-value{font-size:.875rem}.size-large .rating-value{font-size:1.125rem}\n"] }]
20940
- }], propDecorators: { preset: [{
21102
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:inline-block}.rating-container{display:inline-flex;align-items:center;gap:4px}.rating-container.readonly{pointer-events:none}.rating-container.disabled{opacity:.5;pointer-events:none}.rating-container.size-small ion-icon{font-size:1rem}.rating-container.size-medium ion-icon{font-size:1.5rem}.rating-container.size-large ion-icon{font-size:2rem}.rating-star{display:inline-flex;align-items:center;justify-content:center;padding:0;margin:0;border:none;background:none;color:inherit;line-height:0;cursor:default}.rating-star:focus{outline:none}.rating-star:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.rating-star.clickable{cursor:pointer}.rating-star.clickable:hover ion-icon{transform:scale(1.2)}.rating-star:disabled{cursor:default}ion-icon{transition:transform .15s ease,color .15s ease}.rating-value{margin-left:8px;font-weight:600;color:var(--ion-color-dark)}.size-small .rating-value{font-size:.75rem}.size-medium .rating-value{font-size:.875rem}.size-large .rating-value{font-size:1.125rem}\n"] }]
21103
+ }], ctorParameters: () => [], propDecorators: { preset: [{
20941
21104
  type: Input
20942
21105
  }], props: [{
20943
21106
  type: Input
@@ -21303,6 +21466,14 @@ addIcons({
21303
21466
  flag,
21304
21467
  share,
21305
21468
  });
21469
+ /**
21470
+ * Defaults i18n (es/en) — auto-registrados si el consumer no proveyó el
21471
+ * namespace `Comment`. Cubre el aria-label del autor (avatar + nombre).
21472
+ */
21473
+ const COMMENT_I18N = {
21474
+ es: { viewProfileOf: 'Ver perfil de {name}' },
21475
+ en: { viewProfileOf: 'View profile of {name}' },
21476
+ };
21306
21477
  /**
21307
21478
  * val-comment
21308
21479
  *
@@ -21353,10 +21524,18 @@ class CommentComponent {
21353
21524
  this.loadMoreClick = new EventEmitter();
21354
21525
  this.collapseToggle = new EventEmitter();
21355
21526
  this.displayContent = '';
21527
+ if (!this.i18n.hasNamespace('Comment')) {
21528
+ this.i18n.registerContent('Comment', COMMENT_I18N);
21529
+ }
21356
21530
  }
21357
21531
  ngOnInit() {
21358
21532
  this.displayContent = this.props.content || this.props.contentFallback || '';
21359
21533
  }
21534
+ /** Aria-label accesible del autor (avatar + nombre clicables). */
21535
+ authorLabel() {
21536
+ this.i18n.lang();
21537
+ return this.i18n.t('viewProfileOf', 'Comment', { name: this.props.author.name });
21538
+ }
21360
21539
  getInitials(name) {
21361
21540
  return name
21362
21541
  .split(' ')
@@ -21525,7 +21704,7 @@ class CommentComponent {
21525
21704
  }
21526
21705
 
21527
21706
  <div class="comment-main">
21528
- <div class="comment-avatar" (click)="onAuthorClick()">
21707
+ <button type="button" class="comment-avatar" [attr.aria-label]="authorLabel()" (click)="onAuthorClick()">
21529
21708
  @if (props.author.avatar) {
21530
21709
  <val-avatar [props]="props.author.avatar"></val-avatar>
21531
21710
  } @else {
@@ -21533,11 +21712,11 @@ class CommentComponent {
21533
21712
  {{ getInitials(props.author.name) }}
21534
21713
  </div>
21535
21714
  }
21536
- </div>
21715
+ </button>
21537
21716
 
21538
21717
  <div class="comment-body">
21539
21718
  <div class="comment-header">
21540
- <div class="author-info" (click)="onAuthorClick()">
21719
+ <button type="button" class="author-info" [attr.aria-label]="authorLabel()" (click)="onAuthorClick()">
21541
21720
  <span class="author-name">{{ props.author.name }}</span>
21542
21721
  @if (props.author.verified) {
21543
21722
  <ion-icon name="checkmark-circle" class="verified-badge"></ion-icon>
@@ -21545,7 +21724,7 @@ class CommentComponent {
21545
21724
  @if (props.author.username) {
21546
21725
  <span class="author-username">&#64;{{ props.author.username }}</span>
21547
21726
  }
21548
- </div>
21727
+ </button>
21549
21728
 
21550
21729
  <div class="comment-meta">
21551
21730
  <span class="timestamp">{{ formatTimestamp(props.timestamp) }}</span>
@@ -21686,7 +21865,7 @@ class CommentComponent {
21686
21865
  </div>
21687
21866
  }
21688
21867
  </div>
21689
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"], dependencies: [{ kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "ngmodule", type: CommonModule }, { 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"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
21868
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer;padding:0;border:none;background:none;line-height:0;border-radius:50%}.comment-avatar:focus{outline:none}.comment-avatar:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer;padding:0;border:none;background:none;font:inherit;color:inherit;text-align:inherit}.author-info:focus{outline:none}.author-info:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"], dependencies: [{ kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "ngmodule", type: CommonModule }, { 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"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
21690
21869
  }
21691
21870
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentComponent, decorators: [{
21692
21871
  type: Component,
@@ -21715,7 +21894,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
21715
21894
  }
21716
21895
 
21717
21896
  <div class="comment-main">
21718
- <div class="comment-avatar" (click)="onAuthorClick()">
21897
+ <button type="button" class="comment-avatar" [attr.aria-label]="authorLabel()" (click)="onAuthorClick()">
21719
21898
  @if (props.author.avatar) {
21720
21899
  <val-avatar [props]="props.author.avatar"></val-avatar>
21721
21900
  } @else {
@@ -21723,11 +21902,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
21723
21902
  {{ getInitials(props.author.name) }}
21724
21903
  </div>
21725
21904
  }
21726
- </div>
21905
+ </button>
21727
21906
 
21728
21907
  <div class="comment-body">
21729
21908
  <div class="comment-header">
21730
- <div class="author-info" (click)="onAuthorClick()">
21909
+ <button type="button" class="author-info" [attr.aria-label]="authorLabel()" (click)="onAuthorClick()">
21731
21910
  <span class="author-name">{{ props.author.name }}</span>
21732
21911
  @if (props.author.verified) {
21733
21912
  <ion-icon name="checkmark-circle" class="verified-badge"></ion-icon>
@@ -21735,7 +21914,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
21735
21914
  @if (props.author.username) {
21736
21915
  <span class="author-username">&#64;{{ props.author.username }}</span>
21737
21916
  }
21738
- </div>
21917
+ </button>
21739
21918
 
21740
21919
  <div class="comment-meta">
21741
21920
  <span class="timestamp">{{ formatTimestamp(props.timestamp) }}</span>
@@ -21876,8 +22055,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
21876
22055
  </div>
21877
22056
  }
21878
22057
  </div>
21879
- `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"] }]
21880
- }], propDecorators: { props: [{
22058
+ `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer;padding:0;border:none;background:none;line-height:0;border-radius:50%}.comment-avatar:focus{outline:none}.comment-avatar:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer;padding:0;border:none;background:none;font:inherit;color:inherit;text-align:inherit}.author-info:focus{outline:none}.author-info:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px;border-radius:inherit}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"] }]
22059
+ }], ctorParameters: () => [], propDecorators: { props: [{
21881
22060
  type: Input
21882
22061
  }], authorClick: [{
21883
22062
  type: Output
@@ -25360,42 +25539,86 @@ class FeaturesListComponent {
25360
25539
  [class.features-list--center]="config().alignment === 'center'"
25361
25540
  >
25362
25541
  @for (feature of visibleFeatures(); track feature.titleKey) {
25363
- <div class="feature" [class.feature--clickable]="feature.token != null" (click)="onItem(feature)">
25364
- <div
25365
- class="feature__icon"
25366
- [style.color]="iconColorStyle()"
25367
- [style.width.px]="config().iconSize"
25368
- [style.height.px]="config().iconSize"
25542
+ @if (feature.token != null) {
25543
+ <button
25544
+ type="button"
25545
+ class="feature feature--clickable"
25546
+ [attr.aria-label]="getTitle(feature)"
25547
+ (click)="onItem(feature)"
25369
25548
  >
25370
- @if (feature.image) {
25371
- <img
25372
- class="feature__image"
25373
- [class.feature__image--circle]="config().imageShape === 'circle'"
25374
- [src]="feature.image"
25375
- [alt]="getTitle(feature)"
25376
- />
25377
- } @else if (feature.icon === 'custom' && feature.svgPath) {
25378
- <svg
25379
- [attr.width]="config().iconSize"
25380
- [attr.height]="config().iconSize"
25381
- viewBox="0 0 24 24"
25382
- fill="none"
25383
- stroke="currentColor"
25384
- stroke-width="1.5"
25385
- stroke-linecap="round"
25386
- stroke-linejoin="round"
25387
- >
25388
- <path [attr.d]="feature.svgPath" />
25389
- </svg>
25390
- } @else if (feature.icon) {
25391
- <ion-icon [name]="feature.icon" [style.font-size.px]="config().iconSize"></ion-icon>
25392
- }
25393
- </div>
25394
- <div class="feature__content">
25395
- <strong class="feature__title">{{ getTitle(feature) }}</strong>
25396
- <p class="feature__description">{{ getDescription(feature) }}</p>
25549
+ <div
25550
+ class="feature__icon"
25551
+ [style.color]="iconColorStyle()"
25552
+ [style.width.px]="config().iconSize"
25553
+ [style.height.px]="config().iconSize"
25554
+ >
25555
+ @if (feature.image) {
25556
+ <img
25557
+ class="feature__image"
25558
+ [class.feature__image--circle]="config().imageShape === 'circle'"
25559
+ [src]="feature.image"
25560
+ [alt]="getTitle(feature)"
25561
+ />
25562
+ } @else if (feature.icon === 'custom' && feature.svgPath) {
25563
+ <svg
25564
+ [attr.width]="config().iconSize"
25565
+ [attr.height]="config().iconSize"
25566
+ viewBox="0 0 24 24"
25567
+ fill="none"
25568
+ stroke="currentColor"
25569
+ stroke-width="1.5"
25570
+ stroke-linecap="round"
25571
+ stroke-linejoin="round"
25572
+ >
25573
+ <path [attr.d]="feature.svgPath" />
25574
+ </svg>
25575
+ } @else if (feature.icon) {
25576
+ <ion-icon [name]="feature.icon" [style.font-size.px]="config().iconSize"></ion-icon>
25577
+ }
25578
+ </div>
25579
+ <div class="feature__content">
25580
+ <strong class="feature__title">{{ getTitle(feature) }}</strong>
25581
+ <p class="feature__description">{{ getDescription(feature) }}</p>
25582
+ </div>
25583
+ </button>
25584
+ } @else {
25585
+ <div class="feature">
25586
+ <div
25587
+ class="feature__icon"
25588
+ [style.color]="iconColorStyle()"
25589
+ [style.width.px]="config().iconSize"
25590
+ [style.height.px]="config().iconSize"
25591
+ >
25592
+ @if (feature.image) {
25593
+ <img
25594
+ class="feature__image"
25595
+ [class.feature__image--circle]="config().imageShape === 'circle'"
25596
+ [src]="feature.image"
25597
+ [alt]="getTitle(feature)"
25598
+ />
25599
+ } @else if (feature.icon === 'custom' && feature.svgPath) {
25600
+ <svg
25601
+ [attr.width]="config().iconSize"
25602
+ [attr.height]="config().iconSize"
25603
+ viewBox="0 0 24 24"
25604
+ fill="none"
25605
+ stroke="currentColor"
25606
+ stroke-width="1.5"
25607
+ stroke-linecap="round"
25608
+ stroke-linejoin="round"
25609
+ >
25610
+ <path [attr.d]="feature.svgPath" />
25611
+ </svg>
25612
+ } @else if (feature.icon) {
25613
+ <ion-icon [name]="feature.icon" [style.font-size.px]="config().iconSize"></ion-icon>
25614
+ }
25615
+ </div>
25616
+ <div class="feature__content">
25617
+ <strong class="feature__title">{{ getTitle(feature) }}</strong>
25618
+ <p class="feature__description">{{ getDescription(feature) }}</p>
25619
+ </div>
25397
25620
  </div>
25398
- </div>
25621
+ }
25399
25622
  }
25400
25623
 
25401
25624
  @if (canCollapse()) {
@@ -25410,7 +25633,7 @@ class FeaturesListComponent {
25410
25633
  </a>
25411
25634
  }
25412
25635
  </div>
25413
- `, isInline: true, styles: [":host{display:block}.features-list{display:flex}.features-list--vertical{flex-direction:column}.features-list--horizontal{flex-direction:row;flex-wrap:wrap}.features-list--horizontal .feature{flex:1;min-width:200px}.features-list--gap-small{gap:1rem}.features-list--gap-medium{gap:1.5rem}.features-list--gap-large{gap:2rem}.features-list--center{align-items:center;text-align:center}.features-list--center .feature{flex-direction:column;align-items:center}.features-list--center .feature__content{text-align:center}.feature{display:flex;align-items:flex-start;gap:1rem}.feature--clickable{cursor:pointer;border-radius:10px;transition:background-color .15s ease}.feature--clickable:hover{background:var(--ion-color-light, rgba(0, 0, 0, .03))}.feature__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.feature__image{width:100%;height:100%;object-fit:contain;border-radius:8px}.feature__image--circle{object-fit:cover;border-radius:50%}.feature__content{flex:1}.feature__title{display:block;font-size:1.1rem;font-weight:600;color:var(--ion-text-color);margin-bottom:.25rem}.feature__description{margin:0;font-size:.95rem;color:var(--ion-color-medium);line-height:1.5}.features-list__more{align-self:flex-start;margin-top:.25rem;padding:0;background:none;border:none;font:inherit;font-weight:600;color:var(--ion-color-primary);cursor:pointer}.features-list--center .features-list__more,.features-list--center .features-list__footer{align-self:center}.features-list__footer{align-self:flex-start;margin-top:.25rem;font-weight:600;color:var(--ion-color-primary);text-decoration:none;cursor:pointer}.features-list__footer:hover{text-decoration:underline}:host-context(.dark) .feature__title,:host-context(.ion-palette-dark) .feature__title,:host-context(html.ion-palette-dark) .feature__title,:host-context(body.dark) .feature__title,:host-context([data-theme=\"dark\"]) .feature__title{color:var(--ion-text-color, #fff)}:host-context(.dark) .feature__description,:host-context(.ion-palette-dark) .feature__description,:host-context(html.ion-palette-dark) .feature__description,:host-context(body.dark) .feature__description,:host-context([data-theme=\"dark\"]) .feature__description{color:var(--ion-color-medium, #a0a0a0)}:host-context(.dark) .feature--clickable:hover,:host-context(.ion-palette-dark) .feature--clickable:hover,:host-context(html.ion-palette-dark) .feature--clickable:hover,:host-context(body.dark) .feature--clickable:hover,:host-context([data-theme=\"dark\"]) .feature--clickable:hover{background:#ffffff0a}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
25636
+ `, isInline: true, styles: [":host{display:block}.features-list{display:flex}.features-list--vertical{flex-direction:column}.features-list--horizontal{flex-direction:row;flex-wrap:wrap}.features-list--horizontal .feature{flex:1;min-width:200px}.features-list--gap-small{gap:1rem}.features-list--gap-medium{gap:1.5rem}.features-list--gap-large{gap:2rem}.features-list--center{align-items:center;text-align:center}.features-list--center .feature{flex-direction:column;align-items:center}.features-list--center .feature__content{text-align:center}.feature{display:flex;align-items:flex-start;gap:1rem}.feature--clickable{cursor:pointer;border-radius:10px;transition:background-color .15s ease;width:100%;text-align:left;border:none;background:none;font:inherit;color:inherit;padding:.25rem}.feature--clickable:hover{background:var(--ion-color-light, rgba(0, 0, 0, .03))}.feature--clickable:focus{outline:none}.feature--clickable:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px}.feature__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.feature__image{width:100%;height:100%;object-fit:contain;border-radius:8px}.feature__image--circle{object-fit:cover;border-radius:50%}.feature__content{flex:1}.feature__title{display:block;font-size:1.1rem;font-weight:600;color:var(--ion-text-color);margin-bottom:.25rem}.feature__description{margin:0;font-size:.95rem;color:var(--ion-color-medium);line-height:1.5}.features-list__more{align-self:flex-start;margin-top:.25rem;padding:0;background:none;border:none;font:inherit;font-weight:600;color:var(--ion-color-primary);cursor:pointer}.features-list--center .features-list__more,.features-list--center .features-list__footer{align-self:center}.features-list__footer{align-self:flex-start;margin-top:.25rem;font-weight:600;color:var(--ion-color-primary);text-decoration:none;cursor:pointer}.features-list__footer:hover{text-decoration:underline}:host-context(.dark) .feature__title,:host-context(.ion-palette-dark) .feature__title,:host-context(html.ion-palette-dark) .feature__title,:host-context(body.dark) .feature__title,:host-context([data-theme=\"dark\"]) .feature__title{color:var(--ion-text-color, #fff)}:host-context(.dark) .feature__description,:host-context(.ion-palette-dark) .feature__description,:host-context(html.ion-palette-dark) .feature__description,:host-context(body.dark) .feature__description,:host-context([data-theme=\"dark\"]) .feature__description{color:var(--ion-color-medium, #a0a0a0)}:host-context(.dark) .feature--clickable:hover,:host-context(.ion-palette-dark) .feature--clickable:hover,:host-context(html.ion-palette-dark) .feature--clickable:hover,:host-context(body.dark) .feature--clickable:hover,:host-context([data-theme=\"dark\"]) .feature--clickable:hover{background:#ffffff0a}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
25414
25637
  }
25415
25638
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FeaturesListComponent, decorators: [{
25416
25639
  type: Component,
@@ -25425,42 +25648,86 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
25425
25648
  [class.features-list--center]="config().alignment === 'center'"
25426
25649
  >
25427
25650
  @for (feature of visibleFeatures(); track feature.titleKey) {
25428
- <div class="feature" [class.feature--clickable]="feature.token != null" (click)="onItem(feature)">
25429
- <div
25430
- class="feature__icon"
25431
- [style.color]="iconColorStyle()"
25432
- [style.width.px]="config().iconSize"
25433
- [style.height.px]="config().iconSize"
25651
+ @if (feature.token != null) {
25652
+ <button
25653
+ type="button"
25654
+ class="feature feature--clickable"
25655
+ [attr.aria-label]="getTitle(feature)"
25656
+ (click)="onItem(feature)"
25434
25657
  >
25435
- @if (feature.image) {
25436
- <img
25437
- class="feature__image"
25438
- [class.feature__image--circle]="config().imageShape === 'circle'"
25439
- [src]="feature.image"
25440
- [alt]="getTitle(feature)"
25441
- />
25442
- } @else if (feature.icon === 'custom' && feature.svgPath) {
25443
- <svg
25444
- [attr.width]="config().iconSize"
25445
- [attr.height]="config().iconSize"
25446
- viewBox="0 0 24 24"
25447
- fill="none"
25448
- stroke="currentColor"
25449
- stroke-width="1.5"
25450
- stroke-linecap="round"
25451
- stroke-linejoin="round"
25452
- >
25453
- <path [attr.d]="feature.svgPath" />
25454
- </svg>
25455
- } @else if (feature.icon) {
25456
- <ion-icon [name]="feature.icon" [style.font-size.px]="config().iconSize"></ion-icon>
25457
- }
25458
- </div>
25459
- <div class="feature__content">
25460
- <strong class="feature__title">{{ getTitle(feature) }}</strong>
25461
- <p class="feature__description">{{ getDescription(feature) }}</p>
25658
+ <div
25659
+ class="feature__icon"
25660
+ [style.color]="iconColorStyle()"
25661
+ [style.width.px]="config().iconSize"
25662
+ [style.height.px]="config().iconSize"
25663
+ >
25664
+ @if (feature.image) {
25665
+ <img
25666
+ class="feature__image"
25667
+ [class.feature__image--circle]="config().imageShape === 'circle'"
25668
+ [src]="feature.image"
25669
+ [alt]="getTitle(feature)"
25670
+ />
25671
+ } @else if (feature.icon === 'custom' && feature.svgPath) {
25672
+ <svg
25673
+ [attr.width]="config().iconSize"
25674
+ [attr.height]="config().iconSize"
25675
+ viewBox="0 0 24 24"
25676
+ fill="none"
25677
+ stroke="currentColor"
25678
+ stroke-width="1.5"
25679
+ stroke-linecap="round"
25680
+ stroke-linejoin="round"
25681
+ >
25682
+ <path [attr.d]="feature.svgPath" />
25683
+ </svg>
25684
+ } @else if (feature.icon) {
25685
+ <ion-icon [name]="feature.icon" [style.font-size.px]="config().iconSize"></ion-icon>
25686
+ }
25687
+ </div>
25688
+ <div class="feature__content">
25689
+ <strong class="feature__title">{{ getTitle(feature) }}</strong>
25690
+ <p class="feature__description">{{ getDescription(feature) }}</p>
25691
+ </div>
25692
+ </button>
25693
+ } @else {
25694
+ <div class="feature">
25695
+ <div
25696
+ class="feature__icon"
25697
+ [style.color]="iconColorStyle()"
25698
+ [style.width.px]="config().iconSize"
25699
+ [style.height.px]="config().iconSize"
25700
+ >
25701
+ @if (feature.image) {
25702
+ <img
25703
+ class="feature__image"
25704
+ [class.feature__image--circle]="config().imageShape === 'circle'"
25705
+ [src]="feature.image"
25706
+ [alt]="getTitle(feature)"
25707
+ />
25708
+ } @else if (feature.icon === 'custom' && feature.svgPath) {
25709
+ <svg
25710
+ [attr.width]="config().iconSize"
25711
+ [attr.height]="config().iconSize"
25712
+ viewBox="0 0 24 24"
25713
+ fill="none"
25714
+ stroke="currentColor"
25715
+ stroke-width="1.5"
25716
+ stroke-linecap="round"
25717
+ stroke-linejoin="round"
25718
+ >
25719
+ <path [attr.d]="feature.svgPath" />
25720
+ </svg>
25721
+ } @else if (feature.icon) {
25722
+ <ion-icon [name]="feature.icon" [style.font-size.px]="config().iconSize"></ion-icon>
25723
+ }
25724
+ </div>
25725
+ <div class="feature__content">
25726
+ <strong class="feature__title">{{ getTitle(feature) }}</strong>
25727
+ <p class="feature__description">{{ getDescription(feature) }}</p>
25728
+ </div>
25462
25729
  </div>
25463
- </div>
25730
+ }
25464
25731
  }
25465
25732
 
25466
25733
  @if (canCollapse()) {
@@ -25475,7 +25742,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
25475
25742
  </a>
25476
25743
  }
25477
25744
  </div>
25478
- `, styles: [":host{display:block}.features-list{display:flex}.features-list--vertical{flex-direction:column}.features-list--horizontal{flex-direction:row;flex-wrap:wrap}.features-list--horizontal .feature{flex:1;min-width:200px}.features-list--gap-small{gap:1rem}.features-list--gap-medium{gap:1.5rem}.features-list--gap-large{gap:2rem}.features-list--center{align-items:center;text-align:center}.features-list--center .feature{flex-direction:column;align-items:center}.features-list--center .feature__content{text-align:center}.feature{display:flex;align-items:flex-start;gap:1rem}.feature--clickable{cursor:pointer;border-radius:10px;transition:background-color .15s ease}.feature--clickable:hover{background:var(--ion-color-light, rgba(0, 0, 0, .03))}.feature__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.feature__image{width:100%;height:100%;object-fit:contain;border-radius:8px}.feature__image--circle{object-fit:cover;border-radius:50%}.feature__content{flex:1}.feature__title{display:block;font-size:1.1rem;font-weight:600;color:var(--ion-text-color);margin-bottom:.25rem}.feature__description{margin:0;font-size:.95rem;color:var(--ion-color-medium);line-height:1.5}.features-list__more{align-self:flex-start;margin-top:.25rem;padding:0;background:none;border:none;font:inherit;font-weight:600;color:var(--ion-color-primary);cursor:pointer}.features-list--center .features-list__more,.features-list--center .features-list__footer{align-self:center}.features-list__footer{align-self:flex-start;margin-top:.25rem;font-weight:600;color:var(--ion-color-primary);text-decoration:none;cursor:pointer}.features-list__footer:hover{text-decoration:underline}:host-context(.dark) .feature__title,:host-context(.ion-palette-dark) .feature__title,:host-context(html.ion-palette-dark) .feature__title,:host-context(body.dark) .feature__title,:host-context([data-theme=\"dark\"]) .feature__title{color:var(--ion-text-color, #fff)}:host-context(.dark) .feature__description,:host-context(.ion-palette-dark) .feature__description,:host-context(html.ion-palette-dark) .feature__description,:host-context(body.dark) .feature__description,:host-context([data-theme=\"dark\"]) .feature__description{color:var(--ion-color-medium, #a0a0a0)}:host-context(.dark) .feature--clickable:hover,:host-context(.ion-palette-dark) .feature--clickable:hover,:host-context(html.ion-palette-dark) .feature--clickable:hover,:host-context(body.dark) .feature--clickable:hover,:host-context([data-theme=\"dark\"]) .feature--clickable:hover{background:#ffffff0a}\n"] }]
25745
+ `, styles: [":host{display:block}.features-list{display:flex}.features-list--vertical{flex-direction:column}.features-list--horizontal{flex-direction:row;flex-wrap:wrap}.features-list--horizontal .feature{flex:1;min-width:200px}.features-list--gap-small{gap:1rem}.features-list--gap-medium{gap:1.5rem}.features-list--gap-large{gap:2rem}.features-list--center{align-items:center;text-align:center}.features-list--center .feature{flex-direction:column;align-items:center}.features-list--center .feature__content{text-align:center}.feature{display:flex;align-items:flex-start;gap:1rem}.feature--clickable{cursor:pointer;border-radius:10px;transition:background-color .15s ease;width:100%;text-align:left;border:none;background:none;font:inherit;color:inherit;padding:.25rem}.feature--clickable:hover{background:var(--ion-color-light, rgba(0, 0, 0, .03))}.feature--clickable:focus{outline:none}.feature--clickable:focus-visible{outline:.125rem solid var(--ion-color-primary, #7026df);outline-offset:2px}.feature__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.feature__image{width:100%;height:100%;object-fit:contain;border-radius:8px}.feature__image--circle{object-fit:cover;border-radius:50%}.feature__content{flex:1}.feature__title{display:block;font-size:1.1rem;font-weight:600;color:var(--ion-text-color);margin-bottom:.25rem}.feature__description{margin:0;font-size:.95rem;color:var(--ion-color-medium);line-height:1.5}.features-list__more{align-self:flex-start;margin-top:.25rem;padding:0;background:none;border:none;font:inherit;font-weight:600;color:var(--ion-color-primary);cursor:pointer}.features-list--center .features-list__more,.features-list--center .features-list__footer{align-self:center}.features-list__footer{align-self:flex-start;margin-top:.25rem;font-weight:600;color:var(--ion-color-primary);text-decoration:none;cursor:pointer}.features-list__footer:hover{text-decoration:underline}:host-context(.dark) .feature__title,:host-context(.ion-palette-dark) .feature__title,:host-context(html.ion-palette-dark) .feature__title,:host-context(body.dark) .feature__title,:host-context([data-theme=\"dark\"]) .feature__title{color:var(--ion-text-color, #fff)}:host-context(.dark) .feature__description,:host-context(.ion-palette-dark) .feature__description,:host-context(html.ion-palette-dark) .feature__description,:host-context(body.dark) .feature__description,:host-context([data-theme=\"dark\"]) .feature__description{color:var(--ion-color-medium, #a0a0a0)}:host-context(.dark) .feature--clickable:hover,:host-context(.ion-palette-dark) .feature--clickable:hover,:host-context(html.ion-palette-dark) .feature--clickable:hover,:host-context(body.dark) .feature--clickable:hover,:host-context([data-theme=\"dark\"]) .feature--clickable:hover{background:#ffffff0a}\n"] }]
25479
25746
  }], ctorParameters: () => [] });
25480
25747
 
25481
25748
  /**
@@ -27123,6 +27390,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
27123
27390
  `, styles: ["@charset \"UTF-8\";:host{display:contents}.val-update-banner{position:fixed;top:0;left:0;right:0;z-index:1100;display:flex;justify-content:center;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;pointer-events:none}.val-update-banner__backdrop{position:fixed;inset:0;z-index:-1;background:#0000008c;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);pointer-events:auto}.val-update-banner__panel{pointer-events:auto;display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;max-width:640px;padding:12px 16px;background:var(--ion-background-color, #fff);border:1px solid var(--val-border-color, rgba(0, 0, 0, .08));border-radius:var(--val-border-radius, 12px);box-shadow:0 4px 24px #0000001f;animation:val-update-banner-in .25s ease-out}.val-update-banner--required{align-items:center;height:100%}.val-update-banner--required .val-update-banner__panel{flex-direction:column;text-align:center;max-width:420px}.val-update-banner__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;background:color-mix(in srgb,var(--ion-color-primary) 14%,transparent);font-size:22px}.val-update-banner__icon val-icon{display:flex;line-height:0}.val-update-banner__icon ::ng-deep ion-icon{display:block}.val-update-banner--required .val-update-banner__icon{background:color-mix(in srgb,var(--ion-color-warning) 16%,transparent)}.val-update-banner__body{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.val-update-banner__actions{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:4px}.val-update-banner--required .val-update-banner__actions{margin-top:8px}@keyframes val-update-banner-in{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 540px){.val-update-banner__panel{flex-direction:column;text-align:center}.val-update-banner__actions{width:100%;justify-content:center}}\n"] }]
27124
27391
  }] });
27125
27392
 
27393
+ /**
27394
+ * Ionic color helpers — single source of truth.
27395
+ *
27396
+ * Several presentational cards used to inline a literal `IONIC_COLORS` array
27397
+ * plus a `resolveColor()` copy. This util consolidates that logic so the named
27398
+ * Ionic palette and the CSS-var resolution live in one place.
27399
+ */
27400
+ /** The named Ionic color palette tokens. */
27401
+ const IONIC_COLORS$5 = [
27402
+ 'primary',
27403
+ 'secondary',
27404
+ 'tertiary',
27405
+ 'success',
27406
+ 'warning',
27407
+ 'danger',
27408
+ 'light',
27409
+ 'medium',
27410
+ 'dark',
27411
+ ];
27412
+ /** True when `value` is one of the named Ionic palette tokens. */
27413
+ function isIonicColor(value) {
27414
+ return !!value && IONIC_COLORS$5.includes(value);
27415
+ }
27416
+ /**
27417
+ * Resolve a color value to a usable CSS color.
27418
+ *
27419
+ * - A named Ionic token (e.g. `primary`) becomes `var(--ion-color-primary)`.
27420
+ * - Any other value (hex, rgb, CSS var, etc.) is returned unchanged.
27421
+ * - `undefined`/empty returns `undefined`.
27422
+ */
27423
+ function resolveIonicColor(value) {
27424
+ if (!value)
27425
+ return undefined;
27426
+ return isIonicColor(value) ? `var(--ion-color-${value})` : value;
27427
+ }
27428
+
27126
27429
  /**
27127
27430
  * Default values for ActionCardMetadata
27128
27431
  */
@@ -27135,7 +27438,6 @@ const ACTION_CARD_DEFAULTS = {
27135
27438
  };
27136
27439
 
27137
27440
  addIcons({ chevronForwardOutline });
27138
- const IONIC_COLORS$8 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27139
27441
  /**
27140
27442
  * val-action-card
27141
27443
  *
@@ -27211,14 +27513,9 @@ class ActionCardComponent {
27211
27513
  }
27212
27514
  return cfg.description || '';
27213
27515
  }
27214
- /** Resolve color to CSS value */
27516
+ /** Resolve color to CSS value (named Ionic token → CSS var, else passthrough) */
27215
27517
  resolveColor(color) {
27216
- if (!color)
27217
- return null;
27218
- if (IONIC_COLORS$8.includes(color)) {
27219
- return `var(--ion-color-${color})`;
27220
- }
27221
- return color;
27518
+ return resolveIonicColor(color) ?? null;
27222
27519
  }
27223
27520
  getBackgroundColor() {
27224
27521
  return this.resolveColor(this.config().backgroundColor);
@@ -27408,7 +27705,7 @@ const MEDIA_OBJECT_DEFAULTS = {
27408
27705
  circle: false,
27409
27706
  };
27410
27707
 
27411
- const IONIC_COLORS$7 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27708
+ const IONIC_COLORS$4 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27412
27709
  /**
27413
27710
  * val-media-object
27414
27711
  *
@@ -27448,7 +27745,7 @@ class MediaObjectComponent {
27448
27745
  const color = this.config().color;
27449
27746
  if (!color)
27450
27747
  return 'var(--ion-color-primary)';
27451
- return IONIC_COLORS$7.includes(color) ? `var(--ion-color-${color})` : color;
27748
+ return IONIC_COLORS$4.includes(color) ? `var(--ion-color-${color})` : color;
27452
27749
  }
27453
27750
  handleLinkClick(event) {
27454
27751
  const link = this.config().link;
@@ -27552,7 +27849,7 @@ const STATS_BAR_DEFAULTS = {
27552
27849
  stackOnMobile: true,
27553
27850
  };
27554
27851
 
27555
- const IONIC_COLORS$6 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27852
+ const IONIC_COLORS$3 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27556
27853
  /**
27557
27854
  * val-stats-bar
27558
27855
  *
@@ -27589,7 +27886,7 @@ class StatsBarComponent {
27589
27886
  const color = stat.color;
27590
27887
  if (!color)
27591
27888
  return null;
27592
- return IONIC_COLORS$6.includes(color) ? `var(--ion-color-${color})` : color;
27889
+ return IONIC_COLORS$3.includes(color) ? `var(--ion-color-${color})` : color;
27593
27890
  }
27594
27891
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StatsBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
27595
27892
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: StatsBarComponent, isStandalone: true, selector: "val-stats-bar", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
@@ -27657,7 +27954,7 @@ const ARTICLE_CARD_DEFAULTS = {
27657
27954
  excerptLines: 3,
27658
27955
  };
27659
27956
 
27660
- const IONIC_COLORS$5 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27957
+ const IONIC_COLORS$2 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27661
27958
  /**
27662
27959
  * val-article-card
27663
27960
  *
@@ -27700,7 +27997,7 @@ class ArticleCardComponent {
27700
27997
  const color = this.config().topicColor;
27701
27998
  if (!color)
27702
27999
  return 'var(--ion-color-primary)';
27703
- return IONIC_COLORS$5.includes(color) ? `var(--ion-color-${color})` : color;
28000
+ return IONIC_COLORS$2.includes(color) ? `var(--ion-color-${color})` : color;
27704
28001
  }
27705
28002
  handleClick(event) {
27706
28003
  const cfg = this.config();
@@ -27815,7 +28112,6 @@ const CTA_CARD_DEFAULTS = {
27815
28112
  shadowed: false,
27816
28113
  };
27817
28114
 
27818
- const IONIC_COLORS$4 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
27819
28115
  /**
27820
28116
  * val-cta-card
27821
28117
  *
@@ -27856,16 +28152,11 @@ class CtaCardComponent {
27856
28152
  ...this.props(),
27857
28153
  }));
27858
28154
  }
27859
- resolveColor(color) {
27860
- if (!color)
27861
- return null;
27862
- return IONIC_COLORS$4.includes(color) ? `var(--ion-color-${color})` : color;
27863
- }
27864
28155
  getBackground() {
27865
- return this.resolveColor(this.config().backgroundColor) || 'var(--ion-color-light, #f4f5f8)';
28156
+ return resolveIonicColor(this.config().backgroundColor) || 'var(--ion-color-light, #f4f5f8)';
27866
28157
  }
27867
28158
  getColor() {
27868
- return this.resolveColor(this.config().color);
28159
+ return resolveIonicColor(this.config().color) ?? null;
27869
28160
  }
27870
28161
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CtaCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
27871
28162
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CtaCardComponent, isStandalone: true, selector: "val-cta-card", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: `
@@ -30908,6 +31199,13 @@ class FormComponent {
30908
31199
  this.usernamePropMemo = new WeakMap();
30909
31200
  this.textareaPropMemo = new WeakMap();
30910
31201
  this.selectPropMemo = new WeakMap();
31202
+ // Memo de props con un inputType HTML inyectado (EMAIL/NUMBER/HOUR colapsados
31203
+ // en val-text-input). Clave por field para conservar identidad de referencia.
31204
+ this.textInputPropMemo = new WeakMap();
31205
+ // Ids estables por field para el wiring de accesibilidad label↔input↔error.
31206
+ // Estables entre CD cycles (memoizados por referencia de field) → aria-* no parpadea.
31207
+ this.fieldIdMemo = new WeakMap();
31208
+ this.fieldUid = 0;
30911
31209
  this.previousUploadingCount = 0;
30912
31210
  // Campos ATTACHMENT con uploads en curso — bloquea submit + DESHABILITA el
30913
31211
  // botón (no loading: el spinner se reserva para el submit real del form).
@@ -31067,6 +31365,28 @@ class FormComponent {
31067
31365
  getControl(field) {
31068
31366
  return this.Form.get(field);
31069
31367
  }
31368
+ /**
31369
+ * Ids estables (label + error) para un field. Memoizados por referencia para
31370
+ * que el wiring `aria-labelledby` / `aria-describedby` no cambie entre ciclos
31371
+ * de change detection.
31372
+ */
31373
+ fieldIds(field) {
31374
+ let ids = this.fieldIdMemo.get(field);
31375
+ if (!ids) {
31376
+ const base = `val-form-field-${this.fieldUid++}`;
31377
+ ids = { labelId: `${base}-label`, errorId: `${base}-error` };
31378
+ this.fieldIdMemo.set(field, ids);
31379
+ }
31380
+ return ids;
31381
+ }
31382
+ /** Id del label visible del campo (consumido por el template + el input). */
31383
+ labelId(field) {
31384
+ return this.fieldIds(field).labelId;
31385
+ }
31386
+ /** Id del contenedor de error (`val-hint`) del campo. */
31387
+ errorId(field) {
31388
+ return this.fieldIds(field).errorId;
31389
+ }
31070
31390
  getFieldProp(field) {
31071
31391
  const cached = this.fieldPropMemo.get(field);
31072
31392
  if (cached)
@@ -31074,19 +31394,34 @@ class FormComponent {
31074
31394
  if (!field.token) {
31075
31395
  field.token = `input-${field.type}-${field.name}`;
31076
31396
  }
31397
+ const ids = this.fieldIds(field);
31077
31398
  let result;
31078
31399
  if (field.type === this.types.NUMBER_FROM_TO) {
31079
31400
  const fromControl = this.getControl(`${field.name}_from`);
31080
31401
  const toControl = this.getControl(`${field.name}_to`);
31081
- result = { ...field, fromControl, toControl, control: undefined };
31402
+ result = { ...field, fromControl, toControl, control: undefined, labelId: ids.labelId, errorId: ids.errorId };
31082
31403
  }
31083
31404
  else {
31084
31405
  const control = this.getControl(field.name);
31085
- result = { ...field, control };
31406
+ result = { ...field, control, labelId: ids.labelId, errorId: ids.errorId };
31086
31407
  }
31087
31408
  this.fieldPropMemo.set(field, result);
31088
31409
  return result;
31089
31410
  }
31411
+ /**
31412
+ * Adapter para los tipos colapsados en `val-text-input` (EMAIL/NUMBER/HOUR).
31413
+ * Reusa `getFieldProp` (con su control + wiring de ids) e inyecta el `inputType`
31414
+ * HTML nativo. Memoizado por referencia de field para no romper la identidad.
31415
+ */
31416
+ getTextInputProp(field, inputType) {
31417
+ const cached = this.textInputPropMemo.get(field);
31418
+ if (cached)
31419
+ return cached;
31420
+ const base = this.getFieldProp(field);
31421
+ const result = { ...base, inputType };
31422
+ this.textInputPropMemo.set(field, result);
31423
+ return result;
31424
+ }
31090
31425
  /**
31091
31426
  * Adapter para SELECT — igual que `getFieldProp` pero limpia `label`.
31092
31427
  * val-form ya renderiza el título del campo con `<val-title>` arriba del input;
@@ -31208,7 +31543,9 @@ class FormComponent {
31208
31543
  @for (f of s.fields; track f.name) {
31209
31544
  <div class="input" [attr.data-testid]="f.token">
31210
31545
  @if (f.type !== types.PHONE && f.type !== types.HANDLE && f.type !== types.ATTACHMENT) {
31211
- <val-title [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"></val-title>
31546
+ <div [attr.id]="labelId(f)">
31547
+ <val-title [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"></val-title>
31548
+ </div>
31212
31549
  }
31213
31550
  @if (f.description) {
31214
31551
  <span class="field-description">{{ f.description }}</span>
@@ -31230,16 +31567,16 @@ class FormComponent {
31230
31567
  <val-date-input [props]="getFieldProp(f)"></val-date-input>
31231
31568
  }
31232
31569
  @case (types.EMAIL) {
31233
- <val-email-input [props]="getFieldProp(f)"></val-email-input>
31570
+ <val-text-input [props]="getTextInputProp(f, 'email')"></val-text-input>
31234
31571
  }
31235
31572
  @case (types.FILE) {
31236
31573
  <val-file-input [props]="getFieldProp(f)"></val-file-input>
31237
31574
  }
31238
31575
  @case (types.HOUR) {
31239
- <val-hour-input [props]="getFieldProp(f)"></val-hour-input>
31576
+ <val-text-input [props]="getTextInputProp(f, 'time')"></val-text-input>
31240
31577
  }
31241
31578
  @case (types.NUMBER) {
31242
- <val-number-input [props]="getFieldProp(f)"></val-number-input>
31579
+ <val-text-input [props]="getTextInputProp(f, 'number')"></val-text-input>
31243
31580
  }
31244
31581
  @case (types.NUMBER_FROM_TO) {
31245
31582
  <val-number-from-to [props]="getFieldProp(f)"></val-number-from-to>
@@ -31286,7 +31623,7 @@ class FormComponent {
31286
31623
  ></val-attachment-uploader>
31287
31624
  }
31288
31625
  }
31289
- <val-hint [props]="getFieldProp(f)"></val-hint>
31626
+ <val-hint [props]="getFieldProp(f)" [id]="errorId(f)"></val-hint>
31290
31627
  </div>
31291
31628
  }
31292
31629
  <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
@@ -31303,7 +31640,7 @@ class FormComponent {
31303
31640
  }
31304
31641
  </form>
31305
31642
  </div>
31306
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.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: ["preset", "props"] }, { kind: "component", type: TextareaInputComponent, selector: "val-textarea-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input", inputs: ["preset", "props"] }, { 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: ["preset", "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: ["preset", "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: ["preset", "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: ["preset", "props"] }, { kind: "component", type: PhoneInputComponent, selector: "val-phone-input", inputs: ["preset", "props"], outputs: ["phoneChange"] }, { kind: "component", type: ToggleInputComponent, selector: "val-toggle-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckboxRadioInputComponent, selector: "val-checkbox-radio-input", inputs: ["props"] }, { kind: "component", type: UsernameInputComponent, selector: "val-username-input", inputs: ["props"] }, { kind: "component", type: AttachmentUploaderComponent, selector: "val-attachment-uploader", inputs: ["props"], outputs: ["attachmentsChange"] }] }); }
31643
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--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)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--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:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.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: ["preset", "props"] }, { kind: "component", type: TextareaInputComponent, selector: "val-textarea-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input", inputs: ["preset", "props"] }, { 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", "id", "isError"] }, { kind: "component", type: CommentInputComponent, selector: "val-comment-input", inputs: ["props"] }, { kind: "component", type: DateInputComponent, selector: "val-date-input", inputs: ["preset", "props"] }, { kind: "component", type: FileInputComponent, selector: "val-file-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: ["preset", "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: ["preset", "props"] }, { kind: "component", type: PhoneInputComponent, selector: "val-phone-input", inputs: ["preset", "props"], outputs: ["phoneChange"] }, { kind: "component", type: ToggleInputComponent, selector: "val-toggle-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckboxRadioInputComponent, selector: "val-checkbox-radio-input", inputs: ["props"] }, { kind: "component", type: UsernameInputComponent, selector: "val-username-input", inputs: ["props"] }, { kind: "component", type: AttachmentUploaderComponent, selector: "val-attachment-uploader", inputs: ["props"], outputs: ["attachmentsChange"] }] }); }
31307
31644
  }
31308
31645
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormComponent, decorators: [{
31309
31646
  type: Component,
@@ -31321,9 +31658,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
31321
31658
  CommentInputComponent,
31322
31659
  DateInputComponent,
31323
31660
  FileInputComponent,
31324
- HourInputComponent,
31325
- EmailInputComponent,
31326
- NumberInputComponent,
31327
31661
  NumberFromToComponent,
31328
31662
  RadioInputComponent,
31329
31663
  PasswordInputComponent,
@@ -31354,7 +31688,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
31354
31688
  @for (f of s.fields; track f.name) {
31355
31689
  <div class="input" [attr.data-testid]="f.token">
31356
31690
  @if (f.type !== types.PHONE && f.type !== types.HANDLE && f.type !== types.ATTACHMENT) {
31357
- <val-title [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"></val-title>
31691
+ <div [attr.id]="labelId(f)">
31692
+ <val-title [props]="{ content: f.label, size: 'small', color: 'dark', bold: false }"></val-title>
31693
+ </div>
31358
31694
  }
31359
31695
  @if (f.description) {
31360
31696
  <span class="field-description">{{ f.description }}</span>
@@ -31376,16 +31712,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
31376
31712
  <val-date-input [props]="getFieldProp(f)"></val-date-input>
31377
31713
  }
31378
31714
  @case (types.EMAIL) {
31379
- <val-email-input [props]="getFieldProp(f)"></val-email-input>
31715
+ <val-text-input [props]="getTextInputProp(f, 'email')"></val-text-input>
31380
31716
  }
31381
31717
  @case (types.FILE) {
31382
31718
  <val-file-input [props]="getFieldProp(f)"></val-file-input>
31383
31719
  }
31384
31720
  @case (types.HOUR) {
31385
- <val-hour-input [props]="getFieldProp(f)"></val-hour-input>
31721
+ <val-text-input [props]="getTextInputProp(f, 'time')"></val-text-input>
31386
31722
  }
31387
31723
  @case (types.NUMBER) {
31388
- <val-number-input [props]="getFieldProp(f)"></val-number-input>
31724
+ <val-text-input [props]="getTextInputProp(f, 'number')"></val-text-input>
31389
31725
  }
31390
31726
  @case (types.NUMBER_FROM_TO) {
31391
31727
  <val-number-from-to [props]="getFieldProp(f)"></val-number-from-to>
@@ -31432,7 +31768,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
31432
31768
  ></val-attachment-uploader>
31433
31769
  }
31434
31770
  }
31435
- <val-hint [props]="getFieldProp(f)"></val-hint>
31771
+ <val-hint [props]="getFieldProp(f)" [id]="errorId(f)"></val-hint>
31436
31772
  </div>
31437
31773
  }
31438
31774
  <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'medium' }"></val-divider>
@@ -32560,7 +32896,7 @@ class ChangePasswordModalComponent {
32560
32896
  },
32561
32897
  ],
32562
32898
  actions: {
32563
- ...SolidDefaultBlock('', 'submit'),
32899
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
32564
32900
  token: 'set-submit',
32565
32901
  textKey: 'setPasswordSubmit',
32566
32902
  },
@@ -32594,7 +32930,7 @@ class ChangePasswordModalComponent {
32594
32930
  },
32595
32931
  ],
32596
32932
  actions: {
32597
- ...SolidDefaultBlock('', 'submit'),
32933
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
32598
32934
  token: 'change-submit',
32599
32935
  textKey: 'changePasswordSubmit',
32600
32936
  },
@@ -32819,7 +33155,7 @@ class ChangeEmailModalComponent {
32819
33155
  },
32820
33156
  ],
32821
33157
  actions: {
32822
- ...SolidDefaultBlock('', 'submit'),
33158
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
32823
33159
  token: 'change-email-initiate',
32824
33160
  textKey: 'changeEmailInitiate',
32825
33161
  },
@@ -32852,7 +33188,7 @@ class ChangeEmailModalComponent {
32852
33188
  },
32853
33189
  ],
32854
33190
  actions: {
32855
- ...SolidDefaultBlock('', 'submit'),
33191
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
32856
33192
  token: 'change-email-confirm-1',
32857
33193
  textKey: 'changeEmailConfirm1',
32858
33194
  },
@@ -32888,7 +33224,7 @@ class ChangeEmailModalComponent {
32888
33224
  },
32889
33225
  ],
32890
33226
  actions: {
32891
- ...SolidDefaultBlock('', 'submit'),
33227
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
32892
33228
  token: 'change-email-confirm-2',
32893
33229
  textKey: 'changeEmailConfirm2',
32894
33230
  },
@@ -33262,7 +33598,7 @@ const FUN_MODAL_DEFAULTS = {
33262
33598
  imageRadius: 16,
33263
33599
  };
33264
33600
 
33265
- const IONIC_COLORS$3 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
33601
+ const IONIC_COLORS$1 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
33266
33602
  /**
33267
33603
  * `val-fun-modal` — modal moderno tipo promo/onboarding: imagen o ilustración
33268
33604
  * arriba, título, cuerpo y botones de acción, con redondeo personalizable.
@@ -33312,7 +33648,7 @@ class FunModalComponent {
33312
33648
  const color = this.config().backgroundColor;
33313
33649
  if (!color)
33314
33650
  return null;
33315
- return IONIC_COLORS$3.includes(color) ? `var(--ion-color-${color})` : color;
33651
+ return IONIC_COLORS$1.includes(color) ? `var(--ion-color-${color})` : color;
33316
33652
  }
33317
33653
  close() {
33318
33654
  this._isOpen = false;
@@ -34539,7 +34875,7 @@ class MfaModalComponent {
34539
34875
  },
34540
34876
  ],
34541
34877
  actions: {
34542
- ...SolidDefaultBlock('', 'submit'),
34878
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
34543
34879
  token: 'mfa-disable-submit',
34544
34880
  textKey: 'mfaDisableButton',
34545
34881
  },
@@ -34983,7 +35319,7 @@ class ItemListComponent {
34983
35319
  * Devuelve el color de borde de la lista.
34984
35320
  */
34985
35321
  color() {
34986
- return resolveColor$1(this.props.color || this.defaultColor);
35322
+ return resolveColor(this.props.color || this.defaultColor);
34987
35323
  }
34988
35324
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ItemListComponent, deps: [{ token: IconService }], target: i0.ɵɵFactoryTarget.Component }); }
34989
35325
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ItemListComponent, isStandalone: true, selector: "val-item-list", inputs: { props: "props" }, outputs: { onClick: "onClick", onActionClick: "onActionClick" }, ngImport: i0, template: `
@@ -39388,7 +39724,7 @@ class LoginComponent {
39388
39724
  },
39389
39725
  ],
39390
39726
  actions: {
39391
- ...SolidDefaultBlock('', 'submit'),
39727
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
39392
39728
  token: 'login-submit',
39393
39729
  textKey: 'loginSubmit',
39394
39730
  },
@@ -39454,7 +39790,7 @@ class LoginComponent {
39454
39790
  },
39455
39791
  ],
39456
39792
  actions: {
39457
- ...SolidDefaultBlock('', 'submit'),
39793
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
39458
39794
  token: 'register-submit',
39459
39795
  textKey: 'registerSubmit',
39460
39796
  },
@@ -39495,7 +39831,7 @@ class LoginComponent {
39495
39831
  },
39496
39832
  ],
39497
39833
  actions: {
39498
- ...SolidDefaultBlock('', 'submit'),
39834
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
39499
39835
  token: 'verify-submit',
39500
39836
  textKey: 'verifySubmit',
39501
39837
  },
@@ -39538,7 +39874,7 @@ class LoginComponent {
39538
39874
  },
39539
39875
  ],
39540
39876
  actions: {
39541
- ...SolidDefaultBlock('', 'submit'),
39877
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
39542
39878
  token: 'mfa-verify-submit',
39543
39879
  textKey: 'verifySubmit',
39544
39880
  },
@@ -39575,7 +39911,7 @@ class LoginComponent {
39575
39911
  },
39576
39912
  ],
39577
39913
  actions: {
39578
- ...SolidDefaultBlock('', 'submit'),
39914
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
39579
39915
  token: 'forgot-submit',
39580
39916
  textKey: 'forgotSubmit',
39581
39917
  },
@@ -39631,7 +39967,7 @@ class LoginComponent {
39631
39967
  },
39632
39968
  ],
39633
39969
  actions: {
39634
- ...SolidDefaultBlock('', 'submit'),
39970
+ ...button({ text: '', type: 'submit', fill: 'solid', expand: 'block' }),
39635
39971
  token: 'reset-submit',
39636
39972
  textKey: 'resetSubmit',
39637
39973
  },
@@ -56828,7 +57164,7 @@ class PageContentComponent {
56828
57164
  if (!bg) {
56829
57165
  return 'var(--ion-background-color)';
56830
57166
  }
56831
- return resolveColor$1(bg);
57167
+ return resolveColor(bg);
56832
57168
  }
56833
57169
  /**
56834
57170
  * Handles header action clicks.
@@ -57132,7 +57468,7 @@ class PageWrapperComponent {
57132
57468
  if (!bg) {
57133
57469
  return 'var(--ion-background-color)';
57134
57470
  }
57135
- return resolveColor$1(bg);
57471
+ return resolveColor(bg);
57136
57472
  });
57137
57473
  }
57138
57474
  /**
@@ -65073,7 +65409,12 @@ class RequestFormBuilderService {
65073
65409
  return {
65074
65410
  name: formName,
65075
65411
  sections: [section],
65076
- actions: SolidDefaultBlock(this.i18n.t(submitLabelKey, i18nNamespace), 'submit'),
65412
+ actions: button({
65413
+ text: this.i18n.t(submitLabelKey, i18nNamespace),
65414
+ type: 'submit',
65415
+ fill: 'solid',
65416
+ expand: 'block',
65417
+ }),
65077
65418
  state,
65078
65419
  };
65079
65420
  }
@@ -65346,138 +65687,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
65346
65687
  type: Output
65347
65688
  }] } });
65348
65689
 
65349
- /**
65350
- * Default values for InfoCardMetadata.
65351
- */
65352
- const INFO_CARD_DEFAULTS = {
65353
- iconColor: 'primary',
65354
- bordered: true,
65355
- shadowed: false,
65356
- padding: '1.5rem',
65357
- borderRadius: '16px',
65358
- };
65359
-
65360
- const IONIC_COLORS$2 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
65361
- /**
65362
- * val-info-card
65363
- *
65364
- * Card with icon + overtitle + title + subtitle on the left side, and a list
65365
- * of key-value pairs (label: value) on the right side. Inspired by npm's
65366
- * "Provenance" / metadata panel style.
65367
- *
65368
- * Two-column layout on desktop, stacked single-column on mobile.
65369
- *
65370
- * Presentational — pass already-resolved strings.
65371
- *
65372
- * @example
65373
- * ```html
65374
- * <val-info-card
65375
- * [props]="{
65376
- * icon: 'cube-outline',
65377
- * title: 'valtech-components',
65378
- * subtitle: 'v2.0.962',
65379
- * keyValues: [
65380
- * { label: 'License', value: 'MIT' },
65381
- * { label: 'Downloads', value: '1.2M' }
65382
- * ]
65383
- * }"
65384
- * />
65385
- * ```
65386
- */
65387
- class InfoCardComponent {
65388
- constructor() {
65389
- /** Component configuration */
65390
- this.props = input({});
65391
- /** Merged configuration with defaults */
65392
- this.config = computed(() => ({
65393
- ...INFO_CARD_DEFAULTS,
65394
- ...this.props(),
65395
- }));
65396
- }
65397
- getIconColor() {
65398
- const color = this.config().iconColor;
65399
- if (!color)
65400
- return `var(--ion-color-primary)`;
65401
- return IONIC_COLORS$2.includes(color) ? `var(--ion-color-${color})` : color;
65402
- }
65403
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InfoCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
65404
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: InfoCardComponent, isStandalone: true, selector: "val-info-card", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
65405
- <div
65406
- class="info-card"
65407
- [class.info-card--bordered]="config().bordered"
65408
- [class.info-card--shadowed]="config().shadowed"
65409
- [style.padding]="config().padding"
65410
- [style.border-radius]="config().borderRadius"
65411
- >
65412
- <div class="info-card__left">
65413
- @if (config().icon) {
65414
- <ion-icon class="info-card__icon" [name]="config().icon" [style.color]="getIconColor()"></ion-icon>
65415
- }
65416
-
65417
- @if (config().overtitle) {
65418
- <span class="info-card__overtitle">{{ config().overtitle }}</span>
65419
- }
65420
-
65421
- <h3 class="info-card__title">{{ config().title }}</h3>
65422
-
65423
- @if (config().subtitle) {
65424
- <p class="info-card__subtitle">{{ config().subtitle }}</p>
65425
- }
65426
- </div>
65427
-
65428
- @if (config().keyValues?.length) {
65429
- <div class="info-card__right">
65430
- @for (kv of config().keyValues; track $index) {
65431
- <div class="info-card__kv">
65432
- <span class="info-card__kv-label">{{ kv.label }}</span>
65433
- <span class="info-card__kv-value">{{ kv.value }}</span>
65434
- </div>
65435
- }
65436
- </div>
65437
- }
65438
- </div>
65439
- `, isInline: true, styles: [":host{display:block}.info-card{display:flex;flex-direction:row;gap:2rem;background:var(--ion-card-background, var(--ion-background-color))}.info-card--bordered{border:1px solid var(--ion-color-light-shade, rgba(0, 0, 0, .1))}.info-card--shadowed{box-shadow:0 2px 8px #00000014}.info-card__left{display:flex;flex-direction:column;gap:.35rem;flex:1 1 0;min-width:0}.info-card__icon{font-size:2rem;margin-bottom:.25rem}.info-card__overtitle{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.08em;color:var(--ion-color-medium)}.info-card__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--ion-text-color);line-height:1.3}.info-card__subtitle{margin:0;font-size:.875rem;color:var(--ion-color-medium-shade)}.info-card__right{display:flex;flex-direction:column;gap:.6rem;flex:0 0 auto;min-width:160px;max-width:260px}.info-card__kv{display:flex;flex-direction:column;gap:.1rem}.info-card__kv-label{font-size:.75rem;color:var(--ion-color-medium)}.info-card__kv-value{font-size:.9rem;font-weight:600;color:var(--ion-text-color);word-break:break-word}@media (max-width: 600px){.info-card{flex-direction:column;gap:1.25rem}.info-card__right{max-width:100%;flex-direction:row;flex-wrap:wrap;gap:.75rem 1.5rem}.info-card__kv{flex:0 0 auto}}:host-context(body.dark) .info-card--bordered,:host-context(html.ion-palette-dark) .info-card--bordered,:host-context([data-theme=dark]) .info-card--bordered{border-color:#ffffff1f}:host-context(body.dark) .info-card--shadowed,:host-context(html.ion-palette-dark) .info-card--shadowed,:host-context([data-theme=dark]) .info-card--shadowed{box-shadow:0 2px 8px #0000004d}\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"] }] }); }
65440
- }
65441
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InfoCardComponent, decorators: [{
65442
- type: Component,
65443
- args: [{ selector: 'val-info-card', standalone: true, imports: [CommonModule, IonIcon], template: `
65444
- <div
65445
- class="info-card"
65446
- [class.info-card--bordered]="config().bordered"
65447
- [class.info-card--shadowed]="config().shadowed"
65448
- [style.padding]="config().padding"
65449
- [style.border-radius]="config().borderRadius"
65450
- >
65451
- <div class="info-card__left">
65452
- @if (config().icon) {
65453
- <ion-icon class="info-card__icon" [name]="config().icon" [style.color]="getIconColor()"></ion-icon>
65454
- }
65455
-
65456
- @if (config().overtitle) {
65457
- <span class="info-card__overtitle">{{ config().overtitle }}</span>
65458
- }
65459
-
65460
- <h3 class="info-card__title">{{ config().title }}</h3>
65461
-
65462
- @if (config().subtitle) {
65463
- <p class="info-card__subtitle">{{ config().subtitle }}</p>
65464
- }
65465
- </div>
65466
-
65467
- @if (config().keyValues?.length) {
65468
- <div class="info-card__right">
65469
- @for (kv of config().keyValues; track $index) {
65470
- <div class="info-card__kv">
65471
- <span class="info-card__kv-label">{{ kv.label }}</span>
65472
- <span class="info-card__kv-value">{{ kv.value }}</span>
65473
- </div>
65474
- }
65475
- </div>
65476
- }
65477
- </div>
65478
- `, styles: [":host{display:block}.info-card{display:flex;flex-direction:row;gap:2rem;background:var(--ion-card-background, var(--ion-background-color))}.info-card--bordered{border:1px solid var(--ion-color-light-shade, rgba(0, 0, 0, .1))}.info-card--shadowed{box-shadow:0 2px 8px #00000014}.info-card__left{display:flex;flex-direction:column;gap:.35rem;flex:1 1 0;min-width:0}.info-card__icon{font-size:2rem;margin-bottom:.25rem}.info-card__overtitle{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.08em;color:var(--ion-color-medium)}.info-card__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--ion-text-color);line-height:1.3}.info-card__subtitle{margin:0;font-size:.875rem;color:var(--ion-color-medium-shade)}.info-card__right{display:flex;flex-direction:column;gap:.6rem;flex:0 0 auto;min-width:160px;max-width:260px}.info-card__kv{display:flex;flex-direction:column;gap:.1rem}.info-card__kv-label{font-size:.75rem;color:var(--ion-color-medium)}.info-card__kv-value{font-size:.9rem;font-weight:600;color:var(--ion-text-color);word-break:break-word}@media (max-width: 600px){.info-card{flex-direction:column;gap:1.25rem}.info-card__right{max-width:100%;flex-direction:row;flex-wrap:wrap;gap:.75rem 1.5rem}.info-card__kv{flex:0 0 auto}}:host-context(body.dark) .info-card--bordered,:host-context(html.ion-palette-dark) .info-card--bordered,:host-context([data-theme=dark]) .info-card--bordered{border-color:#ffffff1f}:host-context(body.dark) .info-card--shadowed,:host-context(html.ion-palette-dark) .info-card--shadowed,:host-context([data-theme=dark]) .info-card--shadowed{box-shadow:0 2px 8px #0000004d}\n"] }]
65479
- }] });
65480
-
65481
65690
  /**
65482
65691
  * Default values for MetricCardMetadata.
65483
65692
  */
@@ -65627,99 +65836,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
65627
65836
  type: Output
65628
65837
  }] } });
65629
65838
 
65630
- /**
65631
- * Default values for ContentCardMetadata.
65632
- */
65633
- const CONTENT_CARD_DEFAULTS = {
65634
- padding: '1.5rem',
65635
- borderRadius: '20px',
65636
- bordered: false,
65637
- shadowed: true,
65638
- align: 'start',
65639
- };
65640
-
65641
- const IONIC_COLORS$1 = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
65642
- function resolveColor(value) {
65643
- if (!value)
65644
- return undefined;
65645
- return IONIC_COLORS$1.includes(value) ? `var(--ion-color-${value})` : value;
65646
- }
65647
- /**
65648
- * val-content-card
65649
- *
65650
- * Generic container card with configurable padding, border radius, background
65651
- * color and shadow. Accepts arbitrary content via ng-content. Use it to wrap
65652
- * val-article, stats, or any other content that needs a card shell.
65653
- *
65654
- * @example
65655
- * ```html
65656
- * <val-content-card [props]="{ title: 'Summary', shadowed: true }">
65657
- * <p>Any inner content here.</p>
65658
- * </val-content-card>
65659
- * ```
65660
- */
65661
- class ContentCardComponent {
65662
- constructor() {
65663
- /** Component configuration */
65664
- this.props = input({});
65665
- /** Merged configuration with defaults */
65666
- this.config = computed(() => ({
65667
- ...CONTENT_CARD_DEFAULTS,
65668
- ...this.props(),
65669
- }));
65670
- this.resolvedBg = computed(() => resolveColor(this.config().backgroundColor));
65671
- this.resolvedColor = computed(() => resolveColor(this.config().color));
65672
- }
65673
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContentCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
65674
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ContentCardComponent, isStandalone: true, selector: "val-content-card", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
65675
- <div
65676
- class="content-card"
65677
- [class.content-card--bordered]="config().bordered"
65678
- [class.content-card--shadowed]="config().shadowed"
65679
- [class.content-card--center]="config().align === 'center'"
65680
- [style.padding]="config().padding"
65681
- [style.border-radius]="config().borderRadius"
65682
- [style.background-color]="resolvedBg()"
65683
- [style.color]="resolvedColor()"
65684
- >
65685
- @if (config().title) {
65686
- <h3 class="content-card__title">{{ config().title }}</h3>
65687
- }
65688
-
65689
- @if (config().description) {
65690
- <p class="content-card__description">{{ config().description }}</p>
65691
- }
65692
-
65693
- <ng-content></ng-content>
65694
- </div>
65695
- `, isInline: true, styles: [":host{display:block}.content-card{background:var(--ion-card-background, var(--ion-background-color))}.content-card--bordered{border:1px solid var(--ion-color-light-shade, rgba(0, 0, 0, .1))}.content-card--shadowed{box-shadow:0 4px 16px #00000014}.content-card--center{text-align:center}.content-card__title{margin:0 0 .5rem;font-size:1.1rem;font-weight:700;color:inherit;line-height:1.3}.content-card__description{margin:0 0 1rem;font-size:.875rem;color:var(--ion-color-medium-shade);line-height:1.5}:host-context(body.dark) .content-card--bordered,:host-context(html.ion-palette-dark) .content-card--bordered,:host-context([data-theme=dark]) .content-card--bordered{border-color:#ffffff1f}:host-context(body.dark) .content-card--shadowed,:host-context(html.ion-palette-dark) .content-card--shadowed,:host-context([data-theme=dark]) .content-card--shadowed{box-shadow:0 4px 16px #0000004d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
65696
- }
65697
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContentCardComponent, decorators: [{
65698
- type: Component,
65699
- args: [{ selector: 'val-content-card', standalone: true, imports: [CommonModule], template: `
65700
- <div
65701
- class="content-card"
65702
- [class.content-card--bordered]="config().bordered"
65703
- [class.content-card--shadowed]="config().shadowed"
65704
- [class.content-card--center]="config().align === 'center'"
65705
- [style.padding]="config().padding"
65706
- [style.border-radius]="config().borderRadius"
65707
- [style.background-color]="resolvedBg()"
65708
- [style.color]="resolvedColor()"
65709
- >
65710
- @if (config().title) {
65711
- <h3 class="content-card__title">{{ config().title }}</h3>
65712
- }
65713
-
65714
- @if (config().description) {
65715
- <p class="content-card__description">{{ config().description }}</p>
65716
- }
65717
-
65718
- <ng-content></ng-content>
65719
- </div>
65720
- `, styles: [":host{display:block}.content-card{background:var(--ion-card-background, var(--ion-background-color))}.content-card--bordered{border:1px solid var(--ion-color-light-shade, rgba(0, 0, 0, .1))}.content-card--shadowed{box-shadow:0 4px 16px #00000014}.content-card--center{text-align:center}.content-card__title{margin:0 0 .5rem;font-size:1.1rem;font-weight:700;color:inherit;line-height:1.3}.content-card__description{margin:0 0 1rem;font-size:.875rem;color:var(--ion-color-medium-shade);line-height:1.5}:host-context(body.dark) .content-card--bordered,:host-context(html.ion-palette-dark) .content-card--bordered,:host-context([data-theme=dark]) .content-card--bordered{border-color:#ffffff1f}:host-context(body.dark) .content-card--shadowed,:host-context(html.ion-palette-dark) .content-card--shadowed,:host-context([data-theme=dark]) .content-card--shadowed{box-shadow:0 4px 16px #0000004d}\n"] }]
65721
- }] });
65722
-
65723
65839
  /**
65724
65840
  * Default values for AuthCtaMetadata.
65725
65841
  */
@@ -66438,5 +66554,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
66438
66554
  * Generated bundle index. Do not edit.
66439
66555
  */
66440
66556
 
66441
- export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionSelectorComponent, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketCardComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createPermissionLabeler, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
66557
+ export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionSelectorComponent, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketCardComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, button, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createPermissionLabeler, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
66442
66558
  //# sourceMappingURL=valtech-components.mjs.map