valtech-components 2.0.419 → 2.0.420

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 (107) hide show
  1. package/esm2022/lib/components/atoms/button/button.component.mjs +30 -102
  2. package/esm2022/lib/components/atoms/countdown/countdown.component.mjs +2 -7
  3. package/esm2022/lib/components/atoms/display/display.component.mjs +18 -101
  4. package/esm2022/lib/components/atoms/image/image.component.mjs +2 -5
  5. package/esm2022/lib/components/atoms/price-tag/price-tag.component.mjs +2 -12
  6. package/esm2022/lib/components/atoms/qr-code/qr-code.component.mjs +4 -29
  7. package/esm2022/lib/components/atoms/text/text.component.mjs +49 -171
  8. package/esm2022/lib/components/atoms/title/title.component.mjs +23 -65
  9. package/esm2022/lib/components/atoms/title/types.mjs +7 -19
  10. package/esm2022/lib/components/molecules/accordion/accordion.component.mjs +7 -53
  11. package/esm2022/lib/components/molecules/alert-box/alert-box.component.mjs +7 -26
  12. package/esm2022/lib/components/molecules/breadcrumb/breadcrumb.component.mjs +7 -42
  13. package/esm2022/lib/components/molecules/check-input/check-input.component.mjs +12 -41
  14. package/esm2022/lib/components/molecules/chip-group/chip-group.component.mjs +3 -28
  15. package/esm2022/lib/components/molecules/code-display/code-display.component.mjs +2 -5
  16. package/esm2022/lib/components/molecules/command-display/command-display.component.mjs +3 -6
  17. package/esm2022/lib/components/molecules/comment/comment.component.mjs +5 -31
  18. package/esm2022/lib/components/molecules/currency-input/currency-input.component.mjs +2 -23
  19. package/esm2022/lib/components/molecules/date-range-input/date-range-input.component.mjs +2 -29
  20. package/esm2022/lib/components/molecules/expandable-text/expandable-text.component.mjs +4 -6
  21. package/esm2022/lib/components/molecules/glow-card/glow-card.component.mjs +16 -40
  22. package/esm2022/lib/components/molecules/language-selector/language-selector.component.mjs +25 -125
  23. package/esm2022/lib/components/molecules/multi-select-search/multi-select-search.component.mjs +4 -6
  24. package/esm2022/lib/components/molecules/number-stepper/number-stepper.component.mjs +2 -10
  25. package/esm2022/lib/components/molecules/participant-card/participant-card.component.mjs +2 -4
  26. package/esm2022/lib/components/molecules/phone-input/phone-input.component.mjs +2 -23
  27. package/esm2022/lib/components/molecules/plain-code-box/plain-code-box.component.mjs +3 -6
  28. package/esm2022/lib/components/molecules/popover-selector/popover-selector.component.mjs +9 -12
  29. package/esm2022/lib/components/molecules/raffle-status-card/raffle-status-card.component.mjs +3 -11
  30. package/esm2022/lib/components/molecules/range-input/range-input.component.mjs +4 -25
  31. package/esm2022/lib/components/molecules/segment-control/segment-control.component.mjs +3 -34
  32. package/esm2022/lib/components/molecules/select-input/select-input.component.mjs +11 -20
  33. package/esm2022/lib/components/molecules/select-search/select-search.component.mjs +4 -6
  34. package/esm2022/lib/components/molecules/share-buttons/share-buttons.component.mjs +1 -6
  35. package/esm2022/lib/components/molecules/stepper/stepper.component.mjs +3 -28
  36. package/esm2022/lib/components/molecules/tabs/tabs.component.mjs +7 -41
  37. package/esm2022/lib/components/molecules/textarea-input/textarea-input.component.mjs +2 -27
  38. package/esm2022/lib/components/molecules/ticket-grid/ticket-grid.component.mjs +2 -10
  39. package/esm2022/lib/components/molecules/toggle-input/toggle-input.component.mjs +7 -37
  40. package/esm2022/lib/components/molecules/winner-display/winner-display.component.mjs +1 -12
  41. package/esm2022/lib/components/organisms/comment-section/comment-section.component.mjs +8 -54
  42. package/esm2022/lib/components/organisms/data-table/data-table.component.mjs +1 -3
  43. package/esm2022/lib/components/organisms/wizard/wizard.component.mjs +3 -5
  44. package/esm2022/lib/services/locale.service.mjs +75 -0
  45. package/esm2022/lib/services/types.mjs +5 -3
  46. package/esm2022/public-api.mjs +2 -7
  47. package/fesm2022/valtech-components.mjs +366 -2279
  48. package/fesm2022/valtech-components.mjs.map +1 -1
  49. package/lib/components/atoms/button/button.component.d.ts +12 -37
  50. package/lib/components/atoms/countdown/countdown.component.d.ts +0 -1
  51. package/lib/components/atoms/display/display.component.d.ts +8 -60
  52. package/lib/components/atoms/image/image.component.d.ts +0 -2
  53. package/lib/components/atoms/price-tag/price-tag.component.d.ts +0 -1
  54. package/lib/components/atoms/qr-code/qr-code.component.d.ts +2 -6
  55. package/lib/components/atoms/text/text.component.d.ts +20 -68
  56. package/lib/components/atoms/title/title.component.d.ts +7 -12
  57. package/lib/components/atoms/title/types.d.ts +11 -24
  58. package/lib/components/molecules/accordion/accordion.component.d.ts +2 -9
  59. package/lib/components/molecules/alert-box/alert-box.component.d.ts +3 -8
  60. package/lib/components/molecules/breadcrumb/breadcrumb.component.d.ts +2 -8
  61. package/lib/components/molecules/check-input/check-input.component.d.ts +2 -10
  62. package/lib/components/molecules/chip-group/chip-group.component.d.ts +2 -8
  63. package/lib/components/molecules/code-display/code-display.component.d.ts +0 -2
  64. package/lib/components/molecules/command-display/command-display.component.d.ts +0 -3
  65. package/lib/components/molecules/comment/comment.component.d.ts +2 -6
  66. package/lib/components/molecules/currency-input/currency-input.component.d.ts +0 -3
  67. package/lib/components/molecules/date-range-input/date-range-input.component.d.ts +0 -3
  68. package/lib/components/molecules/expandable-text/expandable-text.component.d.ts +0 -1
  69. package/lib/components/molecules/glow-card/glow-card.component.d.ts +5 -9
  70. package/lib/components/molecules/language-selector/language-selector.component.d.ts +7 -19
  71. package/lib/components/molecules/multi-select-search/multi-select-search.component.d.ts +0 -2
  72. package/lib/components/molecules/number-stepper/number-stepper.component.d.ts +0 -1
  73. package/lib/components/molecules/participant-card/participant-card.component.d.ts +0 -1
  74. package/lib/components/molecules/phone-input/phone-input.component.d.ts +0 -3
  75. package/lib/components/molecules/plain-code-box/plain-code-box.component.d.ts +0 -3
  76. package/lib/components/molecules/popover-selector/popover-selector.component.d.ts +3 -4
  77. package/lib/components/molecules/raffle-status-card/raffle-status-card.component.d.ts +0 -1
  78. package/lib/components/molecules/range-input/range-input.component.d.ts +3 -8
  79. package/lib/components/molecules/segment-control/segment-control.component.d.ts +2 -8
  80. package/lib/components/molecules/select-input/select-input.component.d.ts +2 -3
  81. package/lib/components/molecules/select-search/select-search.component.d.ts +0 -2
  82. package/lib/components/molecules/share-buttons/share-buttons.component.d.ts +0 -1
  83. package/lib/components/molecules/stepper/stepper.component.d.ts +2 -8
  84. package/lib/components/molecules/tabs/tabs.component.d.ts +2 -8
  85. package/lib/components/molecules/textarea-input/textarea-input.component.d.ts +2 -6
  86. package/lib/components/molecules/ticket-grid/ticket-grid.component.d.ts +0 -1
  87. package/lib/components/molecules/toggle-input/toggle-input.component.d.ts +2 -8
  88. package/lib/components/molecules/winner-display/winner-display.component.d.ts +0 -1
  89. package/lib/components/organisms/comment-section/comment-section.component.d.ts +2 -6
  90. package/lib/components/organisms/data-table/data-table.component.d.ts +0 -1
  91. package/lib/components/organisms/wizard/wizard.component.d.ts +0 -2
  92. package/lib/services/locale.service.d.ts +52 -0
  93. package/lib/services/types.d.ts +1 -6
  94. package/package.json +1 -1
  95. package/public-api.d.ts +1 -5
  96. package/esm2022/lib/services/lang-provider/components/lang-settings.mjs +0 -13
  97. package/esm2022/lib/services/lang-provider/content.mjs +0 -156
  98. package/esm2022/lib/services/lang-provider/lang-provider.service.mjs +0 -530
  99. package/esm2022/lib/services/lang-provider/types.mjs +0 -23
  100. package/esm2022/lib/shared/utils/content.mjs +0 -186
  101. package/esm2022/lib/shared/utils/simple-content.mjs +0 -119
  102. package/lib/services/lang-provider/components/lang-settings.d.ts +0 -3
  103. package/lib/services/lang-provider/content.d.ts +0 -17
  104. package/lib/services/lang-provider/lang-provider.service.d.ts +0 -264
  105. package/lib/services/lang-provider/types.d.ts +0 -30
  106. package/lib/shared/utils/content.d.ts +0 -199
  107. package/lib/shared/utils/simple-content.d.ts +0 -120
@@ -1,12 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, Component, Input, Output, Injectable, inject, InjectionToken, Inject, ChangeDetectorRef, HostListener, Pipe, ChangeDetectionStrategy, ViewChild, ElementRef } from '@angular/core';
2
+ import { EventEmitter, Component, Input, Output, Injectable, inject, HostListener, Pipe, ChangeDetectionStrategy, ViewChild, ChangeDetectorRef, ElementRef } from '@angular/core';
3
3
  import * as i2$1 from '@ionic/angular/standalone';
4
4
  import { 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, IonDatetimeButton, IonInput, IonSelect, IonSelectOption, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonAccordion, IonAccordionGroup, IonItem, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonPopover, IonList, IonNote, ToastController as ToastController$1, IonCol, IonRow, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, AlertController, ModalController } from '@ionic/angular/standalone';
5
5
  import * as i1 from '@angular/common';
6
- import { CommonModule, NgStyle, Location, AsyncPipe, NgFor, NgClass } from '@angular/common';
6
+ import { CommonModule, NgStyle, Location, NgFor, NgClass } from '@angular/common';
7
7
  import { addIcons } from 'ionicons';
8
- import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globe, list, grid, apps, menu, settings, home, search, person, helpCircle, informationCircle, documentText, notifications, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, checkmark, 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, shuffleOutline, logoWhatsapp, paperPlaneOutline, mailOutline, trophyOutline, ticketOutline, giftOutline, personOutline, ellipsisVertical, closeCircle, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, documentOutline } from 'ionicons/icons';
9
- import { BehaviorSubject, distinctUntilChanged, shareReplay, map, Subscription, of, combineLatest, filter } from 'rxjs';
8
+ import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, list, grid, apps, menu, settings, home, search, person, helpCircle, informationCircle, documentText, notifications, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, checkmark, 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, shuffleOutline, logoWhatsapp, paperPlaneOutline, mailOutline, trophyOutline, ticketOutline, giftOutline, personOutline, ellipsisVertical, closeCircle, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, documentOutline } from 'ionicons/icons';
10
9
  import * as i1$4 from '@angular/router';
11
10
  import { Router, RouterLink, NavigationEnd, RouterOutlet } from '@angular/router';
12
11
  import { Browser } from '@capacitor/browser';
@@ -14,7 +13,7 @@ import * as i1$1 from '@angular/platform-browser';
14
13
  import QRCodeStyling from 'qr-code-styling';
15
14
  import * as i1$2 from '@angular/forms';
16
15
  import { ReactiveFormsModule, FormsModule, FormControl, Validators } from '@angular/forms';
17
- import { map as map$1 } from 'rxjs/operators';
16
+ import { BehaviorSubject, filter } from 'rxjs';
18
17
  import * as i1$3 from 'ng-otp-input';
19
18
  import { NgOtpInputComponent, NgOtpInputModule } from 'ng-otp-input';
20
19
  import * as i2 from '@ionic/angular';
@@ -233,125 +232,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
233
232
  type: Output
234
233
  }] } });
235
234
 
236
- /**
237
- * Simplified content utilities for the new LangService-only system.
238
- * This replaces the old reactive-content.ts with a much simpler approach.
239
- */
240
- /**
241
- * Helper function to determine if component should use reactive content.
242
- * @param metadata Component metadata
243
- * @returns True if component should use reactive content
244
- */
245
- function shouldUseReactiveContent(metadata) {
246
- return !metadata.content && !!(metadata.contentKey && metadata.contentClass);
247
- }
248
- /**
249
- * Extract content configuration from metadata.
250
- * @param metadata Component metadata
251
- * @returns Content configuration for LangService
252
- */
253
- function extractContentConfig(metadata) {
254
- return {
255
- className: metadata.contentClass || '',
256
- key: metadata.contentKey || '',
257
- fallback: metadata.contentFallback,
258
- };
259
- }
260
- /**
261
- * Create reactive content metadata with defaults.
262
- * @param config Partial content configuration
263
- * @returns Complete reactive content metadata
264
- */
265
- function createReactiveContentMetadata(config) {
266
- return {
267
- content: config.content,
268
- contentKey: config.contentKey,
269
- contentClass: config.contentClass,
270
- contentFallback: config.contentFallback,
271
- };
272
- }
273
- /**
274
- * Interpolate content string with values.
275
- * Replaces placeholders like {{key}} or {key} with actual values.
276
- *
277
- * @param content - Content string with placeholders
278
- * @param values - Values to interpolate
279
- * @returns Interpolated string
280
- *
281
- * @example
282
- * ```typescript
283
- * interpolateContent('Hello {{name}}!', { name: 'World' })
284
- * // Returns: 'Hello World!'
285
- * ```
286
- */
287
- function interpolateContent$1(content, values) {
288
- if (!values || !content) {
289
- return content;
290
- }
291
- return content.replace(/\{\{?(\w+)\}?\}/g, (match, key) => {
292
- const value = values[key];
293
- return value !== undefined ? String(value) : match;
294
- });
295
- }
296
- /**
297
- * Check if component should use reactive content with interpolation.
298
- * @param metadata Component metadata with interpolation
299
- * @returns True if component should use reactive content with interpolation
300
- */
301
- function shouldUseReactiveContentWithInterpolation(metadata) {
302
- return shouldUseReactiveContent(metadata) && !!metadata.contentInterpolation;
303
- }
304
- /**
305
- * Extract content configuration with interpolation from metadata.
306
- * @param metadata Component metadata with interpolation
307
- * @returns Content configuration for LangService with interpolation data
308
- */
309
- function extractContentConfigWithInterpolation(metadata) {
310
- return {
311
- className: metadata.contentClass || '',
312
- key: metadata.contentKey || '',
313
- fallback: metadata.contentFallback,
314
- interpolation: metadata.contentInterpolation,
315
- };
316
- }
317
- /**
318
- * Helper function to get reactive content with interpolation using LangService.
319
- * This provides a unified way to get reactive, interpolated content.
320
- *
321
- * @param langService - The LangService instance
322
- * @param metadata - Component metadata with interpolation
323
- * @returns Observable that emits interpolated content
324
- *
325
- * @example
326
- * ```typescript
327
- * const content$ = fromContentWithInterpolation(this.langService, {
328
- * contentClass: 'MyComponent',
329
- * contentKey: 'greeting',
330
- * contentInterpolation: { name: 'World' }
331
- * });
332
- * ```
333
- */
334
- function fromContentWithInterpolation$1(langService, // LangService type would cause circular dependency
335
- metadata) {
336
- // Observable<string> but avoiding import
337
- const config = extractContentConfigWithInterpolation(metadata);
338
- if (!config.className || !config.key) {
339
- throw new Error('fromContentWithInterpolation requires both contentClass and contentKey');
340
- }
341
- return langService.getContentWithInterpolation(config.className, config.key, config.interpolation, config.fallback);
342
- }
343
- /**
344
- * Helper function to get static content with interpolation.
345
- * This provides interpolation for static content strings.
346
- *
347
- * @param content - Static content string
348
- * @param interpolationData - Values to interpolate
349
- * @returns Interpolated string
350
- */
351
- function interpolateStaticContent(content, interpolationData) {
352
- return interpolateContent$1(content, interpolationData);
353
- }
354
-
355
235
  const ENABLED = 'ENABLED';
356
236
  const DISABLED = 'DISABLED';
357
237
  const WORKING = 'WORKING';
@@ -583,600 +463,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
583
463
  }]
584
464
  }], ctorParameters: () => [] });
585
465
 
586
- const LANG = 'LANG';
587
- const THEME = 'THEME';
588
-
589
- /**
590
- * Utility service for interacting with browser localStorage in a type-safe way.
591
- * Provides static methods for setting, getting, removing, and clearing items.
592
- */
593
- class LocalStorageService {
594
- /**
595
- * Stores a value in localStorage under the given reference key.
596
- * @param reference The key to store the value under
597
- * @param value The value to store
598
- */
599
- static set(reference, value) {
600
- localStorage.setItem(reference, JSON.stringify(value));
601
- }
602
- /**
603
- * Retrieves a value from localStorage by key.
604
- * @param reference The key to retrieve
605
- * @returns The parsed value
606
- */
607
- static get(reference) {
608
- const value = localStorage.getItem(reference);
609
- return JSON.parse(value);
610
- }
611
- /**
612
- * Removes an item from localStorage by key.
613
- * @param reference The key to remove
614
- */
615
- static remove(reference) {
616
- localStorage.removeItem(reference);
617
- }
618
- /**
619
- * Clears all items from localStorage.
620
- */
621
- static clear() {
622
- localStorage.clear();
623
- }
624
- }
625
-
626
- const ValtechConfigService = new InjectionToken('ValtechConfig');
627
-
628
- class TextContent {
629
- constructor(text) {
630
- this.text = text;
631
- }
632
- get Content() {
633
- return this.text;
634
- }
635
- }
636
- /**
637
- * Common language constants for convenience.
638
- * Users can still use any language code string directly.
639
- */
640
- const LANGUAGES = {
641
- ES: 'es',
642
- EN: 'en',
643
- FR: 'fr',
644
- DE: 'de',
645
- PT: 'pt',
646
- IT: 'it',
647
- ZH: 'zh',
648
- JA: 'ja',
649
- };
650
-
651
- /**
652
- * LangService - Reactive language and content management service.
653
- *
654
- * This service provides reactive content management with Observable-based language switching.
655
- * Components can subscribe to content changes and automatically update when the language changes.
656
- *
657
- * The service automatically detects available languages from the content configuration
658
- * and provides intelligent fallbacks with console warnings for missing translations.
659
- *
660
- * @example Basic usage:
661
- * ```typescript
662
- * constructor(private langService: LangService) {}
663
- *
664
- * // Get current language
665
- * const currentLang = this.langService.currentLang;
666
- *
667
- * // Subscribe to language changes
668
- * this.langService.currentLang$.subscribe(lang => console.log('Language changed:', lang));
669
- *
670
- * // Get static text
671
- * const text = this.langService.getText('ComponentName', 'textKey');
672
- *
673
- * // Get reactive text
674
- * const text$ = this.langService.getContent('ComponentName', 'textKey');
675
- * ```
676
- */
677
- class LangService {
678
- constructor(config) {
679
- this.availableLanguages = [];
680
- this.warnedMissingLanguages = new Set();
681
- console.log('LangService: Injected config:', config);
682
- this.content = config.content;
683
- this.config = config;
684
- // Detect available languages from content
685
- this.detectAvailableLanguages();
686
- // Set default language (prefer Spanish, then English, then first available)
687
- this.defaultLang = this.determineDefaultLanguage();
688
- // Initialize with stored language or default
689
- const current = LocalStorageService.get(LANG);
690
- const initialLang = this.validateLanguage(current) || this.defaultLang;
691
- this.selectedLang = new BehaviorSubject(initialLang);
692
- console.log('LangService: Initialized with languages:', {
693
- available: this.availableLanguages,
694
- default: this.defaultLang,
695
- current: initialLang,
696
- });
697
- }
698
- /**
699
- * Detect available languages from the content configuration.
700
- * Scans all component content to find which languages are actually configured.
701
- */
702
- detectAvailableLanguages() {
703
- const languageSet = new Set();
704
- Object.values(this.content).forEach(componentContent => {
705
- if (componentContent?.Content) {
706
- Object.keys(componentContent.Content).forEach(lang => {
707
- languageSet.add(lang);
708
- });
709
- }
710
- });
711
- this.availableLanguages = Array.from(languageSet).sort();
712
- if (this.availableLanguages.length === 0) {
713
- console.warn('LangService: No languages detected in content configuration!');
714
- this.availableLanguages = [LANGUAGES.ES]; // Fallback
715
- }
716
- }
717
- /**
718
- * Determine the best default language based on available content.
719
- */
720
- determineDefaultLanguage() {
721
- // Preference order: Spanish, English, then first available
722
- const preferredOrder = [LANGUAGES.ES, LANGUAGES.EN];
723
- for (const preferred of preferredOrder) {
724
- if (this.availableLanguages.includes(preferred)) {
725
- return preferred;
726
- }
727
- }
728
- return this.availableLanguages[0];
729
- }
730
- /**
731
- * Validate if a language is available in the content.
732
- */
733
- validateLanguage(lang) {
734
- if (!lang)
735
- return null;
736
- return this.availableLanguages.includes(lang) ? lang : null;
737
- }
738
- /**
739
- * Get the best available language for a component and key.
740
- * Provides intelligent fallback with warnings.
741
- */
742
- getBestAvailableContent(className, key, requestedLang) {
743
- const componentContent = this.content[className];
744
- if (!componentContent) {
745
- return {
746
- content: undefined,
747
- actualLang: requestedLang,
748
- shouldWarn: false,
749
- };
750
- }
751
- // Try requested language first
752
- const requestedContent = componentContent.Content[requestedLang];
753
- if (requestedContent?.[key]) {
754
- return {
755
- content: requestedContent[key],
756
- actualLang: requestedLang,
757
- shouldWarn: false,
758
- };
759
- }
760
- // Language not available, try fallbacks
761
- const warningKey = `${className}.${key}.${requestedLang}`;
762
- const shouldWarn = !this.warnedMissingLanguages.has(warningKey);
763
- if (shouldWarn) {
764
- this.warnedMissingLanguages.add(warningKey);
765
- }
766
- // Try default language
767
- if (requestedLang !== this.defaultLang) {
768
- const defaultContent = componentContent.Content[this.defaultLang];
769
- if (defaultContent?.[key]) {
770
- return {
771
- content: defaultContent[key],
772
- actualLang: this.defaultLang,
773
- shouldWarn,
774
- };
775
- }
776
- }
777
- // Try first available language
778
- for (const availableLang of this.availableLanguages) {
779
- const availableContent = componentContent.Content[availableLang];
780
- if (availableContent?.[key]) {
781
- return {
782
- content: availableContent[key],
783
- actualLang: availableLang,
784
- shouldWarn,
785
- };
786
- }
787
- }
788
- return {
789
- content: undefined,
790
- actualLang: requestedLang,
791
- shouldWarn,
792
- };
793
- }
794
- /**
795
- * Observable that emits the current language whenever it changes.
796
- * Use this to subscribe to language changes in components.
797
- */
798
- get currentLang$() {
799
- return this.selectedLang.asObservable().pipe(distinctUntilChanged(), shareReplay(1) // Ensure new subscribers get the current value
800
- );
801
- }
802
- /**
803
- * Get the current language synchronously.
804
- */
805
- get currentLang() {
806
- return this.selectedLang.value;
807
- }
808
- /**
809
- * Get array of available languages detected from content.
810
- */
811
- get availableLangs() {
812
- return [...this.availableLanguages];
813
- }
814
- /**
815
- * Get the default language.
816
- */
817
- get defaultLanguage() {
818
- return this.defaultLang;
819
- }
820
- /**
821
- * Set the current language and persist it to localStorage.
822
- * This will trigger updates in all reactive content subscriptions.
823
- *
824
- * Validates that the language is available and warns if not.
825
- *
826
- * @param lang - The language to set
827
- */
828
- setLang(lang) {
829
- if (!this.availableLanguages.includes(lang)) {
830
- console.warn(`LangService: Language "${lang}" is not available. Available languages:`, this.availableLanguages);
831
- console.warn(`LangService: Falling back to default language "${this.defaultLang}"`);
832
- lang = this.defaultLang;
833
- }
834
- this.selectedLang.next(lang);
835
- LocalStorageService.set(LANG, lang);
836
- }
837
- /**
838
- * Get content for a component class and key (legacy method).
839
- *
840
- * @deprecated Use getText() or getContent() for better type safety
841
- */
842
- Text(className) {
843
- const componentContent = this.content[className];
844
- return componentContent?.Content[this.selectedLang.value] || {};
845
- }
846
- /**
847
- * Get a single content string synchronously for the current language.
848
- * Provides intelligent fallback with warnings for missing translations.
849
- *
850
- * @param className - The component class name
851
- * @param key - The text key
852
- * @param fallback - Optional fallback text if key is not found
853
- * @returns The text string or fallback
854
- */
855
- getText(className, key, fallback) {
856
- const result = this.getBestAvailableContent(className, key, this.selectedLang.value);
857
- if (result.shouldWarn && result.actualLang !== this.selectedLang.value) {
858
- console.warn(`LangService: Content "${className}.${key}" not available in "${this.selectedLang.value}".`, `Using "${result.actualLang}" instead. Available languages:`, this.availableLanguages);
859
- }
860
- return result.content || fallback || `[${className}.${key}]`;
861
- }
862
- /**
863
- * Get a reactive Observable for a specific text key that updates when language changes.
864
- * This is the recommended method for components that need reactive content.
865
- * Provides intelligent fallback with warnings for missing translations.
866
- *
867
- * @param className - The component class name
868
- * @param key - The text key
869
- * @param fallback - Optional fallback text if key is not found
870
- * @returns Observable that emits the text string whenever language changes
871
- */
872
- getContent(className, key, fallback) {
873
- return this.currentLang$.pipe(map(lang => {
874
- const result = this.getBestAvailableContent(className, key, lang);
875
- if (result.shouldWarn && result.actualLang !== lang) {
876
- console.warn(`LangService: Content "${className}.${key}" not available in "${lang}".`, `Using "${result.actualLang}" instead. Available languages:`, this.availableLanguages);
877
- }
878
- return result.content || fallback || `[${className}.${key}]`;
879
- }), distinctUntilChanged());
880
- }
881
- /**
882
- * Get reactive content for multiple keys at once.
883
- * Provides intelligent fallback with warnings for missing translations.
884
- *
885
- * @param className - The component class name
886
- * @param keys - Array of text keys to retrieve
887
- * @returns Observable that emits an object with all requested keys
888
- */
889
- getMultipleContent(className, keys) {
890
- return this.currentLang$.pipe(map(lang => {
891
- const result = {};
892
- keys.forEach(key => {
893
- const contentResult = this.getBestAvailableContent(className, key, lang);
894
- if (contentResult.shouldWarn && contentResult.actualLang !== lang) {
895
- console.warn(`LangService: Content "${className}.${key}" not available in "${lang}".`, `Using "${contentResult.actualLang}" instead.`);
896
- }
897
- result[key] = contentResult.content || `[${className}.${key}]`;
898
- });
899
- return result;
900
- }), distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)));
901
- }
902
- /**
903
- * Check if a content key exists for a component in any available language.
904
- *
905
- * @param className - The component class name
906
- * @param key - The text key
907
- * @returns True if the key exists in any language
908
- */
909
- hasContent(className, key) {
910
- const classContent = this.content[className];
911
- if (!classContent)
912
- return false;
913
- return Object.values(classContent.Content).some(langContent => langContent && typeof langContent[key] === 'string');
914
- }
915
- /**
916
- * Check if a content key exists for a component in a specific language.
917
- *
918
- * @param className - The component class name
919
- * @param key - The text key
920
- * @param lang - The language to check (defaults to current language)
921
- * @returns True if the key exists in the specified language
922
- */
923
- hasContentInLanguage(className, key, lang) {
924
- const targetLang = lang || this.currentLang;
925
- const classContent = this.content[className]?.Content[targetLang];
926
- return classContent && typeof classContent[key] === 'string';
927
- }
928
- /**
929
- * Get available languages for a specific component.
930
- *
931
- * @param className - The component class name
932
- * @returns Array of language codes available for the component
933
- */
934
- getAvailableLanguagesForComponent(className) {
935
- const classContent = this.content[className];
936
- if (!classContent)
937
- return [];
938
- return Object.keys(classContent.Content).filter(lang => classContent.Content[lang] && Object.keys(classContent.Content[lang]).length > 0);
939
- }
940
- /**
941
- * Get missing content keys for a component in a specific language.
942
- * Useful for identifying incomplete translations.
943
- *
944
- * @param className - The component class name
945
- * @param lang - The language to check
946
- * @param referenceLang - The reference language to compare against (defaults to default language)
947
- * @returns Array of missing keys
948
- */
949
- getMissingContentKeys(className, lang, referenceLang) {
950
- const refLang = referenceLang || this.defaultLang;
951
- const classContent = this.content[className];
952
- if (!classContent)
953
- return [];
954
- const referenceContent = classContent.Content[refLang] || {};
955
- const targetContent = classContent.Content[lang] || {};
956
- return Object.keys(referenceContent).filter(key => !targetContent[key] || typeof targetContent[key] !== 'string');
957
- }
958
- /**
959
- * Register or update content for a component dynamically.
960
- * This allows registering content at runtime without APP_INITIALIZER.
961
- *
962
- * @param className - The component class name
963
- * @param content - The multilingual content object
964
- * @param merge - Whether to merge with existing content (default: true)
965
- *
966
- * @example
967
- * ```typescript
968
- * this.langService.registerContent('MyComponent', {
969
- * [LANGUAGES.ES]: { title: 'Título', description: 'Descripción' },
970
- * [LANGUAGES.EN]: { title: 'Title', description: 'Description' }
971
- * });
972
- * ```
973
- */
974
- registerContent(className, content, merge = true) {
975
- if (!className) {
976
- console.error('LangService: className is required for registerContent');
977
- return;
978
- }
979
- if (!content || typeof content !== 'object') {
980
- console.error('LangService: Invalid content provided for registerContent');
981
- return;
982
- }
983
- console.log(`LangService: Registering content for "${className}"`, {
984
- merge,
985
- languages: Object.keys(content),
986
- });
987
- // Initialize component content if it doesn't exist
988
- if (!this.content[className]) {
989
- this.content[className] = new TextContent({});
990
- }
991
- // Merge or replace content for each language
992
- Object.entries(content).forEach(([lang, langContent]) => {
993
- if (!langContent || typeof langContent !== 'object') {
994
- console.warn(`LangService: Invalid content for language "${lang}" in "${className}"`);
995
- return;
996
- }
997
- if (!this.content[className].Content[lang]) {
998
- this.content[className].Content[lang] = {};
999
- }
1000
- if (merge) {
1001
- this.content[className].Content[lang] = {
1002
- ...this.content[className].Content[lang],
1003
- ...langContent,
1004
- };
1005
- }
1006
- else {
1007
- this.content[className].Content[lang] = { ...langContent };
1008
- }
1009
- });
1010
- // Update available languages
1011
- this.detectAvailableLanguages();
1012
- console.log(`LangService: Content registered successfully for "${className}"`);
1013
- }
1014
- /**
1015
- * Update multiple content registrations at once.
1016
- *
1017
- * @param contentMap - Map of className to content
1018
- * @param merge - Whether to merge with existing content (default: true)
1019
- *
1020
- * @example
1021
- * ```typescript
1022
- * this.langService.registerMultipleContent({
1023
- * 'Component1': { [LANGUAGES.ES]: { key1: 'valor1' } },
1024
- * 'Component2': { [LANGUAGES.EN]: { key2: 'value2' } }
1025
- * });
1026
- * ```
1027
- */
1028
- registerMultipleContent(contentMap, merge = true) {
1029
- if (!contentMap || typeof contentMap !== 'object') {
1030
- console.error('LangService: Invalid contentMap provided for registerMultipleContent');
1031
- return;
1032
- }
1033
- console.log('LangService: Registering multiple content entries', {
1034
- classes: Object.keys(contentMap),
1035
- merge,
1036
- });
1037
- Object.entries(contentMap).forEach(([className, content]) => {
1038
- this.registerContent(className, content, merge);
1039
- });
1040
- console.log('LangService: Multiple content registration completed');
1041
- }
1042
- /**
1043
- * Remove content for a specific component.
1044
- *
1045
- * @param className - The component class name to remove
1046
- */
1047
- removeContent(className) {
1048
- if (!className) {
1049
- console.error('LangService: className is required for removeContent');
1050
- return;
1051
- }
1052
- if (this.content[className]) {
1053
- delete this.content[className];
1054
- this.detectAvailableLanguages();
1055
- console.log(`LangService: Content removed for "${className}"`);
1056
- }
1057
- else {
1058
- console.warn(`LangService: No content found for "${className}" to remove`);
1059
- }
1060
- }
1061
- /**
1062
- * Get a list of all registered component classes.
1063
- *
1064
- * @returns Array of registered class names
1065
- */
1066
- getRegisteredClasses() {
1067
- return Object.keys(this.content);
1068
- }
1069
- /**
1070
- * Get the complete content configuration (for debugging purposes).
1071
- * Returns a deep copy to prevent accidental mutations.
1072
- *
1073
- * @returns Complete content configuration
1074
- */
1075
- getContentConfiguration() {
1076
- return JSON.parse(JSON.stringify(this.content));
1077
- }
1078
- /**
1079
- * Clear all content and reset to initial state.
1080
- * Useful for testing or complete reinitialization.
1081
- */
1082
- clearAllContent() {
1083
- console.log('LangService: Clearing all content');
1084
- this.content = {};
1085
- this.availableLanguages = [LANGUAGES.ES]; // Reset to default
1086
- this.warnedMissingLanguages.clear();
1087
- console.log('LangService: All content cleared');
1088
- }
1089
- /**
1090
- * Get content with interpolation support.
1091
- * Retrieves content and replaces placeholders with provided values.
1092
- *
1093
- * @param className - The component class name
1094
- * @param key - The text key
1095
- * @param interpolationData - Object with values to interpolate
1096
- * @param fallback - Optional fallback text if key is not found
1097
- * @returns Text with interpolated values
1098
- */
1099
- getTextWithInterpolation(className, key, interpolationData, fallback) {
1100
- const content = this.getText(className, key, fallback);
1101
- return this.interpolateString(content, interpolationData);
1102
- }
1103
- /**
1104
- * Get reactive content with interpolation support.
1105
- * Returns an Observable that emits interpolated content when language changes.
1106
- *
1107
- * @param className - The component class name
1108
- * @param key - The text key
1109
- * @param interpolationData - Object with values to interpolate
1110
- * @param fallback - Optional fallback text if key is not found
1111
- * @returns Observable that emits interpolated text
1112
- */
1113
- getContentWithInterpolation(className, key, interpolationData, fallback) {
1114
- return this.getContent(className, key, fallback).pipe(map(content => this.interpolateString(content, interpolationData)));
1115
- }
1116
- /**
1117
- * Interpolate a string with provided values.
1118
- * Replaces placeholders like {{key}} or {key} with actual values.
1119
- *
1120
- * @param content - Content string with placeholders
1121
- * @param values - Values to interpolate
1122
- * @returns Interpolated string
1123
- *
1124
- * @example
1125
- * ```typescript
1126
- * interpolateString('Hello {{name}}!', { name: 'World' })
1127
- * // Returns: 'Hello World!'
1128
- * ```
1129
- */
1130
- interpolateString(content, values) {
1131
- if (!values || !content) {
1132
- return content;
1133
- }
1134
- return content.replace(/\{\{?(\w+)\}?\}/g, (match, key) => {
1135
- const value = values[key];
1136
- return value !== undefined ? String(value) : match;
1137
- });
1138
- }
1139
- /**
1140
- * Legacy function equivalent to the old fromContentWithInterpolation.
1141
- * Provides reactive content with interpolation support for backward compatibility.
1142
- *
1143
- * @param className - The component class name
1144
- * @param key - The text key
1145
- * @param interpolationData - Object with values to interpolate
1146
- * @param fallback - Optional fallback text if key is not found
1147
- * @returns Observable that emits interpolated text
1148
- *
1149
- * @deprecated Use getContentWithInterpolation instead
1150
- */
1151
- fromContentWithInterpolation(className, key, interpolationData, fallback) {
1152
- return this.getContentWithInterpolation(className, key, interpolationData, fallback);
1153
- }
1154
- // Legacy getters/setters for backward compatibility
1155
- get Lang() {
1156
- return this.currentLang;
1157
- }
1158
- set Lang(lang) {
1159
- this.setLang(lang);
1160
- }
1161
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LangService, deps: [{ token: ValtechConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1162
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LangService, providedIn: 'root' }); }
1163
- }
1164
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LangService, decorators: [{
1165
- type: Injectable,
1166
- args: [{
1167
- providedIn: 'root',
1168
- }]
1169
- }], ctorParameters: () => [{ type: undefined, decorators: [{
1170
- type: Inject,
1171
- args: [ValtechConfigService]
1172
- }] }] });
1173
-
1174
466
  /**
1175
467
  * val-button
1176
468
  *
1177
- * A customizable button supporting icons, loading state, navigation, and reactive content.
1178
- * Supports both static text and reactive content from the content service.
1179
- * Follows the same content pattern as val-text for consistency.
469
+ * A customizable button supporting icons, loading state, and navigation.
1180
470
  *
1181
471
  * @example Static text:
1182
472
  * <val-button [props]="{
@@ -1187,38 +477,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1187
477
  * icon: { name: 'save', slot: 'start' }
1188
478
  * }" (onClick)="handler()"></val-button>
1189
479
  *
1190
- * @example Reactive content:
1191
- * <val-button [props]="{
1192
- * contentKey: 'save',
1193
- * contentClass: 'MyComponent',
1194
- * contentFallback: 'Save',
1195
- * color: 'primary',
1196
- * type: 'button',
1197
- * state: 'ENABLED',
1198
- * icon: { name: 'save', slot: 'start' }
1199
- * }" (onClick)="handler()"></val-button>
1200
- *
1201
- * @example Reactive content with interpolation:
1202
- * <val-button [props]="{
1203
- * contentKey: 'saveCount',
1204
- * contentClass: 'MyComponent',
1205
- * contentInterpolation: { count: 5 },
1206
- * contentFallback: 'Save Items',
1207
- * color: 'primary',
1208
- * type: 'button',
1209
- * state: 'ENABLED'
1210
- * }" (onClick)="handler()"></val-button>
1211
- *
1212
- * @input props: ButtonMetadata - Configuration for the button (text/content, color, icon, state, etc.)
480
+ * @input props: ButtonMetadata - Configuration for the button (text, color, icon, state, etc.)
1213
481
  * @output onClick - Emits when the button is clicked
1214
482
  */
1215
483
  class ButtonComponent {
1216
- constructor(download, icon, navigation, langService) {
484
+ constructor(download, icon, navigation) {
1217
485
  this.download = download;
1218
486
  this.navigation = navigation;
1219
- this.langService = langService;
1220
487
  this.states = ComponentStates;
1221
- this.subscriptions = new Subscription();
488
+ /**
489
+ * The text to display on the button.
490
+ */
491
+ this.displayText = '';
1222
492
  /**
1223
493
  * Event emitted when the button is clicked.
1224
494
  */
@@ -1227,44 +497,35 @@ class ButtonComponent {
1227
497
  ngOnInit() {
1228
498
  this.setupDisplayText();
1229
499
  }
1230
- ngOnDestroy() {
1231
- this.subscriptions.unsubscribe();
1232
- }
1233
500
  /**
1234
- * Set up the text content observable based on the props configuration.
1235
- * Priority: static text > reactive content with interpolation > reactive content
1236
- * This follows the same pattern as val-text component.
501
+ * Set up the text content based on the props configuration.
1237
502
  */
1238
503
  setupDisplayText() {
1239
504
  if (this.props.text) {
1240
- // Static text takes precedence
1241
505
  if (this.props.contentInterpolation) {
1242
- // Static text with interpolation
1243
- const interpolatedText = interpolateStaticContent(this.props.text, this.props.contentInterpolation);
1244
- this.displayText$ = of(interpolatedText);
506
+ this.displayText = this.interpolateContent(this.props.text, this.props.contentInterpolation);
1245
507
  }
1246
508
  else {
1247
- // Simple static text
1248
- this.displayText$ = of(this.props.text);
509
+ this.displayText = this.props.text;
1249
510
  }
1250
511
  }
1251
- else if (this.props.contentKey && this.props.contentClass) {
1252
- // Reactive content from language service
1253
- if (this.props.contentInterpolation) {
1254
- // With interpolation
1255
- this.displayText$ = this.langService.getContentWithInterpolation(this.props.contentClass, this.props.contentKey, this.props.contentInterpolation, this.props.contentFallback);
1256
- }
1257
- else {
1258
- // Simple reactive content
1259
- this.displayText$ = this.langService.getContent(this.props.contentClass, this.props.contentKey, this.props.contentFallback);
1260
- }
512
+ else if (this.props.contentFallback) {
513
+ // Backwards compatibility: use fallback if text is not provided
514
+ this.displayText = this.props.contentFallback;
1261
515
  }
1262
516
  else {
1263
- // Fallback to empty string if no valid content configuration
1264
- console.warn('val-button: No valid content configuration provided. Use either "text" for static text or "contentKey" + "contentClass" for reactive content.');
1265
- this.displayText$ = of(this.props.contentFallback || '');
517
+ this.displayText = '';
1266
518
  }
1267
519
  }
520
+ /**
521
+ * Interpolate placeholders in content with provided values.
522
+ * Supports {{placeholder}} format.
523
+ */
524
+ interpolateContent(content, values) {
525
+ return content.replace(/\{\{(\w+)\}\}/g, (match, key) => {
526
+ return values[key] !== undefined ? String(values[key]) : match;
527
+ });
528
+ }
1268
529
  clickHandler() {
1269
530
  if (this.props.state === this.states.DISABLED) {
1270
531
  return;
@@ -1280,7 +541,7 @@ class ButtonComponent {
1280
541
  }
1281
542
  this.onClick.emit(this.props.token);
1282
543
  }
1283
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, deps: [{ token: DownloadService }, { token: IconService }, { token: NavigationService }, { token: LangService }], target: i0.ɵɵFactoryTarget.Component }); }
544
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, deps: [{ token: DownloadService }, { token: IconService }, { token: NavigationService }], target: i0.ɵɵFactoryTarget.Component }); }
1284
545
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ButtonComponent, isStandalone: true, selector: "val-button", inputs: { props: "props" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
1285
546
  <ion-button
1286
547
  [type]="props.type"
@@ -1297,9 +558,9 @@ class ButtonComponent {
1297
558
  >
1298
559
  <ion-icon *ngIf="props.icon" [slot]="props.icon.slot" [name]="props.icon.name"></ion-icon>
1299
560
  <ion-spinner *ngIf="props.state === states.WORKING" name="circular"></ion-spinner>
1300
- <ion-text *ngIf="props.state !== states.WORKING">{{ displayText$ | async }}</ion-text>
561
+ <ion-text *ngIf="props.state !== states.WORKING">{{ displayText }}</ion-text>
1301
562
  </ion-button>
1302
- `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;min-width:6.25rem;margin:0}ion-button.small{--padding-bottom: 12px;--padding-end: 14px;--padding-start: 14px;--padding-top: 12px}ion-button.button-clear{padding:0;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { 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: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
563
+ `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;min-width:6.25rem;margin:0}ion-button.small{--padding-bottom: 12px;--padding-end: 14px;--padding-start: 14px;--padding-top: 12px}ion-button.button-clear{padding:0;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "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: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
1303
564
  }
1304
565
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, decorators: [{
1305
566
  type: Component,
@@ -1319,52 +580,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1319
580
  >
1320
581
  <ion-icon *ngIf="props.icon" [slot]="props.icon.slot" [name]="props.icon.name"></ion-icon>
1321
582
  <ion-spinner *ngIf="props.state === states.WORKING" name="circular"></ion-spinner>
1322
- <ion-text *ngIf="props.state !== states.WORKING">{{ displayText$ | async }}</ion-text>
583
+ <ion-text *ngIf="props.state !== states.WORKING">{{ displayText }}</ion-text>
1323
584
  </ion-button>
1324
585
  `, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;min-width:6.25rem;margin:0}ion-button.small{--padding-bottom: 12px;--padding-end: 14px;--padding-start: 14px;--padding-top: 12px}ion-button.button-clear{padding:0;margin:0}\n"] }]
1325
- }], ctorParameters: () => [{ type: DownloadService }, { type: IconService }, { type: NavigationService }, { type: LangService }], propDecorators: { props: [{
586
+ }], ctorParameters: () => [{ type: DownloadService }, { type: IconService }, { type: NavigationService }], propDecorators: { props: [{
1326
587
  type: Input
1327
588
  }], onClick: [{
1328
589
  type: Output
1329
590
  }] } });
1330
- /**
1331
- * Helper function to create reactive button props from content configuration.
1332
- * This provides a convenient way to create val-button props with reactive content.
1333
- * Follows the same pattern as createTextProps for consistency.
1334
- *
1335
- * @param contentConfig - Content configuration
1336
- * @param styleConfig - Optional style and behavior configuration
1337
- * @returns ButtonMetadata with content properties set
1338
- *
1339
- * @example
1340
- * ```typescript
1341
- * // In component
1342
- * saveButtonProps: ButtonMetadata = createButtonProps({
1343
- * contentKey: 'save',
1344
- * contentClass: 'MyComponent'
1345
- * }, {
1346
- * color: 'primary',
1347
- * icon: { name: 'save', slot: 'start' }
1348
- * });
1349
- * ```
1350
- */
1351
- function createButtonProps(contentConfig, styleConfig = {}) {
1352
- return {
1353
- contentKey: contentConfig.contentKey,
1354
- contentClass: contentConfig.contentClass,
1355
- contentFallback: contentConfig.contentFallback,
1356
- contentInterpolation: contentConfig.contentInterpolation,
1357
- color: styleConfig.color || 'primary',
1358
- type: styleConfig.type || 'button',
1359
- state: styleConfig.state || ComponentStates.ENABLED,
1360
- size: styleConfig.size,
1361
- fill: styleConfig.fill,
1362
- icon: styleConfig.icon,
1363
- expand: styleConfig.expand,
1364
- shape: styleConfig.shape,
1365
- handler: styleConfig.handler,
1366
- };
1367
- }
1368
591
 
1369
592
  const Icon = (name, slot) => {
1370
593
  return {
@@ -1587,128 +810,48 @@ const SecondarySolidBlockIconHrefButton = (text, icon, href, target) => {
1587
810
  * val-display
1588
811
  *
1589
812
  * Displays prominent text or titles with custom color and size.
1590
- * Supports both static and reactive content patterns.
1591
813
  *
1592
814
  * @example
1593
- * // Static content
1594
815
  * <val-display [props]="{ content: 'Title', color: 'dark', size: 'large' }"></val-display>
1595
816
  *
1596
- * // Reactive content
1597
- * <val-display [props]="{ contentConfig: { key: 'welcome.title' }, color: 'primary', size: 'xlarge' }"></val-display>
1598
- *
1599
- * @input props: DisplayMetadata - Configuration for the display (content/contentConfig, color, size)
817
+ * @input props: DisplayMetadata - Configuration for the display (content, color, size)
1600
818
  */
1601
819
  class DisplayComponent {
1602
- constructor() {
1603
- this.subscriptions = new Subscription();
1604
- this.langService = inject(LangService);
1605
- this.cdr = inject(ChangeDetectorRef);
1606
- }
1607
- ngOnInit() {
1608
- this.initializeDisplayContent();
1609
- }
1610
- ngOnChanges(changes) {
1611
- if (changes['props']) {
1612
- this.initializeDisplayContent();
1613
- this.cdr.detectChanges();
1614
- }
1615
- }
1616
- ngOnDestroy() {
1617
- this.subscriptions.unsubscribe();
1618
- }
1619
- initializeDisplayContent() {
1620
- // Static content takes precedence
820
+ /**
821
+ * Returns the content to display.
822
+ * Uses static content, or contentConfig fallback for backwards compatibility.
823
+ */
824
+ getDisplayContent() {
1621
825
  if (this.props.content !== undefined) {
1622
- this.displayContent$ = of(this.props.content);
1623
- return;
826
+ return this.props.content;
1624
827
  }
1625
- // Use reactive content if configured
1626
- if (this.props.contentConfig) {
1627
- this.displayContent$ = this.langService.getContent(this.props.contentConfig.className || '_global', this.props.contentConfig.key, this.props.contentConfig.fallback || this.props.contentConfig.key
1628
- // interpolation: this.props.contentConfig.interpolation,
1629
- );
1630
- return;
828
+ // Backwards compatibility: use fallback from contentConfig if present
829
+ if (this.props.contentConfig?.fallback) {
830
+ return this.props.contentConfig.fallback;
1631
831
  }
1632
- // No content configured - use empty string
1633
- this.displayContent$ = of('');
832
+ return '';
1634
833
  }
1635
834
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DisplayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1636
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DisplayComponent, isStandalone: true, selector: "val-display", inputs: { props: "props" }, usesOnChanges: true, ngImport: i0, template: `
835
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DisplayComponent, isStandalone: true, selector: "val-display", inputs: { props: "props" }, ngImport: i0, template: `
1637
836
  <ion-text [color]="props.color">
1638
837
  <p [class]="props.size">
1639
- {{ displayContent$ | async }}
838
+ {{ getDisplayContent() }}
1640
839
  </p>
1641
840
  </ion-text>
1642
- `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:1.5rem;line-height:2rem;font-weight:800}@media (min-width: 768px){.small{font-size:2rem;line-height:2.5rem}}.medium{font-size:2rem;line-height:2.5rem;font-weight:800}@media (min-width: 768px){.medium{font-size:2.5rem;line-height:3rem}}.large{font-size:2.5rem;line-height:3rem;font-weight:800}@media (min-width: 768px){.large{font-size:3rem;line-height:3.5rem}}.xlarge{font-size:3rem;line-height:2.5rem;font-weight:800}@media (min-width: 768px){.xlarge{font-size:4.375rem;line-height:4.125rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
841
+ `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:1.5rem;line-height:2rem;font-weight:800}@media (min-width: 768px){.small{font-size:2rem;line-height:2.5rem}}.medium{font-size:2rem;line-height:2.5rem;font-weight:800}@media (min-width: 768px){.medium{font-size:2.5rem;line-height:3rem}}.large{font-size:2.5rem;line-height:3rem;font-weight:800}@media (min-width: 768px){.large{font-size:3rem;line-height:3.5rem}}.xlarge{font-size:3rem;line-height:2.5rem;font-weight:800}@media (min-width: 768px){.xlarge{font-size:4.375rem;line-height:4.125rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
1643
842
  }
1644
843
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DisplayComponent, decorators: [{
1645
844
  type: Component,
1646
845
  args: [{ selector: 'val-display', standalone: true, imports: [CommonModule, IonText], template: `
1647
846
  <ion-text [color]="props.color">
1648
847
  <p [class]="props.size">
1649
- {{ displayContent$ | async }}
848
+ {{ getDisplayContent() }}
1650
849
  </p>
1651
850
  </ion-text>
1652
851
  `, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:1.5rem;line-height:2rem;font-weight:800}@media (min-width: 768px){.small{font-size:2rem;line-height:2.5rem}}.medium{font-size:2rem;line-height:2.5rem;font-weight:800}@media (min-width: 768px){.medium{font-size:2.5rem;line-height:3rem}}.large{font-size:2.5rem;line-height:3rem;font-weight:800}@media (min-width: 768px){.large{font-size:3rem;line-height:3.5rem}}.xlarge{font-size:3rem;line-height:2.5rem;font-weight:800}@media (min-width: 768px){.xlarge{font-size:4.375rem;line-height:4.125rem}}\n"] }]
1653
- }], ctorParameters: () => [], propDecorators: { props: [{
852
+ }], propDecorators: { props: [{
1654
853
  type: Input
1655
854
  }] } });
1656
- /**
1657
- * Helper function to create reactive display props from content configuration.
1658
- * This provides a convenient way to create val-display props with reactive content.
1659
- *
1660
- * @param contentConfig - Content configuration for reactive content
1661
- * @param styleConfig - Optional style configuration (color and size)
1662
- * @returns DisplayMetadata with content properties set
1663
- *
1664
- * @example
1665
- * ```typescript
1666
- * // In component
1667
- * titleProps: DisplayMetadata = createDisplayProps({
1668
- * key: 'title',
1669
- * className: 'HeaderComponent',
1670
- * fallback: 'Default Title'
1671
- * }, {
1672
- * color: 'primary',
1673
- * size: 'large'
1674
- * });
1675
- * ```
1676
- *
1677
- * @example
1678
- * ```typescript
1679
- * // With interpolation
1680
- * greetingProps: DisplayMetadata = createDisplayProps({
1681
- * key: 'greeting',
1682
- * className: 'UserComponent',
1683
- * fallback: 'Hello!',
1684
- * interpolation: { name: 'John', count: 5 }
1685
- * }, {
1686
- * color: 'secondary',
1687
- * size: 'medium'
1688
- * });
1689
- * ```
1690
- *
1691
- * @example
1692
- * ```typescript
1693
- * // Using default style values
1694
- * simpleProps: DisplayMetadata = createDisplayProps({
1695
- * key: 'welcomeMessage',
1696
- * className: 'HomeComponent'
1697
- * }); // Will use default color: 'dark' and size: 'medium'
1698
- * ```
1699
- */
1700
- function createDisplayProps(contentConfig, styleConfig = {}) {
1701
- return {
1702
- contentConfig: {
1703
- key: contentConfig.key,
1704
- className: contentConfig.className,
1705
- fallback: contentConfig.fallback,
1706
- interpolation: contentConfig.interpolation,
1707
- },
1708
- color: styleConfig.color || 'dark',
1709
- size: styleConfig.size || 'medium',
1710
- };
1711
- }
1712
855
 
1713
856
  /**
1714
857
  * val-divider
@@ -1870,8 +1013,6 @@ class ImageComponent {
1870
1013
  this.initialDistance = 0;
1871
1014
  this.initialZoom = 1;
1872
1015
  this.touches = [];
1873
- // Lang service
1874
- this.langService = inject(LangService);
1875
1016
  // Math for template
1876
1017
  this.Math = Math;
1877
1018
  }
@@ -2661,42 +1802,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
2661
1802
  standalone: true,
2662
1803
  }]
2663
1804
  }] });
2664
-
2665
- /**
2666
- * val-text
2667
- *
2668
- * Enhanced text component that supports both static content and reactive content from the language service.
2669
- * The component automatically updates when the language changes if using reactive content.
2670
- *
2671
- * @example Static content:
2672
- * ```html
2673
- * <val-text [props]="{
2674
- * content: 'Static text',
2675
- * color: 'primary',
2676
- * size: 'medium',
2677
- * bold: false
2678
- * }"></val-text>
2679
- * ```
2680
- *
2681
- * @example Reactive content:
2682
- * ```html
2683
- * <val-text [props]="{
2684
- * contentKey: 'welcomeMessage',
2685
- * contentClass: 'HomeComponent',
2686
- * contentFallback: 'Welcome!',
2687
- * color: 'primary',
2688
- * size: 'large',
2689
- * bold: true
2690
- * }"></val-text>
2691
- * ```
1805
+
1806
+ /**
1807
+ * val-text
1808
+ *
1809
+ * Text component that supports static content with optional interpolation.
2692
1810
  *
2693
- * @example Reactive content with interpolation:
1811
+ * @example Static content:
2694
1812
  * ```html
2695
1813
  * <val-text [props]="{
2696
- * contentKey: 'greeting',
2697
- * contentClass: 'UserComponent',
2698
- * contentInterpolation: { name: 'John', count: 5 },
2699
- * color: 'secondary',
1814
+ * content: 'Static text',
1815
+ * color: 'primary',
2700
1816
  * size: 'medium',
2701
1817
  * bold: false
2702
1818
  * }"></val-text>
@@ -2705,15 +1821,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
2705
1821
  * @example With automatic link processing:
2706
1822
  * ```html
2707
1823
  * <val-text [props]="{
2708
- * content: 'Visit https://example.com or go to /profile for more info',
1824
+ * content: 'Visit https://example.com for more info',
2709
1825
  * processLinks: true,
2710
- * linkConfig: {
2711
- * openExternalInNewTab: true,
2712
- * openInternalInNewTab: false,
2713
- * linkClass: 'custom-link',
2714
- * externalLinkClass: 'external',
2715
- * internalLinkClass: 'internal'
2716
- * },
2717
1826
  * color: 'primary',
2718
1827
  * size: 'medium'
2719
1828
  * }"></val-text>
@@ -2722,91 +1831,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
2722
1831
  * @example With partial bold support:
2723
1832
  * ```html
2724
1833
  * <val-text [props]="{
2725
- * content: 'Hola <b>Victor</b>, cómo estás? También puedes usar <strong>strong</strong>',
1834
+ * content: 'Hola <b>Victor</b>, cómo estás?',
2726
1835
  * allowPartialBold: true,
2727
1836
  * color: 'dark',
2728
- * size: 'medium',
2729
- * bold: false
2730
- * }"></val-text>
2731
- * ```
2732
- *
2733
- * @example Reactive content with partial bold:
2734
- * ```html
2735
- * <val-text [props]="{
2736
- * contentKey: 'welcomeWithName',
2737
- * contentClass: 'UserComponent',
2738
- * contentInterpolation: { name: '<b>Juan</b>' },
2739
- * allowPartialBold: true,
2740
- * color: 'primary',
2741
- * size: 'large',
2742
- * bold: false
1837
+ * size: 'medium'
2743
1838
  * }"></val-text>
2744
1839
  * ```
2745
1840
  *
2746
- * @example Using ContentService helper:
2747
- * ```typescript
2748
- * // In component
2749
- * content = inject(ContentService);
2750
- * componentContent = this.content.forComponent('MyComponent');
2751
- *
2752
- * textProps = {
2753
- * content: this.componentContent.getText('title'), // sync
2754
- * color: 'primary',
2755
- * size: 'large',
2756
- * bold: true
2757
- * };
2758
- * // Or with reactive binding:
2759
- * title$ = this.componentContent.get('title');
2760
- * ```
2761
- *
2762
- * @input props: TextMetadata - Configuration for the text (content, styling, and reactive content options)
1841
+ * @input props: TextMetadata - Configuration for the text (content, color, size, bold, etc.)
2763
1842
  */
2764
1843
  class TextComponent {
2765
- constructor(langService, linkProcessor) {
2766
- this.langService = langService;
2767
- this.linkProcessor = linkProcessor;
2768
- this.subscription = new Subscription();
1844
+ constructor() {
1845
+ /**
1846
+ * The content to display.
1847
+ */
1848
+ this.displayContent = '';
2769
1849
  }
2770
1850
  ngOnInit() {
2771
1851
  this.setupDisplayContent();
2772
1852
  }
2773
- ngOnDestroy() {
2774
- this.subscription.unsubscribe();
2775
- }
2776
1853
  /**
2777
- * Set up the content observable based on the props configuration.
2778
- * Priority: static content > reactive content with interpolation > reactive content
1854
+ * Set up the content based on the props configuration.
2779
1855
  */
2780
1856
  setupDisplayContent() {
2781
1857
  if (this.props.content) {
2782
- // Static content takes precedence
2783
1858
  if (this.props.contentInterpolation) {
2784
- // Static content with interpolation
2785
- const interpolatedContent = interpolateStaticContent(this.props.content, this.props.contentInterpolation);
2786
- this.displayContent$ = of(interpolatedContent);
1859
+ this.displayContent = this.interpolateContent(this.props.content, this.props.contentInterpolation);
2787
1860
  }
2788
1861
  else {
2789
- // Simple static content
2790
- this.displayContent$ = of(this.props.content);
1862
+ this.displayContent = this.props.content;
2791
1863
  }
2792
1864
  }
2793
- else if (shouldUseReactiveContent(this.props)) {
2794
- // Reactive content from language service
2795
- if (this.props.contentInterpolation) {
2796
- // With interpolation
2797
- this.displayContent$ = this.langService.getContentWithInterpolation(this.props.contentClass, this.props.contentKey, this.props.contentInterpolation, this.props.contentFallback);
2798
- }
2799
- else {
2800
- // Simple reactive content
2801
- this.displayContent$ = this.langService.getContent(this.props.contentClass, this.props.contentKey, this.props.contentFallback);
2802
- }
1865
+ else if (this.props.contentFallback) {
1866
+ // Backwards compatibility: use fallback if content is not provided
1867
+ this.displayContent = this.props.contentFallback;
2803
1868
  }
2804
1869
  else {
2805
- // Fallback to empty string if no valid content configuration
2806
- console.warn('val-text: No valid content configuration provided. Use either "content" for static text or "contentKey" + "contentClass" for reactive content.');
2807
- this.displayContent$ = of(this.props.contentFallback || '');
1870
+ this.displayContent = '';
2808
1871
  }
2809
1872
  }
1873
+ /**
1874
+ * Check if content has partial bold tags.
1875
+ */
1876
+ hasPartialBold() {
1877
+ return this.displayContent?.includes('<b>') || this.displayContent?.includes('<strong>');
1878
+ }
2810
1879
  /**
2811
1880
  * Process partial bold tags in the content.
2812
1881
  * Converts <b> and <strong> tags to properly styled bold spans.
@@ -2823,235 +1892,139 @@ class TextComponent {
2823
1892
  processedContent = processedContent.replace(/<strong>(.*?)<\/strong>/gi, '<span class="partial-bold">$1</span>');
2824
1893
  return processedContent;
2825
1894
  }
2826
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextComponent, deps: [{ token: LangService }, { token: LinkProcessorService }], target: i0.ɵɵFactoryTarget.Component }); }
1895
+ /**
1896
+ * Interpolate placeholders in content with provided values.
1897
+ * Supports {{placeholder}} format.
1898
+ *
1899
+ * @param content - The content with placeholders
1900
+ * @param values - Object with key-value pairs to interpolate
1901
+ * @returns Interpolated content
1902
+ */
1903
+ interpolateContent(content, values) {
1904
+ return content.replace(/\{\{(\w+)\}\}/g, (match, key) => {
1905
+ return values[key] !== undefined ? String(values[key]) : match;
1906
+ });
1907
+ }
1908
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2827
1909
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TextComponent, isStandalone: true, selector: "val-text", inputs: { props: "props" }, ngImport: i0, template: `
2828
1910
  <ion-text [color]="props.color">
2829
1911
  @if (props.processLinks) {
2830
1912
  <p
2831
1913
  [class]="props.size"
2832
1914
  [class.bold]="props.bold"
2833
- [innerHTML]="displayContent$ | async | processLinks: props.linkConfig"
1915
+ [innerHTML]="displayContent | processLinks: props.linkConfig"
2834
1916
  ></p>
2835
- } @else if (
2836
- (props.allowPartialBold && (displayContent$ | async)?.includes('<b>')) ||
2837
- (displayContent$ | async)?.includes('<strong>')
2838
- ) {
2839
- <p [class]="props.size" [class.bold]="props.bold" [innerHTML]="processPartialBold(displayContent$ | async)"></p>
1917
+ } @else if (props.allowPartialBold && hasPartialBold()) {
1918
+ <p [class]="props.size" [class.bold]="props.bold" [innerHTML]="processPartialBold(displayContent)"></p>
2840
1919
  } @else {
2841
- <p [class]="props.size" [class.bold]="props.bold">{{ displayContent$ | async }}</p>
1920
+ <p [class]="props.size" [class.bold]="props.bold">{{ displayContent }}</p>
2842
1921
  }
2843
1922
  </ion-text>
2844
- `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .partial-bold{font-weight:700}\n"], dependencies: [{ kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: ProcessLinksPipe, name: "processLinks" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1923
+ `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .partial-bold{font-weight:700}\n"], dependencies: [{ kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "pipe", type: ProcessLinksPipe, name: "processLinks" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2845
1924
  }
2846
1925
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextComponent, decorators: [{
2847
1926
  type: Component,
2848
- args: [{ selector: 'val-text', standalone: true, imports: [IonText, AsyncPipe, ProcessLinksPipe], template: `
1927
+ args: [{ selector: 'val-text', standalone: true, imports: [IonText, ProcessLinksPipe], template: `
2849
1928
  <ion-text [color]="props.color">
2850
1929
  @if (props.processLinks) {
2851
1930
  <p
2852
1931
  [class]="props.size"
2853
1932
  [class.bold]="props.bold"
2854
- [innerHTML]="displayContent$ | async | processLinks: props.linkConfig"
1933
+ [innerHTML]="displayContent | processLinks: props.linkConfig"
2855
1934
  ></p>
2856
- } @else if (
2857
- (props.allowPartialBold && (displayContent$ | async)?.includes('<b>')) ||
2858
- (displayContent$ | async)?.includes('<strong>')
2859
- ) {
2860
- <p [class]="props.size" [class.bold]="props.bold" [innerHTML]="processPartialBold(displayContent$ | async)"></p>
1935
+ } @else if (props.allowPartialBold && hasPartialBold()) {
1936
+ <p [class]="props.size" [class.bold]="props.bold" [innerHTML]="processPartialBold(displayContent)"></p>
2861
1937
  } @else {
2862
- <p [class]="props.size" [class.bold]="props.bold">{{ displayContent$ | async }}</p>
1938
+ <p [class]="props.size" [class.bold]="props.bold">{{ displayContent }}</p>
2863
1939
  }
2864
1940
  </ion-text>
2865
1941
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .partial-bold{font-weight:700}\n"] }]
2866
- }], ctorParameters: () => [{ type: LangService }, { type: LinkProcessorService }], propDecorators: { props: [{
1942
+ }], propDecorators: { props: [{
2867
1943
  type: Input
2868
1944
  }] } });
2869
- /**
2870
- * Helper function to create reactive text props from content configuration.
2871
- * This provides a convenient way to create val-text props with reactive content.
2872
- *
2873
- * @param contentConfig - Content configuration
2874
- * @param styleConfig - Optional style configuration
2875
- * @returns Partial TextMetadata with content properties set
2876
- *
2877
- * @example
2878
- * ```typescript
2879
- * // In component
2880
- * titleProps: TextMetadata = {
2881
- * ...createTextProps({
2882
- * contentKey: 'title',
2883
- * contentClass: 'HeaderComponent'
2884
- * }, {
2885
- * color: 'primary',
2886
- * size: 'large',
2887
- * bold: true
2888
- * })
2889
- * };
2890
- * ```
2891
- *
2892
- * @example With partial bold support:
2893
- * ```typescript
2894
- * // In component
2895
- * greetingProps: TextMetadata = {
2896
- * ...createTextProps({
2897
- * contentKey: 'greeting',
2898
- * contentClass: 'UserComponent',
2899
- * contentInterpolation: { name: '<b>Juan</b>' }
2900
- * }, {
2901
- * color: 'primary',
2902
- * size: 'medium',
2903
- * bold: false,
2904
- * allowPartialBold: true
2905
- * })
2906
- * };
2907
- * ```
2908
- */
2909
- function createTextProps(contentConfig, styleConfig = {}) {
2910
- return {
2911
- contentKey: contentConfig.contentKey,
2912
- contentClass: contentConfig.contentClass,
2913
- contentFallback: contentConfig.contentFallback,
2914
- contentInterpolation: contentConfig.contentInterpolation,
2915
- color: styleConfig.color || 'dark',
2916
- size: styleConfig.size || 'medium',
2917
- bold: styleConfig.bold || false,
2918
- allowPartialBold: styleConfig.allowPartialBold || false,
2919
- };
2920
- }
2921
1945
 
2922
1946
  /**
2923
1947
  * val-title
2924
1948
  *
2925
1949
  * A styled title or heading, with options for size, color, and boldness.
2926
- * Supports both static content and reactive content from the language service.
2927
1950
  *
2928
- * @example Static content:
2929
- * ```html
1951
+ * @example
2930
1952
  * <val-title [props]="{ content: 'My Title', size: 'large', color: 'primary', bold: true }"></val-title>
2931
- * ```
2932
- *
2933
- * @example Reactive content:
2934
- * ```html
2935
- * <val-title [props]="{
2936
- * contentConfig: { key: 'pageTitle', fallback: 'Default Title' },
2937
- * size: 'large',
2938
- * color: 'primary',
2939
- * bold: true
2940
- * }"></val-title>
2941
- * ```
2942
- *
2943
- * @example Reactive content with interpolation:
2944
- * ```html
2945
- * <val-title [props]="{
2946
- * contentConfig: {
2947
- * key: 'welcomeTitle',
2948
- * interpolation: { name: 'John' },
2949
- * fallback: 'Welcome!'
2950
- * },
2951
- * size: 'large',
2952
- * color: 'primary',
2953
- * bold: true
2954
- * }"></val-title>
2955
- * ```
2956
1953
  *
2957
1954
  * @input props: TitleMetadata - Configuration for the title (content, color, size, bold, thin)
2958
1955
  */
2959
1956
  class TitleComponent {
2960
- constructor() {
2961
- this.langService = inject(LangService);
2962
- this.cdr = inject(ChangeDetectorRef);
2963
- }
2964
- ngOnInit() {
2965
- this.updateContent();
2966
- }
2967
- ngOnChanges(changes) {
2968
- if (changes['props']) {
2969
- this.updateContent();
2970
- this.cdr.detectChanges();
2971
- }
2972
- }
2973
- updateContent() {
2974
- // Always convert to Observable for consistent template handling
2975
- if (shouldUseReactiveContent(this.props)) {
2976
- // Use reactive content with LangService
2977
- const config = extractContentConfig(this.props);
2978
- this.displayContent$ = this.langService.getContent(config.className, config.key, config.fallback);
1957
+ /**
1958
+ * Returns the content to display.
1959
+ * Uses static content, or contentFallback for backwards compatibility.
1960
+ */
1961
+ getDisplayContent() {
1962
+ if (this.props.content) {
1963
+ return this.props.content;
2979
1964
  }
2980
- else {
2981
- // Convert static content to Observable
2982
- const staticContent = this.props.content || '';
2983
- this.displayContent$ = of(staticContent);
1965
+ // Backwards compatibility: use contentFallback if present
1966
+ if (this.props.contentFallback) {
1967
+ return this.props.contentFallback;
2984
1968
  }
1969
+ return '';
2985
1970
  }
2986
1971
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2987
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TitleComponent, isStandalone: true, selector: "val-title", inputs: { props: "props" }, usesOnChanges: true, ngImport: i0, template: `
1972
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TitleComponent, isStandalone: true, selector: "val-title", inputs: { props: "props" }, ngImport: i0, template: `
2988
1973
  <ion-text [color]="props.color">
2989
1974
  @if (!props.bold) {
2990
1975
  <p [ngClass]="[props.size]" [class.thin]="props.thin">
2991
- {{ displayContent$ | async }}
1976
+ {{ getDisplayContent() }}
2992
1977
  </p>
2993
1978
  } @else {
2994
1979
  <b>
2995
1980
  <p [class]="props.size">
2996
- {{ displayContent$ | async }}
1981
+ {{ getDisplayContent() }}
2997
1982
  </p>
2998
1983
  </b>
2999
1984
  }
3000
1985
  </ion-text>
3001
- `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.small{font-size:1rem;line-height:1.5rem}}.small.thin{font-weight:500}.medium{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium{font-size:1.125rem;line-height:1.5rem}}.medium.thin{font-weight:500}.large{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large{font-size:1.5rem;line-height:2rem}}.large.thin{font-weight:500}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.thin{font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1986
+ `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.small{font-size:1rem;line-height:1.5rem}}.small.thin{font-weight:500}.medium{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium{font-size:1.125rem;line-height:1.5rem}}.medium.thin{font-weight:500}.large{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large{font-size:1.5rem;line-height:2rem}}.large.thin{font-weight:500}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.thin{font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3002
1987
  }
3003
1988
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TitleComponent, decorators: [{
3004
1989
  type: Component,
3005
- args: [{ selector: 'val-title', standalone: true, imports: [CommonModule, IonText, AsyncPipe], template: `
1990
+ args: [{ selector: 'val-title', standalone: true, imports: [CommonModule, IonText], template: `
3006
1991
  <ion-text [color]="props.color">
3007
1992
  @if (!props.bold) {
3008
1993
  <p [ngClass]="[props.size]" [class.thin]="props.thin">
3009
- {{ displayContent$ | async }}
1994
+ {{ getDisplayContent() }}
3010
1995
  </p>
3011
1996
  } @else {
3012
1997
  <b>
3013
1998
  <p [class]="props.size">
3014
- {{ displayContent$ | async }}
1999
+ {{ getDisplayContent() }}
3015
2000
  </p>
3016
2001
  </b>
3017
2002
  }
3018
2003
  </ion-text>
3019
2004
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.small{font-size:1rem;line-height:1.5rem}}.small.thin{font-weight:500}.medium{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium{font-size:1.125rem;line-height:1.5rem}}.medium.thin{font-weight:500}.large{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large{font-size:1.5rem;line-height:2rem}}.large.thin{font-weight:500}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.thin{font-weight:500}\n"] }]
3020
- }], ctorParameters: () => [], propDecorators: { props: [{
2005
+ }], propDecorators: { props: [{
3021
2006
  type: Input
3022
2007
  }] } });
3023
2008
 
3024
2009
  /**
3025
- * Factory function to create title props with reactive content support.
2010
+ * Factory function to create title props.
3026
2011
  *
3027
2012
  * @param styleConfig - Title styling configuration
3028
- * @param contentConfig - Content configuration (static or reactive)
2013
+ * @param content - The title text
3029
2014
  * @returns Complete TitleMetadata object
3030
2015
  *
3031
- * @example Static content:
3032
- * ```typescript
3033
- * const props = createTitleProps(
3034
- * { size: 'large', color: 'primary', bold: true },
3035
- * { content: 'Static Title' }
3036
- * );
3037
- * ```
3038
- *
3039
- * @example Reactive content:
2016
+ * @example
3040
2017
  * ```typescript
3041
2018
  * const props = createTitleProps(
3042
2019
  * { size: 'large', color: 'primary', bold: true },
3043
- * {
3044
- * contentKey: 'pageTitle',
3045
- * contentClass: 'MyComponent',
3046
- * contentFallback: 'Default Title'
3047
- * }
2020
+ * 'My Title'
3048
2021
  * );
3049
2022
  * ```
3050
2023
  */
3051
- function createTitleProps(styleConfig, contentConfig) {
2024
+ function createTitleProps(styleConfig, content) {
3052
2025
  return {
3053
2026
  ...styleConfig,
3054
- ...contentConfig,
2027
+ content,
3055
2028
  };
3056
2029
  }
3057
2030
 
@@ -3973,26 +2946,11 @@ class QrCodeComponent {
3973
2946
  this.imageError = new EventEmitter();
3974
2947
  this.canShare = false;
3975
2948
  this.canCopy = false;
3976
- this.langSubscription = null;
3977
- this.langService = inject(LangService);
3978
2949
  this.qrService = inject(QrGeneratorService);
3979
2950
  }
3980
2951
  ngOnInit() {
3981
2952
  this.canShare = this.qrService.canShare();
3982
2953
  this.canCopy = this.qrService.canCopyToClipboard();
3983
- if (this.hasReactiveContent()) {
3984
- this.langSubscription = this.langService.currentLang$.subscribe(() => {
3985
- // Trigger change detection for labels
3986
- });
3987
- }
3988
- }
3989
- ngOnDestroy() {
3990
- this.langSubscription?.unsubscribe();
3991
- }
3992
- hasReactiveContent() {
3993
- return !!((this.props.downloadLabelContentKey && this.props.contentClass) ||
3994
- (this.props.copyLabelContentKey && this.props.contentClass) ||
3995
- (this.props.shareLabelContentKey && this.props.contentClass));
3996
2954
  }
3997
2955
  getDisplaySize() {
3998
2956
  if (this.props.displaySize) {
@@ -4057,22 +3015,13 @@ class QrCodeComponent {
4057
3015
  return !!(this.props.showDownload || this.props.showCopy || this.props.showShare);
4058
3016
  }
4059
3017
  getDownloadLabel() {
4060
- if (this.props.downloadLabelContentKey && this.props.contentClass) {
4061
- return this.langService.getText(this.props.contentClass, this.props.downloadLabelContentKey, this.props.downloadLabel || 'Download');
4062
- }
4063
- return this.props.downloadLabel || 'Download';
3018
+ return this.props.downloadLabel || 'Descargar';
4064
3019
  }
4065
3020
  getCopyLabel() {
4066
- if (this.props.copyLabelContentKey && this.props.contentClass) {
4067
- return this.langService.getText(this.props.contentClass, this.props.copyLabelContentKey, this.props.copyLabel || 'Copy');
4068
- }
4069
- return this.props.copyLabel || 'Copy';
3021
+ return this.props.copyLabel || 'Copiar';
4070
3022
  }
4071
3023
  getShareLabel() {
4072
- if (this.props.shareLabelContentKey && this.props.contentClass) {
4073
- return this.langService.getText(this.props.contentClass, this.props.shareLabelContentKey, this.props.shareLabel || 'Share');
4074
- }
4075
- return this.props.shareLabel || 'Share';
3024
+ return this.props.shareLabel || 'Compartir';
4076
3025
  }
4077
3026
  async onDownload() {
4078
3027
  try {
@@ -4422,7 +3371,6 @@ class CountdownComponent {
4422
3371
  };
4423
3372
  this.isExpired = false;
4424
3373
  this.intervalId = null;
4425
- this.langService = inject(LangService);
4426
3374
  }
4427
3375
  ngOnInit() {
4428
3376
  if (this.props.autoStart !== false) {
@@ -4545,9 +3493,6 @@ class CountdownComponent {
4545
3493
  return labels[unit] || unit;
4546
3494
  }
4547
3495
  getExpiredMessage() {
4548
- if (this.props.expiredMessageContentKey && this.props.contentClass) {
4549
- return this.langService.getText(this.props.contentClass, this.props.expiredMessageContentKey, this.props.expiredMessage || 'Tiempo agotado');
4550
- }
4551
3496
  return this.props.expiredMessage || 'Tiempo agotado';
4552
3497
  }
4553
3498
  getColor() {
@@ -4768,9 +3713,6 @@ const CURRENCY_INFO = {
4768
3713
  * ```
4769
3714
  */
4770
3715
  class PriceTagComponent {
4771
- constructor() {
4772
- this.langService = inject(LangService);
4773
- }
4774
3716
  get currencyInfo() {
4775
3717
  const currency = this.props.currency || 'MXN';
4776
3718
  return CURRENCY_INFO[currency] || CURRENCY_INFO['USD'];
@@ -4810,15 +3752,9 @@ class PriceTagComponent {
4810
3752
  return `${formattedNumber}${symbol}`;
4811
3753
  }
4812
3754
  getPrefix() {
4813
- if (this.props.prefixContentKey && this.props.contentClass) {
4814
- return this.langService.getText(this.props.contentClass, this.props.prefixContentKey, this.props.prefix || '');
4815
- }
4816
3755
  return this.props.prefix || '';
4817
3756
  }
4818
3757
  getPeriod() {
4819
- if (this.props.periodContentKey && this.props.contentClass) {
4820
- return this.langService.getText(this.props.contentClass, this.props.periodContentKey, this.props.period || '');
4821
- }
4822
3758
  return this.props.period || '';
4823
3759
  }
4824
3760
  getColor() {
@@ -5119,14 +4055,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5119
4055
  * val-alert-box
5120
4056
  *
5121
4057
  * Displays an alert box with an icon and text, using a styled box container.
5122
- * Supports both static and reactive content patterns.
5123
4058
  *
5124
4059
  * @example
5125
- * // Legacy pattern with TextMetadata
5126
- * <val-alert-box [props]="{ box: {...}, icon: {...}, text: {...} }"></val-alert-box>
5127
- *
5128
- * // Reactive pattern with simplified configuration
5129
- * <val-alert-box [props]="{ box: {...}, icon: {...}, textConfig: { key: 'alert.warning' } }"></val-alert-box>
4060
+ * <val-alert-box [props]="{ box: {...}, icon: {...}, text: { content: 'Alerta' } }"></val-alert-box>
5130
4061
  *
5131
4062
  * @input props: AlertBoxMetadata | ReactiveAlertBoxMetadata - Configuration for the alert box
5132
4063
  */
@@ -5139,19 +4070,12 @@ class AlertBoxComponent {
5139
4070
  getLegacyTextProps() {
5140
4071
  return this.props.text;
5141
4072
  }
5142
- constructor(langService) {
5143
- this.langService = langService;
5144
- this.subscriptions = new Subscription();
5145
- }
5146
4073
  ngOnInit() {
5147
4074
  if (!this.isLegacyProps) {
5148
- this.initializeReactiveTextProps();
4075
+ this.initializeTextProps();
5149
4076
  }
5150
4077
  }
5151
- ngOnDestroy() {
5152
- this.subscriptions.unsubscribe();
5153
- }
5154
- initializeReactiveTextProps() {
4078
+ initializeTextProps() {
5155
4079
  const reactiveProps = this.props;
5156
4080
  // Base text properties with styling
5157
4081
  this.computedTextProps = {
@@ -5159,17 +4083,12 @@ class AlertBoxComponent {
5159
4083
  color: reactiveProps.textStyle?.color,
5160
4084
  bold: reactiveProps.textStyle?.bold || false,
5161
4085
  };
5162
- // Add content configuration
4086
+ // Add content - use static text only
5163
4087
  if (reactiveProps.text !== undefined) {
5164
- // Static text
5165
4088
  this.computedTextProps.content = reactiveProps.text;
5166
4089
  }
5167
- else if (reactiveProps.textConfig) {
5168
- // Reactive content
5169
- this.computedTextProps.contentConfig = reactiveProps.textConfig;
5170
- }
5171
4090
  }
5172
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AlertBoxComponent, deps: [{ token: LangService }], target: i0.ɵɵFactoryTarget.Component }); }
4091
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AlertBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5173
4092
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AlertBoxComponent, isStandalone: true, selector: "val-alert-box", inputs: { props: "props" }, ngImport: i0, template: `
5174
4093
  <val-box [props]="props.box">
5175
4094
  <div class="content-container" body>
@@ -5199,7 +4118,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5199
4118
  </div>
5200
4119
  </val-box>
5201
4120
  `, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.text{margin-left:.25rem}.content-container{display:flex;align-items:flex-start}\n"] }]
5202
- }], ctorParameters: () => [{ type: LangService }], propDecorators: { props: [{
4121
+ }], propDecorators: { props: [{
5203
4122
  type: Input
5204
4123
  }] } });
5205
4124
 
@@ -5649,54 +4568,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5649
4568
  * val-check-input
5650
4569
  *
5651
4570
  * A checkbox input for boolean values, integrated with Angular forms.
5652
- * Supports i18n for label text via static or reactive content.
5653
4571
  *
5654
- * @example Static label:
4572
+ * @example
5655
4573
  * <val-check-input [props]="{ control: myControl, label: 'I agree' }"></val-check-input>
5656
4574
  *
5657
- * @example Reactive i18n label:
5658
- * <val-check-input [props]="{
5659
- * control: myControl,
5660
- * contentKey: 'termsAgreement',
5661
- * contentClass: 'MyComponent',
5662
- * contentFallback: 'I agree to the terms'
5663
- * }"></val-check-input>
5664
- *
5665
- * @input props: InputMetadata - Configuration for the checkbox (form control, label, content config, etc.)
4575
+ * @input props: InputMetadata - Configuration for the checkbox (form control, label, etc.)
5666
4576
  */
5667
4577
  class CheckInputComponent {
5668
- constructor() {
5669
- this.langService = inject(LangService);
5670
- }
5671
- ngOnInit() {
5672
- this.setupDisplayLabel();
5673
- }
5674
- setupDisplayLabel() {
5675
- if (this.props.label) {
5676
- // Static label
5677
- this.displayLabel$ = of(this.props.label);
5678
- }
5679
- else if (this.props.contentKey && this.props.contentClass) {
5680
- // Reactive content from language service
5681
- this.displayLabel$ = this.langService.getContent(this.props.contentClass, this.props.contentKey, this.props.contentFallback);
5682
- }
5683
- else {
5684
- // Fallback
5685
- this.displayLabel$ = of(this.props.contentFallback || '');
5686
- }
4578
+ getDisplayLabel() {
4579
+ return this.props.label || this.props.contentFallback || '';
5687
4580
  }
5688
4581
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CheckInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5689
4582
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CheckInputComponent, isStandalone: true, selector: "val-check-input", inputs: { props: "props" }, ngImport: i0, template: `
5690
4583
  <ion-checkbox [formControl]="props.control" [labelPlacement]="props.labelPlacement || 'end'">
5691
- {{ displayLabel$ | async }}
4584
+ {{ getDisplayLabel() }}
5692
4585
  </ion-checkbox>
5693
- `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }] }); }
4586
+ `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }] }); }
5694
4587
  }
5695
4588
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CheckInputComponent, decorators: [{
5696
4589
  type: Component,
5697
- args: [{ selector: 'val-check-input', standalone: true, imports: [CommonModule, AsyncPipe, ReactiveFormsModule, IonCheckbox], template: `
4590
+ args: [{ selector: 'val-check-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, IonCheckbox], template: `
5698
4591
  <ion-checkbox [formControl]="props.control" [labelPlacement]="props.labelPlacement || 'end'">
5699
- {{ displayLabel$ | async }}
4592
+ {{ getDisplayLabel() }}
5700
4593
  </ion-checkbox>
5701
4594
  ` }]
5702
4595
  }], propDecorators: { props: [{
@@ -6037,17 +4930,16 @@ class ExpandableTextComponent {
6037
4930
  constructor() {
6038
4931
  this.expanded = false;
6039
4932
  this.defaultColor = 'primary';
6040
- this.langService = inject(LangService);
6041
4933
  }
6042
4934
  get truncatedText() {
6043
- const maxLength = this.props.limit || 100; // Longitud por defecto
4935
+ const maxLength = this.props.limit || 100;
6044
4936
  return this.props.content?.length > maxLength ? this.props.content.slice(0, maxLength) + '...' : this.props.content;
6045
4937
  }
6046
4938
  get isTruncated() {
6047
4939
  return this.props.content?.length > (this.props.limit || 100);
6048
4940
  }
6049
4941
  getExpandText() {
6050
- return this.props.expandText || this.langService.getText('_global', 'seeMore', 'ver más');
4942
+ return this.props.expandText || 'ver más';
6051
4943
  }
6052
4944
  toggleExpand() {
6053
4945
  this.expanded = !this.expanded;
@@ -6273,6 +5165,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6273
5165
  type: Input
6274
5166
  }] } });
6275
5167
 
5168
+ /**
5169
+ * Clave para persistir el idioma en localStorage
5170
+ */
5171
+ const LANG_STORAGE_KEY = 'app_lang';
5172
+ /**
5173
+ * Idioma por defecto
5174
+ */
5175
+ const DEFAULT_LANG = 'es';
5176
+ /**
5177
+ * Servicio mínimo de localización.
5178
+ *
5179
+ * - Lee el idioma desde localStorage al iniciar
5180
+ * - Proporciona método para cambiar idioma (recarga la página)
5181
+ * - Sin observables ni subscripciones
5182
+ *
5183
+ * @example
5184
+ * // En un componente
5185
+ * locale = inject(LocaleService);
5186
+ *
5187
+ * // Obtener idioma actual
5188
+ * console.log(this.locale.lang); // 'es' o 'en'
5189
+ *
5190
+ * // Cambiar idioma (recarga la página)
5191
+ * this.locale.setLang('en');
5192
+ */
5193
+ class LocaleService {
5194
+ constructor() {
5195
+ this.lang = this.getStoredLang();
5196
+ }
5197
+ /**
5198
+ * Cambia el idioma de la aplicación.
5199
+ * Guarda en localStorage y recarga la página para aplicar el cambio.
5200
+ *
5201
+ * @param lang Nuevo idioma ('es' o 'en')
5202
+ */
5203
+ setLang(lang) {
5204
+ if (lang === this.lang) {
5205
+ return;
5206
+ }
5207
+ localStorage.setItem(LANG_STORAGE_KEY, lang);
5208
+ window.location.reload();
5209
+ }
5210
+ /**
5211
+ * Obtiene el idioma almacenado en localStorage.
5212
+ * Si no existe o no es válido, retorna el idioma por defecto.
5213
+ */
5214
+ getStoredLang() {
5215
+ const stored = localStorage.getItem(LANG_STORAGE_KEY);
5216
+ if (stored === 'es' || stored === 'en') {
5217
+ return stored;
5218
+ }
5219
+ return DEFAULT_LANG;
5220
+ }
5221
+ /**
5222
+ * Verifica si el idioma actual es español
5223
+ */
5224
+ get isSpanish() {
5225
+ return this.lang === 'es';
5226
+ }
5227
+ /**
5228
+ * Verifica si el idioma actual es inglés
5229
+ */
5230
+ get isEnglish() {
5231
+ return this.lang === 'en';
5232
+ }
5233
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5234
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocaleService, providedIn: 'root' }); }
5235
+ }
5236
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocaleService, decorators: [{
5237
+ type: Injectable,
5238
+ args: [{ providedIn: 'root' }]
5239
+ }], ctorParameters: () => [] });
5240
+
6276
5241
  /**
6277
5242
  * val-popover-selector
6278
5243
  *
@@ -6311,27 +5276,26 @@ class PopoverSelectorComponent {
6311
5276
  * Emits the selected value(s).
6312
5277
  */
6313
5278
  this.selectionChange = new EventEmitter();
6314
- this.langService = inject(LangService);
6315
5279
  // Register required icons
6316
5280
  addIcons({ chevronDown });
6317
5281
  }
6318
5282
  /**
6319
- * Get reactive placeholder text.
5283
+ * Get placeholder text.
6320
5284
  */
6321
5285
  getPlaceholderText() {
6322
- return this.props.placeholder || this.langService.getText('_global', 'select', 'Seleccionar...');
5286
+ return this.props.placeholder || 'Seleccionar...';
6323
5287
  }
6324
5288
  /**
6325
- * Get reactive cancel text.
5289
+ * Get cancel text.
6326
5290
  */
6327
5291
  getCancelText() {
6328
- return this.props.cancelText || this.langService.getText('_global', 'cancel', 'Cancelar');
5292
+ return this.props.cancelText || 'Cancelar';
6329
5293
  }
6330
5294
  /**
6331
- * Get reactive ok text.
5295
+ * Get ok text.
6332
5296
  */
6333
5297
  getOkText() {
6334
- return this.props.okText || this.langService.getText('_global', 'ok', 'Aceptar');
5298
+ return this.props.okText || 'Aceptar';
6335
5299
  }
6336
5300
  /**
6337
5301
  * Handle selection change from the ion-select.
@@ -6359,8 +5323,7 @@ class PopoverSelectorComponent {
6359
5323
  const option = this.props.options.find(opt => opt.value === this.props.selectedValue[0]);
6360
5324
  return option?.label || this.props.selectedValue[0];
6361
5325
  }
6362
- const selectedText = this.langService.getText('_global', 'selected', 'seleccionados');
6363
- return `${this.props.selectedValue.length} ${selectedText}`;
5326
+ return `${this.props.selectedValue.length} seleccionados`;
6364
5327
  }
6365
5328
  // Single selection
6366
5329
  const selectedOption = this.props.options.find(opt => opt.value === this.props.selectedValue);
@@ -6457,154 +5420,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6457
5420
  /**
6458
5421
  * val-language-selector
6459
5422
  *
6460
- * A specialized language selector component that integrates with the LangService.
6461
- * Uses the popover-selector component internally and provides language-specific functionality.
5423
+ * A language selector component that uses LocaleService.
5424
+ * When the language changes, the page will reload.
6462
5425
  *
6463
5426
  * @example
6464
- * // Basic usage (auto-detects languages from LangService)
6465
5427
  * <val-language-selector
6466
5428
  * [props]="{ showLabel: true, showFlags: true }">
6467
5429
  * </val-language-selector>
6468
5430
  *
6469
- * @example
6470
- * // Custom configuration
6471
- * const languageProps: LanguageSelectorMetadata = {
6472
- * showLabel: true,
6473
- * label: 'Choose Language',
6474
- * showFlags: true,
6475
- * color: 'primary',
6476
- * size: 'large',
6477
- * fill: 'outline',
6478
- * customLanguageNames: {
6479
- * 'es': 'Español',
6480
- * 'en': 'English',
6481
- * 'fr': 'Français'
6482
- * }
6483
- * };
6484
- *
6485
- * @example
6486
- * // With reactive content
6487
- * const languageProps: LanguageSelectorMetadata = {
6488
- * showLabel: true,
6489
- * labelConfig: {
6490
- * className: 'myComponent',
6491
- * key: 'languageLabel',
6492
- * fallback: 'Language'
6493
- * },
6494
- * color: 'tertiary'
6495
- * };
6496
- *
6497
5431
  * @input props: LanguageSelectorMetadata - Configuration for the language selector
6498
- * @output languageChange: EventEmitter<string> - Emitted when language changes
5432
+ * @output languageChange: EventEmitter<string> - Emitted when language changes (before reload)
6499
5433
  */
6500
5434
  class LanguageSelectorComponent {
6501
- constructor(langService) {
6502
- this.langService = langService;
5435
+ constructor() {
6503
5436
  /**
6504
5437
  * Language selector configuration object.
6505
- * @type {LanguageSelectorMetadata}
6506
5438
  */
6507
5439
  this.props = {};
6508
5440
  /**
6509
5441
  * Event emitted when the language selection changes.
6510
5442
  * Emits the selected language code.
5443
+ * Note: Page will reload after this event.
6511
5444
  */
6512
5445
  this.languageChange = new EventEmitter();
6513
- this.subscriptions = new Subscription();
5446
+ this.localeService = inject(LocaleService);
6514
5447
  /** Default language display names */
6515
5448
  this.defaultLanguageNames = {
6516
5449
  es: 'Español',
6517
5450
  en: 'English',
6518
- fr: 'Français',
6519
- de: 'Deutsch',
6520
- pt: 'Português',
6521
- it: 'Italiano',
6522
- zh: '中文',
6523
- ja: '日本語',
6524
- ko: '한국어',
6525
- ru: 'Русский',
6526
- ar: 'العربية',
6527
5451
  };
6528
5452
  /** Default flag icons for languages */
6529
5453
  this.defaultLanguageFlags = {
6530
5454
  es: '🇪🇸',
6531
5455
  en: '🇺🇸',
6532
- fr: '🇫🇷',
6533
- de: '🇩🇪',
6534
- pt: '🇵🇹',
6535
- it: '🇮🇹',
6536
- zh: '🇨🇳',
6537
- ja: '🇯🇵',
6538
- ko: '🇰🇷',
6539
- ru: '🇷🇺',
6540
- ar: '🇸🇦',
6541
5456
  };
6542
- // Register required icons
6543
- addIcons({ language, globe });
5457
+ /** Available languages */
5458
+ this.availableLanguages = ['es', 'en'];
5459
+ addIcons({ language });
6544
5460
  }
6545
5461
  ngOnInit() {
6546
- this.initializeLanguageState();
6547
- this.initializeLabel();
6548
5462
  this.initializePopoverProps();
6549
5463
  }
6550
- ngOnDestroy() {
6551
- this.subscriptions.unsubscribe();
6552
- }
6553
- initializeLanguageState() {
6554
- // Get current language and available languages from LangService
6555
- this.currentLanguage$ = this.langService.currentLang$;
6556
- this.availableLanguages$ = this.currentLanguage$.pipe(map$1(() => this.props.availableLanguages || this.langService.availableLangs));
6557
- }
6558
- initializeLabel() {
6559
- // Initialize label observable based on configuration
6560
- if (this.props.label !== undefined) {
6561
- // Static label
6562
- this.label$ = of(this.props.label);
6563
- }
6564
- else if (this.props.labelConfig) {
6565
- // Reactive label
6566
- this.label$ = this.langService.getContent(this.props.labelConfig.className || '_global', this.props.labelConfig.key, this.props.labelConfig.fallback || 'Language');
6567
- }
6568
- else {
6569
- // Default label from global content
6570
- this.label$ = this.langService.getContent('_global', 'language', 'Idioma');
6571
- }
6572
- }
6573
5464
  initializePopoverProps() {
6574
- // Subscribe to language state changes and content changes to update popover props
6575
- const languageSubscription = combineLatest([
6576
- this.availableLanguages$,
6577
- this.currentLanguage$,
6578
- this.langService.currentLang$, // This will trigger updates when language changes
6579
- ]).subscribe(([availableLanguages, currentLanguage]) => {
6580
- this.updatePopoverProps(availableLanguages, currentLanguage);
6581
- });
6582
- this.subscriptions.add(languageSubscription);
6583
- // Subscribe to label changes
6584
- const labelSubscription = this.label$.subscribe(label => {
6585
- if (this.popoverProps) {
6586
- this.popoverProps = {
6587
- ...this.popoverProps,
6588
- label: this.props.showLabel !== false ? label : undefined,
6589
- };
6590
- }
6591
- });
6592
- this.subscriptions.add(labelSubscription);
6593
- }
6594
- updatePopoverProps(availableLanguages, currentLanguage) {
5465
+ const currentLanguage = this.localeService.lang;
6595
5466
  // Convert language codes to popover options
6596
- const options = availableLanguages.map(lang => ({
5467
+ const options = this.availableLanguages.map(lang => ({
6597
5468
  value: lang,
6598
5469
  label: this.getLanguageDisplayName(lang),
6599
- icon: this.props.showFlags ? undefined : undefined, // We'll use text flags instead
6600
5470
  }));
6601
5471
  // Create popover configuration
6602
5472
  this.popoverProps = {
6603
5473
  options,
6604
5474
  selectedValue: currentLanguage,
6605
- label: this.props.showLabel !== false ? '' : undefined, // Will be set by label subscription
5475
+ label: this.props.showLabel !== false ? (this.props.label || 'Idioma') : undefined,
6606
5476
  icon: 'language',
6607
- placeholder: this.langService.getText('_global', 'selectLanguage', 'Seleccionar idioma...'),
5477
+ placeholder: 'Seleccionar idioma...',
6608
5478
  color: this.props.color || 'medium',
6609
5479
  size: this.props.size || 'default',
6610
5480
  fill: this.props.fill || 'outline',
@@ -6625,15 +5495,9 @@ class LanguageSelectorComponent {
6625
5495
  const flag = this.props.showFlags ? this.defaultLanguageFlags[languageCode] : '';
6626
5496
  return flag ? `${flag} ${customName}` : customName;
6627
5497
  }
6628
- // Use reactive content for translated language names
6629
- // Note: This will use the current language since getLanguageDisplayName is called during subscription updates
6630
- const translatedName = this.langService.getText('_global', `languageName_${languageCode}`);
6631
- const flag = this.props.showFlags ? this.defaultLanguageFlags[languageCode] : '';
6632
- if (translatedName && translatedName !== `languageName_${languageCode}`) {
6633
- return flag ? `${flag} ${translatedName}` : translatedName;
6634
- }
6635
- // Fallback to default names, then to code
5498
+ // Use default names
6636
5499
  const defaultName = this.defaultLanguageNames[languageCode] || languageCode.toUpperCase();
5500
+ const flag = this.props.showFlags ? this.defaultLanguageFlags[languageCode] : '';
6637
5501
  return flag ? `${flag} ${defaultName}` : defaultName;
6638
5502
  }
6639
5503
  /**
@@ -6642,13 +5506,14 @@ class LanguageSelectorComponent {
6642
5506
  */
6643
5507
  onLanguageChange(selectedLanguage) {
6644
5508
  if (typeof selectedLanguage === 'string') {
6645
- // Update the language service
6646
- this.langService.setLang(selectedLanguage);
6647
- // Emit the change event
5509
+ const newLang = selectedLanguage;
5510
+ // Emit the change event before reload
6648
5511
  this.languageChange.emit(selectedLanguage);
5512
+ // Set the new language (this will reload the page)
5513
+ this.localeService.setLang(newLang);
6649
5514
  }
6650
5515
  }
6651
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LanguageSelectorComponent, deps: [{ token: LangService }], target: i0.ɵɵFactoryTarget.Component }); }
5516
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LanguageSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6652
5517
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: LanguageSelectorComponent, isStandalone: true, selector: "val-language-selector", inputs: { props: "props" }, outputs: { languageChange: "languageChange" }, ngImport: i0, template: `
6653
5518
  <val-popover-selector [props]="popoverProps" (selectionChange)="onLanguageChange($event)"> </val-popover-selector>
6654
5519
  `, isInline: true, styles: [":host{display:inline-block;width:auto}val-popover-selector .popover-selector-container{display:inline-block;width:auto}val-popover-selector .selector-trigger .trigger-text{display:inline-flex;align-items:center;gap:8px;font-weight:700}val-popover-selector .selector-trigger .trigger-text .flag-emoji{font-size:1.2em;line-height:1;filter:drop-shadow(0 1px 2px rgba(0,0,0,.1));transition:transform .2s ease}val-popover-selector .selector-trigger.has-flag .trigger-text{letter-spacing:.025em}val-popover-selector .selector-trigger:hover:not([disabled]) .trigger-text .flag-emoji{transform:scale(1.1)}val-popover-selector .option-content{gap:10px;padding:8px 0}val-popover-selector .option-content .flag-emoji{font-size:1.1em;filter:drop-shadow(0 1px 2px rgba(0,0,0,.08))}val-popover-selector .option-content span{font-weight:600;letter-spacing:.01em}.language-flag{font-size:1.2em;margin-right:6px;vertical-align:middle;line-height:1;filter:drop-shadow(0 1px 3px rgba(0,0,0,.1));transition:all .2s ease}@media (max-width: 768px){val-popover-selector .selector-trigger .trigger-text{font-size:13px;gap:6px}val-popover-selector .selector-trigger .trigger-text .flag-emoji{font-size:1.1em}}val-popover-selector .selector-trigger:hover:not([disabled]) .trigger-text .flag-emoji{transform:scale(1.1) rotate(3deg);transition:transform .25s cubic-bezier(.4,0,.2,1)}val-popover-selector .selector-trigger:active .trigger-text .flag-emoji{transform:scale(1.05)}val-popover-selector .language-changing .flag-emoji{animation:languageSwitch .4s ease-in-out}@keyframes languageSwitch{0%{transform:scale(1)}50%{transform:scale(1.15) rotate(8deg)}to{transform:scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: PopoverSelectorComponent, selector: "val-popover-selector", inputs: ["props"], outputs: ["selectionChange"] }] }); }
@@ -6658,12 +5523,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6658
5523
  args: [{ selector: 'val-language-selector', standalone: true, imports: [CommonModule, PopoverSelectorComponent], template: `
6659
5524
  <val-popover-selector [props]="popoverProps" (selectionChange)="onLanguageChange($event)"> </val-popover-selector>
6660
5525
  `, styles: [":host{display:inline-block;width:auto}val-popover-selector .popover-selector-container{display:inline-block;width:auto}val-popover-selector .selector-trigger .trigger-text{display:inline-flex;align-items:center;gap:8px;font-weight:700}val-popover-selector .selector-trigger .trigger-text .flag-emoji{font-size:1.2em;line-height:1;filter:drop-shadow(0 1px 2px rgba(0,0,0,.1));transition:transform .2s ease}val-popover-selector .selector-trigger.has-flag .trigger-text{letter-spacing:.025em}val-popover-selector .selector-trigger:hover:not([disabled]) .trigger-text .flag-emoji{transform:scale(1.1)}val-popover-selector .option-content{gap:10px;padding:8px 0}val-popover-selector .option-content .flag-emoji{font-size:1.1em;filter:drop-shadow(0 1px 2px rgba(0,0,0,.08))}val-popover-selector .option-content span{font-weight:600;letter-spacing:.01em}.language-flag{font-size:1.2em;margin-right:6px;vertical-align:middle;line-height:1;filter:drop-shadow(0 1px 3px rgba(0,0,0,.1));transition:all .2s ease}@media (max-width: 768px){val-popover-selector .selector-trigger .trigger-text{font-size:13px;gap:6px}val-popover-selector .selector-trigger .trigger-text .flag-emoji{font-size:1.1em}}val-popover-selector .selector-trigger:hover:not([disabled]) .trigger-text .flag-emoji{transform:scale(1.1) rotate(3deg);transition:transform .25s cubic-bezier(.4,0,.2,1)}val-popover-selector .selector-trigger:active .trigger-text .flag-emoji{transform:scale(1.05)}val-popover-selector .language-changing .flag-emoji{animation:languageSwitch .4s ease-in-out}@keyframes languageSwitch{0%{transform:scale(1)}50%{transform:scale(1.15) rotate(8deg)}to{transform:scale(1)}}\n"] }]
6661
- }], ctorParameters: () => [{ type: LangService }], propDecorators: { props: [{
5526
+ }], ctorParameters: () => [], propDecorators: { props: [{
6662
5527
  type: Input
6663
5528
  }], languageChange: [{
6664
5529
  type: Output
6665
5530
  }] } });
6666
5531
 
5532
+ const LANG = 'LANG';
5533
+ const THEME = 'THEME';
5534
+
5535
+ /**
5536
+ * Utility service for interacting with browser localStorage in a type-safe way.
5537
+ * Provides static methods for setting, getting, removing, and clearing items.
5538
+ */
5539
+ class LocalStorageService {
5540
+ /**
5541
+ * Stores a value in localStorage under the given reference key.
5542
+ * @param reference The key to store the value under
5543
+ * @param value The value to store
5544
+ */
5545
+ static set(reference, value) {
5546
+ localStorage.setItem(reference, JSON.stringify(value));
5547
+ }
5548
+ /**
5549
+ * Retrieves a value from localStorage by key.
5550
+ * @param reference The key to retrieve
5551
+ * @returns The parsed value
5552
+ */
5553
+ static get(reference) {
5554
+ const value = localStorage.getItem(reference);
5555
+ return JSON.parse(value);
5556
+ }
5557
+ /**
5558
+ * Removes an item from localStorage by key.
5559
+ * @param reference The key to remove
5560
+ */
5561
+ static remove(reference) {
5562
+ localStorage.removeItem(reference);
5563
+ }
5564
+ /**
5565
+ * Clears all items from localStorage.
5566
+ */
5567
+ static clear() {
5568
+ localStorage.clear();
5569
+ }
5570
+ }
5571
+
6667
5572
  /**
6668
5573
  * Service for managing application themes (light, dark, auto).
6669
5574
  * Handles user preferences, system theme detection, and theme toggling.
@@ -7673,15 +6578,10 @@ class RangeInputComponent {
7673
6578
  */
7674
6579
  this.rangeChange = new EventEmitter();
7675
6580
  this.states = ComponentStates;
7676
- this.displayLabel = '';
7677
- this.langService = inject(LangService);
7678
6581
  this.defaultPinFormatter = (value) => `${value}`;
7679
6582
  }
7680
- ngOnInit() {
7681
- this.setupLabel();
7682
- }
7683
- ngOnDestroy() {
7684
- this.subscription?.unsubscribe();
6583
+ get displayLabel() {
6584
+ return this.props.label || this.props.contentFallback || '';
7685
6585
  }
7686
6586
  onRangeChange(event) {
7687
6587
  const value = event.detail.value;
@@ -7696,21 +6596,6 @@ class RangeInputComponent {
7696
6596
  }
7697
6597
  }
7698
6598
  }
7699
- setupLabel() {
7700
- if (this.props.label) {
7701
- this.displayLabel = this.props.label;
7702
- }
7703
- else if (this.props.contentKey && this.props.contentClass) {
7704
- this.subscription = this.langService
7705
- .getContent(this.props.contentClass, this.props.contentKey, this.props.contentFallback)
7706
- .subscribe((content) => {
7707
- this.displayLabel = content;
7708
- });
7709
- }
7710
- else if (this.props.contentFallback) {
7711
- this.displayLabel = this.props.contentFallback;
7712
- }
7713
- }
7714
6599
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RangeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7715
6600
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RangeInputComponent, isStandalone: true, selector: "val-range-input", inputs: { props: "props" }, outputs: { rangeChange: "rangeChange" }, ngImport: i0, template: `
7716
6601
  @if (displayLabel) {
@@ -7859,41 +6744,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
7859
6744
  * val-select-input
7860
6745
  *
7861
6746
  * A select/dropdown input integrated with Angular forms, using Ionic's select component.
7862
- * Supports i18n for modal buttons and header text via GlobalContent.
7863
- *
7864
- * @example Basic usage:
7865
- * <val-select-input [props]="{ control: myControl, label: 'Choose', options: [{ id: '1', name: 'Option 1' }] }"></val-select-input>
7866
6747
  *
7867
- * @example With custom modal texts:
6748
+ * @example
7868
6749
  * <val-select-input [props]="{
7869
6750
  * control: myControl,
7870
- * label: 'Choose',
7871
- * options: [...],
7872
- * modalHeader: 'Select an option',
7873
- * cancelText: 'Cancel',
7874
- * okText: 'Confirm'
6751
+ * label: 'Seleccionar',
6752
+ * options: [{ id: '1', name: 'Opción 1' }],
6753
+ * cancelText: 'Cancelar',
6754
+ * okText: 'Aceptar'
7875
6755
  * }"></val-select-input>
7876
6756
  *
7877
6757
  * @input props: InputMetadata - Configuration for the select input (form control, label, options, etc.)
7878
6758
  */
7879
6759
  class SearchSelectorComponent {
7880
- constructor() {
7881
- this.langService = inject(LangService);
7882
- }
7883
6760
  ngOnInit() {
7884
6761
  if (this.props?.withDefault || this.props?.value) {
7885
6762
  applyDefaultValueToControl(this.props);
7886
6763
  }
7887
6764
  // Set modal header from props or use label as fallback
7888
- const headerText = this.props.modalHeader || this.props.label || this.langService.getText('_global', 'selectOption');
6765
+ const headerText = this.props.modalHeader || this.props.label || 'Seleccionar opción';
7889
6766
  this.customModalOptions = {
7890
6767
  header: headerText,
7891
6768
  breakpoints: [0, 0.6],
7892
6769
  initialBreakpoint: 0.6,
7893
6770
  };
7894
- // Set button texts from props or use i18n defaults
7895
- this.cancelText = this.props.cancelText || this.langService.getText('_global', 'cancel');
7896
- this.okText = this.props.okText || this.langService.getText('_global', 'ok');
6771
+ // Set button texts from props or use defaults
6772
+ this.cancelText = this.props.cancelText || 'Cancelar';
6773
+ this.okText = this.props.okText || 'Aceptar';
7897
6774
  }
7898
6775
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SearchSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7899
6776
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SearchSelectorComponent, isStandalone: true, selector: "val-select-input", inputs: { props: "props" }, ngImport: i0, template: `
@@ -7957,10 +6834,11 @@ const replaceSpecialChars = (text) => text.normalize('NFD').replace(/[\u0300-\u0
7957
6834
  */
7958
6835
  class SelectSearchComponent {
7959
6836
  constructor() {
6837
+ this.label = 'Seleccionar';
7960
6838
  this.labelProperty = 'name';
7961
6839
  this.valueProperty = 'id';
7962
6840
  this.multiple = false;
7963
- this.langService = inject(LangService);
6841
+ this.placeholder = 'Seleccione una opción';
7964
6842
  this.icon = inject(IconService);
7965
6843
  this.changeDetector = inject(ChangeDetectorRef);
7966
6844
  this.searchTerm = '';
@@ -7969,8 +6847,6 @@ class SelectSearchComponent {
7969
6847
  this.displayValue = '';
7970
6848
  this.previousOptions = [];
7971
6849
  this.isProcessingChanges = false;
7972
- this.label = this.langService.getText('_global', 'select', 'Seleccionar');
7973
- this.placeholder = this.langService.getText('_global', 'selectOption', 'Seleccione una opción');
7974
6850
  }
7975
6851
  ngOnInit() {
7976
6852
  this.applyDefaultValue();
@@ -8302,7 +7178,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8302
7178
  </ng-template>
8303
7179
  </ion-modal>
8304
7180
  `, styles: ["ion-header{padding:8px 8px 0}\n"] }]
8305
- }], ctorParameters: () => [], propDecorators: { modal: [{
7181
+ }], propDecorators: { modal: [{
8306
7182
  type: ViewChild,
8307
7183
  args: ['modal']
8308
7184
  }], label: [{
@@ -8356,43 +7232,13 @@ class SegmentControlComponent {
8356
7232
  */
8357
7233
  this.segmentChange = new EventEmitter();
8358
7234
  this.states = ComponentStates;
8359
- this.optionLabels = new Map();
8360
- this.langService = inject(LangService);
8361
- this.subscriptions = [];
8362
- }
8363
- ngOnInit() {
8364
- this.setupOptionLabels();
8365
- }
8366
- ngOnDestroy() {
8367
- this.subscriptions.forEach((sub) => sub.unsubscribe());
8368
7235
  }
8369
7236
  onSegmentChange(event) {
8370
7237
  const value = event.detail.value;
8371
7238
  this.segmentChange.emit(value);
8372
7239
  }
8373
7240
  getOptionLabel(option) {
8374
- if (option.label) {
8375
- return option.label;
8376
- }
8377
- return this.optionLabels.get(option.value) || option.contentFallback || '';
8378
- }
8379
- setupOptionLabels() {
8380
- this.props.options.forEach((option) => {
8381
- if (option.label) {
8382
- this.optionLabels.set(option.value, option.label);
8383
- }
8384
- else if (option.contentKey && option.contentClass) {
8385
- const sub = this.langService
8386
- .getContent(option.contentClass, option.contentKey, option.contentFallback)
8387
- .subscribe((content) => {
8388
- this.optionLabels.set(option.value, content);
8389
- });
8390
- this.subscriptions.push(sub);
8391
- }
8392
- else if (option.contentFallback) {
8393
- this.optionLabels.set(option.value, option.contentFallback);
8394
- }
8395
- });
7241
+ return option.label || option.contentFallback || '';
8396
7242
  }
8397
7243
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SegmentControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8398
7244
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SegmentControlComponent, isStandalone: true, selector: "val-segment-control", inputs: { props: "props" }, outputs: { segmentChange: "segmentChange" }, ngImport: i0, template: `
@@ -8500,52 +7346,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8500
7346
  * val-toggle-input
8501
7347
  *
8502
7348
  * A toggle/switch input for boolean values, integrated with Angular forms.
8503
- * Supports reactive content for labels.
8504
7349
  *
8505
7350
  * @example
8506
7351
  * <val-toggle-input [props]="{
8507
7352
  * control: myBooleanControl,
8508
- * label: 'Enable notifications',
7353
+ * label: 'Activar notificaciones',
8509
7354
  * color: 'primary',
8510
7355
  * labelPosition: 'end'
8511
7356
  * }"></val-toggle-input>
8512
7357
  *
8513
- * @example With reactive content
8514
- * <val-toggle-input [props]="{
8515
- * control: myControl,
8516
- * contentKey: 'enableNotifications',
8517
- * contentClass: 'SettingsComponent',
8518
- * contentFallback: 'Enable notifications'
8519
- * }"></val-toggle-input>
8520
- *
8521
7358
  * @input props: ToggleInputMetadata - Configuration for the toggle input
8522
7359
  */
8523
7360
  class ToggleInputComponent {
8524
7361
  constructor() {
8525
7362
  this.states = ComponentStates;
8526
- this.displayLabel = '';
8527
- this.langService = inject(LangService);
8528
- }
8529
- ngOnInit() {
8530
- this.setupLabel();
8531
- }
8532
- ngOnDestroy() {
8533
- this.subscription?.unsubscribe();
8534
7363
  }
8535
- setupLabel() {
8536
- if (this.props.label) {
8537
- this.displayLabel = this.props.label;
8538
- }
8539
- else if (this.props.contentKey && this.props.contentClass) {
8540
- this.subscription = this.langService
8541
- .getContent(this.props.contentClass, this.props.contentKey, this.props.contentFallback)
8542
- .subscribe((content) => {
8543
- this.displayLabel = content;
8544
- });
8545
- }
8546
- else if (this.props.contentFallback) {
8547
- this.displayLabel = this.props.contentFallback;
8548
- }
7364
+ getDisplayLabel() {
7365
+ return this.props.label || this.props.contentFallback || '';
8549
7366
  }
8550
7367
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ToggleInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8551
7368
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ToggleInputComponent, isStandalone: true, selector: "val-toggle-input", inputs: { props: "props" }, ngImport: i0, template: `
@@ -8556,7 +7373,7 @@ class ToggleInputComponent {
8556
7373
  [labelPlacement]="props.labelPosition || 'end'"
8557
7374
  [justify]="props.justify || 'start'"
8558
7375
  >
8559
- {{ displayLabel }}
7376
+ {{ getDisplayLabel() }}
8560
7377
  </ion-toggle>
8561
7378
  `, isInline: true, styles: [":host{display:block}ion-toggle{--handle-spacing: 3px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonToggle, selector: "ion-toggle", inputs: ["checked", "color", "disabled", "enableOnOffLabels", "errorText", "helperText", "justify", "labelPlacement", "mode", "name", "value"] }] }); }
8562
7379
  }
@@ -8570,7 +7387,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8570
7387
  [labelPlacement]="props.labelPosition || 'end'"
8571
7388
  [justify]="props.justify || 'start'"
8572
7389
  >
8573
- {{ displayLabel }}
7390
+ {{ getDisplayLabel() }}
8574
7391
  </ion-toggle>
8575
7392
  `, styles: [":host{display:block}ion-toggle{--handle-spacing: 3px}\n"] }]
8576
7393
  }], propDecorators: { props: [{
@@ -8581,7 +7398,6 @@ class CodeDisplayComponent {
8581
7398
  constructor(cdr) {
8582
7399
  this.cdr = cdr;
8583
7400
  this.toast = inject(ToastController);
8584
- this.langService = inject(LangService);
8585
7401
  this.selectedTab = 0;
8586
7402
  }
8587
7403
  ngOnChanges(changes) {
@@ -8609,8 +7425,7 @@ class CodeDisplayComponent {
8609
7425
  try {
8610
7426
  const code = this.props.tabs.length > 0 ? this.props.tabs[this.selectedTab]?.code : this.props.code;
8611
7427
  await Clipboard.write({ string: code || '' });
8612
- const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
8613
- this.presentToast(copiedMessage);
7428
+ this.presentToast('¡Copiado al portapapeles!');
8614
7429
  }
8615
7430
  catch (error) {
8616
7431
  console.error('Error al copiar al portapapeles:', error);
@@ -8740,15 +7555,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8740
7555
  class CommandDisplayComponent {
8741
7556
  constructor() {
8742
7557
  this.toast = inject(ToastController);
8743
- this.langService = inject(LangService);
8744
7558
  }
8745
7559
  async copyCommand() {
8746
7560
  if (this.props.text) {
8747
7561
  await Clipboard.write({
8748
7562
  string: this.props.text,
8749
7563
  });
8750
- const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
8751
- this.presentToast(copiedMessage);
7564
+ this.presentToast('¡Copiado al portapapeles!');
8752
7565
  }
8753
7566
  }
8754
7567
  async presentToast(message) {
@@ -8776,7 +7589,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8776
7589
  <ion-icon name="copy-outline" class="copy-icon" (click)="copyCommand()"></ion-icon>
8777
7590
  </div>
8778
7591
  `, 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"] }]
8779
- }], ctorParameters: () => [], propDecorators: { props: [{
7592
+ }], propDecorators: { props: [{
8780
7593
  type: Input
8781
7594
  }] } });
8782
7595
 
@@ -8825,7 +7638,6 @@ class PlainCodeBoxComponent {
8825
7638
  constructor() {
8826
7639
  this.toast = inject(ToastController);
8827
7640
  this.cdr = inject(ChangeDetectorRef);
8828
- this.langService = inject(LangService);
8829
7641
  this.props = { lines: [] };
8830
7642
  }
8831
7643
  ngOnChanges(changes) {
@@ -8848,8 +7660,7 @@ class PlainCodeBoxComponent {
8848
7660
  await Clipboard.write({
8849
7661
  string: fullCode,
8850
7662
  });
8851
- const copiedMessage = this.langService.getText('_global', 'copied', '¡Copiado al portapapeles!');
8852
- this.presentToast(copiedMessage);
7663
+ this.presentToast('¡Copiado al portapapeles!');
8853
7664
  }
8854
7665
  }
8855
7666
  async presentToast(message) {
@@ -8883,7 +7694,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8883
7694
  </ng-container></code></pre>
8884
7695
  </div>
8885
7696
  `, styles: [".code-box-container{position:relative;background-color:#282c34;border-radius:16px;overflow:hidden;box-shadow:0 4px 15px #0009;margin:0}@media (prefers-color-scheme: light){.code-box-container{background-color:#fff;box-shadow:0 2px 4px #0000001a}}.copy-button{position:absolute;top:8px;right:8px;z-index:10;--padding-start: 2px;--padding-end: 2px;--padding-top: 2px;--padding-bottom: 2px;min-width:28px;min-height:28px;height:28px;width:28px;color:#61afef;background:#0006;border-radius:6px;box-shadow:0 1px 4px #0000000d;display:flex;align-items:center;justify-content:center;transition:background .2s ease,color .2s ease}.copy-button:hover{background:#00000080;color:#8cc4ff}.copy-button ion-icon{font-size:1.2em;margin:0}@media (prefers-color-scheme: light){.copy-button{color:var(--ion-color-primary, #007bff);background:#ffffffb3}.copy-button:hover{background:#ffffffe6;color:var(--ion-color-primary-tint, #3880ff)}}pre{margin:0;padding:0;background-color:transparent;min-width:100%;min-height:100%;white-space:pre-wrap;word-break:normal;font-family:Roboto Mono,monospace}code{font-family:Roboto Mono,monospace;font-size:.9em;line-height:1.6;display:block;white-space:inherit;word-break:inherit;color:#abb2bf;margin:0}@media (prefers-color-scheme: light){code{color:#333}}code .line-normal{color:#abb2bf}@media (prefers-color-scheme: light){code .line-normal{color:#333}}code .line-command{color:#c678dd}@media (prefers-color-scheme: light){code .line-command{color:var(--ion-color-primary, #3880ff)}}code .line-error{color:#e06c75}@media (prefers-color-scheme: light){code .line-error{color:var(--ion-color-danger, #eb445a)}}code .line-success{color:#98c379}@media (prefers-color-scheme: light){code .line-success{color:var(--ion-color-success, #2dd36f)}}code .token.comment{color:#5c6370}code .token.selector,code .token.string{color:#98c379}code .token.punctuation{color:#abb2bf}code .token.operator{color:#c678dd}code .token.boolean,code .token.number{color:#d19a66}code .token.function{color:#61afef}code .token.keyword{color:#c678dd}code .token.class-name{color:#e6c07b}code .token.tag{color:#e06c75}code .token.attr-name{color:#d19a66}code .token.attr-value{color:#98c379}code .token.property{color:#56b6c2}code .token.variable{color:#e06c75}@media (max-width: 600px){.code-box-container{border-radius:16px}.copy-button{top:6px;right:6px;min-width:24px;min-height:24px;height:24px;width:24px}.copy-button ion-icon{font-size:1em}pre{padding:0;margin:0}code{font-size:.8em;line-height:1.5;margin:0}}@media (min-width: 601px) and (max-width: 1024px){code{font-size:.9em}}@media (min-width: 1025px){code{font-size:1em}}\n"] }]
8886
- }], ctorParameters: () => [], propDecorators: { props: [{
7697
+ }], propDecorators: { props: [{
8887
7698
  type: Input
8888
7699
  }], codeBlock: [{
8889
7700
  type: ViewChild,
@@ -8897,74 +7708,29 @@ addIcons({ chevronDown, helpCircle, informationCircle, documentText });
8897
7708
  * An accordion component for collapsible content sections.
8898
7709
  * Ideal for FAQs, settings, and expandable content.
8899
7710
  *
8900
- * @example Basic usage
7711
+ * @example
8901
7712
  * <val-accordion [props]="{
8902
7713
  * items: [
8903
- * { value: 'faq1', header: 'What is this?', content: 'This is an accordion.' },
8904
- * { value: 'faq2', header: 'How does it work?', content: 'Click to expand.' }
7714
+ * { value: 'faq1', header: '¿Qué es esto?', content: 'Es un acordeón.' },
7715
+ * { value: 'faq2', header: '¿Cómo funciona?', content: 'Haz clic para expandir.' }
8905
7716
  * ]
8906
7717
  * }"></val-accordion>
8907
7718
  *
8908
- * @example Multiple open
8909
- * <val-accordion [props]="{
8910
- * items: [...],
8911
- * multiple: true,
8912
- * value: ['faq1', 'faq2']
8913
- * }"></val-accordion>
8914
- *
8915
7719
  * @input props: AccordionMetadata - Configuration for the accordion
8916
7720
  * @output accordionChange: string | string[] - Emits expanded value(s)
8917
7721
  */
8918
7722
  class AccordionComponent {
8919
7723
  constructor() {
8920
7724
  this.accordionChange = new EventEmitter();
8921
- this.langService = inject(LangService);
8922
- this.subscriptions = [];
8923
- this.headerLabels = new Map();
8924
- this.contentLabels = new Map();
8925
- }
8926
- ngOnInit() {
8927
- this.setupLabels();
8928
- }
8929
- ngOnDestroy() {
8930
- this.subscriptions.forEach((sub) => sub.unsubscribe());
8931
7725
  }
8932
7726
  onAccordionChange(event) {
8933
7727
  this.accordionChange.emit(event.detail.value);
8934
7728
  }
8935
7729
  getItemHeader(item) {
8936
- if (item.header)
8937
- return item.header;
8938
- return this.headerLabels.get(item.value) || item.headerFallback || '';
7730
+ return item.header || item.headerFallback || '';
8939
7731
  }
8940
7732
  getItemContent(item) {
8941
- if (item.content)
8942
- return item.content;
8943
- return this.contentLabels.get(item.value) || item.contentFallback || '';
8944
- }
8945
- setupLabels() {
8946
- this.props.items.forEach((item) => {
8947
- // Setup header
8948
- if (item.header) {
8949
- this.headerLabels.set(item.value, item.header);
8950
- }
8951
- else if (item.headerKey && item.contentClass) {
8952
- const sub = this.langService
8953
- .getContent(item.contentClass, item.headerKey, item.headerFallback)
8954
- .subscribe((content) => this.headerLabels.set(item.value, content));
8955
- this.subscriptions.push(sub);
8956
- }
8957
- // Setup content
8958
- if (item.content) {
8959
- this.contentLabels.set(item.value, item.content);
8960
- }
8961
- else if (item.contentKey && item.contentClass) {
8962
- const sub = this.langService
8963
- .getContent(item.contentClass, item.contentKey, item.contentFallback)
8964
- .subscribe((content) => this.contentLabels.set(item.value, content));
8965
- this.subscriptions.push(sub);
8966
- }
8967
- });
7733
+ return item.content || item.contentFallback || '';
8968
7734
  }
8969
7735
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8970
7736
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AccordionComponent, isStandalone: true, selector: "val-accordion", inputs: { props: "props" }, outputs: { accordionChange: "accordionChange" }, ngImport: i0, template: `
@@ -9027,41 +7793,23 @@ addIcons({ home, settings, person, search, heart, star, notifications, mail, cal
9027
7793
  * val-tabs
9028
7794
  *
9029
7795
  * A tab bar component for navigation between views.
9030
- * Can be positioned at top or bottom of the screen.
9031
7796
  *
9032
- * @example Basic usage
7797
+ * @example
9033
7798
  * <val-tabs [props]="{
9034
7799
  * tabs: [
9035
- * { value: 'home', label: 'Home', icon: 'home' },
9036
- * { value: 'search', label: 'Search', icon: 'search' },
9037
- * { value: 'profile', label: 'Profile', icon: 'person' }
7800
+ * { value: 'home', label: 'Inicio', icon: 'home' },
7801
+ * { value: 'search', label: 'Buscar', icon: 'search' },
7802
+ * { value: 'profile', label: 'Perfil', icon: 'person' }
9038
7803
  * ],
9039
7804
  * selectedTab: 'home'
9040
7805
  * }" (tabChange)="onTabChange($event)"></val-tabs>
9041
7806
  *
9042
- * @example With badges
9043
- * <val-tabs [props]="{
9044
- * tabs: [
9045
- * { value: 'inbox', label: 'Inbox', icon: 'mail', badge: 5 },
9046
- * { value: 'notifications', label: 'Alerts', icon: 'notifications', badge: '99+' }
9047
- * ]
9048
- * }"></val-tabs>
9049
- *
9050
7807
  * @input props: TabsMetadata - Configuration for the tabs
9051
7808
  * @output tabChange: TabMetadata - Emits when a tab is selected
9052
7809
  */
9053
7810
  class TabsComponent {
9054
7811
  constructor() {
9055
7812
  this.tabChange = new EventEmitter();
9056
- this.langService = inject(LangService);
9057
- this.subscriptions = [];
9058
- this.tabLabels = new Map();
9059
- }
9060
- ngOnInit() {
9061
- this.setupLabels();
9062
- }
9063
- ngOnDestroy() {
9064
- this.subscriptions.forEach((sub) => sub.unsubscribe());
9065
7813
  }
9066
7814
  onTabClick(tab) {
9067
7815
  if (!tab.disabled) {
@@ -9069,22 +7817,7 @@ class TabsComponent {
9069
7817
  }
9070
7818
  }
9071
7819
  getTabLabel(tab) {
9072
- if (tab.label)
9073
- return tab.label;
9074
- return this.tabLabels.get(tab.value) || tab.contentFallback || '';
9075
- }
9076
- setupLabels() {
9077
- this.props.tabs.forEach((tab) => {
9078
- if (tab.label) {
9079
- this.tabLabels.set(tab.value, tab.label);
9080
- }
9081
- else if (tab.contentKey && tab.contentClass) {
9082
- const sub = this.langService
9083
- .getContent(tab.contentClass, tab.contentKey, tab.contentFallback)
9084
- .subscribe((content) => this.tabLabels.set(tab.value, content));
9085
- this.subscriptions.push(sub);
9086
- }
9087
- });
7820
+ return tab.label || tab.contentFallback || '';
9088
7821
  }
9089
7822
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9090
7823
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TabsComponent, isStandalone: true, selector: "val-tabs", inputs: { props: "props" }, outputs: { tabChange: "tabChange" }, ngImport: i0, template: `
@@ -9155,25 +7888,16 @@ addIcons({ chevronForward, home, ellipsisHorizontal });
9155
7888
  * val-breadcrumb
9156
7889
  *
9157
7890
  * A breadcrumb navigation component for hierarchical navigation.
9158
- * Supports collapsing items when there are too many.
9159
7891
  *
9160
- * @example Basic usage
7892
+ * @example
9161
7893
  * <val-breadcrumb [props]="{
9162
7894
  * items: [
9163
- * { label: 'Home', href: '/', icon: 'home' },
9164
- * { label: 'Products', href: '/products' },
9165
- * { label: 'Electronics', href: '/products/electronics' },
9166
- * { label: 'Phones', active: true }
7895
+ * { label: 'Inicio', href: '/', icon: 'home' },
7896
+ * { label: 'Productos', href: '/products' },
7897
+ * { label: 'Electrónica', active: true }
9167
7898
  * ]
9168
7899
  * }"></val-breadcrumb>
9169
7900
  *
9170
- * @example With max items (collapse)
9171
- * <val-breadcrumb [props]="{
9172
- * items: [...],
9173
- * maxItems: 4,
9174
- * separatorIcon: 'chevron-forward'
9175
- * }"></val-breadcrumb>
9176
- *
9177
7901
  * @input props: BreadcrumbMetadata - Configuration for the breadcrumb
9178
7902
  * @output breadcrumbClick: { item: BreadcrumbItemMetadata, index: number }
9179
7903
  */
@@ -9181,15 +7905,6 @@ class BreadcrumbComponent {
9181
7905
  constructor() {
9182
7906
  this.breadcrumbClick = new EventEmitter();
9183
7907
  this.collapsedClick = new EventEmitter();
9184
- this.langService = inject(LangService);
9185
- this.subscriptions = [];
9186
- this.itemLabels = new Map();
9187
- }
9188
- ngOnInit() {
9189
- this.setupLabels();
9190
- }
9191
- ngOnDestroy() {
9192
- this.subscriptions.forEach((sub) => sub.unsubscribe());
9193
7908
  }
9194
7909
  onBreadcrumbClick(event, item, index) {
9195
7910
  if (!item.disabled && !item.active) {
@@ -9200,23 +7915,7 @@ class BreadcrumbComponent {
9200
7915
  this.collapsedClick.emit(event);
9201
7916
  }
9202
7917
  getItemLabel(item) {
9203
- const index = this.props.items.indexOf(item);
9204
- if (item.label)
9205
- return item.label;
9206
- return this.itemLabels.get(index) || item.contentFallback || '';
9207
- }
9208
- setupLabels() {
9209
- this.props.items.forEach((item, index) => {
9210
- if (item.label) {
9211
- this.itemLabels.set(index, item.label);
9212
- }
9213
- else if (item.contentKey && item.contentClass) {
9214
- const sub = this.langService
9215
- .getContent(item.contentClass, item.contentKey, item.contentFallback)
9216
- .subscribe((content) => this.itemLabels.set(index, content));
9217
- this.subscriptions.push(sub);
9218
- }
9219
- });
7918
+ return item.label || item.contentFallback || '';
9220
7919
  }
9221
7920
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9222
7921
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: BreadcrumbComponent, isStandalone: true, selector: "val-breadcrumb", inputs: { props: "props" }, outputs: { breadcrumbClick: "breadcrumbClick", collapsedClick: "collapsedClick" }, ngImport: i0, template: `
@@ -9561,15 +8260,6 @@ addIcons({ checkmark, close, ellipse });
9561
8260
  class StepperComponent {
9562
8261
  constructor() {
9563
8262
  this.stepChange = new EventEmitter();
9564
- this.langService = inject(LangService);
9565
- this.subscriptions = [];
9566
- this.stepLabels = new Map();
9567
- }
9568
- ngOnInit() {
9569
- this.setupLabels();
9570
- }
9571
- ngOnDestroy() {
9572
- this.subscriptions.forEach((sub) => sub.unsubscribe());
9573
8263
  }
9574
8264
  getCurrentIndex() {
9575
8265
  if (this.props.currentIndex !== undefined) {
@@ -9626,22 +8316,7 @@ class StepperComponent {
9626
8316
  });
9627
8317
  }
9628
8318
  getStepLabel(step) {
9629
- if (step.label)
9630
- return step.label;
9631
- return this.stepLabels.get(step.value) || step.contentFallback || '';
9632
- }
9633
- setupLabels() {
9634
- this.props.steps.forEach((step) => {
9635
- if (step.label) {
9636
- this.stepLabels.set(step.value, step.label);
9637
- }
9638
- else if (step.contentKey && step.contentClass) {
9639
- const sub = this.langService
9640
- .getContent(step.contentClass, step.contentKey, step.contentFallback)
9641
- .subscribe((content) => this.stepLabels.set(step.value, content));
9642
- this.subscriptions.push(sub);
9643
- }
9644
- });
8319
+ return step.label || step.contentFallback || '';
9645
8320
  }
9646
8321
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9647
8322
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: StepperComponent, isStandalone: true, selector: "val-stepper", inputs: { props: "props" }, outputs: { stepChange: "stepChange" }, ngImport: i0, template: `
@@ -9796,15 +8471,6 @@ class ChipGroupComponent {
9796
8471
  this.selectionChange = new EventEmitter();
9797
8472
  this.chipRemove = new EventEmitter();
9798
8473
  this.chipClick = new EventEmitter();
9799
- this.langService = inject(LangService);
9800
- this.subscriptions = [];
9801
- this.chipLabels = new Map();
9802
- }
9803
- ngOnInit() {
9804
- this.setupLabels();
9805
- }
9806
- ngOnDestroy() {
9807
- this.subscriptions.forEach((sub) => sub.unsubscribe());
9808
8474
  }
9809
8475
  getChipColor(chip) {
9810
8476
  if (chip.selected && this.props.selectedColor) {
@@ -9813,9 +8479,7 @@ class ChipGroupComponent {
9813
8479
  return chip.color || this.props.color || 'primary';
9814
8480
  }
9815
8481
  getChipLabel(chip) {
9816
- if (chip.label)
9817
- return chip.label;
9818
- return this.chipLabels.get(chip.value) || chip.contentFallback || '';
8482
+ return chip.label || chip.contentFallback || '';
9819
8483
  }
9820
8484
  onChipClick(chip) {
9821
8485
  if (chip.disabled)
@@ -9853,19 +8517,6 @@ class ChipGroupComponent {
9853
8517
  values: this.props.multiple ? values : values[0],
9854
8518
  });
9855
8519
  }
9856
- setupLabels() {
9857
- this.props.chips.forEach((chip) => {
9858
- if (chip.label) {
9859
- this.chipLabels.set(chip.value, chip.label);
9860
- }
9861
- else if (chip.contentKey && chip.contentClass) {
9862
- const sub = this.langService
9863
- .getContent(chip.contentClass, chip.contentKey, chip.contentFallback)
9864
- .subscribe((content) => this.chipLabels.set(chip.value, content));
9865
- this.subscriptions.push(sub);
9866
- }
9867
- });
9868
- }
9869
8520
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChipGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9870
8521
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ChipGroupComponent, isStandalone: true, selector: "val-chip-group", inputs: { props: "props" }, outputs: { selectionChange: "selectionChange", chipRemove: "chipRemove", chipClick: "chipClick" }, ngImport: i0, template: `
9871
8522
  <div class="chip-group" [class.wrap]="props.wrap !== false">
@@ -10431,28 +9082,9 @@ class CommentComponent {
10431
9082
  this.loadMoreClick = new EventEmitter();
10432
9083
  this.collapseToggle = new EventEmitter();
10433
9084
  this.displayContent = '';
10434
- this.langSubscription = null;
10435
- this.langService = inject(LangService);
10436
9085
  }
10437
9086
  ngOnInit() {
10438
- this.updateDisplayContent();
10439
- if (this.props.contentKey && this.props.contentClass) {
10440
- this.langSubscription = this.langService.currentLang$.subscribe(() => {
10441
- this.updateDisplayContent();
10442
- });
10443
- }
10444
- }
10445
- ngOnDestroy() {
10446
- this.langSubscription?.unsubscribe();
10447
- }
10448
- updateDisplayContent() {
10449
- if (this.props.contentKey && this.props.contentClass) {
10450
- this.displayContent =
10451
- this.langService.getText(this.props.contentClass, this.props.contentKey, this.props.contentFallback || this.props.content);
10452
- }
10453
- else {
10454
- this.displayContent = this.props.content;
10455
- }
9087
+ this.displayContent = this.props.content || this.props.contentFallback || '';
10456
9088
  }
10457
9089
  getInitials(name) {
10458
9090
  return name
@@ -10528,16 +9160,10 @@ class CommentComponent {
10528
9160
  return 'var(--ion-color-medium)';
10529
9161
  }
10530
9162
  getActionLabel(action) {
10531
- if (action.contentKey && action.contentClass) {
10532
- return this.langService.getText(action.contentClass, action.contentKey, action.contentFallback || action.label);
10533
- }
10534
- return action.label;
9163
+ return action.label || action.contentFallback || '';
10535
9164
  }
10536
9165
  getMenuItemLabel(item) {
10537
- if (item.contentKey && item.contentClass) {
10538
- return this.langService.getText(item.contentClass, item.contentKey, item.contentFallback || item.label);
10539
- }
10540
- return item.label;
9166
+ return item.label || item.contentFallback || '';
10541
9167
  }
10542
9168
  hasChildren() {
10543
9169
  return !!(this.props.children && this.props.children.length > 0) ||
@@ -10990,9 +9616,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10990
9616
 
10991
9617
  class MultiSelectSearchComponent {
10992
9618
  constructor() {
9619
+ this.label = 'Seleccionar opciones';
10993
9620
  this.labelProperty = 'name';
10994
9621
  this.valueProperty = 'id';
10995
- this.langService = inject(LangService);
9622
+ this.placeholder = 'Seleccione opciones';
10996
9623
  this.icon = inject(IconService);
10997
9624
  this.changeDetector = inject(ChangeDetectorRef);
10998
9625
  this.searchTerm = '';
@@ -11001,8 +9628,6 @@ class MultiSelectSearchComponent {
11001
9628
  this.displayValue = '';
11002
9629
  this.previousOptions = [];
11003
9630
  this.isProcessingChanges = false;
11004
- this.label = this.langService.getText('_global', 'selectOptions', 'Seleccionar opciones');
11005
- this.placeholder = this.langService.getText('_global', 'selectOptions', 'Seleccione opciones');
11006
9631
  }
11007
9632
  ngOnInit() {
11008
9633
  this.applyDefaultValue();
@@ -11403,7 +10028,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11403
10028
  </ng-template>
11404
10029
  </ion-modal>
11405
10030
  `, styles: ["ion-header{padding:8px 8px 0}.actions-container{display:flex;justify-content:space-between;align-items:center}\n"] }]
11406
- }], ctorParameters: () => [], propDecorators: { modal: [{
10031
+ }], propDecorators: { modal: [{
11407
10032
  type: ViewChild,
11408
10033
  args: ['modal']
11409
10034
  }], label: [{
@@ -11605,8 +10230,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11605
10230
  class TextareaInputComponent {
11606
10231
  constructor() {
11607
10232
  this.states = ComponentStates;
11608
- this.langSubscription = null;
11609
- this.langService = inject(LangService);
11610
10233
  // Counter formatter for Ionic's built-in counter
11611
10234
  this.counterFormatter = (inputLength, maxLength) => {
11612
10235
  return `${inputLength}/${maxLength}`;
@@ -11620,36 +10243,14 @@ class TextareaInputComponent {
11620
10243
  this.props.control.setValue(defaultValue);
11621
10244
  }
11622
10245
  }
11623
- // Subscribe to language changes for reactive content
11624
- if (this.hasReactiveContent()) {
11625
- this.langSubscription = this.langService.currentLang$.subscribe(() => {
11626
- // Trigger change detection for labels
11627
- });
11628
- }
11629
- }
11630
- ngOnDestroy() {
11631
- this.langSubscription?.unsubscribe();
11632
- }
11633
- hasReactiveContent() {
11634
- return !!(this.props.contentClass &&
11635
- (this.props.labelContentKey || this.props.placeholderContentKey || this.props.hintContentKey));
11636
10246
  }
11637
10247
  getLabel() {
11638
- if (this.props.labelContentKey && this.props.contentClass) {
11639
- return this.langService.getText(this.props.contentClass, this.props.labelContentKey, this.props.label || '');
11640
- }
11641
10248
  return this.props.label || '';
11642
10249
  }
11643
10250
  getPlaceholder() {
11644
- if (this.props.placeholderContentKey && this.props.contentClass) {
11645
- return this.langService.getText(this.props.contentClass, this.props.placeholderContentKey, this.props.placeholder || '');
11646
- }
11647
10251
  return this.props.placeholder || '';
11648
10252
  }
11649
10253
  getHint() {
11650
- if (this.props.hintContentKey && this.props.contentClass) {
11651
- return this.langService.getText(this.props.contentClass, this.props.hintContentKey, this.props.hint || '');
11652
- }
11653
10254
  return this.props.hint || '';
11654
10255
  }
11655
10256
  get hasError() {
@@ -11821,9 +10422,7 @@ class PhoneInputComponent {
11821
10422
  this.states = ComponentStates;
11822
10423
  this.internalCountryControl = new FormControl('');
11823
10424
  this.internalNumberControl = new FormControl('');
11824
- this.langSubscription = null;
11825
10425
  this.valueSubscription = null;
11826
- this.langService = inject(LangService);
11827
10426
  this.isInternalUpdate = false;
11828
10427
  }
11829
10428
  ngOnInit() {
@@ -11847,13 +10446,8 @@ class PhoneInputComponent {
11847
10446
  this.parsePhoneNumber(value);
11848
10447
  }
11849
10448
  });
11850
- // Subscribe to language changes
11851
- if (this.hasReactiveContent()) {
11852
- this.langSubscription = this.langService.currentLang$.subscribe(() => { });
11853
- }
11854
10449
  }
11855
10450
  ngOnDestroy() {
11856
- this.langSubscription?.unsubscribe();
11857
10451
  this.valueSubscription?.unsubscribe();
11858
10452
  }
11859
10453
  parsePhoneNumber(value) {
@@ -11871,20 +10465,10 @@ class PhoneInputComponent {
11871
10465
  // If no country code found, just set the number
11872
10466
  this.internalNumberControl.setValue(value);
11873
10467
  }
11874
- hasReactiveContent() {
11875
- return !!(this.props.contentClass &&
11876
- (this.props.labelContentKey || this.props.placeholderContentKey || this.props.hintContentKey));
11877
- }
11878
10468
  getLabel() {
11879
- if (this.props.labelContentKey && this.props.contentClass) {
11880
- return this.langService.getText(this.props.contentClass, this.props.labelContentKey, this.props.label || '');
11881
- }
11882
10469
  return this.props.label || '';
11883
10470
  }
11884
10471
  getPlaceholder() {
11885
- if (this.props.placeholderContentKey && this.props.contentClass) {
11886
- return this.langService.getText(this.props.contentClass, this.props.placeholderContentKey, this.props.placeholder || '');
11887
- }
11888
10472
  // Use format from selected country if available
11889
10473
  const country = this.getSelectedCountry();
11890
10474
  if (country?.format && !this.props.placeholder) {
@@ -11893,9 +10477,6 @@ class PhoneInputComponent {
11893
10477
  return this.props.placeholder || '';
11894
10478
  }
11895
10479
  getHint() {
11896
- if (this.props.hintContentKey && this.props.contentClass) {
11897
- return this.langService.getText(this.props.contentClass, this.props.hintContentKey, this.props.hint || '');
11898
- }
11899
10480
  return this.props.hint || '';
11900
10481
  }
11901
10482
  getCountryList() {
@@ -12165,9 +10746,7 @@ class CurrencyInputComponent {
12165
10746
  this.states = ComponentStates;
12166
10747
  this.displayControl = new FormControl('');
12167
10748
  this.currencyControl = new FormControl('');
12168
- this.langSubscription = null;
12169
10749
  this.valueSubscription = null;
12170
- this.langService = inject(LangService);
12171
10750
  this.isFocused = false;
12172
10751
  }
12173
10752
  ngOnInit() {
@@ -12184,35 +10763,17 @@ class CurrencyInputComponent {
12184
10763
  this.displayControl.setValue(this.formatValue(value));
12185
10764
  }
12186
10765
  });
12187
- // Subscribe to language changes
12188
- if (this.hasReactiveContent()) {
12189
- this.langSubscription = this.langService.currentLang$.subscribe(() => { });
12190
- }
12191
10766
  }
12192
10767
  ngOnDestroy() {
12193
- this.langSubscription?.unsubscribe();
12194
10768
  this.valueSubscription?.unsubscribe();
12195
10769
  }
12196
- hasReactiveContent() {
12197
- return !!(this.props.contentClass &&
12198
- (this.props.labelContentKey || this.props.placeholderContentKey || this.props.hintContentKey));
12199
- }
12200
10770
  getLabel() {
12201
- if (this.props.labelContentKey && this.props.contentClass) {
12202
- return this.langService.getText(this.props.contentClass, this.props.labelContentKey, this.props.label || '');
12203
- }
12204
10771
  return this.props.label || '';
12205
10772
  }
12206
10773
  getPlaceholder() {
12207
- if (this.props.placeholderContentKey && this.props.contentClass) {
12208
- return this.langService.getText(this.props.contentClass, this.props.placeholderContentKey, this.props.placeholder || '');
12209
- }
12210
10774
  return this.props.placeholder || this.getDefaultPlaceholder();
12211
10775
  }
12212
10776
  getHint() {
12213
- if (this.props.hintContentKey && this.props.contentClass) {
12214
- return this.langService.getText(this.props.contentClass, this.props.hintContentKey, this.props.hint || '');
12215
- }
12216
10777
  return this.props.hint || '';
12217
10778
  }
12218
10779
  getDefaultPlaceholder() {
@@ -12528,9 +11089,7 @@ class DateRangeInputComponent {
12528
11089
  this.startDatetimeId = `start-datetime-${Math.random().toString(36).substr(2, 9)}`;
12529
11090
  this.endDatetimeId = `end-datetime-${Math.random().toString(36).substr(2, 9)}`;
12530
11091
  this.showDayCount = true;
12531
- this.langSubscription = null;
12532
11092
  this.valueSubscription = null;
12533
- this.langService = inject(LangService);
12534
11093
  }
12535
11094
  ngOnInit() {
12536
11095
  // Use provided controls or internal ones
@@ -12561,44 +11120,20 @@ class DateRangeInputComponent {
12561
11120
  }
12562
11121
  }
12563
11122
  });
12564
- // Subscribe to language changes
12565
- if (this.hasReactiveContent()) {
12566
- this.langSubscription = this.langService.currentLang$.subscribe(() => { });
12567
- }
12568
11123
  }
12569
11124
  ngOnDestroy() {
12570
- this.langSubscription?.unsubscribe();
12571
11125
  this.valueSubscription?.unsubscribe();
12572
11126
  }
12573
- hasReactiveContent() {
12574
- return !!(this.props.contentClass &&
12575
- (this.props.labelContentKey ||
12576
- this.props.startLabelContentKey ||
12577
- this.props.endLabelContentKey ||
12578
- this.props.hintContentKey));
12579
- }
12580
11127
  getLabel() {
12581
- if (this.props.labelContentKey && this.props.contentClass) {
12582
- return this.langService.getText(this.props.contentClass, this.props.labelContentKey, this.props.label || '');
12583
- }
12584
11128
  return this.props.label || '';
12585
11129
  }
12586
11130
  getStartLabel() {
12587
- if (this.props.startLabelContentKey && this.props.contentClass) {
12588
- return this.langService.getText(this.props.contentClass, this.props.startLabelContentKey, this.props.startLabel || '');
12589
- }
12590
11131
  return this.props.startLabel || '';
12591
11132
  }
12592
11133
  getEndLabel() {
12593
- if (this.props.endLabelContentKey && this.props.contentClass) {
12594
- return this.langService.getText(this.props.contentClass, this.props.endLabelContentKey, this.props.endLabel || '');
12595
- }
12596
11134
  return this.props.endLabel || '';
12597
11135
  }
12598
11136
  getHint() {
12599
- if (this.props.hintContentKey && this.props.contentClass) {
12600
- return this.langService.getText(this.props.contentClass, this.props.hintContentKey, this.props.hint || '');
12601
- }
12602
11137
  return this.props.hint || '';
12603
11138
  }
12604
11139
  getMinDate() {
@@ -12952,7 +11487,6 @@ class NumberStepperComponent {
12952
11487
  this.valueChange = new EventEmitter();
12953
11488
  this.states = ComponentStates;
12954
11489
  this.valueSubscription = null;
12955
- this.langService = inject(LangService);
12956
11490
  }
12957
11491
  ngOnInit() {
12958
11492
  // Ensure initial value is within bounds
@@ -13029,15 +11563,9 @@ class NumberStepperComponent {
13029
11563
  });
13030
11564
  }
13031
11565
  getLabel() {
13032
- if (this.props.labelContentKey && this.props.contentClass) {
13033
- return this.langService.getText(this.props.contentClass, this.props.labelContentKey, this.props.label || '');
13034
- }
13035
11566
  return this.props.label || '';
13036
11567
  }
13037
11568
  getUnitLabel() {
13038
- if (this.props.unitLabelContentKey && this.props.contentClass) {
13039
- return this.langService.getText(this.props.contentClass, this.props.unitLabelContentKey, this.currentValue === 1 ? this.props.unitLabelSingular || this.props.unitLabel || '' : this.props.unitLabel || '');
13040
- }
13041
11569
  if (this.currentValue === 1 && this.props.unitLabelSingular) {
13042
11570
  return this.props.unitLabelSingular;
13043
11571
  }
@@ -13317,7 +11845,6 @@ class TicketGridComponent {
13317
11845
  this.selectedTickets = [];
13318
11846
  this.searchTerm = '';
13319
11847
  this.highlightedNumbers = [];
13320
- this.langService = inject(LangService);
13321
11848
  }
13322
11849
  ngOnInit() {
13323
11850
  this.buildTickets();
@@ -13531,15 +12058,9 @@ class TicketGridComponent {
13531
12058
  return `Boleto ${this.formatNumber(ticket.number)}, ${statusLabel}`;
13532
12059
  }
13533
12060
  getSearchPlaceholder() {
13534
- if (this.props.searchPlaceholderContentKey && this.props.contentClass) {
13535
- return this.langService.getText(this.props.contentClass, this.props.searchPlaceholderContentKey, this.props.searchPlaceholder || 'Buscar número...');
13536
- }
13537
12061
  return this.props.searchPlaceholder || 'Buscar número...';
13538
12062
  }
13539
12063
  getRandomSelectLabel() {
13540
- if (this.props.randomSelectLabelContentKey && this.props.contentClass) {
13541
- return this.langService.getText(this.props.contentClass, this.props.randomSelectLabelContentKey, this.props.randomSelectLabel || 'Aleatorio');
13542
- }
13543
12064
  return this.props.randomSelectLabel || 'Aleatorio';
13544
12065
  }
13545
12066
  getColor() {
@@ -13909,7 +12430,6 @@ class ShareButtonsComponent {
13909
12430
  constructor() {
13910
12431
  this.shareComplete = new EventEmitter();
13911
12432
  this.toastController = inject(ToastController$1);
13912
- this.langService = inject(LangService);
13913
12433
  }
13914
12434
  getButtons() {
13915
12435
  if (this.props.buttons?.length) {
@@ -14023,9 +12543,6 @@ class ShareButtonsComponent {
14023
12543
  }
14024
12544
  }
14025
12545
  getCopySuccessMessage() {
14026
- if (this.props.copySuccessMessageContentKey && this.props.contentClass) {
14027
- return this.langService.getText(this.props.contentClass, this.props.copySuccessMessageContentKey, this.props.copySuccessMessage || '¡Enlace copiado!');
14028
- }
14029
12546
  return this.props.copySuccessMessage || '¡Enlace copiado!';
14030
12547
  }
14031
12548
  isNativeShareSupported() {
@@ -14174,7 +12691,6 @@ class WinnerDisplayComponent {
14174
12691
  this.confettiPieces = Array.from({ length: 50 }, (_, i) => i);
14175
12692
  this.revealTimeout = null;
14176
12693
  this.animationTimeout = null;
14177
- this.langService = inject(LangService);
14178
12694
  this.elementRef = inject(ElementRef);
14179
12695
  }
14180
12696
  ngOnInit() {
@@ -14244,21 +12760,12 @@ class WinnerDisplayComponent {
14244
12760
  return `${(index * 37) % 360}deg`;
14245
12761
  }
14246
12762
  getWinnerLabel() {
14247
- if (this.props.winnerLabelContentKey && this.props.contentClass) {
14248
- return this.langService.getText(this.props.contentClass, this.props.winnerLabelContentKey, this.props.winnerLabel || DEFAULT_WINNER_LABELS.winner);
14249
- }
14250
12763
  return this.props.winnerLabel || DEFAULT_WINNER_LABELS.winner;
14251
12764
  }
14252
12765
  getTicketLabel() {
14253
- if (this.props.ticketLabelContentKey && this.props.contentClass) {
14254
- return this.langService.getText(this.props.contentClass, this.props.ticketLabelContentKey, this.props.ticketLabel || DEFAULT_WINNER_LABELS.ticket);
14255
- }
14256
12766
  return this.props.ticketLabel || DEFAULT_WINNER_LABELS.ticket;
14257
12767
  }
14258
12768
  getPrizeLabel() {
14259
- if (this.props.prizeLabelContentKey && this.props.contentClass) {
14260
- return this.langService.getText(this.props.contentClass, this.props.prizeLabelContentKey, this.props.prizeLabel || DEFAULT_WINNER_LABELS.prize);
14261
- }
14262
12769
  return this.props.prizeLabel || DEFAULT_WINNER_LABELS.prize;
14263
12770
  }
14264
12771
  getColor() {
@@ -14566,7 +13073,6 @@ class RaffleStatusCardComponent {
14566
13073
  constructor() {
14567
13074
  this.primaryActionClick = new EventEmitter();
14568
13075
  this.secondaryActionClick = new EventEmitter();
14569
- this.langService = inject(LangService);
14570
13076
  }
14571
13077
  get isActiveOrUpcoming() {
14572
13078
  return this.props.status === 'active' || this.props.status === 'upcoming';
@@ -14596,15 +13102,9 @@ class RaffleStatusCardComponent {
14596
13102
  return 'primary';
14597
13103
  }
14598
13104
  getTitle() {
14599
- if (this.props.titleContentKey && this.props.contentClass) {
14600
- return this.langService.getText(this.props.contentClass, this.props.titleContentKey, this.props.title);
14601
- }
14602
- return this.props.title;
13105
+ return this.props.title || '';
14603
13106
  }
14604
13107
  getDescription() {
14605
- if (this.props.descriptionContentKey && this.props.contentClass) {
14606
- return this.langService.getText(this.props.contentClass, this.props.descriptionContentKey, this.props.description || '');
14607
- }
14608
13108
  return this.props.description || '';
14609
13109
  }
14610
13110
  formatCurrency(amount) {
@@ -15076,7 +13576,6 @@ class ParticipantCardComponent {
15076
13576
  this.cardClick = new EventEmitter();
15077
13577
  this.actionClick = new EventEmitter();
15078
13578
  this.showAllTickets = false;
15079
- this.langService = inject(LangService);
15080
13579
  }
15081
13580
  get ticketNumbers() {
15082
13581
  return this.props.participant.tickets || [];
@@ -15504,12 +14003,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15504
14003
  class GlowCardComponent {
15505
14004
  constructor() {
15506
14005
  this.onClick = new EventEmitter();
15507
- this.langService = inject(LangService);
15508
14006
  this.navigationService = inject(NavigationService);
15509
14007
  this.themeService = inject(ThemeService);
15510
- this.title$ = of('');
15511
- this.description$ = of('');
15512
- this.ctaText$ = of('');
15513
14008
  this.ionicColors = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'];
15514
14009
  // RGB values with SPACE separator for CSS rgb(var() / alpha) syntax
15515
14010
  this.colorRgbMap = {
@@ -15522,34 +14017,17 @@ class GlowCardComponent {
15522
14017
  };
15523
14018
  addIcons({ arrowForwardOutline });
15524
14019
  }
15525
- ngOnInit() {
15526
- this.initializeContent();
15527
- }
15528
14020
  get isDark() {
15529
14021
  return this.themeService.IsDark;
15530
14022
  }
15531
- initializeContent() {
15532
- // Title: static or reactive
15533
- if (this.props.title) {
15534
- this.title$ = of(this.props.title);
15535
- }
15536
- else if (this.props.titleKey && this.props.titleClass) {
15537
- this.title$ = this.langService.getContent(this.props.titleClass, this.props.titleKey, this.props.titleFallback);
15538
- }
15539
- // Description: static or reactive
15540
- if (this.props.description) {
15541
- this.description$ = of(this.props.description);
15542
- }
15543
- else if (this.props.descriptionKey && this.props.descriptionClass) {
15544
- this.description$ = this.langService.getContent(this.props.descriptionClass, this.props.descriptionKey, this.props.descriptionFallback);
15545
- }
15546
- // CTA Text: static or reactive
15547
- if (this.props.cta.text) {
15548
- this.ctaText$ = of(this.props.cta.text);
15549
- }
15550
- else if (this.props.cta.contentKey && this.props.cta.contentClass) {
15551
- this.ctaText$ = this.langService.getContent(this.props.cta.contentClass, this.props.cta.contentKey, this.props.cta.contentFallback);
15552
- }
14023
+ getTitle() {
14024
+ return this.props.title || this.props.titleFallback || '';
14025
+ }
14026
+ getDescription() {
14027
+ return this.props.description || this.props.descriptionFallback || '';
14028
+ }
14029
+ getCtaText() {
14030
+ return this.props.cta.text || this.props.cta.contentFallback || 'Ver más';
15553
14031
  }
15554
14032
  getGlowColor() {
15555
14033
  const color = this.props.glow?.color;
@@ -15664,12 +14142,12 @@ class GlowCardComponent {
15664
14142
  <div class="glow-card__content">
15665
14143
  <!-- Title -->
15666
14144
  <h3 class="glow-card__title">
15667
- {{ title$ | async }}
14145
+ {{ getTitle() }}
15668
14146
  </h3>
15669
14147
 
15670
14148
  <!-- Description -->
15671
14149
  <p class="glow-card__description">
15672
- {{ description$ | async }}
14150
+ {{ getDescription() }}
15673
14151
  </p>
15674
14152
 
15675
14153
  <!-- CTA Link with expanding animation -->
@@ -15678,7 +14156,7 @@ class GlowCardComponent {
15678
14156
  [href]="props.cta.url"
15679
14157
  (click)="onCtaClick($event)"
15680
14158
  >
15681
- <span class="glow-card__cta-text">{{ ctaText$ | async }}</span>
14159
+ <span class="glow-card__cta-text">{{ getCtaText() }}</span>
15682
14160
  <ion-icon
15683
14161
  class="glow-card__cta-icon"
15684
14162
  [name]="props.cta.icon || 'arrow-forward-outline'"
@@ -15686,7 +14164,7 @@ class GlowCardComponent {
15686
14164
  </a>
15687
14165
  </div>
15688
14166
  </article>
15689
- `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{--glow-color: var(--ion-color-primary);--glow-color-rgb: 112 38 223;--aspect-ratio: 16 / 9;--card-border-radius: 1.25rem;--image-border-radius: 1rem;--transition-duration: .3s;--transition-timing: cubic-bezier(.4, 0, .2, 1);display:block}.glow-card{position:relative;display:flex;flex-direction:column;background:var(--ion-background-color, #ffffff);border-radius:var(--card-border-radius);overflow:hidden;cursor:pointer;transition:transform var(--transition-duration) var(--transition-timing),box-shadow var(--transition-duration) var(--transition-timing)}.glow-card__image-container{position:relative;width:calc(100% - 1.5rem);aspect-ratio:var(--aspect-ratio);overflow:hidden;border-radius:var(--image-border-radius);margin:.75rem;margin-bottom:0}.glow-card__image{width:100%;height:100%;object-fit:cover;border-radius:var(--image-border-radius);transition:transform var(--transition-duration) var(--transition-timing)}.glow-card__content{padding:1rem 1.25rem 1.25rem;display:flex;flex-direction:column;gap:.5rem}.glow-card__title{margin:0;font-size:1.125rem;font-weight:700;line-height:1.3;color:var(--ion-color-darki, var(--ion-text-color, #000))}.glow-card__description{margin:0;font-size:.875rem;line-height:1.5;color:var(--ion-color-texti, var(--ion-color-medium, #666));display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.glow-card__cta{display:inline-flex;align-items:center;gap:.25rem;margin-top:.5rem;padding:.25rem 0;text-decoration:none;color:var(--glow-color);font-weight:600;font-size:.875rem;transition:gap var(--transition-duration) var(--transition-timing)}.glow-card__cta:hover{gap:.5rem}.glow-card__cta-text{max-width:0;opacity:0;overflow:hidden;white-space:nowrap;transition:max-width var(--transition-duration) var(--transition-timing),opacity var(--transition-duration) var(--transition-timing)}.glow-card__cta-icon{font-size:1.25rem;flex-shrink:0;transition:transform var(--transition-duration) var(--transition-timing)}.glow-card:hover{transform:translateY(-.25rem)}.glow-card:hover .glow-card__image{transform:scale(1.08)}.glow-card:hover .glow-card__cta-text{max-width:12.5rem;opacity:1}.glow-card:hover .glow-card__cta-icon{transform:translate(.125rem)}.glow-card.glow-enabled:hover{box-shadow:0 .25rem .75rem #00000014,0 .5rem 1.5rem #0000001a,0 .25rem 1.25rem rgb(var(--glow-color-rgb)/.15)}.glow-card.glow-enabled.glow-subtle:hover{box-shadow:0 .25rem .75rem #0000000f,0 .375rem 1rem #00000014,0 .125rem .75rem rgb(var(--glow-color-rgb)/.1)}.glow-card.glow-enabled.glow-medium:hover{box-shadow:0 .375rem 1rem #00000014,0 .75rem 2rem #0000001a,0 .375rem 1.5rem rgb(var(--glow-color-rgb)/.2)}.glow-card.glow-enabled.glow-intense:hover{box-shadow:0 .5rem 1.25rem #00000014,0 1rem 2.5rem #0000001a,0 .5rem 2rem rgb(var(--glow-color-rgb)/.3)}.glow-card.glow-enabled.dark-mode:hover{box-shadow:0 0 1.25rem rgb(var(--glow-color-rgb)/.25),0 0 2.5rem rgb(var(--glow-color-rgb)/.18),0 0 3.75rem rgb(var(--glow-color-rgb)/.12)}.glow-card.glow-enabled.dark-mode.glow-subtle:hover{box-shadow:0 0 .75rem rgb(var(--glow-color-rgb)/.18),0 0 1.5rem rgb(var(--glow-color-rgb)/.12)}.glow-card.glow-enabled.dark-mode.glow-medium:hover{box-shadow:0 0 1.5rem rgb(var(--glow-color-rgb)/.3),0 0 3rem rgb(var(--glow-color-rgb)/.22),0 0 4.5rem rgb(var(--glow-color-rgb)/.15)}.glow-card.glow-enabled.dark-mode.glow-intense:hover{box-shadow:0 0 2rem rgb(var(--glow-color-rgb)/.4),0 0 4rem rgb(var(--glow-color-rgb)/.3),0 0 6rem rgb(var(--glow-color-rgb)/.2)}.glow-card.dark-mode{background:var(--ion-card-background, #1e1e1e)}.glow-card.bordered{border:.0625rem solid var(--border-color, var(--ion-color-medium))}@media (max-width: 768px){.glow-card{--card-border-radius: 1rem;--image-border-radius: .75rem}.glow-card__content{padding:.75rem 1rem 1rem}.glow-card__title{font-size:1rem}.glow-card__description{font-size:.8125rem;-webkit-line-clamp:2}}@media (prefers-reduced-motion: reduce){.glow-card,.glow-card__image,.glow-card__cta,.glow-card__cta-text,.glow-card__cta-icon{transition:none}.glow-card:hover,.glow-card:hover .glow-card__image{transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
14167
+ `, isInline: true, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{--glow-color: var(--ion-color-primary);--glow-color-rgb: 112 38 223;--aspect-ratio: 16 / 9;--card-border-radius: 1.25rem;--image-border-radius: 1rem;--transition-duration: .3s;--transition-timing: cubic-bezier(.4, 0, .2, 1);display:block}.glow-card{position:relative;display:flex;flex-direction:column;background:var(--ion-background-color, #ffffff);border-radius:var(--card-border-radius);overflow:hidden;cursor:pointer;transition:transform var(--transition-duration) var(--transition-timing),box-shadow var(--transition-duration) var(--transition-timing)}.glow-card__image-container{position:relative;width:calc(100% - 1.5rem);aspect-ratio:var(--aspect-ratio);overflow:hidden;border-radius:var(--image-border-radius);margin:.75rem;margin-bottom:0}.glow-card__image{width:100%;height:100%;object-fit:cover;border-radius:var(--image-border-radius);transition:transform var(--transition-duration) var(--transition-timing)}.glow-card__content{padding:1rem 1.25rem 1.25rem;display:flex;flex-direction:column;gap:.5rem}.glow-card__title{margin:0;font-size:1.125rem;font-weight:700;line-height:1.3;color:var(--ion-color-darki, var(--ion-text-color, #000))}.glow-card__description{margin:0;font-size:.875rem;line-height:1.5;color:var(--ion-color-texti, var(--ion-color-medium, #666));display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.glow-card__cta{display:inline-flex;align-items:center;gap:.25rem;margin-top:.5rem;padding:.25rem 0;text-decoration:none;color:var(--glow-color);font-weight:600;font-size:.875rem;transition:gap var(--transition-duration) var(--transition-timing)}.glow-card__cta:hover{gap:.5rem}.glow-card__cta-text{max-width:0;opacity:0;overflow:hidden;white-space:nowrap;transition:max-width var(--transition-duration) var(--transition-timing),opacity var(--transition-duration) var(--transition-timing)}.glow-card__cta-icon{font-size:1.25rem;flex-shrink:0;transition:transform var(--transition-duration) var(--transition-timing)}.glow-card:hover{transform:translateY(-.25rem)}.glow-card:hover .glow-card__image{transform:scale(1.08)}.glow-card:hover .glow-card__cta-text{max-width:12.5rem;opacity:1}.glow-card:hover .glow-card__cta-icon{transform:translate(.125rem)}.glow-card.glow-enabled:hover{box-shadow:0 .25rem .75rem #00000014,0 .5rem 1.5rem #0000001a,0 .25rem 1.25rem rgb(var(--glow-color-rgb)/.15)}.glow-card.glow-enabled.glow-subtle:hover{box-shadow:0 .25rem .75rem #0000000f,0 .375rem 1rem #00000014,0 .125rem .75rem rgb(var(--glow-color-rgb)/.1)}.glow-card.glow-enabled.glow-medium:hover{box-shadow:0 .375rem 1rem #00000014,0 .75rem 2rem #0000001a,0 .375rem 1.5rem rgb(var(--glow-color-rgb)/.2)}.glow-card.glow-enabled.glow-intense:hover{box-shadow:0 .5rem 1.25rem #00000014,0 1rem 2.5rem #0000001a,0 .5rem 2rem rgb(var(--glow-color-rgb)/.3)}.glow-card.glow-enabled.dark-mode:hover{box-shadow:0 0 1.25rem rgb(var(--glow-color-rgb)/.25),0 0 2.5rem rgb(var(--glow-color-rgb)/.18),0 0 3.75rem rgb(var(--glow-color-rgb)/.12)}.glow-card.glow-enabled.dark-mode.glow-subtle:hover{box-shadow:0 0 .75rem rgb(var(--glow-color-rgb)/.18),0 0 1.5rem rgb(var(--glow-color-rgb)/.12)}.glow-card.glow-enabled.dark-mode.glow-medium:hover{box-shadow:0 0 1.5rem rgb(var(--glow-color-rgb)/.3),0 0 3rem rgb(var(--glow-color-rgb)/.22),0 0 4.5rem rgb(var(--glow-color-rgb)/.15)}.glow-card.glow-enabled.dark-mode.glow-intense:hover{box-shadow:0 0 2rem rgb(var(--glow-color-rgb)/.4),0 0 4rem rgb(var(--glow-color-rgb)/.3),0 0 6rem rgb(var(--glow-color-rgb)/.2)}.glow-card.dark-mode{background:var(--ion-card-background, #1e1e1e)}.glow-card.bordered{border:.0625rem solid var(--border-color, var(--ion-color-medium))}@media (max-width: 768px){.glow-card{--card-border-radius: 1rem;--image-border-radius: .75rem}.glow-card__content{padding:.75rem 1rem 1rem}.glow-card__title{font-size:1rem}.glow-card__description{font-size:.8125rem;-webkit-line-clamp:2}}@media (prefers-reduced-motion: reduce){.glow-card,.glow-card__image,.glow-card__cta,.glow-card__cta-text,.glow-card__cta-icon{transition:none}.glow-card:hover,.glow-card:hover .glow-card__image{transform:none}}\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"] }] }); }
15690
14168
  }
15691
14169
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GlowCardComponent, decorators: [{
15692
14170
  type: Component,
@@ -15719,12 +14197,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15719
14197
  <div class="glow-card__content">
15720
14198
  <!-- Title -->
15721
14199
  <h3 class="glow-card__title">
15722
- {{ title$ | async }}
14200
+ {{ getTitle() }}
15723
14201
  </h3>
15724
14202
 
15725
14203
  <!-- Description -->
15726
14204
  <p class="glow-card__description">
15727
- {{ description$ | async }}
14205
+ {{ getDescription() }}
15728
14206
  </p>
15729
14207
 
15730
14208
  <!-- CTA Link with expanding animation -->
@@ -15733,7 +14211,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15733
14211
  [href]="props.cta.url"
15734
14212
  (click)="onCtaClick($event)"
15735
14213
  >
15736
- <span class="glow-card__cta-text">{{ ctaText$ | async }}</span>
14214
+ <span class="glow-card__cta-text">{{ getCtaText() }}</span>
15737
14215
  <ion-icon
15738
14216
  class="glow-card__cta-icon"
15739
14217
  [name]="props.cta.icon || 'arrow-forward-outline'"
@@ -18643,9 +17121,8 @@ class WizardComponent {
18643
17121
  this.wrapperId = 'wizard-wrapper';
18644
17122
  this.currentStep = null;
18645
17123
  this.currentStepTitles = null;
17124
+ this.loadingText = 'Por favor espere...';
18646
17125
  this.cdr = inject(ChangeDetectorRef);
18647
- this.langService = inject(LangService);
18648
- this.loadingText = this.langService.getText('_global', 'pleaseWait', 'Por favor espere...');
18649
17126
  }
18650
17127
  ngOnInit() {
18651
17128
  this.updateCurrentStep();
@@ -18784,7 +17261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
18784
17261
  </ng-container>
18785
17262
  </div>
18786
17263
  `, styles: [":root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.wrapper{height:auto;display:flex;flex-direction:column;justify-content:space-between;position:relative;min-height:320px}.step{min-height:9.375rem;margin:16px 0;text-align:center}\n"] }]
18787
- }], ctorParameters: () => [], propDecorators: { props: [{
17264
+ }], propDecorators: { props: [{
18788
17265
  type: Input
18789
17266
  }], onClick: [{
18790
17267
  type: Output
@@ -18859,40 +17336,14 @@ class CommentSectionComponent {
18859
17336
  this.replyingTo = null;
18860
17337
  this.displayTitle = '';
18861
17338
  this.displayLoadMoreLabel = '';
18862
- this.langSubscription = null;
18863
- this.langService = inject(LangService);
18864
17339
  this.infiniteScrollEvent = null;
18865
17340
  }
18866
17341
  ngOnInit() {
18867
17342
  this.updateDisplayTexts();
18868
- if (this.hasReactiveContent()) {
18869
- this.langSubscription = this.langService.currentLang$.subscribe(() => {
18870
- this.updateDisplayTexts();
18871
- });
18872
- }
18873
- }
18874
- ngOnDestroy() {
18875
- this.langSubscription?.unsubscribe();
18876
- }
18877
- hasReactiveContent() {
18878
- return !!((this.props.titleContentKey && this.props.contentClass) ||
18879
- (this.props.loadMoreContentKey && this.props.contentClass));
18880
17343
  }
18881
17344
  updateDisplayTexts() {
18882
- // Title
18883
- if (this.props.titleContentKey && this.props.contentClass) {
18884
- this.displayTitle = this.langService.getText(this.props.contentClass, this.props.titleContentKey, this.props.titleContentFallback || this.props.title || 'Comments');
18885
- }
18886
- else {
18887
- this.displayTitle = this.props.title || 'Comments';
18888
- }
18889
- // Load more label
18890
- if (this.props.loadMoreContentKey && this.props.contentClass) {
18891
- this.displayLoadMoreLabel = this.langService.getText(this.props.contentClass, this.props.loadMoreContentKey, this.props.loadMoreLabel || 'Load more comments');
18892
- }
18893
- else {
18894
- this.displayLoadMoreLabel = this.props.loadMoreLabel || 'Load more comments';
18895
- }
17345
+ this.displayTitle = this.props.title || 'Comentarios';
17346
+ this.displayLoadMoreLabel = this.props.loadMoreLabel || 'Cargar más comentarios';
18896
17347
  }
18897
17348
  formatCount(count) {
18898
17349
  if (count >= 1000000) {
@@ -18904,38 +17355,19 @@ class CommentSectionComponent {
18904
17355
  return count.toString();
18905
17356
  }
18906
17357
  getSortOptionLabel(option) {
18907
- if (option.contentKey && option.contentClass) {
18908
- return this.langService.getText(option.contentClass, option.contentKey, option.contentFallback || option.label);
18909
- }
18910
17358
  return option.label;
18911
17359
  }
18912
17360
  getInputPlaceholder() {
18913
- const config = this.props.inputConfig;
18914
- if (config?.placeholderContentKey && config?.contentClass) {
18915
- return this.langService.getText(config.contentClass, config.placeholderContentKey, config.placeholder || 'Write a comment...');
18916
- }
18917
- return config?.placeholder || 'Write a comment...';
17361
+ return this.props.inputConfig?.placeholder || 'Escribe un comentario...';
18918
17362
  }
18919
17363
  getSubmitLabel() {
18920
- const config = this.props.inputConfig;
18921
- if (config?.submitLabelContentKey && config?.contentClass) {
18922
- return this.langService.getText(config.contentClass, config.submitLabelContentKey, config.submitLabel || 'Post');
18923
- }
18924
- return config?.submitLabel || 'Post';
17364
+ return this.props.inputConfig?.submitLabel || 'Publicar';
18925
17365
  }
18926
17366
  getEmptyTitle() {
18927
- const empty = this.props.emptyState;
18928
- if (empty?.titleContentKey && empty?.contentClass) {
18929
- return this.langService.getText(empty.contentClass, empty.titleContentKey, empty.title || 'No comments yet');
18930
- }
18931
- return empty?.title || 'No comments yet';
17367
+ return this.props.emptyState?.title || 'Sin comentarios aún';
18932
17368
  }
18933
17369
  getEmptyMessage() {
18934
- const empty = this.props.emptyState;
18935
- if (empty?.messageContentKey && empty?.contentClass) {
18936
- return this.langService.getText(empty.contentClass, empty.messageContentKey, empty.message || 'Be the first to share your thoughts!');
18937
- }
18938
- return empty?.message || 'Be the first to share your thoughts!';
17370
+ return this.props.emptyState?.message || '¡Sé el primero en compartir tu opinión!';
18939
17371
  }
18940
17372
  getSkeletonArray() {
18941
17373
  const count = this.props.skeletonCount || 3;
@@ -19430,7 +17862,6 @@ class DataTableComponent {
19430
17862
  this.selectedRows = new Set();
19431
17863
  /** Cached visible columns for performance */
19432
17864
  this._visibleColumns = [];
19433
- this.langService = inject(LangService);
19434
17865
  this.cdr = inject(ChangeDetectorRef);
19435
17866
  }
19436
17867
  ngOnInit() {
@@ -21622,169 +20053,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
21622
20053
  type: Output
21623
20054
  }] } });
21624
20055
 
21625
- const text = {
21626
- es: {
21627
- spanish: 'Español',
21628
- english: 'Inglés',
21629
- },
21630
- en: {
21631
- spanish: 'Spanish',
21632
- english: 'English',
21633
- },
21634
- };
21635
- var LangSettings = new TextContent(text);
21636
-
21637
- /**
21638
- * Global content that can be used across all components.
21639
- * These are common texts like buttons, actions, states, etc.
21640
- * Structure: {es: {key1: 'value1', key2: 'value2'}, en: {key1: 'value1', key2: 'value2'}, fr: {...}}
21641
- *
21642
- * Note: You can add any language code. The system will automatically detect available languages
21643
- * and provide intelligent fallbacks with warnings for missing translations.
21644
- */
21645
- const globalContentData = {
21646
- es: {
21647
- // Common buttons
21648
- ok: 'Aceptar',
21649
- cancel: 'Cancelar',
21650
- save: 'Guardar',
21651
- delete: 'Eliminar',
21652
- edit: 'Editar',
21653
- close: 'Cerrar',
21654
- back: 'Volver',
21655
- next: 'Siguiente',
21656
- previous: 'Anterior',
21657
- finish: 'Finalizar',
21658
- continue: 'Continuar',
21659
- // Common actions
21660
- add: 'Agregar',
21661
- remove: 'Quitar',
21662
- search: 'Buscar',
21663
- filter: 'Filtrar',
21664
- sort: 'Ordenar',
21665
- refresh: 'Actualizar',
21666
- // Common states and messages
21667
- loading: 'Cargando...',
21668
- pleaseWait: 'Por favor espere...',
21669
- noData: 'No hay datos disponibles',
21670
- error: 'Error',
21671
- success: 'Éxito',
21672
- warning: 'Advertencia',
21673
- info: 'Información',
21674
- language: 'Idioma',
21675
- // Common confirmations
21676
- areYouSure: '¿Estás seguro?',
21677
- // Language names (translated) - flat keys for type compatibility
21678
- languageName_es: 'Español',
21679
- languageName_en: 'Inglés',
21680
- languageName_fr: 'Francés',
21681
- languageName_de: 'Alemán',
21682
- languageName_pt: 'Portugués',
21683
- languageName_it: 'Italiano',
21684
- languageName_zh: 'Chino',
21685
- languageName_ja: 'Japonés',
21686
- languageName_ko: 'Coreano',
21687
- languageName_ru: 'Ruso',
21688
- languageName_ar: 'Árabe',
21689
- deleteConfirmation: '¿Estás seguro de que deseas eliminar {itemName}?',
21690
- unsavedChanges: 'Tienes cambios sin guardar. ¿Deseas continuar?',
21691
- // Common placeholders
21692
- searchPlaceholder: 'Buscar...',
21693
- select: 'Seleccionar...',
21694
- selectOption: 'Seleccione una opción',
21695
- selectLanguage: 'Seleccionar idioma...',
21696
- // Status messages
21697
- copied: '¡Copiado al portapapeles!',
21698
- seeMore: 'ver más',
21699
- selected: 'seleccionados',
21700
- // Image preview
21701
- zoomIn: 'Acercar',
21702
- zoomOut: 'Alejar',
21703
- resetZoom: 'Restablecer zoom',
21704
- },
21705
- en: {
21706
- // Common buttons
21707
- ok: 'OK',
21708
- cancel: 'Cancel',
21709
- save: 'Save',
21710
- delete: 'Delete',
21711
- edit: 'Edit',
21712
- close: 'Close',
21713
- back: 'Back',
21714
- next: 'Next',
21715
- previous: 'Previous',
21716
- finish: 'Finish',
21717
- continue: 'Continue',
21718
- // Common actions
21719
- add: 'Add',
21720
- remove: 'Remove',
21721
- search: 'Search',
21722
- filter: 'Filter',
21723
- sort: 'Sort',
21724
- refresh: 'Refresh',
21725
- // Common states and messages
21726
- loading: 'Loading...',
21727
- pleaseWait: 'Please wait...',
21728
- noData: 'No data available',
21729
- error: 'Error',
21730
- success: 'Success',
21731
- warning: 'Warning',
21732
- info: 'Information',
21733
- language: 'Language',
21734
- // Common confirmations
21735
- areYouSure: 'Are you sure?',
21736
- // Language names (translated) - flat keys for type compatibility
21737
- languageName_es: 'Spanish',
21738
- languageName_en: 'English',
21739
- languageName_fr: 'French',
21740
- languageName_de: 'German',
21741
- languageName_pt: 'Portuguese',
21742
- languageName_it: 'Italian',
21743
- languageName_zh: 'Chinese',
21744
- languageName_ja: 'Japanese',
21745
- languageName_ko: 'Korean',
21746
- languageName_ru: 'Russian',
21747
- languageName_ar: 'Arabic',
21748
- deleteConfirmation: 'Are you sure you want to delete {itemName}?',
21749
- unsavedChanges: 'You have unsaved changes. Do you want to continue?',
21750
- // Common placeholders
21751
- searchPlaceholder: 'Search...',
21752
- select: 'Select...',
21753
- selectOption: 'Select an option',
21754
- selectLanguage: 'Select language...',
21755
- // Status messages
21756
- copied: 'Copied to clipboard!',
21757
- seeMore: 'see more',
21758
- selected: 'selected',
21759
- // Image preview
21760
- zoomIn: 'Zoom in',
21761
- zoomOut: 'Zoom out',
21762
- resetZoom: 'Reset zoom',
21763
- },
21764
- };
21765
- const GlobalContent = new TextContent(globalContentData);
21766
- // ImageComponent specific content
21767
- const imageComponentData = {
21768
- es: {
21769
- close: 'Cerrar',
21770
- zoomIn: 'Acercar',
21771
- zoomOut: 'Alejar',
21772
- resetZoom: 'Restablecer zoom',
21773
- },
21774
- en: {
21775
- close: 'Close',
21776
- zoomIn: 'Zoom in',
21777
- zoomOut: 'Zoom out',
21778
- resetZoom: 'Reset zoom',
21779
- },
21780
- };
21781
- const ImageComponentContent = new TextContent(imageComponentData);
21782
- const content = {
21783
- _global: GlobalContent,
21784
- LangSettings,
21785
- ImageComponent: ImageComponentContent,
21786
- };
21787
-
21788
20056
  /**
21789
20057
  * Service for displaying toast notifications using Ionic's ToastController.
21790
20058
  * Provides methods to show and present toasts with custom options.
@@ -21829,6 +20097,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
21829
20097
  }]
21830
20098
  }], ctorParameters: () => [{ type: i2.ToastController }] });
21831
20099
 
20100
+ // Types for valtech-components services
20101
+ // ValtechConfig and LangProvider have been removed in v3.0.0
20102
+ // Use LocaleService for language management instead
20103
+
21832
20104
  /**
21833
20105
  * Default confirmation dialog options.
21834
20106
  */
@@ -22254,191 +20526,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
22254
20526
  }]
22255
20527
  }] });
22256
20528
 
22257
- /**
22258
- * Create a reactive content observable from a content key.
22259
- * This is the primary utility for the `fromContent` pattern with unified support
22260
- * for both simple content and content with interpolation.
22261
- *
22262
- * @param langService - The language service instance
22263
- * @param config - Content configuration with optional interpolation
22264
- * @returns Observable that emits the content string and updates on language change
22265
- *
22266
- * @example Simple content:
22267
- * ```typescript
22268
- * // Component-specific content
22269
- * this.title$ = fromContent(this.langService, {
22270
- * className: 'HeaderComponent',
22271
- * key: 'title',
22272
- * fallback: 'Default Title'
22273
- * });
22274
- *
22275
- * // Global content (no className needed)
22276
- * this.saveButton$ = fromContent(this.langService, {
22277
- * key: 'save'
22278
- * });
22279
- * ```
22280
- *
22281
- * @example Content with interpolation:
22282
- * ```typescript
22283
- * // Content: "Hello {name}, you have {count} messages"
22284
- * this.greeting$ = fromContent(this.langService, {
22285
- * className: 'WelcomeComponent',
22286
- * key: 'greeting',
22287
- * interpolation: { name: 'John', count: 5 }
22288
- * });
22289
- * // Results in: "Hello John, you have 5 messages"
22290
- * ```
22291
- */
22292
- function fromContent(langService, config) {
22293
- // Use _global as default className if not provided
22294
- const finalClassName = config.className || '_global';
22295
- const contentObservable = langService.getContent(finalClassName, config.key, config.fallback);
22296
- // If interpolation is provided, apply it
22297
- if (config.interpolation) {
22298
- return contentObservable.pipe(map(content => interpolateContent(content, config.interpolation)));
22299
- }
22300
- return contentObservable;
22301
- }
22302
- /**
22303
- * Create a reactive content observable with interpolation support.
22304
- *
22305
- * @deprecated Use fromContent() with interpolation property instead.
22306
- * This method is kept for backward compatibility.
22307
- *
22308
- * @param langService - The language service instance
22309
- * @param config - Interpolated content configuration
22310
- * @returns Observable that emits the interpolated content string
22311
- *
22312
- * @example Migration:
22313
- * ```typescript
22314
- * // OLD (deprecated):
22315
- * this.greeting$ = fromContentWithInterpolation(this.langService, {
22316
- * className: 'WelcomeComponent',
22317
- * key: 'greeting',
22318
- * interpolation: { name: 'John', count: 5 }
22319
- * });
22320
- *
22321
- * // NEW (recommended):
22322
- * this.greeting$ = fromContent(this.langService, {
22323
- * className: 'WelcomeComponent',
22324
- * key: 'greeting',
22325
- * interpolation: { name: 'John', count: 5 }
22326
- * });
22327
- * ```
22328
- */
22329
- function fromContentWithInterpolation(langService, config) {
22330
- // Delegate to the unified fromContent method
22331
- return fromContent(langService, config);
22332
- }
22333
- /**
22334
- * Create multiple reactive content observables at once.
22335
- * Useful when a component needs several content strings.
22336
- *
22337
- * @param langService - The language service instance
22338
- * @param className - The component class name
22339
- * @param keys - Array of content keys to retrieve
22340
- * @returns Observable that emits an object with all requested content
22341
- *
22342
- * @example
22343
- * ```typescript
22344
- * this.content$ = fromMultipleContent(this.langService, 'FormComponent', [
22345
- * 'title', 'submitButton', 'cancelButton'
22346
- * ]);
22347
- *
22348
- * // In template
22349
- * <ng-container *ngIf="content$ | async as content">
22350
- * <h2>{{ content.title }}</h2>
22351
- * <button>{{ content.submitButton }}</button>
22352
- * <button>{{ content.cancelButton }}</button>
22353
- * </ng-container>
22354
- * ```
22355
- */
22356
- function fromMultipleContent(langService, className, keys) {
22357
- return langService.getMultipleContent(className, keys);
22358
- }
22359
- /**
22360
- * Helper function to interpolate values into a content string.
22361
- * Replaces placeholders in the format {key} with corresponding values.
22362
- *
22363
- * @param content - The content string with placeholders
22364
- * @param values - Object with values to interpolate
22365
- * @returns The interpolated string
22366
- *
22367
- * @example
22368
- * ```typescript
22369
- * const result = interpolateContent("Hello {name}!", { name: "World" });
22370
- * // Returns: "Hello World!"
22371
- * ```
22372
- */
22373
- function interpolateContent(content, values) {
22374
- if (!values)
22375
- return content;
22376
- return Object.entries(values).reduce((result, [key, value]) => {
22377
- return result.replace(new RegExp(`\\{${key}\\}`, 'g'), String(value));
22378
- }, content);
22379
- }
22380
- /**
22381
- * Factory function to create a content helper bound to a specific component class.
22382
- * This creates a more convenient API for components that need multiple content strings.
22383
- *
22384
- * @param langService - The language service instance
22385
- * @param className - The component class name
22386
- * @returns Object with convenient methods for content retrieval
22387
- *
22388
- * @example
22389
- * ```typescript
22390
- * export class MyComponent {
22391
- * private content = createContentHelper(this.langService, 'MyComponent');
22392
- *
22393
- * constructor(private langService: LangService) {}
22394
- *
22395
- * ngOnInit() {
22396
- * this.title$ = this.content.get('title');
22397
- * this.allContent$ = this.content.getMultiple(['title', 'description']);
22398
- * }
22399
- * }
22400
- * ```
22401
- */
22402
- function createContentHelper(langService, className) {
22403
- return {
22404
- /**
22405
- * Get a single content string reactively.
22406
- */
22407
- get(key, fallback) {
22408
- return fromContent(langService, { className, key, fallback });
22409
- },
22410
- /**
22411
- * Get multiple content strings reactively.
22412
- */
22413
- getMultiple(keys) {
22414
- return fromMultipleContent(langService, className, keys);
22415
- },
22416
- /**
22417
- * Get content with interpolation.
22418
- */
22419
- getWithInterpolation(key, interpolation, fallback) {
22420
- return fromContentWithInterpolation(langService, {
22421
- className,
22422
- key,
22423
- interpolation,
22424
- fallback,
22425
- });
22426
- },
22427
- /**
22428
- * Get a single content string synchronously (current language only).
22429
- */
22430
- getText(key, fallback) {
22431
- return langService.getText(className, key, fallback);
22432
- },
22433
- /**
22434
- * Check if a content key exists.
22435
- */
22436
- hasContent(key) {
22437
- return langService.hasContent(className, key);
22438
- },
22439
- };
22440
- }
22441
-
22442
20529
  /*
22443
20530
  * Public API Surface of valtech-components
22444
20531
  */
@@ -22447,5 +20534,5 @@ function createContentHelper(langService, className) {
22447
20534
  * Generated bundle index. Do not edit.
22448
20535
  */
22449
20536
 
22450
- export { ARTICLE_SPACING, AccordionComponent, ActionHeaderComponent, ActionType, AlertBoxComponent, ArticleBuilder, ArticleComponent, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContentLoaderComponent, CountdownComponent, CurrencyInputComponent, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_LEGEND_LABELS, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PAYMENT_STATUS_COLORS, DEFAULT_PAYMENT_STATUS_LABELS, DEFAULT_PLATFORMS, DEFAULT_STATUS_COLORS, DEFAULT_STATUS_LABELS, DEFAULT_WINNER_LABELS, DataTableComponent, DateInputComponent, DateRangeInputComponent, DisplayComponent, DividerComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FabComponent, FileInputComponent, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FunHeaderComponent, GlobalContent, GlowCardComponent, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InfoComponent, InputType, ItemListComponent, LANGUAGES, LangService, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksAccordionComponent, LinksCakeComponent, LocalStorageService, MODAL_SIZES, MOTION, MenuComponent, ModalService, MultiSelectSearchComponent, NavigationService, NoContentComponent, NotesBoxComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, ParticipantCardComponent, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QuoteBoxComponent, RadioInputComponent, RaffleStatusCardComponent, RangeInputComponent, RatingComponent, RecapCardComponent, RightsFooterComponent, SKELETON_PRESETS, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SegmentControlComponent, SelectSearchComponent, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, SwipeCarouselComponent, TabsComponent, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextContent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketGridComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, ToolbarActionType, ToolbarComponent, ValtechConfigService, WinnerDisplayComponent, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, content, createButtonProps, createContentHelper, createDisplayProps, createGlowCardProps, createNumberFromToField, createReactiveContentMetadata, createTextProps, createTitleProps, extractContentConfig, extractContentConfigWithInterpolation, fromContent, fromContentWithInterpolation, fromMultipleContent, globalContentData, goToTop, interpolateContent, interpolateStaticContent, isAtEnd, maxLength, replaceSpecialChars, resolveColor, resolveInputDefaultValue, shouldUseReactiveContent, shouldUseReactiveContentWithInterpolation };
20537
+ export { ARTICLE_SPACING, AccordionComponent, ActionHeaderComponent, ActionType, AlertBoxComponent, ArticleBuilder, ArticleComponent, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContentLoaderComponent, CountdownComponent, CurrencyInputComponent, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_LEGEND_LABELS, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PAYMENT_STATUS_COLORS, DEFAULT_PAYMENT_STATUS_LABELS, DEFAULT_PLATFORMS, DEFAULT_STATUS_COLORS, DEFAULT_STATUS_LABELS, DEFAULT_WINNER_LABELS, DataTableComponent, DateInputComponent, DateRangeInputComponent, DisplayComponent, DividerComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FabComponent, FileInputComponent, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FunHeaderComponent, GlowCardComponent, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InfoComponent, InputType, ItemListComponent, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksAccordionComponent, LinksCakeComponent, LocalStorageService, LocaleService, MODAL_SIZES, MOTION, MenuComponent, ModalService, MultiSelectSearchComponent, NavigationService, NoContentComponent, NotesBoxComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, ParticipantCardComponent, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QuoteBoxComponent, RadioInputComponent, RaffleStatusCardComponent, RangeInputComponent, RatingComponent, RecapCardComponent, RightsFooterComponent, SKELETON_PRESETS, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SegmentControlComponent, SelectSearchComponent, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, SwipeCarouselComponent, TabsComponent, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketGridComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, ToolbarActionType, ToolbarComponent, WinnerDisplayComponent, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, createGlowCardProps, createNumberFromToField, createTitleProps, goToTop, isAtEnd, maxLength, replaceSpecialChars, resolveColor, resolveInputDefaultValue };
22451
20538
  //# sourceMappingURL=valtech-components.mjs.map