valtech-components 2.0.713 → 2.0.714

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 (36) hide show
  1. package/esm2022/lib/components/organisms/cards-carousel/cards-carousel.component.mjs +63 -16
  2. package/esm2022/lib/components/organisms/cards-carousel/types.mjs +1 -1
  3. package/esm2022/lib/components/templates/simple/simple.component.mjs +7 -9
  4. package/esm2022/lib/services/auth/auth.service.mjs +33 -17
  5. package/esm2022/lib/version.mjs +2 -2
  6. package/esm2022/public-api.mjs +1 -12
  7. package/fesm2022/valtech-components.mjs +100 -1995
  8. package/fesm2022/valtech-components.mjs.map +1 -1
  9. package/lib/components/organisms/bottom-nav/bottom-nav.component.d.ts +1 -1
  10. package/lib/components/organisms/cards-carousel/cards-carousel.component.d.ts +12 -6
  11. package/lib/components/organisms/cards-carousel/types.d.ts +32 -3
  12. package/lib/version.d.ts +1 -1
  13. package/package.json +1 -1
  14. package/public-api.d.ts +0 -11
  15. package/esm2022/lib/components/molecules/participant-card/participant-card.component.mjs +0 -514
  16. package/esm2022/lib/components/molecules/participant-card/types.mjs +0 -21
  17. package/esm2022/lib/components/molecules/raffle-status-card/raffle-status-card.component.mjs +0 -476
  18. package/esm2022/lib/components/molecules/raffle-status-card/types.mjs +0 -23
  19. package/esm2022/lib/components/molecules/recap-card/recap-card.component.mjs +0 -78
  20. package/esm2022/lib/components/molecules/recap-card/types.mjs +0 -2
  21. package/esm2022/lib/components/molecules/ticket-grid/ticket-grid.component.mjs +0 -489
  22. package/esm2022/lib/components/molecules/ticket-grid/types.mjs +0 -11
  23. package/esm2022/lib/components/molecules/winner-display/types.mjs +0 -9
  24. package/esm2022/lib/components/molecules/winner-display/winner-display.component.mjs +0 -359
  25. package/esm2022/lib/components/templates/layout/layout.component.mjs +0 -19
  26. package/lib/components/molecules/participant-card/participant-card.component.d.ts +0 -34
  27. package/lib/components/molecules/participant-card/types.d.ts +0 -132
  28. package/lib/components/molecules/raffle-status-card/raffle-status-card.component.d.ts +0 -21
  29. package/lib/components/molecules/raffle-status-card/types.d.ts +0 -108
  30. package/lib/components/molecules/recap-card/recap-card.component.d.ts +0 -36
  31. package/lib/components/molecules/recap-card/types.d.ts +0 -30
  32. package/lib/components/molecules/ticket-grid/ticket-grid.component.d.ts +0 -40
  33. package/lib/components/molecules/ticket-grid/types.d.ts +0 -122
  34. package/lib/components/molecules/winner-display/types.d.ts +0 -103
  35. package/lib/components/molecules/winner-display/winner-display.component.d.ts +0 -36
  36. package/lib/components/templates/layout/layout.component.d.ts +0 -5
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, Injectable, makeEnvironmentProviders, APP_INITIALIZER, inject, EventEmitter, Component, Input, Output, computed, HostListener, Pipe, input, ChangeDetectionStrategy, ViewChild, ChangeDetectorRef, ElementRef, ContentChild, PLATFORM_ID, Inject, ErrorHandler, DestroyRef, InjectionToken, runInInjectionContext, effect, Optional, TemplateRef, ViewContainerRef, isSignal, Directive, ViewEncapsulation } from '@angular/core';
2
+ import { signal, Injectable, makeEnvironmentProviders, APP_INITIALIZER, inject, EventEmitter, Component, Input, Output, computed, HostListener, Pipe, input, ChangeDetectionStrategy, ViewChild, ChangeDetectorRef, ContentChild, PLATFORM_ID, Inject, ErrorHandler, DestroyRef, InjectionToken, runInInjectionContext, effect, Optional, TemplateRef, ViewContainerRef, isSignal, Directive, ElementRef, ViewEncapsulation } 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, IonPopover, IonList, IonItem, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonRippleEffect, AlertController, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
5
5
  import * as i1 from '@angular/common';
6
6
  import { CommonModule, NgStyle, NgFor, isPlatformBrowser, NgClass } from '@angular/common';
7
7
  import { addIcons } from 'ionicons';
8
- import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, shuffleOutline, logoWhatsapp, paperPlaneOutline, mailOutline, trophyOutline, ticketOutline, giftOutline, personOutline, ellipsisVertical, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, documentOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, cameraOutline, bugOutline, bulbOutline, closeCircleOutline, menuOutline } from 'ionicons/icons';
8
+ import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, documentOutline, searchOutline, personOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, cameraOutline, bugOutline, bulbOutline, closeCircleOutline, menuOutline } from 'ionicons/icons';
9
9
  import * as i1$1 from '@angular/router';
10
10
  import { Router, NavigationEnd, RouterLink, RouterOutlet, RouterModule } from '@angular/router';
11
11
  import { Browser } from '@capacitor/browser';
@@ -50,7 +50,7 @@ import 'prismjs/components/prism-json';
50
50
  * Current version of valtech-components.
51
51
  * This is automatically updated during the publish process.
52
52
  */
53
- const VERSION = '2.0.713';
53
+ const VERSION = '2.0.714';
54
54
 
55
55
  /**
56
56
  * Servicio para gestionar presets de componentes.
@@ -14442,498 +14442,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
14442
14442
  type: Output
14443
14443
  }] } });
14444
14444
 
14445
- /**
14446
- * Default legend labels in Spanish.
14447
- */
14448
- const DEFAULT_LEGEND_LABELS = {
14449
- available: 'Disponible',
14450
- sold: 'Vendido',
14451
- reserved: 'Reservado',
14452
- selected: 'Seleccionado',
14453
- disabled: 'No disponible',
14454
- };
14455
-
14456
- addIcons({ shuffleOutline });
14457
- /**
14458
- * val-ticket-grid
14459
- *
14460
- * A grid for selecting ticket numbers, commonly used in raffles and lotteries.
14461
- *
14462
- * @example Basic usage
14463
- * ```html
14464
- * <val-ticket-grid
14465
- * [props]="{
14466
- * totalTickets: 100,
14467
- * soldTickets: [1, 5, 12, 23],
14468
- * selectionMode: 'multiple',
14469
- * maxSelection: 10
14470
- * }"
14471
- * (selectionChange)="onSelectionChange($event)"
14472
- * ></val-ticket-grid>
14473
- * ```
14474
- *
14475
- * @example With legend and search
14476
- * ```html
14477
- * <val-ticket-grid
14478
- * [props]="{
14479
- * totalTickets: 500,
14480
- * soldTickets: soldNumbers,
14481
- * reservedTickets: reservedNumbers,
14482
- * columns: 20,
14483
- * showLegend: true,
14484
- * showSearch: true,
14485
- * showRandomSelect: true,
14486
- * randomSelectCount: 5,
14487
- * maxSelection: 10
14488
- * }"
14489
- * ></val-ticket-grid>
14490
- * ```
14491
- */
14492
- class TicketGridComponent {
14493
- constructor() {
14494
- this.selectionChange = new EventEmitter();
14495
- this.ticketClick = new EventEmitter();
14496
- this.tickets = [];
14497
- this.displayedTickets = [];
14498
- this.selectedTickets = [];
14499
- this.searchTerm = '';
14500
- this.highlightedNumbers = [];
14501
- }
14502
- ngOnInit() {
14503
- this.buildTickets();
14504
- }
14505
- ngOnChanges(changes) {
14506
- if (changes['props']) {
14507
- this.buildTickets();
14508
- }
14509
- }
14510
- buildTickets() {
14511
- const start = this.props.startNumber ?? 1;
14512
- const total = this.props.totalTickets;
14513
- const soldSet = new Set(this.props.soldTickets || []);
14514
- const reservedSet = new Set(this.props.reservedTickets || []);
14515
- const disabledSet = new Set(this.props.disabledTickets || []);
14516
- const selectedSet = new Set(this.props.selectedTickets || []);
14517
- // Initialize selected tickets from props
14518
- this.selectedTickets = [...(this.props.selectedTickets || [])];
14519
- // Build ticket array
14520
- if (this.props.ticketData?.length) {
14521
- // Use custom ticket data
14522
- this.tickets = [...this.props.ticketData];
14523
- }
14524
- else {
14525
- // Generate from numbers
14526
- this.tickets = [];
14527
- for (let i = start; i < start + total; i++) {
14528
- let status = 'available';
14529
- if (disabledSet.has(i)) {
14530
- status = 'disabled';
14531
- }
14532
- else if (soldSet.has(i)) {
14533
- status = 'sold';
14534
- }
14535
- else if (reservedSet.has(i)) {
14536
- status = 'reserved';
14537
- }
14538
- else if (selectedSet.has(i)) {
14539
- status = 'selected';
14540
- }
14541
- this.tickets.push({ number: i, status });
14542
- }
14543
- }
14544
- this.applySearch();
14545
- }
14546
- applySearch() {
14547
- if (!this.searchTerm) {
14548
- this.displayedTickets = [...this.tickets];
14549
- this.highlightedNumbers = [];
14550
- }
14551
- else {
14552
- // Filter/highlight tickets matching search
14553
- const term = this.searchTerm.trim();
14554
- this.highlightedNumbers = this.tickets
14555
- .filter(t => this.formatNumber(t.number).includes(term))
14556
- .map(t => t.number);
14557
- this.displayedTickets = [...this.tickets];
14558
- }
14559
- }
14560
- onSearch(event) {
14561
- this.searchTerm = event.detail.value || '';
14562
- this.applySearch();
14563
- }
14564
- isHighlighted(number) {
14565
- return this.highlightedNumbers.includes(number);
14566
- }
14567
- isSelectable(ticket) {
14568
- if (this.props.selectionMode === 'none')
14569
- return false;
14570
- // Check if sold/reserved and admin override
14571
- if (ticket.status === 'sold' || ticket.status === 'reserved') {
14572
- return this.props.allowSelectSold === true;
14573
- }
14574
- if (ticket.status === 'disabled')
14575
- return false;
14576
- // Check max selection
14577
- if (ticket.status !== 'selected' &&
14578
- this.props.maxSelection &&
14579
- this.selectedTickets.length >= this.props.maxSelection) {
14580
- return false;
14581
- }
14582
- return true;
14583
- }
14584
- onTicketClick(ticket) {
14585
- const isSelected = this.selectedTickets.includes(ticket.number);
14586
- // Emit click event regardless
14587
- this.ticketClick.emit({
14588
- number: ticket.number,
14589
- status: ticket.status,
14590
- selected: this.isSelectable(ticket) ? !isSelected : null,
14591
- });
14592
- if (!this.isSelectable(ticket) && ticket.status !== 'selected') {
14593
- return;
14594
- }
14595
- // Handle selection
14596
- if (isSelected) {
14597
- // Deselect
14598
- this.selectedTickets = this.selectedTickets.filter(n => n !== ticket.number);
14599
- ticket.status = 'available';
14600
- this.selectionChange.emit({
14601
- selectedTickets: [...this.selectedTickets],
14602
- changedTicket: ticket.number,
14603
- action: 'deselect',
14604
- count: this.selectedTickets.length,
14605
- maxReached: false,
14606
- });
14607
- }
14608
- else {
14609
- // Select
14610
- if (this.props.selectionMode === 'single') {
14611
- // Deselect previous
14612
- this.selectedTickets.forEach(num => {
14613
- const t = this.tickets.find(x => x.number === num);
14614
- if (t)
14615
- t.status = 'available';
14616
- });
14617
- this.selectedTickets = [ticket.number];
14618
- }
14619
- else {
14620
- this.selectedTickets.push(ticket.number);
14621
- }
14622
- ticket.status = 'selected';
14623
- this.selectionChange.emit({
14624
- selectedTickets: [...this.selectedTickets],
14625
- changedTicket: ticket.number,
14626
- action: 'select',
14627
- count: this.selectedTickets.length,
14628
- maxReached: this.props.maxSelection
14629
- ? this.selectedTickets.length >= this.props.maxSelection
14630
- : false,
14631
- });
14632
- }
14633
- }
14634
- selectRandom() {
14635
- const count = this.props.randomSelectCount || 1;
14636
- const available = this.tickets.filter(t => t.status === 'available' && !this.selectedTickets.includes(t.number));
14637
- // Determine how many we can select
14638
- const maxCanSelect = this.props.maxSelection
14639
- ? Math.min(count, this.props.maxSelection - this.selectedTickets.length)
14640
- : count;
14641
- if (available.length === 0 || maxCanSelect <= 0)
14642
- return;
14643
- // Random shuffle and pick
14644
- const shuffled = [...available].sort(() => Math.random() - 0.5);
14645
- const toSelect = shuffled.slice(0, Math.min(maxCanSelect, available.length));
14646
- toSelect.forEach(ticket => {
14647
- ticket.status = 'selected';
14648
- this.selectedTickets.push(ticket.number);
14649
- });
14650
- this.selectionChange.emit({
14651
- selectedTickets: [...this.selectedTickets],
14652
- changedTicket: toSelect[toSelect.length - 1].number,
14653
- action: 'select',
14654
- count: this.selectedTickets.length,
14655
- maxReached: this.props.maxSelection
14656
- ? this.selectedTickets.length >= this.props.maxSelection
14657
- : false,
14658
- });
14659
- }
14660
- /**
14661
- * Clear all selections.
14662
- */
14663
- clearSelection() {
14664
- this.selectedTickets.forEach(num => {
14665
- const ticket = this.tickets.find(t => t.number === num);
14666
- if (ticket)
14667
- ticket.status = 'available';
14668
- });
14669
- this.selectedTickets = [];
14670
- }
14671
- /**
14672
- * Get selected ticket numbers.
14673
- */
14674
- getSelectedTickets() {
14675
- return [...this.selectedTickets];
14676
- }
14677
- get availableCount() {
14678
- return this.tickets.filter(t => t.status === 'available').length;
14679
- }
14680
- get soldCount() {
14681
- return this.tickets.filter(t => t.status === 'sold').length;
14682
- }
14683
- getLegendItems() {
14684
- if (this.props.legendItems) {
14685
- return this.props.legendItems;
14686
- }
14687
- const items = [
14688
- { status: 'available', label: DEFAULT_LEGEND_LABELS.available, count: this.availableCount },
14689
- { status: 'selected', label: DEFAULT_LEGEND_LABELS.selected, count: this.selectedTickets.length },
14690
- ];
14691
- if (this.props.soldTickets?.length) {
14692
- items.push({ status: 'sold', label: DEFAULT_LEGEND_LABELS.sold, count: this.soldCount });
14693
- }
14694
- if (this.props.reservedTickets?.length) {
14695
- items.push({
14696
- status: 'reserved',
14697
- label: DEFAULT_LEGEND_LABELS.reserved,
14698
- count: this.props.reservedTickets.length,
14699
- });
14700
- }
14701
- return items;
14702
- }
14703
- formatNumber(num) {
14704
- if (this.props.numberPadding) {
14705
- return String(num).padStart(this.props.numberPadding, '0');
14706
- }
14707
- return String(num);
14708
- }
14709
- getTicketAriaLabel(ticket) {
14710
- const statusLabel = DEFAULT_LEGEND_LABELS[ticket.status];
14711
- return `Boleto ${this.formatNumber(ticket.number)}, ${statusLabel}`;
14712
- }
14713
- getSearchPlaceholder() {
14714
- return this.props.searchPlaceholder || 'Buscar número...';
14715
- }
14716
- getRandomSelectLabel() {
14717
- return this.props.randomSelectLabel || 'Aleatorio';
14718
- }
14719
- getColor() {
14720
- if (this.props.color) {
14721
- return `var(--ion-color-${this.props.color})`;
14722
- }
14723
- return 'var(--ion-color-primary)';
14724
- }
14725
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TicketGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14726
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TicketGridComponent, isStandalone: true, selector: "val-ticket-grid", inputs: { props: "props" }, outputs: { selectionChange: "selectionChange", ticketClick: "ticketClick" }, usesOnChanges: true, ngImport: i0, template: `
14727
- <div
14728
- class="ticket-grid-container"
14729
- [class]="props.cssClass"
14730
- [class.size-small]="props.ticketSize === 'small'"
14731
- [class.size-medium]="props.ticketSize === 'medium' || !props.ticketSize"
14732
- [class.size-large]="props.ticketSize === 'large'"
14733
- [style.--grid-columns]="props.columns || 10"
14734
- [style.--grid-gap]="(props.gap || 4) + 'px'"
14735
- [style.--selected-color]="getColor()"
14736
- >
14737
- <!-- Search and controls -->
14738
- @if (props.showSearch || props.showRandomSelect) {
14739
- <div class="grid-controls">
14740
- @if (props.showSearch) {
14741
- <ion-searchbar
14742
- [placeholder]="getSearchPlaceholder()"
14743
- [debounce]="300"
14744
- (ionInput)="onSearch($event)"
14745
- class="ticket-search"
14746
- ></ion-searchbar>
14747
- }
14748
-
14749
- @if (props.showRandomSelect && props.selectionMode !== 'none') {
14750
- <ion-button
14751
- fill="outline"
14752
- [color]="props.color || 'primary'"
14753
- (click)="selectRandom()"
14754
- [disabled]="availableCount < (props.randomSelectCount || 1)"
14755
- >
14756
- <ion-icon slot="start" name="shuffle-outline"></ion-icon>
14757
- {{ getRandomSelectLabel() }}
14758
- </ion-button>
14759
- }
14760
- </div>
14761
- }
14762
-
14763
- <!-- Legend (top) -->
14764
- @if (props.showLegend && props.legendPosition !== 'bottom') {
14765
- <div class="ticket-legend">
14766
- @for (item of getLegendItems(); track item.status) {
14767
- <div class="legend-item">
14768
- <span class="legend-color" [class]="'status-' + item.status"></span>
14769
- <span class="legend-label">{{ item.label }}</span>
14770
- @if (item.count !== undefined) {
14771
- <span class="legend-count">({{ item.count }})</span>
14772
- }
14773
- </div>
14774
- }
14775
- </div>
14776
- }
14777
-
14778
- <!-- Summary -->
14779
- @if (props.showSummary) {
14780
- <div class="ticket-summary">
14781
- <span class="summary-item">
14782
- <strong>{{ selectedTickets.length }}</strong> seleccionado{{ selectedTickets.length !== 1 ? 's' : '' }}
14783
- </span>
14784
- @if (props.maxSelection) {
14785
- <span class="summary-item">
14786
- (máx: {{ props.maxSelection }})
14787
- </span>
14788
- }
14789
- </div>
14790
- }
14791
-
14792
- <!-- Grid -->
14793
- <div class="ticket-grid" role="grid">
14794
- @for (ticket of displayedTickets; track ticket.number) {
14795
- <button
14796
- type="button"
14797
- class="ticket-cell"
14798
- [class]="'status-' + ticket.status"
14799
- [class.highlighted]="isHighlighted(ticket.number)"
14800
- [disabled]="!isSelectable(ticket)"
14801
- [attr.aria-label]="getTicketAriaLabel(ticket)"
14802
- [attr.aria-pressed]="ticket.status === 'selected'"
14803
- (click)="onTicketClick(ticket)"
14804
- >
14805
- {{ formatNumber(ticket.number) }}
14806
- </button>
14807
- }
14808
- </div>
14809
-
14810
- <!-- Legend (bottom) -->
14811
- @if (props.showLegend && props.legendPosition === 'bottom') {
14812
- <div class="ticket-legend bottom">
14813
- @for (item of getLegendItems(); track item.status) {
14814
- <div class="legend-item">
14815
- <span class="legend-color" [class]="'status-' + item.status"></span>
14816
- <span class="legend-label">{{ item.label }}</span>
14817
- @if (item.count !== undefined) {
14818
- <span class="legend-count">({{ item.count }})</span>
14819
- }
14820
- </div>
14821
- }
14822
- </div>
14823
- }
14824
- </div>
14825
- `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:block}.ticket-grid-container{--grid-columns: 10;--grid-gap: 4px;--selected-color: var(--ion-color-primary);display:flex;flex-direction:column;gap:16px}.grid-controls{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.ticket-search{flex:1;min-width:200px;max-width:300px;--border-radius: 8px}.ticket-legend{display:flex;flex-wrap:wrap;gap:16px;padding:8px 0}.ticket-legend.bottom{border-top:1px solid var(--ion-color-light-shade);padding-top:12px;margin-top:8px}.legend-item{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--ion-color-medium-shade)}.legend-color{width:16px;height:16px;border-radius:4px;border:1px solid var(--ion-color-medium)}.legend-color.status-available{background:var(--ion-color-light);border-color:var(--ion-color-medium)}.legend-color.status-selected{background:var(--selected-color);border-color:var(--selected-color)}.legend-color.status-sold{background:var(--ion-color-medium);border-color:var(--ion-color-medium-shade)}.legend-color.status-reserved{background:var(--ion-color-warning-tint);border-color:var(--ion-color-warning)}.legend-color.status-disabled{background:var(--ion-color-light-shade);border-color:var(--ion-color-medium);opacity:.5}.legend-count{color:var(--ion-color-medium);font-size:11px}.ticket-summary{display:flex;gap:8px;align-items:center;font-size:14px;color:var(--ion-color-dark);padding:8px 12px;background:var(--ion-color-light);border-radius:8px}.summary-item:not(:last-child):after{content:\"\\2022\";margin-left:8px;color:var(--ion-color-medium)}.ticket-grid{display:grid;grid-template-columns:repeat(var(--grid-columns),1fr);gap:var(--grid-gap)}.ticket-cell{aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:1px solid var(--ion-color-medium);border-radius:4px;background:var(--ion-color-light);font-size:12px;font-weight:500;color:var(--ion-color-dark);cursor:pointer;transition:all .15s ease;padding:0;font-family:inherit}.ticket-cell:hover:not(:disabled){border-color:var(--selected-color);transform:scale(1.05);z-index:1}.ticket-cell:focus{outline:2px solid var(--selected-color);outline-offset:1px}.ticket-cell.status-available{background:var(--ion-color-light);border-color:var(--ion-color-medium)}.ticket-cell.status-available:hover:not(:disabled){background:var(--ion-color-light-shade)}.ticket-cell.status-selected{background:var(--selected-color);border-color:var(--selected-color);color:#fff;font-weight:600}.ticket-cell.status-sold{background:var(--ion-color-medium);border-color:var(--ion-color-medium-shade);color:var(--ion-color-medium-contrast);cursor:not-allowed;opacity:.7}.ticket-cell.status-reserved{background:var(--ion-color-warning-tint);border-color:var(--ion-color-warning);color:var(--ion-color-warning-shade);cursor:not-allowed}.ticket-cell.status-disabled{background:var(--ion-color-light-shade);border-color:var(--ion-color-medium);color:var(--ion-color-medium);cursor:not-allowed;opacity:.5}.ticket-cell.highlighted{box-shadow:0 0 0 2px var(--ion-color-tertiary);z-index:2}.ticket-cell:disabled{cursor:not-allowed}.size-small .ticket-grid{--grid-gap: 2px}.size-small .ticket-cell{font-size:10px;border-radius:2px}.size-small .ticket-legend{gap:12px}.size-small .legend-color{width:12px;height:12px}.size-small .legend-item{font-size:11px}.size-large .ticket-grid{--grid-gap: 6px}.size-large .ticket-cell{font-size:14px;border-radius:6px;font-weight:600}.size-large .ticket-legend{gap:20px}.size-large .legend-color{width:20px;height:20px}.size-large .legend-item{font-size:14px}@media (max-width: 576px){.grid-controls{flex-direction:column;align-items:stretch}.ticket-search{max-width:100%}.ticket-legend{justify-content:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }] }); }
14826
- }
14827
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TicketGridComponent, decorators: [{
14828
- type: Component,
14829
- args: [{ selector: 'val-ticket-grid', standalone: true, imports: [CommonModule, FormsModule, IonButton, IonIcon, IonSearchbar], template: `
14830
- <div
14831
- class="ticket-grid-container"
14832
- [class]="props.cssClass"
14833
- [class.size-small]="props.ticketSize === 'small'"
14834
- [class.size-medium]="props.ticketSize === 'medium' || !props.ticketSize"
14835
- [class.size-large]="props.ticketSize === 'large'"
14836
- [style.--grid-columns]="props.columns || 10"
14837
- [style.--grid-gap]="(props.gap || 4) + 'px'"
14838
- [style.--selected-color]="getColor()"
14839
- >
14840
- <!-- Search and controls -->
14841
- @if (props.showSearch || props.showRandomSelect) {
14842
- <div class="grid-controls">
14843
- @if (props.showSearch) {
14844
- <ion-searchbar
14845
- [placeholder]="getSearchPlaceholder()"
14846
- [debounce]="300"
14847
- (ionInput)="onSearch($event)"
14848
- class="ticket-search"
14849
- ></ion-searchbar>
14850
- }
14851
-
14852
- @if (props.showRandomSelect && props.selectionMode !== 'none') {
14853
- <ion-button
14854
- fill="outline"
14855
- [color]="props.color || 'primary'"
14856
- (click)="selectRandom()"
14857
- [disabled]="availableCount < (props.randomSelectCount || 1)"
14858
- >
14859
- <ion-icon slot="start" name="shuffle-outline"></ion-icon>
14860
- {{ getRandomSelectLabel() }}
14861
- </ion-button>
14862
- }
14863
- </div>
14864
- }
14865
-
14866
- <!-- Legend (top) -->
14867
- @if (props.showLegend && props.legendPosition !== 'bottom') {
14868
- <div class="ticket-legend">
14869
- @for (item of getLegendItems(); track item.status) {
14870
- <div class="legend-item">
14871
- <span class="legend-color" [class]="'status-' + item.status"></span>
14872
- <span class="legend-label">{{ item.label }}</span>
14873
- @if (item.count !== undefined) {
14874
- <span class="legend-count">({{ item.count }})</span>
14875
- }
14876
- </div>
14877
- }
14878
- </div>
14879
- }
14880
-
14881
- <!-- Summary -->
14882
- @if (props.showSummary) {
14883
- <div class="ticket-summary">
14884
- <span class="summary-item">
14885
- <strong>{{ selectedTickets.length }}</strong> seleccionado{{ selectedTickets.length !== 1 ? 's' : '' }}
14886
- </span>
14887
- @if (props.maxSelection) {
14888
- <span class="summary-item">
14889
- (máx: {{ props.maxSelection }})
14890
- </span>
14891
- }
14892
- </div>
14893
- }
14894
-
14895
- <!-- Grid -->
14896
- <div class="ticket-grid" role="grid">
14897
- @for (ticket of displayedTickets; track ticket.number) {
14898
- <button
14899
- type="button"
14900
- class="ticket-cell"
14901
- [class]="'status-' + ticket.status"
14902
- [class.highlighted]="isHighlighted(ticket.number)"
14903
- [disabled]="!isSelectable(ticket)"
14904
- [attr.aria-label]="getTicketAriaLabel(ticket)"
14905
- [attr.aria-pressed]="ticket.status === 'selected'"
14906
- (click)="onTicketClick(ticket)"
14907
- >
14908
- {{ formatNumber(ticket.number) }}
14909
- </button>
14910
- }
14911
- </div>
14912
-
14913
- <!-- Legend (bottom) -->
14914
- @if (props.showLegend && props.legendPosition === 'bottom') {
14915
- <div class="ticket-legend bottom">
14916
- @for (item of getLegendItems(); track item.status) {
14917
- <div class="legend-item">
14918
- <span class="legend-color" [class]="'status-' + item.status"></span>
14919
- <span class="legend-label">{{ item.label }}</span>
14920
- @if (item.count !== undefined) {
14921
- <span class="legend-count">({{ item.count }})</span>
14922
- }
14923
- </div>
14924
- }
14925
- </div>
14926
- }
14927
- </div>
14928
- `, styles: ["@charset \"UTF-8\";:host{display:block}.ticket-grid-container{--grid-columns: 10;--grid-gap: 4px;--selected-color: var(--ion-color-primary);display:flex;flex-direction:column;gap:16px}.grid-controls{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.ticket-search{flex:1;min-width:200px;max-width:300px;--border-radius: 8px}.ticket-legend{display:flex;flex-wrap:wrap;gap:16px;padding:8px 0}.ticket-legend.bottom{border-top:1px solid var(--ion-color-light-shade);padding-top:12px;margin-top:8px}.legend-item{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--ion-color-medium-shade)}.legend-color{width:16px;height:16px;border-radius:4px;border:1px solid var(--ion-color-medium)}.legend-color.status-available{background:var(--ion-color-light);border-color:var(--ion-color-medium)}.legend-color.status-selected{background:var(--selected-color);border-color:var(--selected-color)}.legend-color.status-sold{background:var(--ion-color-medium);border-color:var(--ion-color-medium-shade)}.legend-color.status-reserved{background:var(--ion-color-warning-tint);border-color:var(--ion-color-warning)}.legend-color.status-disabled{background:var(--ion-color-light-shade);border-color:var(--ion-color-medium);opacity:.5}.legend-count{color:var(--ion-color-medium);font-size:11px}.ticket-summary{display:flex;gap:8px;align-items:center;font-size:14px;color:var(--ion-color-dark);padding:8px 12px;background:var(--ion-color-light);border-radius:8px}.summary-item:not(:last-child):after{content:\"\\2022\";margin-left:8px;color:var(--ion-color-medium)}.ticket-grid{display:grid;grid-template-columns:repeat(var(--grid-columns),1fr);gap:var(--grid-gap)}.ticket-cell{aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:1px solid var(--ion-color-medium);border-radius:4px;background:var(--ion-color-light);font-size:12px;font-weight:500;color:var(--ion-color-dark);cursor:pointer;transition:all .15s ease;padding:0;font-family:inherit}.ticket-cell:hover:not(:disabled){border-color:var(--selected-color);transform:scale(1.05);z-index:1}.ticket-cell:focus{outline:2px solid var(--selected-color);outline-offset:1px}.ticket-cell.status-available{background:var(--ion-color-light);border-color:var(--ion-color-medium)}.ticket-cell.status-available:hover:not(:disabled){background:var(--ion-color-light-shade)}.ticket-cell.status-selected{background:var(--selected-color);border-color:var(--selected-color);color:#fff;font-weight:600}.ticket-cell.status-sold{background:var(--ion-color-medium);border-color:var(--ion-color-medium-shade);color:var(--ion-color-medium-contrast);cursor:not-allowed;opacity:.7}.ticket-cell.status-reserved{background:var(--ion-color-warning-tint);border-color:var(--ion-color-warning);color:var(--ion-color-warning-shade);cursor:not-allowed}.ticket-cell.status-disabled{background:var(--ion-color-light-shade);border-color:var(--ion-color-medium);color:var(--ion-color-medium);cursor:not-allowed;opacity:.5}.ticket-cell.highlighted{box-shadow:0 0 0 2px var(--ion-color-tertiary);z-index:2}.ticket-cell:disabled{cursor:not-allowed}.size-small .ticket-grid{--grid-gap: 2px}.size-small .ticket-cell{font-size:10px;border-radius:2px}.size-small .ticket-legend{gap:12px}.size-small .legend-color{width:12px;height:12px}.size-small .legend-item{font-size:11px}.size-large .ticket-grid{--grid-gap: 6px}.size-large .ticket-cell{font-size:14px;border-radius:6px;font-weight:600}.size-large .ticket-legend{gap:20px}.size-large .legend-color{width:20px;height:20px}.size-large .legend-item{font-size:14px}@media (max-width: 576px){.grid-controls{flex-direction:column;align-items:stretch}.ticket-search{max-width:100%}.ticket-legend{justify-content:center}}\n"] }]
14929
- }], propDecorators: { props: [{
14930
- type: Input
14931
- }], selectionChange: [{
14932
- type: Output
14933
- }], ticketClick: [{
14934
- type: Output
14935
- }] } });
14936
-
14937
14445
  /**
14938
14446
  * Default platform configurations.
14939
14447
  */
@@ -15288,1380 +14796,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15288
14796
  type: Output
15289
14797
  }] } });
15290
14798
 
15291
- /**
15292
- * Default labels.
15293
- */
15294
- const DEFAULT_WINNER_LABELS = {
15295
- winner: '¡Ganador!',
15296
- ticket: 'Boleto #',
15297
- prize: 'Premio:',
15298
- };
15299
-
15300
- addIcons({ trophyOutline, ticketOutline, giftOutline, locationOutline });
15301
- /**
15302
- * val-winner-display
15303
- *
15304
- * A component for displaying raffle winners with celebration animations.
15305
- *
15306
- * @example Basic usage
15307
- * ```html
15308
- * <val-winner-display
15309
- * [props]="{
15310
- * winner: {
15311
- * name: 'Juan Pérez',
15312
- * ticketNumber: 42
15313
- * }
15314
- * }"
15315
- * ></val-winner-display>
15316
- * ```
15317
- *
15318
- * @example Full celebration mode
15319
- * ```html
15320
- * <val-winner-display
15321
- * [props]="{
15322
- * winner: {
15323
- * name: 'María García',
15324
- * ticketNumber: 156,
15325
- * prize: 'iPhone 15 Pro',
15326
- * prizeValue: 25000,
15327
- * location: 'CDMX, México',
15328
- * avatar: { image: 'avatar.jpg' }
15329
- * },
15330
- * mode: 'celebration',
15331
- * showConfetti: true,
15332
- * animation: 'zoom',
15333
- * color: 'warning'
15334
- * }"
15335
- * (animationComplete)="onReveal($event)"
15336
- * ></val-winner-display>
15337
- * ```
15338
- */
15339
- class WinnerDisplayComponent {
15340
- constructor() {
15341
- this.animationComplete = new EventEmitter();
15342
- this.isAnimating = false;
15343
- this.isRevealed = false;
15344
- this.showConfetti = false;
15345
- this.confettiPieces = Array.from({ length: 50 }, (_, i) => i);
15346
- this.revealTimeout = null;
15347
- this.animationTimeout = null;
15348
- this.elementRef = inject(ElementRef);
15349
- }
15350
- ngOnInit() {
15351
- if (this.props.autoPlay !== false) {
15352
- this.startReveal();
15353
- }
15354
- }
15355
- ngAfterViewInit() {
15356
- // Additional setup if needed
15357
- }
15358
- ngOnDestroy() {
15359
- if (this.revealTimeout)
15360
- clearTimeout(this.revealTimeout);
15361
- if (this.animationTimeout)
15362
- clearTimeout(this.animationTimeout);
15363
- }
15364
- startReveal() {
15365
- const delay = this.props.revealDelay || 0;
15366
- this.revealTimeout = setTimeout(() => {
15367
- this.isAnimating = true;
15368
- const animationDuration = this.props.animationDuration || 800;
15369
- this.animationTimeout = setTimeout(() => {
15370
- this.isAnimating = false;
15371
- this.isRevealed = true;
15372
- if (this.props.showConfetti) {
15373
- this.showConfetti = true;
15374
- }
15375
- this.animationComplete.emit({
15376
- animation: this.props.animation || 'fade',
15377
- winner: this.props.winner,
15378
- });
15379
- }, animationDuration);
15380
- }, delay);
15381
- }
15382
- /**
15383
- * Manually trigger the reveal animation.
15384
- */
15385
- reveal() {
15386
- this.isRevealed = false;
15387
- this.showConfetti = false;
15388
- this.startReveal();
15389
- }
15390
- /**
15391
- * Reset to initial state.
15392
- */
15393
- reset() {
15394
- this.isAnimating = false;
15395
- this.isRevealed = false;
15396
- this.showConfetti = false;
15397
- }
15398
- formatTicketNumber() {
15399
- const num = this.props.winner.ticketNumber;
15400
- if (this.props.numberPadding) {
15401
- return String(num).padStart(this.props.numberPadding, '0');
15402
- }
15403
- return String(num);
15404
- }
15405
- formatPrizeValue() {
15406
- if (!this.props.winner.prizeValue)
15407
- return '';
15408
- return `$${this.props.winner.prizeValue.toLocaleString('es-MX')}`;
15409
- }
15410
- getRandomX(index) {
15411
- return `${(index * 17) % 100}%`;
15412
- }
15413
- getRandomRotation(index) {
15414
- return `${(index * 37) % 360}deg`;
15415
- }
15416
- getWinnerLabel() {
15417
- return this.props.winnerLabel || DEFAULT_WINNER_LABELS.winner;
15418
- }
15419
- getTicketLabel() {
15420
- return this.props.ticketLabel || DEFAULT_WINNER_LABELS.ticket;
15421
- }
15422
- getPrizeLabel() {
15423
- return this.props.prizeLabel || DEFAULT_WINNER_LABELS.prize;
15424
- }
15425
- getColor() {
15426
- if (this.props.color) {
15427
- return `var(--ion-color-${this.props.color})`;
15428
- }
15429
- return 'var(--ion-color-warning)';
15430
- }
15431
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WinnerDisplayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15432
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WinnerDisplayComponent, isStandalone: true, selector: "val-winner-display", inputs: { props: "props" }, outputs: { animationComplete: "animationComplete" }, ngImport: i0, template: `
15433
- <div
15434
- class="winner-display-container"
15435
- [class]="props.cssClass"
15436
- [class.mode-compact]="props.mode === 'compact'"
15437
- [class.mode-standard]="props.mode === 'standard' || !props.mode"
15438
- [class.mode-full]="props.mode === 'full'"
15439
- [class.mode-celebration]="props.mode === 'celebration'"
15440
- [class.size-small]="props.size === 'small'"
15441
- [class.size-medium]="props.size === 'medium' || !props.size"
15442
- [class.size-large]="props.size === 'large'"
15443
- [class.bg-solid]="props.background === 'solid' || !props.background"
15444
- [class.bg-gradient]="props.background === 'gradient'"
15445
- [class.bg-transparent]="props.background === 'transparent'"
15446
- [class.animating]="isAnimating"
15447
- [class.revealed]="isRevealed"
15448
- [class.animation-fade]="props.animation === 'fade'"
15449
- [class.animation-zoom]="props.animation === 'zoom'"
15450
- [class.animation-slide]="props.animation === 'slide'"
15451
- [class.animation-spotlight]="props.animation === 'spotlight'"
15452
- [style.--winner-color]="getColor()"
15453
- [style.--animation-duration]="(props.animationDuration || 800) + 'ms'"
15454
- >
15455
- <!-- Confetti overlay -->
15456
- @if (props.showConfetti && (props.mode === 'celebration' || props.mode === 'full')) {
15457
- <div class="confetti-container" [class.active]="showConfetti">
15458
- @for (i of confettiPieces; track i) {
15459
- <div
15460
- class="confetti-piece"
15461
- [style.--delay]="i * 0.1 + 's'"
15462
- [style.--x]="getRandomX(i)"
15463
- [style.--rotation]="getRandomRotation(i)"
15464
- ></div>
15465
- }
15466
- </div>
15467
- }
15468
-
15469
- <!-- Trophy icon -->
15470
- @if (props.showTrophy !== false) {
15471
- <div class="trophy-container">
15472
- <ion-icon name="trophy-outline" class="trophy-icon"></ion-icon>
15473
- </div>
15474
- }
15475
-
15476
- <!-- Winner label -->
15477
- <div class="winner-label">{{ getWinnerLabel() }}</div>
15478
-
15479
- <!-- Winner info -->
15480
- <div class="winner-info">
15481
- <!-- Avatar -->
15482
- @if (props.winner.avatar && (props.mode === 'full' || props.mode === 'celebration')) {
15483
- <val-avatar [props]="props.winner.avatar" class="winner-avatar"></val-avatar>
15484
- }
15485
-
15486
- <!-- Name -->
15487
- <h2 class="winner-name">{{ props.winner.name }}</h2>
15488
-
15489
- <!-- Location -->
15490
- @if (props.showLocation !== false && props.winner.location) {
15491
- <div class="winner-location">
15492
- <ion-icon name="location-outline"></ion-icon>
15493
- <span>{{ props.winner.location }}</span>
15494
- </div>
15495
- }
15496
-
15497
- <!-- Ticket number -->
15498
- @if (props.showTicketNumber !== false) {
15499
- <div class="ticket-info">
15500
- <ion-icon name="ticket-outline"></ion-icon>
15501
- <span class="ticket-label">{{ getTicketLabel() }}</span>
15502
- <span class="ticket-number">{{ formatTicketNumber() }}</span>
15503
- </div>
15504
- }
15505
- </div>
15506
-
15507
- <!-- Prize info -->
15508
- @if (props.showPrize !== false && props.winner.prize) {
15509
- <div class="prize-info">
15510
- @if (props.winner.prizeImage && (props.mode === 'full' || props.mode === 'celebration')) {
15511
- <div class="prize-image">
15512
- <img [src]="props.winner.prizeImage" [alt]="props.winner.prize" />
15513
- </div>
15514
- }
15515
-
15516
- <div class="prize-details">
15517
- <div class="prize-header">
15518
- <ion-icon name="gift-outline"></ion-icon>
15519
- <span class="prize-label">{{ getPrizeLabel() }}</span>
15520
- </div>
15521
- <h3 class="prize-name">{{ props.winner.prize }}</h3>
15522
-
15523
- @if (props.winner.prizeDescription) {
15524
- <p class="prize-description">{{ props.winner.prizeDescription }}</p>
15525
- }
15526
-
15527
- @if (props.showPrizeValue !== false && props.winner.prizeValue) {
15528
- <div class="prize-value">
15529
- {{ formatPrizeValue() }}
15530
- </div>
15531
- }
15532
- </div>
15533
- </div>
15534
- }
15535
- </div>
15536
- `, isInline: true, styles: [":host{display:block}.winner-display-container{--winner-color: var(--ion-color-warning);--animation-duration: .8s;position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;padding:32px 24px;border-radius:16px;overflow:hidden}.bg-solid{background:var(--ion-color-light);border:2px solid var(--winner-color)}.bg-gradient{background:linear-gradient(135deg,var(--ion-color-light) 0%,rgba(var(--ion-color-warning-rgb),.1) 100%);border:2px solid var(--winner-color)}.bg-transparent{background:transparent}.trophy-container{margin-bottom:16px}.trophy-icon{font-size:56px;color:var(--winner-color);filter:drop-shadow(0 4px 8px rgba(0,0,0,.1))}.winner-label{font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:2px;color:var(--winner-color);margin-bottom:8px}.winner-info{display:flex;flex-direction:column;align-items:center;gap:8px;margin-bottom:16px}.winner-avatar{margin-bottom:8px}.winner-name{font-size:28px;font-weight:700;color:var(--ion-color-dark);margin:0;line-height:1.2}.winner-location{display:flex;align-items:center;gap:4px;font-size:14px;color:var(--ion-color-medium-shade)}.winner-location ion-icon{font-size:16px}.ticket-info{display:flex;align-items:center;gap:8px;padding:8px 16px;background:rgba(var(--ion-color-dark-rgb),.05);border-radius:24px;margin-top:8px}.ticket-info ion-icon{font-size:20px;color:var(--winner-color)}.ticket-label{font-size:14px;color:var(--ion-color-medium-shade)}.ticket-number{font-size:18px;font-weight:700;color:var(--ion-color-dark);font-variant-numeric:tabular-nums}.prize-info{display:flex;flex-direction:column;align-items:center;gap:12px;padding:16px;background:var(--ion-color-light-shade);border-radius:12px;width:100%;max-width:400px}.prize-image{width:120px;height:120px;border-radius:8px;overflow:hidden;background:#fff;box-shadow:0 4px 12px #0000001a}.prize-image img{width:100%;height:100%;object-fit:cover}.prize-details{display:flex;flex-direction:column;align-items:center;gap:4px}.prize-header{display:flex;align-items:center;gap:4px;color:var(--ion-color-medium-shade);font-size:12px}.prize-header ion-icon{font-size:16px;color:var(--winner-color)}.prize-label{text-transform:uppercase;letter-spacing:1px}.prize-name{font-size:20px;font-weight:600;color:var(--ion-color-dark);margin:0}.prize-description{font-size:14px;color:var(--ion-color-medium-shade);margin:4px 0 0}.prize-value{font-size:24px;font-weight:700;color:var(--winner-color);margin-top:8px}.confetti-container{position:absolute;inset:0;pointer-events:none;overflow:hidden;opacity:0;transition:opacity .3s}.confetti-container.active{opacity:1}.confetti-piece{position:absolute;width:10px;height:10px;top:-20px;left:var(--x, 50%);background:var(--winner-color);opacity:0;animation:confetti-fall 3s ease-out var(--delay, 0s) forwards}.confetti-piece:nth-child(2n){background:var(--ion-color-primary);width:8px;height:12px}.confetti-piece:nth-child(3n){background:var(--ion-color-danger);border-radius:50%}.confetti-piece:nth-child(5n){background:var(--ion-color-success);width:6px;height:14px}@keyframes confetti-fall{0%{opacity:1;transform:translateY(0) rotate(0)}to{opacity:0;transform:translateY(400px) rotate(var(--rotation, 720deg))}}.animation-fade:not(.revealed) .winner-info,.animation-fade:not(.revealed) .prize-info{opacity:0}.animation-fade.animating .winner-info,.animation-fade.animating .prize-info{animation:fade-in var(--animation-duration) ease-out forwards}.animation-zoom:not(.revealed) .winner-info,.animation-zoom:not(.revealed) .prize-info{opacity:0;transform:scale(.5)}.animation-zoom.animating .winner-info,.animation-zoom.animating .prize-info{animation:zoom-in var(--animation-duration) cubic-bezier(.34,1.56,.64,1) forwards}.animation-slide:not(.revealed) .winner-info,.animation-slide:not(.revealed) .prize-info{opacity:0;transform:translateY(40px)}.animation-slide.animating .winner-info,.animation-slide.animating .prize-info{animation:slide-up var(--animation-duration) ease-out forwards}.animation-slide.animating .prize-info{animation-delay:.2s}.animation-spotlight:not(.revealed) .winner-info,.animation-spotlight:not(.revealed) .prize-info{opacity:0}.animation-spotlight:not(.revealed):before{content:\"\";position:absolute;top:50%;left:50%;width:0;height:0;background:radial-gradient(circle,rgba(255,255,255,.8) 0%,transparent 70%);border-radius:50%;transform:translate(-50%,-50%)}.animation-spotlight.animating:before{animation:spotlight var(--animation-duration) ease-out forwards}.animation-spotlight.animating .winner-info,.animation-spotlight.animating .prize-info{animation:fade-in calc(var(--animation-duration) * .5) ease-out calc(var(--animation-duration) * .5) forwards}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes zoom-in{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}@keyframes slide-up{0%{opacity:0;transform:translateY(40px)}to{opacity:1;transform:translateY(0)}}@keyframes spotlight{0%{width:0;height:0}to{width:200%;height:200%}}.size-small{padding:20px 16px}.size-small .trophy-icon{font-size:40px}.size-small .winner-label{font-size:12px}.size-small .winner-name{font-size:20px}.size-small .ticket-number,.size-small .prize-name{font-size:16px}.size-small .prize-value{font-size:18px}.size-large{padding:48px 32px}.size-large .trophy-icon{font-size:80px}.size-large .winner-label{font-size:18px;letter-spacing:3px}.size-large .winner-name{font-size:40px}.size-large .ticket-number{font-size:24px}.size-large .prize-image{width:160px;height:160px}.size-large .prize-name{font-size:28px}.size-large .prize-value{font-size:32px}.mode-compact{padding:16px}.mode-compact .trophy-container,.mode-compact .prize-info{display:none}.mode-compact .winner-label{font-size:11px;margin-bottom:4px}.mode-compact .winner-name{font-size:18px}.mode-celebration .trophy-icon{animation:trophy-bounce 1s ease-in-out infinite}.mode-celebration.revealed .winner-name{animation:glow 2s ease-in-out infinite}@keyframes trophy-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}@keyframes glow{0%,to{text-shadow:0 0 10px rgba(var(--ion-color-warning-rgb),.3)}50%{text-shadow:0 0 20px rgba(var(--ion-color-warning-rgb),.6)}}\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"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
15537
- }
15538
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WinnerDisplayComponent, decorators: [{
15539
- type: Component,
15540
- args: [{ selector: 'val-winner-display', standalone: true, imports: [CommonModule, IonIcon, AvatarComponent], template: `
15541
- <div
15542
- class="winner-display-container"
15543
- [class]="props.cssClass"
15544
- [class.mode-compact]="props.mode === 'compact'"
15545
- [class.mode-standard]="props.mode === 'standard' || !props.mode"
15546
- [class.mode-full]="props.mode === 'full'"
15547
- [class.mode-celebration]="props.mode === 'celebration'"
15548
- [class.size-small]="props.size === 'small'"
15549
- [class.size-medium]="props.size === 'medium' || !props.size"
15550
- [class.size-large]="props.size === 'large'"
15551
- [class.bg-solid]="props.background === 'solid' || !props.background"
15552
- [class.bg-gradient]="props.background === 'gradient'"
15553
- [class.bg-transparent]="props.background === 'transparent'"
15554
- [class.animating]="isAnimating"
15555
- [class.revealed]="isRevealed"
15556
- [class.animation-fade]="props.animation === 'fade'"
15557
- [class.animation-zoom]="props.animation === 'zoom'"
15558
- [class.animation-slide]="props.animation === 'slide'"
15559
- [class.animation-spotlight]="props.animation === 'spotlight'"
15560
- [style.--winner-color]="getColor()"
15561
- [style.--animation-duration]="(props.animationDuration || 800) + 'ms'"
15562
- >
15563
- <!-- Confetti overlay -->
15564
- @if (props.showConfetti && (props.mode === 'celebration' || props.mode === 'full')) {
15565
- <div class="confetti-container" [class.active]="showConfetti">
15566
- @for (i of confettiPieces; track i) {
15567
- <div
15568
- class="confetti-piece"
15569
- [style.--delay]="i * 0.1 + 's'"
15570
- [style.--x]="getRandomX(i)"
15571
- [style.--rotation]="getRandomRotation(i)"
15572
- ></div>
15573
- }
15574
- </div>
15575
- }
15576
-
15577
- <!-- Trophy icon -->
15578
- @if (props.showTrophy !== false) {
15579
- <div class="trophy-container">
15580
- <ion-icon name="trophy-outline" class="trophy-icon"></ion-icon>
15581
- </div>
15582
- }
15583
-
15584
- <!-- Winner label -->
15585
- <div class="winner-label">{{ getWinnerLabel() }}</div>
15586
-
15587
- <!-- Winner info -->
15588
- <div class="winner-info">
15589
- <!-- Avatar -->
15590
- @if (props.winner.avatar && (props.mode === 'full' || props.mode === 'celebration')) {
15591
- <val-avatar [props]="props.winner.avatar" class="winner-avatar"></val-avatar>
15592
- }
15593
-
15594
- <!-- Name -->
15595
- <h2 class="winner-name">{{ props.winner.name }}</h2>
15596
-
15597
- <!-- Location -->
15598
- @if (props.showLocation !== false && props.winner.location) {
15599
- <div class="winner-location">
15600
- <ion-icon name="location-outline"></ion-icon>
15601
- <span>{{ props.winner.location }}</span>
15602
- </div>
15603
- }
15604
-
15605
- <!-- Ticket number -->
15606
- @if (props.showTicketNumber !== false) {
15607
- <div class="ticket-info">
15608
- <ion-icon name="ticket-outline"></ion-icon>
15609
- <span class="ticket-label">{{ getTicketLabel() }}</span>
15610
- <span class="ticket-number">{{ formatTicketNumber() }}</span>
15611
- </div>
15612
- }
15613
- </div>
15614
-
15615
- <!-- Prize info -->
15616
- @if (props.showPrize !== false && props.winner.prize) {
15617
- <div class="prize-info">
15618
- @if (props.winner.prizeImage && (props.mode === 'full' || props.mode === 'celebration')) {
15619
- <div class="prize-image">
15620
- <img [src]="props.winner.prizeImage" [alt]="props.winner.prize" />
15621
- </div>
15622
- }
15623
-
15624
- <div class="prize-details">
15625
- <div class="prize-header">
15626
- <ion-icon name="gift-outline"></ion-icon>
15627
- <span class="prize-label">{{ getPrizeLabel() }}</span>
15628
- </div>
15629
- <h3 class="prize-name">{{ props.winner.prize }}</h3>
15630
-
15631
- @if (props.winner.prizeDescription) {
15632
- <p class="prize-description">{{ props.winner.prizeDescription }}</p>
15633
- }
15634
-
15635
- @if (props.showPrizeValue !== false && props.winner.prizeValue) {
15636
- <div class="prize-value">
15637
- {{ formatPrizeValue() }}
15638
- </div>
15639
- }
15640
- </div>
15641
- </div>
15642
- }
15643
- </div>
15644
- `, styles: [":host{display:block}.winner-display-container{--winner-color: var(--ion-color-warning);--animation-duration: .8s;position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;padding:32px 24px;border-radius:16px;overflow:hidden}.bg-solid{background:var(--ion-color-light);border:2px solid var(--winner-color)}.bg-gradient{background:linear-gradient(135deg,var(--ion-color-light) 0%,rgba(var(--ion-color-warning-rgb),.1) 100%);border:2px solid var(--winner-color)}.bg-transparent{background:transparent}.trophy-container{margin-bottom:16px}.trophy-icon{font-size:56px;color:var(--winner-color);filter:drop-shadow(0 4px 8px rgba(0,0,0,.1))}.winner-label{font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:2px;color:var(--winner-color);margin-bottom:8px}.winner-info{display:flex;flex-direction:column;align-items:center;gap:8px;margin-bottom:16px}.winner-avatar{margin-bottom:8px}.winner-name{font-size:28px;font-weight:700;color:var(--ion-color-dark);margin:0;line-height:1.2}.winner-location{display:flex;align-items:center;gap:4px;font-size:14px;color:var(--ion-color-medium-shade)}.winner-location ion-icon{font-size:16px}.ticket-info{display:flex;align-items:center;gap:8px;padding:8px 16px;background:rgba(var(--ion-color-dark-rgb),.05);border-radius:24px;margin-top:8px}.ticket-info ion-icon{font-size:20px;color:var(--winner-color)}.ticket-label{font-size:14px;color:var(--ion-color-medium-shade)}.ticket-number{font-size:18px;font-weight:700;color:var(--ion-color-dark);font-variant-numeric:tabular-nums}.prize-info{display:flex;flex-direction:column;align-items:center;gap:12px;padding:16px;background:var(--ion-color-light-shade);border-radius:12px;width:100%;max-width:400px}.prize-image{width:120px;height:120px;border-radius:8px;overflow:hidden;background:#fff;box-shadow:0 4px 12px #0000001a}.prize-image img{width:100%;height:100%;object-fit:cover}.prize-details{display:flex;flex-direction:column;align-items:center;gap:4px}.prize-header{display:flex;align-items:center;gap:4px;color:var(--ion-color-medium-shade);font-size:12px}.prize-header ion-icon{font-size:16px;color:var(--winner-color)}.prize-label{text-transform:uppercase;letter-spacing:1px}.prize-name{font-size:20px;font-weight:600;color:var(--ion-color-dark);margin:0}.prize-description{font-size:14px;color:var(--ion-color-medium-shade);margin:4px 0 0}.prize-value{font-size:24px;font-weight:700;color:var(--winner-color);margin-top:8px}.confetti-container{position:absolute;inset:0;pointer-events:none;overflow:hidden;opacity:0;transition:opacity .3s}.confetti-container.active{opacity:1}.confetti-piece{position:absolute;width:10px;height:10px;top:-20px;left:var(--x, 50%);background:var(--winner-color);opacity:0;animation:confetti-fall 3s ease-out var(--delay, 0s) forwards}.confetti-piece:nth-child(2n){background:var(--ion-color-primary);width:8px;height:12px}.confetti-piece:nth-child(3n){background:var(--ion-color-danger);border-radius:50%}.confetti-piece:nth-child(5n){background:var(--ion-color-success);width:6px;height:14px}@keyframes confetti-fall{0%{opacity:1;transform:translateY(0) rotate(0)}to{opacity:0;transform:translateY(400px) rotate(var(--rotation, 720deg))}}.animation-fade:not(.revealed) .winner-info,.animation-fade:not(.revealed) .prize-info{opacity:0}.animation-fade.animating .winner-info,.animation-fade.animating .prize-info{animation:fade-in var(--animation-duration) ease-out forwards}.animation-zoom:not(.revealed) .winner-info,.animation-zoom:not(.revealed) .prize-info{opacity:0;transform:scale(.5)}.animation-zoom.animating .winner-info,.animation-zoom.animating .prize-info{animation:zoom-in var(--animation-duration) cubic-bezier(.34,1.56,.64,1) forwards}.animation-slide:not(.revealed) .winner-info,.animation-slide:not(.revealed) .prize-info{opacity:0;transform:translateY(40px)}.animation-slide.animating .winner-info,.animation-slide.animating .prize-info{animation:slide-up var(--animation-duration) ease-out forwards}.animation-slide.animating .prize-info{animation-delay:.2s}.animation-spotlight:not(.revealed) .winner-info,.animation-spotlight:not(.revealed) .prize-info{opacity:0}.animation-spotlight:not(.revealed):before{content:\"\";position:absolute;top:50%;left:50%;width:0;height:0;background:radial-gradient(circle,rgba(255,255,255,.8) 0%,transparent 70%);border-radius:50%;transform:translate(-50%,-50%)}.animation-spotlight.animating:before{animation:spotlight var(--animation-duration) ease-out forwards}.animation-spotlight.animating .winner-info,.animation-spotlight.animating .prize-info{animation:fade-in calc(var(--animation-duration) * .5) ease-out calc(var(--animation-duration) * .5) forwards}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes zoom-in{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}@keyframes slide-up{0%{opacity:0;transform:translateY(40px)}to{opacity:1;transform:translateY(0)}}@keyframes spotlight{0%{width:0;height:0}to{width:200%;height:200%}}.size-small{padding:20px 16px}.size-small .trophy-icon{font-size:40px}.size-small .winner-label{font-size:12px}.size-small .winner-name{font-size:20px}.size-small .ticket-number,.size-small .prize-name{font-size:16px}.size-small .prize-value{font-size:18px}.size-large{padding:48px 32px}.size-large .trophy-icon{font-size:80px}.size-large .winner-label{font-size:18px;letter-spacing:3px}.size-large .winner-name{font-size:40px}.size-large .ticket-number{font-size:24px}.size-large .prize-image{width:160px;height:160px}.size-large .prize-name{font-size:28px}.size-large .prize-value{font-size:32px}.mode-compact{padding:16px}.mode-compact .trophy-container,.mode-compact .prize-info{display:none}.mode-compact .winner-label{font-size:11px;margin-bottom:4px}.mode-compact .winner-name{font-size:18px}.mode-celebration .trophy-icon{animation:trophy-bounce 1s ease-in-out infinite}.mode-celebration.revealed .winner-name{animation:glow 2s ease-in-out infinite}@keyframes trophy-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}@keyframes glow{0%,to{text-shadow:0 0 10px rgba(var(--ion-color-warning-rgb),.3)}50%{text-shadow:0 0 20px rgba(var(--ion-color-warning-rgb),.6)}}\n"] }]
15645
- }], propDecorators: { props: [{
15646
- type: Input
15647
- }], animationComplete: [{
15648
- type: Output
15649
- }] } });
15650
-
15651
- /**
15652
- * Default status labels.
15653
- */
15654
- const DEFAULT_STATUS_LABELS = {
15655
- upcoming: 'Próximamente',
15656
- active: 'Activo',
15657
- sold_out: 'Agotado',
15658
- drawing: 'Sorteando',
15659
- completed: 'Finalizado',
15660
- cancelled: 'Cancelado',
15661
- };
15662
- /**
15663
- * Default status colors.
15664
- */
15665
- const DEFAULT_STATUS_COLORS = {
15666
- upcoming: 'medium',
15667
- active: 'success',
15668
- sold_out: 'warning',
15669
- drawing: 'tertiary',
15670
- completed: 'primary',
15671
- cancelled: 'danger',
15672
- };
15673
-
15674
- addIcons({
15675
- ticketOutline,
15676
- calendarOutline,
15677
- giftOutline,
15678
- heartOutline,
15679
- timeOutline,
15680
- });
15681
- /**
15682
- * val-raffle-status-card
15683
- *
15684
- * A card component for displaying raffle status and information.
15685
- *
15686
- * @example Basic usage
15687
- * ```html
15688
- * <val-raffle-status-card
15689
- * [props]="{
15690
- * title: 'Rifa Benéfica 2024',
15691
- * status: 'active',
15692
- * ticketPrice: 50,
15693
- * progress: {
15694
- * totalTickets: 1000,
15695
- * soldTickets: 450
15696
- * }
15697
- * }"
15698
- * ></val-raffle-status-card>
15699
- * ```
15700
- *
15701
- * @example Featured with prize
15702
- * ```html
15703
- * <val-raffle-status-card
15704
- * [props]="{
15705
- * title: 'Gran Sorteo iPhone 15',
15706
- * description: 'Participa y gana un iPhone 15 Pro Max',
15707
- * status: 'active',
15708
- * variant: 'featured',
15709
- * coverImage: { src: 'cover.jpg' },
15710
- * prize: {
15711
- * name: 'iPhone 15 Pro Max 256GB',
15712
- * value: 32000,
15713
- * image: { src: 'iphone.jpg' }
15714
- * },
15715
- * ticketPrice: 100,
15716
- * endDate: '2024-12-25',
15717
- * showCountdown: true,
15718
- * primaryAction: {
15719
- * label: 'Comprar boletos',
15720
- * color: 'success'
15721
- * }
15722
- * }"
15723
- * ></val-raffle-status-card>
15724
- * ```
15725
- */
15726
- class RaffleStatusCardComponent {
15727
- constructor() {
15728
- this.primaryActionClick = new EventEmitter();
15729
- this.secondaryActionClick = new EventEmitter();
15730
- }
15731
- get isActiveOrUpcoming() {
15732
- return this.props.status === 'active' || this.props.status === 'upcoming';
15733
- }
15734
- get progressPercentage() {
15735
- if (!this.props.progress)
15736
- return 0;
15737
- const { soldTickets, totalTickets } = this.props.progress;
15738
- if (totalTickets === 0)
15739
- return 0;
15740
- return Math.round((soldTickets / totalTickets) * 100);
15741
- }
15742
- getStatusLabel() {
15743
- const labels = { ...DEFAULT_STATUS_LABELS, ...this.props.statusLabels };
15744
- return labels[this.props.status] || this.props.status;
15745
- }
15746
- getStatusColor() {
15747
- if (this.props.statusColor)
15748
- return this.props.statusColor;
15749
- return DEFAULT_STATUS_COLORS[this.props.status] || 'medium';
15750
- }
15751
- getProgressColor() {
15752
- if (this.progressPercentage >= 100)
15753
- return 'success';
15754
- if (this.progressPercentage >= 75)
15755
- return 'warning';
15756
- return 'primary';
15757
- }
15758
- getTitle() {
15759
- return this.props.title || '';
15760
- }
15761
- getDescription() {
15762
- return this.props.description || '';
15763
- }
15764
- formatCurrency(amount) {
15765
- const symbol = this.props.currencySymbol || '$';
15766
- return `${symbol}${amount.toLocaleString('es-MX')}`;
15767
- }
15768
- formatDate(date) {
15769
- const d = typeof date === 'string' ? new Date(date) : date;
15770
- return d.toLocaleDateString('es-MX', {
15771
- day: 'numeric',
15772
- month: 'short',
15773
- year: 'numeric',
15774
- });
15775
- }
15776
- onPrimaryAction() {
15777
- this.primaryActionClick.emit();
15778
- }
15779
- onSecondaryAction() {
15780
- this.secondaryActionClick.emit();
15781
- }
15782
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RaffleStatusCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15783
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RaffleStatusCardComponent, isStandalone: true, selector: "val-raffle-status-card", inputs: { props: "props" }, outputs: { primaryActionClick: "primaryActionClick", secondaryActionClick: "secondaryActionClick" }, ngImport: i0, template: `
15784
- <article
15785
- class="raffle-card"
15786
- [class]="props.cssClass"
15787
- [class.variant-default]="props.variant === 'default' || !props.variant"
15788
- [class.variant-featured]="props.variant === 'featured'"
15789
- [class.variant-compact]="props.variant === 'compact'"
15790
- [class.variant-horizontal]="props.variant === 'horizontal'"
15791
- [class.size-small]="props.size === 'small'"
15792
- [class.size-medium]="props.size === 'medium' || !props.size"
15793
- [class.size-large]="props.size === 'large'"
15794
- [class]="'status-' + props.status"
15795
- >
15796
- <!-- Cover image -->
15797
- @if (props.coverImage && props.variant !== 'compact') {
15798
- <div class="card-image">
15799
- <val-image [props]="props.coverImage"></val-image>
15800
-
15801
- <!-- Status badge over image -->
15802
- @if (props.showStatusBadge !== false) {
15803
- <ion-badge [color]="getStatusColor()" class="status-badge">
15804
- {{ getStatusLabel() }}
15805
- </ion-badge>
15806
- }
15807
-
15808
- <!-- Countdown overlay -->
15809
- @if (props.showCountdown && props.endDate && isActiveOrUpcoming) {
15810
- <div class="countdown-overlay">
15811
- <val-countdown
15812
- [props]="{
15813
- targetDate: props.endDate,
15814
- format: 'compact',
15815
- size: 'small',
15816
- color: 'light'
15817
- }"
15818
- ></val-countdown>
15819
- </div>
15820
- }
15821
- </div>
15822
- }
15823
-
15824
- <div class="card-content">
15825
- <!-- Header -->
15826
- <header class="card-header">
15827
- @if (props.showStatusBadge !== false && (props.variant === 'compact' || !props.coverImage)) {
15828
- <ion-badge [color]="getStatusColor()" class="status-badge inline">
15829
- {{ getStatusLabel() }}
15830
- </ion-badge>
15831
- }
15832
-
15833
- <h3 class="card-title">{{ getTitle() }}</h3>
15834
-
15835
- @if (props.description) {
15836
- <p class="card-description">{{ getDescription() }}</p>
15837
- }
15838
- </header>
15839
-
15840
- <!-- Beneficiary -->
15841
- @if (props.beneficiary) {
15842
- <div class="beneficiary-info">
15843
- <ion-icon name="heart-outline"></ion-icon>
15844
- @if (props.beneficiaryImage) {
15845
- <val-image [props]="props.beneficiaryImage" class="beneficiary-image"></val-image>
15846
- }
15847
- <span>{{ props.beneficiary }}</span>
15848
- </div>
15849
- }
15850
-
15851
- <!-- Prize preview -->
15852
- @if (props.prize && props.variant !== 'compact') {
15853
- <div class="prize-preview">
15854
- <div class="prize-header">
15855
- <ion-icon name="gift-outline"></ion-icon>
15856
- <span>Premio</span>
15857
- </div>
15858
- <div class="prize-name">{{ props.prize.name }}</div>
15859
- @if (props.prize.value) {
15860
- <div class="prize-value">
15861
- {{ formatCurrency(props.prize.value) }}
15862
- </div>
15863
- }
15864
- </div>
15865
- }
15866
-
15867
- <!-- Progress -->
15868
- @if (props.showProgress !== false && props.progress) {
15869
- <div class="progress-section">
15870
- <div class="progress-header">
15871
- <span class="progress-label">Progreso</span>
15872
- <span class="progress-value">{{ progressPercentage }}%</span>
15873
- </div>
15874
- <ion-progress-bar
15875
- [value]="progressPercentage / 100"
15876
- [color]="getProgressColor()"
15877
- ></ion-progress-bar>
15878
- </div>
15879
- }
15880
-
15881
- <!-- Ticket stats -->
15882
- @if (props.showTicketStats !== false && props.progress) {
15883
- <div class="ticket-stats">
15884
- <div class="stat">
15885
- <ion-icon name="ticket-outline"></ion-icon>
15886
- <span class="stat-value">{{ props.progress.soldTickets }}</span>
15887
- <span class="stat-label">vendidos</span>
15888
- </div>
15889
- <div class="stat-divider"></div>
15890
- <div class="stat">
15891
- <span class="stat-value">{{ props.progress.totalTickets - props.progress.soldTickets }}</span>
15892
- <span class="stat-label">disponibles</span>
15893
- </div>
15894
- </div>
15895
- }
15896
-
15897
- <!-- Price -->
15898
- @if (props.showPrice !== false && props.ticketPrice) {
15899
- <div class="price-section">
15900
- <val-price-tag
15901
- [props]="{
15902
- amount: props.ticketPrice,
15903
- currency: props.currency || 'MXN',
15904
- currencySymbol: props.currencySymbol,
15905
- period: 'por boleto',
15906
- size: props.size === 'large' ? 'large' : 'medium',
15907
- variant: 'highlight'
15908
- }"
15909
- ></val-price-tag>
15910
- </div>
15911
- }
15912
-
15913
- <!-- Dates -->
15914
- @if (props.showDates !== false && (props.startDate || props.endDate)) {
15915
- <div class="dates-section">
15916
- @if (props.startDate) {
15917
- <div class="date-item">
15918
- <ion-icon name="calendar-outline"></ion-icon>
15919
- <span>Inicia: {{ formatDate(props.startDate) }}</span>
15920
- </div>
15921
- }
15922
- @if (props.endDate) {
15923
- <div class="date-item">
15924
- <ion-icon name="time-outline"></ion-icon>
15925
- <span>Sorteo: {{ formatDate(props.endDate) }}</span>
15926
- </div>
15927
- }
15928
- </div>
15929
- }
15930
-
15931
- <!-- Actions -->
15932
- @if (props.primaryAction || props.secondaryAction) {
15933
- <div class="card-actions">
15934
- @if (props.primaryAction) {
15935
- <val-button
15936
- [props]="props.primaryAction"
15937
- (click)="onPrimaryAction()"
15938
- ></val-button>
15939
- }
15940
- @if (props.secondaryAction) {
15941
- <val-button
15942
- [props]="props.secondaryAction"
15943
- (click)="onSecondaryAction()"
15944
- ></val-button>
15945
- }
15946
- </div>
15947
- }
15948
- </div>
15949
- </article>
15950
- `, isInline: true, styles: [":host{display:block}.raffle-card{display:flex;flex-direction:column;background:var(--ion-color-light);border-radius:12px;overflow:hidden;box-shadow:0 2px 8px #00000014;transition:transform .2s,box-shadow .2s}.raffle-card:hover{transform:translateY(-2px);box-shadow:0 4px 16px #0000001f}.card-image{position:relative;aspect-ratio:16/9;overflow:hidden}.card-image val-image{width:100%;height:100%}.card-image val-image ::ng-deep img{width:100%;height:100%;object-fit:cover}.status-badge{position:absolute;top:12px;left:12px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;padding:4px 10px;border-radius:4px}.status-badge.inline{position:static;margin-bottom:8px}.countdown-overlay{position:absolute;bottom:0;left:0;right:0;padding:8px 12px;background:linear-gradient(transparent,#000000b3)}.card-content{display:flex;flex-direction:column;gap:12px;padding:16px}.card-header{display:flex;flex-direction:column;gap:4px}.card-title{font-size:18px;font-weight:600;color:var(--ion-color-dark);margin:0;line-height:1.3}.card-description{font-size:14px;color:var(--ion-color-medium-shade);margin:0;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.beneficiary-info{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ion-color-medium-shade)}.beneficiary-info ion-icon{font-size:16px;color:var(--ion-color-danger)}.beneficiary-info .beneficiary-image{width:24px;height:24px;border-radius:50%;overflow:hidden}.prize-preview{padding:12px;background:var(--ion-color-light-shade);border-radius:8px}.prize-header{display:flex;align-items:center;gap:4px;font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--ion-color-medium);margin-bottom:4px}.prize-header ion-icon{font-size:14px;color:var(--ion-color-warning)}.prize-name{font-size:15px;font-weight:600;color:var(--ion-color-dark)}.prize-value{font-size:18px;font-weight:700;color:var(--ion-color-success);margin-top:4px}.progress-section{display:flex;flex-direction:column;gap:6px}.progress-header{display:flex;justify-content:space-between;align-items:center}.progress-label{font-size:12px;color:var(--ion-color-medium-shade)}.progress-value{font-size:14px;font-weight:600;color:var(--ion-color-dark)}ion-progress-bar{height:8px;border-radius:4px;--background: var(--ion-color-light-shade)}.ticket-stats{display:flex;align-items:center;justify-content:center;gap:16px;padding:12px;background:var(--ion-color-light-shade);border-radius:8px}.stat{display:flex;align-items:center;gap:6px;font-size:13px}.stat ion-icon{font-size:18px;color:var(--ion-color-primary)}.stat-value{font-weight:700;color:var(--ion-color-dark);font-size:16px}.stat-label{color:var(--ion-color-medium-shade)}.stat-divider{width:1px;height:24px;background:var(--ion-color-medium-tint)}.price-section{display:flex;justify-content:center;padding:8px 0}.dates-section{display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--ion-color-medium-shade)}.date-item{display:flex;align-items:center;gap:6px}.date-item ion-icon{font-size:16px;color:var(--ion-color-primary)}.card-actions{display:flex;gap:8px;margin-top:4px}.card-actions val-button{flex:1}.variant-featured{border:2px solid var(--ion-color-warning)}.variant-featured .card-image{aspect-ratio:2/1}.variant-featured .card-title{font-size:22px}.variant-compact .card-content{padding:12px;gap:8px}.variant-compact .card-title{font-size:15px}.variant-compact .card-description{font-size:13px;-webkit-line-clamp:1}.variant-compact .ticket-stats,.variant-compact .dates-section{display:none}.variant-horizontal{flex-direction:row}.variant-horizontal .card-image{width:40%;min-width:150px;aspect-ratio:1}.variant-horizontal .card-content{flex:1;justify-content:center}.size-small .card-content{padding:12px;gap:8px}.size-small .card-title{font-size:15px}.size-small .card-description{font-size:12px}.size-small .ticket-stats{padding:8px}.size-small .stat-value{font-size:14px}.size-large .card-content{padding:24px;gap:16px}.size-large .card-title{font-size:24px}.size-large .card-description{font-size:16px}.size-large .prize-name{font-size:18px}.size-large .prize-value{font-size:22px}.status-upcoming{opacity:.9}.status-sold_out .card-image:after{content:\"\";position:absolute;inset:0;background:#0000004d}.status-completed .card-actions{opacity:.5;pointer-events:none}.status-cancelled{opacity:.6}.status-cancelled .card-image:after{content:\"\";position:absolute;inset:0;background:#0006}@media (max-width: 480px){.variant-horizontal{flex-direction:column}.variant-horizontal .card-image{width:100%;aspect-ratio:16/9}}\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"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonProgressBar, selector: "ion-progress-bar", inputs: ["buffer", "color", "mode", "reversed", "type", "value"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: CountdownComponent, selector: "val-countdown", inputs: ["props"], outputs: ["complete", "tick"] }, { kind: "component", type: PriceTagComponent, selector: "val-price-tag", inputs: ["props"] }] }); }
15951
- }
15952
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RaffleStatusCardComponent, decorators: [{
15953
- type: Component,
15954
- args: [{ selector: 'val-raffle-status-card', standalone: true, imports: [
15955
- CommonModule,
15956
- IonIcon,
15957
- IonBadge,
15958
- IonProgressBar,
15959
- ImageComponent,
15960
- ButtonComponent,
15961
- CountdownComponent,
15962
- PriceTagComponent,
15963
- ], template: `
15964
- <article
15965
- class="raffle-card"
15966
- [class]="props.cssClass"
15967
- [class.variant-default]="props.variant === 'default' || !props.variant"
15968
- [class.variant-featured]="props.variant === 'featured'"
15969
- [class.variant-compact]="props.variant === 'compact'"
15970
- [class.variant-horizontal]="props.variant === 'horizontal'"
15971
- [class.size-small]="props.size === 'small'"
15972
- [class.size-medium]="props.size === 'medium' || !props.size"
15973
- [class.size-large]="props.size === 'large'"
15974
- [class]="'status-' + props.status"
15975
- >
15976
- <!-- Cover image -->
15977
- @if (props.coverImage && props.variant !== 'compact') {
15978
- <div class="card-image">
15979
- <val-image [props]="props.coverImage"></val-image>
15980
-
15981
- <!-- Status badge over image -->
15982
- @if (props.showStatusBadge !== false) {
15983
- <ion-badge [color]="getStatusColor()" class="status-badge">
15984
- {{ getStatusLabel() }}
15985
- </ion-badge>
15986
- }
15987
-
15988
- <!-- Countdown overlay -->
15989
- @if (props.showCountdown && props.endDate && isActiveOrUpcoming) {
15990
- <div class="countdown-overlay">
15991
- <val-countdown
15992
- [props]="{
15993
- targetDate: props.endDate,
15994
- format: 'compact',
15995
- size: 'small',
15996
- color: 'light'
15997
- }"
15998
- ></val-countdown>
15999
- </div>
16000
- }
16001
- </div>
16002
- }
16003
-
16004
- <div class="card-content">
16005
- <!-- Header -->
16006
- <header class="card-header">
16007
- @if (props.showStatusBadge !== false && (props.variant === 'compact' || !props.coverImage)) {
16008
- <ion-badge [color]="getStatusColor()" class="status-badge inline">
16009
- {{ getStatusLabel() }}
16010
- </ion-badge>
16011
- }
16012
-
16013
- <h3 class="card-title">{{ getTitle() }}</h3>
16014
-
16015
- @if (props.description) {
16016
- <p class="card-description">{{ getDescription() }}</p>
16017
- }
16018
- </header>
16019
-
16020
- <!-- Beneficiary -->
16021
- @if (props.beneficiary) {
16022
- <div class="beneficiary-info">
16023
- <ion-icon name="heart-outline"></ion-icon>
16024
- @if (props.beneficiaryImage) {
16025
- <val-image [props]="props.beneficiaryImage" class="beneficiary-image"></val-image>
16026
- }
16027
- <span>{{ props.beneficiary }}</span>
16028
- </div>
16029
- }
16030
-
16031
- <!-- Prize preview -->
16032
- @if (props.prize && props.variant !== 'compact') {
16033
- <div class="prize-preview">
16034
- <div class="prize-header">
16035
- <ion-icon name="gift-outline"></ion-icon>
16036
- <span>Premio</span>
16037
- </div>
16038
- <div class="prize-name">{{ props.prize.name }}</div>
16039
- @if (props.prize.value) {
16040
- <div class="prize-value">
16041
- {{ formatCurrency(props.prize.value) }}
16042
- </div>
16043
- }
16044
- </div>
16045
- }
16046
-
16047
- <!-- Progress -->
16048
- @if (props.showProgress !== false && props.progress) {
16049
- <div class="progress-section">
16050
- <div class="progress-header">
16051
- <span class="progress-label">Progreso</span>
16052
- <span class="progress-value">{{ progressPercentage }}%</span>
16053
- </div>
16054
- <ion-progress-bar
16055
- [value]="progressPercentage / 100"
16056
- [color]="getProgressColor()"
16057
- ></ion-progress-bar>
16058
- </div>
16059
- }
16060
-
16061
- <!-- Ticket stats -->
16062
- @if (props.showTicketStats !== false && props.progress) {
16063
- <div class="ticket-stats">
16064
- <div class="stat">
16065
- <ion-icon name="ticket-outline"></ion-icon>
16066
- <span class="stat-value">{{ props.progress.soldTickets }}</span>
16067
- <span class="stat-label">vendidos</span>
16068
- </div>
16069
- <div class="stat-divider"></div>
16070
- <div class="stat">
16071
- <span class="stat-value">{{ props.progress.totalTickets - props.progress.soldTickets }}</span>
16072
- <span class="stat-label">disponibles</span>
16073
- </div>
16074
- </div>
16075
- }
16076
-
16077
- <!-- Price -->
16078
- @if (props.showPrice !== false && props.ticketPrice) {
16079
- <div class="price-section">
16080
- <val-price-tag
16081
- [props]="{
16082
- amount: props.ticketPrice,
16083
- currency: props.currency || 'MXN',
16084
- currencySymbol: props.currencySymbol,
16085
- period: 'por boleto',
16086
- size: props.size === 'large' ? 'large' : 'medium',
16087
- variant: 'highlight'
16088
- }"
16089
- ></val-price-tag>
16090
- </div>
16091
- }
16092
-
16093
- <!-- Dates -->
16094
- @if (props.showDates !== false && (props.startDate || props.endDate)) {
16095
- <div class="dates-section">
16096
- @if (props.startDate) {
16097
- <div class="date-item">
16098
- <ion-icon name="calendar-outline"></ion-icon>
16099
- <span>Inicia: {{ formatDate(props.startDate) }}</span>
16100
- </div>
16101
- }
16102
- @if (props.endDate) {
16103
- <div class="date-item">
16104
- <ion-icon name="time-outline"></ion-icon>
16105
- <span>Sorteo: {{ formatDate(props.endDate) }}</span>
16106
- </div>
16107
- }
16108
- </div>
16109
- }
16110
-
16111
- <!-- Actions -->
16112
- @if (props.primaryAction || props.secondaryAction) {
16113
- <div class="card-actions">
16114
- @if (props.primaryAction) {
16115
- <val-button
16116
- [props]="props.primaryAction"
16117
- (click)="onPrimaryAction()"
16118
- ></val-button>
16119
- }
16120
- @if (props.secondaryAction) {
16121
- <val-button
16122
- [props]="props.secondaryAction"
16123
- (click)="onSecondaryAction()"
16124
- ></val-button>
16125
- }
16126
- </div>
16127
- }
16128
- </div>
16129
- </article>
16130
- `, styles: [":host{display:block}.raffle-card{display:flex;flex-direction:column;background:var(--ion-color-light);border-radius:12px;overflow:hidden;box-shadow:0 2px 8px #00000014;transition:transform .2s,box-shadow .2s}.raffle-card:hover{transform:translateY(-2px);box-shadow:0 4px 16px #0000001f}.card-image{position:relative;aspect-ratio:16/9;overflow:hidden}.card-image val-image{width:100%;height:100%}.card-image val-image ::ng-deep img{width:100%;height:100%;object-fit:cover}.status-badge{position:absolute;top:12px;left:12px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;padding:4px 10px;border-radius:4px}.status-badge.inline{position:static;margin-bottom:8px}.countdown-overlay{position:absolute;bottom:0;left:0;right:0;padding:8px 12px;background:linear-gradient(transparent,#000000b3)}.card-content{display:flex;flex-direction:column;gap:12px;padding:16px}.card-header{display:flex;flex-direction:column;gap:4px}.card-title{font-size:18px;font-weight:600;color:var(--ion-color-dark);margin:0;line-height:1.3}.card-description{font-size:14px;color:var(--ion-color-medium-shade);margin:0;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.beneficiary-info{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ion-color-medium-shade)}.beneficiary-info ion-icon{font-size:16px;color:var(--ion-color-danger)}.beneficiary-info .beneficiary-image{width:24px;height:24px;border-radius:50%;overflow:hidden}.prize-preview{padding:12px;background:var(--ion-color-light-shade);border-radius:8px}.prize-header{display:flex;align-items:center;gap:4px;font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--ion-color-medium);margin-bottom:4px}.prize-header ion-icon{font-size:14px;color:var(--ion-color-warning)}.prize-name{font-size:15px;font-weight:600;color:var(--ion-color-dark)}.prize-value{font-size:18px;font-weight:700;color:var(--ion-color-success);margin-top:4px}.progress-section{display:flex;flex-direction:column;gap:6px}.progress-header{display:flex;justify-content:space-between;align-items:center}.progress-label{font-size:12px;color:var(--ion-color-medium-shade)}.progress-value{font-size:14px;font-weight:600;color:var(--ion-color-dark)}ion-progress-bar{height:8px;border-radius:4px;--background: var(--ion-color-light-shade)}.ticket-stats{display:flex;align-items:center;justify-content:center;gap:16px;padding:12px;background:var(--ion-color-light-shade);border-radius:8px}.stat{display:flex;align-items:center;gap:6px;font-size:13px}.stat ion-icon{font-size:18px;color:var(--ion-color-primary)}.stat-value{font-weight:700;color:var(--ion-color-dark);font-size:16px}.stat-label{color:var(--ion-color-medium-shade)}.stat-divider{width:1px;height:24px;background:var(--ion-color-medium-tint)}.price-section{display:flex;justify-content:center;padding:8px 0}.dates-section{display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--ion-color-medium-shade)}.date-item{display:flex;align-items:center;gap:6px}.date-item ion-icon{font-size:16px;color:var(--ion-color-primary)}.card-actions{display:flex;gap:8px;margin-top:4px}.card-actions val-button{flex:1}.variant-featured{border:2px solid var(--ion-color-warning)}.variant-featured .card-image{aspect-ratio:2/1}.variant-featured .card-title{font-size:22px}.variant-compact .card-content{padding:12px;gap:8px}.variant-compact .card-title{font-size:15px}.variant-compact .card-description{font-size:13px;-webkit-line-clamp:1}.variant-compact .ticket-stats,.variant-compact .dates-section{display:none}.variant-horizontal{flex-direction:row}.variant-horizontal .card-image{width:40%;min-width:150px;aspect-ratio:1}.variant-horizontal .card-content{flex:1;justify-content:center}.size-small .card-content{padding:12px;gap:8px}.size-small .card-title{font-size:15px}.size-small .card-description{font-size:12px}.size-small .ticket-stats{padding:8px}.size-small .stat-value{font-size:14px}.size-large .card-content{padding:24px;gap:16px}.size-large .card-title{font-size:24px}.size-large .card-description{font-size:16px}.size-large .prize-name{font-size:18px}.size-large .prize-value{font-size:22px}.status-upcoming{opacity:.9}.status-sold_out .card-image:after{content:\"\";position:absolute;inset:0;background:#0000004d}.status-completed .card-actions{opacity:.5;pointer-events:none}.status-cancelled{opacity:.6}.status-cancelled .card-image:after{content:\"\";position:absolute;inset:0;background:#0006}@media (max-width: 480px){.variant-horizontal{flex-direction:column}.variant-horizontal .card-image{width:100%;aspect-ratio:16/9}}\n"] }]
16131
- }], propDecorators: { props: [{
16132
- type: Input
16133
- }], primaryActionClick: [{
16134
- type: Output
16135
- }], secondaryActionClick: [{
16136
- type: Output
16137
- }] } });
16138
-
16139
- /**
16140
- * Default payment status labels.
16141
- */
16142
- const DEFAULT_PAYMENT_STATUS_LABELS = {
16143
- pending: 'Pendiente',
16144
- processing: 'Procesando',
16145
- paid: 'Pagado',
16146
- refunded: 'Reembolsado',
16147
- failed: 'Fallido',
16148
- };
16149
- /**
16150
- * Default payment status colors.
16151
- */
16152
- const DEFAULT_PAYMENT_STATUS_COLORS = {
16153
- pending: 'warning',
16154
- processing: 'tertiary',
16155
- paid: 'success',
16156
- refunded: 'medium',
16157
- failed: 'danger',
16158
- };
16159
-
16160
- addIcons({
16161
- personOutline,
16162
- mailOutline,
16163
- callOutline,
16164
- ticketOutline,
16165
- locationOutline,
16166
- calendarOutline,
16167
- trophyOutline,
16168
- ellipsisVertical,
16169
- checkmarkCircle,
16170
- timeOutline,
16171
- closeCircle,
16172
- });
16173
- /**
16174
- * val-participant-card
16175
- *
16176
- * A card component for displaying participant information in a raffle.
16177
- *
16178
- * @example Basic usage
16179
- * ```html
16180
- * <val-participant-card
16181
- * [props]="{
16182
- * participant: {
16183
- * id: '1',
16184
- * name: 'Juan Pérez',
16185
- * email: 'juan@email.com',
16186
- * tickets: [42, 156, 789],
16187
- * paymentStatus: 'paid'
16188
- * }
16189
- * }"
16190
- * ></val-participant-card>
16191
- * ```
16192
- *
16193
- * @example Admin variant with actions
16194
- * ```html
16195
- * <val-participant-card
16196
- * [props]="{
16197
- * participant: participant,
16198
- * variant: 'admin',
16199
- * showActions: true,
16200
- * actions: [
16201
- * { id: 'edit', label: 'Editar', icon: 'create-outline' },
16202
- * { id: 'refund', label: 'Reembolsar', icon: 'cash-outline', color: 'warning' },
16203
- * { id: 'delete', label: 'Eliminar', icon: 'trash-outline', destructive: true }
16204
- * ]
16205
- * }"
16206
- * (cardClick)="onParticipantClick($event)"
16207
- * (actionClick)="onActionClick($event)"
16208
- * ></val-participant-card>
16209
- * ```
16210
- *
16211
- * @example Winner highlight
16212
- * ```html
16213
- * <val-participant-card
16214
- * [props]="{
16215
- * participant: {
16216
- * id: '1',
16217
- * name: 'María García',
16218
- * tickets: [{ number: 42, status: 'winner' }],
16219
- * isWinner: true,
16220
- * paymentStatus: 'paid'
16221
- * },
16222
- * highlightWinner: true,
16223
- * variant: 'detailed'
16224
- * }"
16225
- * ></val-participant-card>
16226
- * ```
16227
- */
16228
- class ParticipantCardComponent {
16229
- constructor() {
16230
- this.cardClick = new EventEmitter();
16231
- this.actionClick = new EventEmitter();
16232
- this.i18n = inject(I18nService);
16233
- this.showAllTickets = false;
16234
- }
16235
- /** Get winner badge text */
16236
- getWinnerText() {
16237
- return this.i18n.t('winner');
16238
- }
16239
- /** Get tickets count text */
16240
- getTicketsCountText(count) {
16241
- return `${count} ${count !== 1 ? this.i18n.t('tickets') : this.i18n.t('ticket')}`;
16242
- }
16243
- /** Get more tickets text */
16244
- getMoreText(count) {
16245
- return `+${count} ${this.i18n.t('more')}`;
16246
- }
16247
- /** Get notes label */
16248
- getNotesLabel() {
16249
- return this.i18n.t('notes');
16250
- }
16251
- get ticketNumbers() {
16252
- return this.props.participant.tickets || [];
16253
- }
16254
- get visibleTickets() {
16255
- const max = this.props.maxTicketsVisible || 5;
16256
- if (this.showAllTickets || this.ticketNumbers.length <= max) {
16257
- return this.ticketNumbers;
16258
- }
16259
- return this.ticketNumbers.slice(0, max);
16260
- }
16261
- get hiddenTicketsCount() {
16262
- if (this.showAllTickets)
16263
- return 0;
16264
- const max = this.props.maxTicketsVisible || 5;
16265
- return Math.max(0, this.ticketNumbers.length - max);
16266
- }
16267
- formatTicketNumber(ticket) {
16268
- const num = typeof ticket === 'number' ? ticket : ticket.number;
16269
- if (this.props.numberPadding) {
16270
- return String(num).padStart(this.props.numberPadding, '0');
16271
- }
16272
- return String(num);
16273
- }
16274
- getTicketColor(ticket) {
16275
- if (typeof ticket === 'number')
16276
- return 'primary';
16277
- switch (ticket.status) {
16278
- case 'winner':
16279
- return 'warning';
16280
- case 'reserved':
16281
- return 'tertiary';
16282
- case 'cancelled':
16283
- return 'medium';
16284
- default:
16285
- return 'primary';
16286
- }
16287
- }
16288
- isWinnerTicket(ticket) {
16289
- if (typeof ticket === 'number')
16290
- return false;
16291
- return ticket.status === 'winner';
16292
- }
16293
- getPaymentStatusLabel() {
16294
- const status = this.props.participant.paymentStatus;
16295
- if (!status)
16296
- return '';
16297
- // If custom labels are provided, use them first
16298
- if (this.props.paymentStatusLabels?.[status]) {
16299
- return this.props.paymentStatusLabels[status];
16300
- }
16301
- // Use i18n for default labels
16302
- const i18nKeys = {
16303
- pending: 'paymentPending',
16304
- processing: 'paymentProcessing',
16305
- paid: 'paymentPaid',
16306
- refunded: 'paymentRefunded',
16307
- failed: 'paymentFailed',
16308
- };
16309
- const key = i18nKeys[status];
16310
- return key ? this.i18n.t(key) : status;
16311
- }
16312
- getPaymentStatusColor() {
16313
- const status = this.props.participant.paymentStatus;
16314
- if (!status)
16315
- return 'medium';
16316
- return DEFAULT_PAYMENT_STATUS_COLORS[status] || 'medium';
16317
- }
16318
- getPaymentStatusIcon() {
16319
- const status = this.props.participant.paymentStatus;
16320
- switch (status) {
16321
- case 'paid':
16322
- return 'checkmark-circle';
16323
- case 'pending':
16324
- case 'processing':
16325
- return 'time-outline';
16326
- case 'failed':
16327
- case 'refunded':
16328
- return 'close-circle';
16329
- default:
16330
- return 'time-outline';
16331
- }
16332
- }
16333
- formatCurrency(amount) {
16334
- const symbol = this.props.currencySymbol || '$';
16335
- return `${symbol}${amount.toLocaleString('es-MX')}`;
16336
- }
16337
- formatDate(date) {
16338
- const d = typeof date === 'string' ? new Date(date) : date;
16339
- return d.toLocaleDateString('es-MX', {
16340
- day: 'numeric',
16341
- month: 'short',
16342
- year: 'numeric',
16343
- });
16344
- }
16345
- toggleShowAllTickets(event) {
16346
- event.stopPropagation();
16347
- this.showAllTickets = !this.showAllTickets;
16348
- }
16349
- onCardClick() {
16350
- if (!this.props.clickable)
16351
- return;
16352
- this.cardClick.emit({
16353
- participant: this.props.participant,
16354
- });
16355
- }
16356
- onActionsClick(event) {
16357
- event.stopPropagation();
16358
- // In a real implementation, this would open a popover menu
16359
- // For now, we'll emit the first action
16360
- if (this.props.actions?.length) {
16361
- this.actionClick.emit({
16362
- actionId: this.props.actions[0].id,
16363
- participant: this.props.participant,
16364
- });
16365
- }
16366
- }
16367
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ParticipantCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16368
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ParticipantCardComponent, isStandalone: true, selector: "val-participant-card", inputs: { props: "props" }, outputs: { cardClick: "cardClick", actionClick: "actionClick" }, ngImport: i0, template: `
16369
- <article
16370
- class="participant-card"
16371
- [class]="props.cssClass"
16372
- [class.variant-default]="props.variant === 'default' || !props.variant"
16373
- [class.variant-compact]="props.variant === 'compact'"
16374
- [class.variant-detailed]="props.variant === 'detailed'"
16375
- [class.variant-admin]="props.variant === 'admin'"
16376
- [class.size-small]="props.size === 'small'"
16377
- [class.size-medium]="props.size === 'medium' || !props.size"
16378
- [class.size-large]="props.size === 'large'"
16379
- [class.is-winner]="props.participant.isWinner && props.highlightWinner !== false"
16380
- [class.clickable]="props.clickable"
16381
- (click)="onCardClick()"
16382
- >
16383
- <!-- Winner badge -->
16384
- @if (props.participant.isWinner && props.highlightWinner !== false) {
16385
- <div class="winner-badge">
16386
- <ion-icon name="trophy-outline"></ion-icon>
16387
- <span>{{ getWinnerText() }}</span>
16388
- </div>
16389
- }
16390
-
16391
- <!-- Main content -->
16392
- <div class="card-main">
16393
- <!-- Avatar -->
16394
- @if (props.showAvatar !== false) {
16395
- <div class="avatar-section">
16396
- @if (props.participant.avatar) {
16397
- <val-avatar [props]="props.participant.avatar"></val-avatar>
16398
- } @else {
16399
- <div class="default-avatar">
16400
- <ion-icon name="person-outline"></ion-icon>
16401
- </div>
16402
- }
16403
- </div>
16404
- }
16405
-
16406
- <!-- Info -->
16407
- <div class="info-section">
16408
- <h4 class="participant-name">{{ props.participant.name }}</h4>
16409
-
16410
- @if (props.showEmail !== false && props.participant.email) {
16411
- <div class="info-item">
16412
- <ion-icon name="mail-outline"></ion-icon>
16413
- <span>{{ props.participant.email }}</span>
16414
- </div>
16415
- }
16416
-
16417
- @if (props.showPhone !== false && props.participant.phone) {
16418
- <div class="info-item">
16419
- <ion-icon name="call-outline"></ion-icon>
16420
- <span>{{ props.participant.phone }}</span>
16421
- </div>
16422
- }
16423
-
16424
- @if (props.participant.location) {
16425
- <div class="info-item">
16426
- <ion-icon name="location-outline"></ion-icon>
16427
- <span>{{ props.participant.location }}</span>
16428
- </div>
16429
- }
16430
-
16431
- @if (props.showDate !== false && props.participant.registrationDate) {
16432
- <div class="info-item">
16433
- <ion-icon name="calendar-outline"></ion-icon>
16434
- <span>{{ formatDate(props.participant.registrationDate) }}</span>
16435
- </div>
16436
- }
16437
- </div>
16438
-
16439
- <!-- Status & Amount (right side) -->
16440
- <div class="status-section">
16441
- @if (props.showPaymentStatus !== false && props.participant.paymentStatus) {
16442
- <ion-badge [color]="getPaymentStatusColor()" class="payment-badge">
16443
- <ion-icon [name]="getPaymentStatusIcon()"></ion-icon>
16444
- {{ getPaymentStatusLabel() }}
16445
- </ion-badge>
16446
- }
16447
-
16448
- @if (props.showAmount !== false && props.participant.amountPaid) {
16449
- <div class="amount">
16450
- {{ formatCurrency(props.participant.amountPaid) }}
16451
- </div>
16452
- }
16453
- </div>
16454
-
16455
- <!-- Actions menu -->
16456
- @if (props.showActions && props.actions?.length) {
16457
- <ion-button
16458
- fill="clear"
16459
- class="actions-button"
16460
- (click)="onActionsClick($event)"
16461
- >
16462
- <ion-icon slot="icon-only" name="ellipsis-vertical"></ion-icon>
16463
- </ion-button>
16464
- }
16465
- </div>
16466
-
16467
- <!-- Tickets section -->
16468
- @if (props.showTickets !== false && ticketNumbers.length > 0) {
16469
- <div class="tickets-section">
16470
- <div class="tickets-header">
16471
- <ion-icon name="ticket-outline"></ion-icon>
16472
- <span>{{ getTicketsCountText(ticketNumbers.length) }}</span>
16473
- </div>
16474
-
16475
- <div class="tickets-list">
16476
- @for (ticket of visibleTickets; track $index) {
16477
- <ion-chip
16478
- [color]="getTicketColor(ticket)"
16479
- [class.winner-ticket]="isWinnerTicket(ticket)"
16480
- class="ticket-chip"
16481
- >
16482
- @if (isWinnerTicket(ticket)) {
16483
- <ion-icon name="trophy-outline"></ion-icon>
16484
- }
16485
- {{ formatTicketNumber(ticket) }}
16486
- </ion-chip>
16487
- }
16488
-
16489
- @if (hiddenTicketsCount > 0) {
16490
- <ion-chip
16491
- color="medium"
16492
- class="more-tickets"
16493
- (click)="toggleShowAllTickets($event)"
16494
- >
16495
- {{ getMoreText(hiddenTicketsCount) }}
16496
- </ion-chip>
16497
- }
16498
- </div>
16499
- </div>
16500
- }
16501
-
16502
- <!-- Notes (admin variant) -->
16503
- @if (props.variant === 'admin' && props.participant.notes) {
16504
- <div class="notes-section">
16505
- <span class="notes-label">{{ getNotesLabel() }}</span>
16506
- <p class="notes-text">{{ props.participant.notes }}</p>
16507
- </div>
16508
- }
16509
- </article>
16510
- `, isInline: true, styles: [":host{display:block}.participant-card{position:relative;display:flex;flex-direction:column;gap:12px;padding:16px;background:var(--ion-color-light);border-radius:12px;border:1px solid var(--ion-color-light-shade);transition:all .2s}.participant-card.clickable{cursor:pointer}.participant-card.clickable:hover{background:var(--ion-color-light-shade);border-color:var(--ion-color-medium-tint)}.participant-card.clickable:active{transform:scale(.99)}.is-winner{border:2px solid var(--ion-color-warning);background:linear-gradient(135deg,var(--ion-color-light) 0%,rgba(var(--ion-color-warning-rgb),.1) 100%)}.winner-badge{position:absolute;top:-1px;right:16px;display:flex;align-items:center;gap:4px;padding:4px 12px;background:var(--ion-color-warning);color:var(--ion-color-warning-contrast);border-radius:0 0 8px 8px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.winner-badge ion-icon{font-size:14px}.card-main{display:flex;align-items:flex-start;gap:12px}.avatar-section{flex-shrink:0}.default-avatar{width:48px;height:48px;border-radius:50%;background:var(--ion-color-light-shade);display:flex;align-items:center;justify-content:center}.default-avatar ion-icon{font-size:24px;color:var(--ion-color-medium)}.info-section{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.participant-name{font-size:16px;font-weight:600;color:var(--ion-color-dark);margin:0;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.info-item{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--ion-color-medium-shade)}.info-item ion-icon{font-size:14px;color:var(--ion-color-medium);flex-shrink:0}.info-item span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.status-section{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex-shrink:0}.payment-badge{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:500;padding:4px 8px}.payment-badge ion-icon{font-size:12px}.amount{font-size:16px;font-weight:700;color:var(--ion-color-success)}.actions-button{--padding-start: 4px;--padding-end: 4px;margin:-8px -8px -8px 0}.tickets-section{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--ion-color-light-shade)}.tickets-header{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--ion-color-medium-shade)}.tickets-header ion-icon{font-size:16px;color:var(--ion-color-primary)}.tickets-list{display:flex;flex-wrap:wrap;gap:6px}.ticket-chip{--padding-start: 10px;--padding-end: 10px;height:28px;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}.ticket-chip ion-icon{font-size:14px;margin-right:4px}.ticket-chip.winner-ticket{--background: var(--ion-color-warning);--color: var(--ion-color-warning-contrast)}.more-tickets{--padding-start: 8px;--padding-end: 8px;cursor:pointer;font-size:12px}.notes-section{padding-top:12px;border-top:1px solid var(--ion-color-light-shade)}.notes-label{font-size:12px;color:var(--ion-color-medium);text-transform:uppercase;letter-spacing:.5px}.notes-text{margin:4px 0 0;font-size:13px;color:var(--ion-color-dark-shade);line-height:1.4}.variant-compact{padding:12px;gap:8px}.variant-compact .avatar-section{display:none}.variant-compact .participant-name{font-size:14px}.variant-compact .info-item{font-size:12px}.variant-compact .tickets-section{padding-top:8px}.variant-detailed .info-section{gap:6px}.variant-detailed .info-item{font-size:14px}.variant-admin{border-left:4px solid var(--ion-color-primary)}.variant-admin.is-winner{border-left-color:var(--ion-color-warning)}.size-small{padding:10px;gap:8px}.size-small .default-avatar{width:36px;height:36px}.size-small .default-avatar ion-icon{font-size:18px}.size-small .participant-name{font-size:14px}.size-small .info-item{font-size:12px}.size-small .amount{font-size:14px}.size-small .ticket-chip{height:24px;font-size:11px;--padding-start: 8px;--padding-end: 8px}.size-large{padding:20px;gap:16px}.size-large .default-avatar{width:64px;height:64px}.size-large .default-avatar ion-icon{font-size:32px}.size-large .participant-name{font-size:20px}.size-large .info-item{font-size:15px}.size-large .info-item ion-icon{font-size:18px}.size-large .amount{font-size:20px}.size-large .ticket-chip{height:32px;font-size:14px}@media (max-width: 480px){.card-main{flex-wrap:wrap}.status-section{flex-direction:row;width:100%;justify-content:space-between;margin-top:8px;padding-top:8px;border-top:1px solid var(--ion-color-light-shade)}}\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"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { 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: IonChip, selector: "ion-chip", inputs: ["color", "disabled", "mode", "outline"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
16511
- }
16512
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ParticipantCardComponent, decorators: [{
16513
- type: Component,
16514
- args: [{ selector: 'val-participant-card', standalone: true, imports: [CommonModule, IonIcon, IonBadge, IonButton, IonChip, AvatarComponent], template: `
16515
- <article
16516
- class="participant-card"
16517
- [class]="props.cssClass"
16518
- [class.variant-default]="props.variant === 'default' || !props.variant"
16519
- [class.variant-compact]="props.variant === 'compact'"
16520
- [class.variant-detailed]="props.variant === 'detailed'"
16521
- [class.variant-admin]="props.variant === 'admin'"
16522
- [class.size-small]="props.size === 'small'"
16523
- [class.size-medium]="props.size === 'medium' || !props.size"
16524
- [class.size-large]="props.size === 'large'"
16525
- [class.is-winner]="props.participant.isWinner && props.highlightWinner !== false"
16526
- [class.clickable]="props.clickable"
16527
- (click)="onCardClick()"
16528
- >
16529
- <!-- Winner badge -->
16530
- @if (props.participant.isWinner && props.highlightWinner !== false) {
16531
- <div class="winner-badge">
16532
- <ion-icon name="trophy-outline"></ion-icon>
16533
- <span>{{ getWinnerText() }}</span>
16534
- </div>
16535
- }
16536
-
16537
- <!-- Main content -->
16538
- <div class="card-main">
16539
- <!-- Avatar -->
16540
- @if (props.showAvatar !== false) {
16541
- <div class="avatar-section">
16542
- @if (props.participant.avatar) {
16543
- <val-avatar [props]="props.participant.avatar"></val-avatar>
16544
- } @else {
16545
- <div class="default-avatar">
16546
- <ion-icon name="person-outline"></ion-icon>
16547
- </div>
16548
- }
16549
- </div>
16550
- }
16551
-
16552
- <!-- Info -->
16553
- <div class="info-section">
16554
- <h4 class="participant-name">{{ props.participant.name }}</h4>
16555
-
16556
- @if (props.showEmail !== false && props.participant.email) {
16557
- <div class="info-item">
16558
- <ion-icon name="mail-outline"></ion-icon>
16559
- <span>{{ props.participant.email }}</span>
16560
- </div>
16561
- }
16562
-
16563
- @if (props.showPhone !== false && props.participant.phone) {
16564
- <div class="info-item">
16565
- <ion-icon name="call-outline"></ion-icon>
16566
- <span>{{ props.participant.phone }}</span>
16567
- </div>
16568
- }
16569
-
16570
- @if (props.participant.location) {
16571
- <div class="info-item">
16572
- <ion-icon name="location-outline"></ion-icon>
16573
- <span>{{ props.participant.location }}</span>
16574
- </div>
16575
- }
16576
-
16577
- @if (props.showDate !== false && props.participant.registrationDate) {
16578
- <div class="info-item">
16579
- <ion-icon name="calendar-outline"></ion-icon>
16580
- <span>{{ formatDate(props.participant.registrationDate) }}</span>
16581
- </div>
16582
- }
16583
- </div>
16584
-
16585
- <!-- Status & Amount (right side) -->
16586
- <div class="status-section">
16587
- @if (props.showPaymentStatus !== false && props.participant.paymentStatus) {
16588
- <ion-badge [color]="getPaymentStatusColor()" class="payment-badge">
16589
- <ion-icon [name]="getPaymentStatusIcon()"></ion-icon>
16590
- {{ getPaymentStatusLabel() }}
16591
- </ion-badge>
16592
- }
16593
-
16594
- @if (props.showAmount !== false && props.participant.amountPaid) {
16595
- <div class="amount">
16596
- {{ formatCurrency(props.participant.amountPaid) }}
16597
- </div>
16598
- }
16599
- </div>
16600
-
16601
- <!-- Actions menu -->
16602
- @if (props.showActions && props.actions?.length) {
16603
- <ion-button
16604
- fill="clear"
16605
- class="actions-button"
16606
- (click)="onActionsClick($event)"
16607
- >
16608
- <ion-icon slot="icon-only" name="ellipsis-vertical"></ion-icon>
16609
- </ion-button>
16610
- }
16611
- </div>
16612
-
16613
- <!-- Tickets section -->
16614
- @if (props.showTickets !== false && ticketNumbers.length > 0) {
16615
- <div class="tickets-section">
16616
- <div class="tickets-header">
16617
- <ion-icon name="ticket-outline"></ion-icon>
16618
- <span>{{ getTicketsCountText(ticketNumbers.length) }}</span>
16619
- </div>
16620
-
16621
- <div class="tickets-list">
16622
- @for (ticket of visibleTickets; track $index) {
16623
- <ion-chip
16624
- [color]="getTicketColor(ticket)"
16625
- [class.winner-ticket]="isWinnerTicket(ticket)"
16626
- class="ticket-chip"
16627
- >
16628
- @if (isWinnerTicket(ticket)) {
16629
- <ion-icon name="trophy-outline"></ion-icon>
16630
- }
16631
- {{ formatTicketNumber(ticket) }}
16632
- </ion-chip>
16633
- }
16634
-
16635
- @if (hiddenTicketsCount > 0) {
16636
- <ion-chip
16637
- color="medium"
16638
- class="more-tickets"
16639
- (click)="toggleShowAllTickets($event)"
16640
- >
16641
- {{ getMoreText(hiddenTicketsCount) }}
16642
- </ion-chip>
16643
- }
16644
- </div>
16645
- </div>
16646
- }
16647
-
16648
- <!-- Notes (admin variant) -->
16649
- @if (props.variant === 'admin' && props.participant.notes) {
16650
- <div class="notes-section">
16651
- <span class="notes-label">{{ getNotesLabel() }}</span>
16652
- <p class="notes-text">{{ props.participant.notes }}</p>
16653
- </div>
16654
- }
16655
- </article>
16656
- `, styles: [":host{display:block}.participant-card{position:relative;display:flex;flex-direction:column;gap:12px;padding:16px;background:var(--ion-color-light);border-radius:12px;border:1px solid var(--ion-color-light-shade);transition:all .2s}.participant-card.clickable{cursor:pointer}.participant-card.clickable:hover{background:var(--ion-color-light-shade);border-color:var(--ion-color-medium-tint)}.participant-card.clickable:active{transform:scale(.99)}.is-winner{border:2px solid var(--ion-color-warning);background:linear-gradient(135deg,var(--ion-color-light) 0%,rgba(var(--ion-color-warning-rgb),.1) 100%)}.winner-badge{position:absolute;top:-1px;right:16px;display:flex;align-items:center;gap:4px;padding:4px 12px;background:var(--ion-color-warning);color:var(--ion-color-warning-contrast);border-radius:0 0 8px 8px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.winner-badge ion-icon{font-size:14px}.card-main{display:flex;align-items:flex-start;gap:12px}.avatar-section{flex-shrink:0}.default-avatar{width:48px;height:48px;border-radius:50%;background:var(--ion-color-light-shade);display:flex;align-items:center;justify-content:center}.default-avatar ion-icon{font-size:24px;color:var(--ion-color-medium)}.info-section{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.participant-name{font-size:16px;font-weight:600;color:var(--ion-color-dark);margin:0;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.info-item{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--ion-color-medium-shade)}.info-item ion-icon{font-size:14px;color:var(--ion-color-medium);flex-shrink:0}.info-item span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.status-section{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex-shrink:0}.payment-badge{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:500;padding:4px 8px}.payment-badge ion-icon{font-size:12px}.amount{font-size:16px;font-weight:700;color:var(--ion-color-success)}.actions-button{--padding-start: 4px;--padding-end: 4px;margin:-8px -8px -8px 0}.tickets-section{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--ion-color-light-shade)}.tickets-header{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--ion-color-medium-shade)}.tickets-header ion-icon{font-size:16px;color:var(--ion-color-primary)}.tickets-list{display:flex;flex-wrap:wrap;gap:6px}.ticket-chip{--padding-start: 10px;--padding-end: 10px;height:28px;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}.ticket-chip ion-icon{font-size:14px;margin-right:4px}.ticket-chip.winner-ticket{--background: var(--ion-color-warning);--color: var(--ion-color-warning-contrast)}.more-tickets{--padding-start: 8px;--padding-end: 8px;cursor:pointer;font-size:12px}.notes-section{padding-top:12px;border-top:1px solid var(--ion-color-light-shade)}.notes-label{font-size:12px;color:var(--ion-color-medium);text-transform:uppercase;letter-spacing:.5px}.notes-text{margin:4px 0 0;font-size:13px;color:var(--ion-color-dark-shade);line-height:1.4}.variant-compact{padding:12px;gap:8px}.variant-compact .avatar-section{display:none}.variant-compact .participant-name{font-size:14px}.variant-compact .info-item{font-size:12px}.variant-compact .tickets-section{padding-top:8px}.variant-detailed .info-section{gap:6px}.variant-detailed .info-item{font-size:14px}.variant-admin{border-left:4px solid var(--ion-color-primary)}.variant-admin.is-winner{border-left-color:var(--ion-color-warning)}.size-small{padding:10px;gap:8px}.size-small .default-avatar{width:36px;height:36px}.size-small .default-avatar ion-icon{font-size:18px}.size-small .participant-name{font-size:14px}.size-small .info-item{font-size:12px}.size-small .amount{font-size:14px}.size-small .ticket-chip{height:24px;font-size:11px;--padding-start: 8px;--padding-end: 8px}.size-large{padding:20px;gap:16px}.size-large .default-avatar{width:64px;height:64px}.size-large .default-avatar ion-icon{font-size:32px}.size-large .participant-name{font-size:20px}.size-large .info-item{font-size:15px}.size-large .info-item ion-icon{font-size:18px}.size-large .amount{font-size:20px}.size-large .ticket-chip{height:32px;font-size:14px}@media (max-width: 480px){.card-main{flex-wrap:wrap}.status-section{flex-direction:row;width:100%;justify-content:space-between;margin-top:8px;padding-top:8px;border-top:1px solid var(--ion-color-light-shade)}}\n"] }]
16657
- }], propDecorators: { props: [{
16658
- type: Input
16659
- }], cardClick: [{
16660
- type: Output
16661
- }], actionClick: [{
16662
- type: Output
16663
- }] } });
16664
-
16665
14799
  /**
16666
14800
  * val-glow-card
16667
14801
  *
@@ -17177,77 +15311,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
17177
15311
  args: ['swiperContainer']
17178
15312
  }] } });
17179
15313
 
17180
- /**
17181
- * val-recap-card
17182
- *
17183
- * A decorative card component with geometric shapes, title, and link.
17184
- * Useful for recap sections, feature highlights, or promotional content.
17185
- *
17186
- * @example
17187
- * <val-recap-card
17188
- * [props]="{
17189
- * title: { title: 'Feature Title', subtitle: 'Subtitle here' },
17190
- * link: { text: 'Learn more', url: '/features' },
17191
- * color: 'primary',
17192
- * shapes: [
17193
- * { color: '#ffffff33', style: { top: '-20px', right: '-20px', width: '100px', height: '100px' } }
17194
- * ]
17195
- * }"
17196
- * ></val-recap-card>
17197
- *
17198
- * @input props - Card configuration (title, link, shapes, color)
17199
- */
17200
- class RecapCardComponent {
17201
- /**
17202
- * Merges shape color with additional styles.
17203
- */
17204
- mergeShapeStyle(shape) {
17205
- return { 'background-color': shape.color, ...(shape.style || {}) };
17206
- }
17207
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RecapCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17208
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: RecapCardComponent, isStandalone: true, selector: "val-recap-card", inputs: { props: "props" }, ngImport: i0, template: `
17209
- <ion-card class="recap-card" [color]="props.color || ''">
17210
- <div class="shapes">
17211
- <ng-container *ngFor="let shape of props.shapes">
17212
- <div class="shape" [ngStyle]="mergeShapeStyle(shape)"></div>
17213
- </ng-container>
17214
- </div>
17215
- <ion-card-content
17216
- class="recap-card__content"
17217
- [style.min-height]="props.minHeight || '400px'"
17218
- [style.min-width]="props.width || '280px'"
17219
- [style.max-width]="props.width || '280px'"
17220
- >
17221
- <val-title-block [props]="props.title" />
17222
- <val-link [props]="props.link" />
17223
- </ion-card-content>
17224
- </ion-card>
17225
- `, isInline: true, styles: [".recap-card{border-radius:24px;box-shadow:0 4px 10px #0000001a;margin:10px;position:relative;overflow:hidden}.recap-card .shapes{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.7;pointer-events:none}.recap-card .shapes .shape{position:absolute;border-radius:50%}.recap-card .recap-card__content{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:space-between;height:100%;min-height:400px;min-width:280px;max-width:280px;padding:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: LinkComponent, selector: "val-link", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TitleBlockComponent, selector: "val-title-block", inputs: ["props"] }] }); }
17226
- }
17227
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RecapCardComponent, decorators: [{
17228
- type: Component,
17229
- args: [{ selector: 'val-recap-card', standalone: true, imports: [CommonModule, IonCard, IonCardContent, LinkComponent, TitleBlockComponent], template: `
17230
- <ion-card class="recap-card" [color]="props.color || ''">
17231
- <div class="shapes">
17232
- <ng-container *ngFor="let shape of props.shapes">
17233
- <div class="shape" [ngStyle]="mergeShapeStyle(shape)"></div>
17234
- </ng-container>
17235
- </div>
17236
- <ion-card-content
17237
- class="recap-card__content"
17238
- [style.min-height]="props.minHeight || '400px'"
17239
- [style.min-width]="props.width || '280px'"
17240
- [style.max-width]="props.width || '280px'"
17241
- >
17242
- <val-title-block [props]="props.title" />
17243
- <val-link [props]="props.link" />
17244
- </ion-card-content>
17245
- </ion-card>
17246
- `, styles: [".recap-card{border-radius:24px;box-shadow:0 4px 10px #0000001a;margin:10px;position:relative;overflow:hidden}.recap-card .shapes{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.7;pointer-events:none}.recap-card .shapes .shape{position:absolute;border-radius:50%}.recap-card .recap-card__content{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:space-between;height:100%;min-height:400px;min-width:280px;max-width:280px;padding:16px}\n"] }]
17247
- }], propDecorators: { props: [{
17248
- type: Input
17249
- }] } });
17250
-
17251
15314
  /**
17252
15315
  * val-testimonial-card
17253
15316
  *
@@ -25466,17 +23529,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
25466
23529
  /**
25467
23530
  * val-cards-carousel
25468
23531
  *
25469
- * A horizontal carousel of recap cards with optional action header.
25470
- * Combines HorizontalScroll for smooth horizontal scrolling with RecapCard
25471
- * components for consistent card styling.
23532
+ * A horizontal carousel of cards with optional action header.
23533
+ * Combines HorizontalScroll for smooth horizontal scrolling with inline
23534
+ * card rendering for consistent card styling.
25472
23535
  *
25473
23536
  * @example
25474
23537
  * <val-cards-carousel
25475
23538
  * [props]="{
25476
23539
  * header: { title: 'Featured Items', actionType: 'link', actionLabel: 'View All' },
25477
23540
  * cards: [
25478
- * { title: 'Card 1', description: 'Description', href: '/item/1' },
25479
- * { title: 'Card 2', description: 'Description', href: '/item/2' }
23541
+ * { title: { title: 'Card 1' }, link: { text: 'Learn more', url: '/item/1' } },
23542
+ * { title: { title: 'Card 2' }, link: { text: 'Learn more', url: '/item/2' } }
25480
23543
  * ]
25481
23544
  * }"
25482
23545
  * ></val-cards-carousel>
@@ -25490,30 +23553,74 @@ class CardsCarouselComponent {
25490
23553
  */
25491
23554
  this.props = { cards: [] };
25492
23555
  }
23556
+ /**
23557
+ * Merges shape color with additional styles.
23558
+ */
23559
+ mergeShapeStyle(shape) {
23560
+ return { 'background-color': shape.color, ...(shape.style || {}) };
23561
+ }
25493
23562
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CardsCarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
25494
23563
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CardsCarouselComponent, isStandalone: true, selector: "val-cards-carousel", inputs: { props: "props" }, ngImport: i0, template: `
25495
23564
  @if (props.header) {
25496
23565
  <val-action-header [props]="props.header" />
25497
23566
  }
25498
23567
 
25499
- <val-horizontal-scroll [items]="props.cards" [itemTemplate]="recapCardTemplate" />
25500
- <ng-template #recapCardTemplate let-recap>
25501
- <val-recap-card [props]="recap" />
23568
+ <val-horizontal-scroll [items]="props.cards" [itemTemplate]="cardTemplate" />
23569
+ <ng-template #cardTemplate let-card>
23570
+ <ion-card class="carousel-card" [color]="card.color || ''">
23571
+ <div class="shapes">
23572
+ <ng-container *ngFor="let shape of card.shapes">
23573
+ <div class="shape" [ngStyle]="mergeShapeStyle(shape)"></div>
23574
+ </ng-container>
23575
+ </div>
23576
+ <ion-card-content
23577
+ class="carousel-card__content"
23578
+ [style.min-height]="card.minHeight || '400px'"
23579
+ [style.min-width]="card.width || '280px'"
23580
+ [style.max-width]="card.width || '280px'"
23581
+ >
23582
+ <val-title-block [props]="card.title" />
23583
+ <val-link [props]="card.link" />
23584
+ </ion-card-content>
23585
+ </ion-card>
25502
23586
  </ng-template>
25503
- `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: RecapCardComponent, selector: "val-recap-card", inputs: ["props"] }, { kind: "component", type: HorizontalScrollComponent, selector: "val-horizontal-scroll", inputs: ["items", "itemTemplate", "props"] }, { kind: "component", type: ActionHeaderComponent, selector: "val-action-header", inputs: ["props"] }] }); }
23587
+ `, isInline: true, styles: [":host{display:block}.carousel-card{border-radius:24px;box-shadow:0 4px 10px #0000001a;margin:10px;position:relative;overflow:hidden;.shapes{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.7;pointer-events:none;.shape{position:absolute;border-radius:50%}}.carousel-card__content{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:space-between;height:100%;padding:16px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: HorizontalScrollComponent, selector: "val-horizontal-scroll", inputs: ["items", "itemTemplate", "props"] }, { kind: "component", type: ActionHeaderComponent, selector: "val-action-header", inputs: ["props"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: LinkComponent, selector: "val-link", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TitleBlockComponent, selector: "val-title-block", inputs: ["props"] }] }); }
25504
23588
  }
25505
23589
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CardsCarouselComponent, decorators: [{
25506
23590
  type: Component,
25507
- args: [{ selector: 'val-cards-carousel', standalone: true, imports: [CommonModule, RecapCardComponent, HorizontalScrollComponent, ActionHeaderComponent], template: `
23591
+ args: [{ selector: 'val-cards-carousel', standalone: true, imports: [
23592
+ CommonModule,
23593
+ HorizontalScrollComponent,
23594
+ ActionHeaderComponent,
23595
+ IonCard,
23596
+ IonCardContent,
23597
+ LinkComponent,
23598
+ TitleBlockComponent,
23599
+ ], template: `
25508
23600
  @if (props.header) {
25509
23601
  <val-action-header [props]="props.header" />
25510
23602
  }
25511
23603
 
25512
- <val-horizontal-scroll [items]="props.cards" [itemTemplate]="recapCardTemplate" />
25513
- <ng-template #recapCardTemplate let-recap>
25514
- <val-recap-card [props]="recap" />
23604
+ <val-horizontal-scroll [items]="props.cards" [itemTemplate]="cardTemplate" />
23605
+ <ng-template #cardTemplate let-card>
23606
+ <ion-card class="carousel-card" [color]="card.color || ''">
23607
+ <div class="shapes">
23608
+ <ng-container *ngFor="let shape of card.shapes">
23609
+ <div class="shape" [ngStyle]="mergeShapeStyle(shape)"></div>
23610
+ </ng-container>
23611
+ </div>
23612
+ <ion-card-content
23613
+ class="carousel-card__content"
23614
+ [style.min-height]="card.minHeight || '400px'"
23615
+ [style.min-width]="card.width || '280px'"
23616
+ [style.max-width]="card.width || '280px'"
23617
+ >
23618
+ <val-title-block [props]="card.title" />
23619
+ <val-link [props]="card.link" />
23620
+ </ion-card-content>
23621
+ </ion-card>
25515
23622
  </ng-template>
25516
- `, styles: [":host{display:block}\n"] }]
23623
+ `, styles: [":host{display:block}.carousel-card{border-radius:24px;box-shadow:0 4px 10px #0000001a;margin:10px;position:relative;overflow:hidden;.shapes{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.7;pointer-events:none;.shape{position:absolute;border-radius:50%}}.carousel-card__content{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:space-between;height:100%;padding:16px}}\n"] }]
25517
23624
  }], propDecorators: { props: [{
25518
23625
  type: Input
25519
23626
  }] } });
@@ -30829,13 +28936,16 @@ class AuthService {
30829
28936
  this.stateService.updateRefreshToken(response.refreshToken); // NUEVO: guardar refresh rotado
30830
28937
  this.storageService.saveAccessToken(response.accessToken, expiresAt);
30831
28938
  this.storageService.saveRefreshToken(response.refreshToken); // NUEVO: persistir refresh rotado
28939
+ if (this.config.enableFirebaseIntegration && response.firebaseToken) {
28940
+ this.signInWithFirebase(response.firebaseToken);
28941
+ }
30832
28942
  this.startRefreshTimer();
30833
28943
  this.syncService.broadcast({
30834
28944
  type: 'TOKEN_REFRESH',
30835
28945
  payload: {
30836
28946
  accessToken: response.accessToken,
30837
28947
  refreshToken: response.refreshToken, // NUEVO: sincronizar entre tabs
30838
- expiresAt
28948
+ expiresAt,
30839
28949
  },
30840
28950
  });
30841
28951
  }), catchError$1(error => {
@@ -30977,9 +29087,7 @@ class AuthService {
30977
29087
  * ```
30978
29088
  */
30979
29089
  switchOrg(organizationId) {
30980
- return this.http
30981
- .post(`${this.baseUrl}/switch-org`, { organizationId })
30982
- .pipe(switchMap$1(response => {
29090
+ return this.http.post(`${this.baseUrl}/switch-org`, { organizationId }).pipe(switchMap$1(response => {
30983
29091
  // Re-autenticar en Firebase con el nuevo token
30984
29092
  // Usar switchMap + from para esperar a que Firebase complete
30985
29093
  const firebaseAuth$ = response.firebaseToken
@@ -31350,7 +29458,7 @@ class AuthService {
31350
29458
  console.warn('[ValtechAuth] MessagingService not available');
31351
29459
  return { granted: false };
31352
29460
  }
31353
- if (!await this.messagingService.isSupported()) {
29461
+ if (!(await this.messagingService.isSupported())) {
31354
29462
  console.warn('[ValtechAuth] Push notifications not supported');
31355
29463
  return { granted: false };
31356
29464
  }
@@ -31389,9 +29497,11 @@ class AuthService {
31389
29497
  const token = this.messagingService.currentToken;
31390
29498
  if (token) {
31391
29499
  // Eliminar del backend
31392
- await firstValueFrom(this.http.request('DELETE', `${this.config.apiUrl}/v2/users/me/devices/by-token`, {
31393
- body: { token }
31394
- }).pipe(catchError$1(() => of(null))));
29500
+ await firstValueFrom(this.http
29501
+ .request('DELETE', `${this.config.apiUrl}/v2/users/me/devices/by-token`, {
29502
+ body: { token },
29503
+ })
29504
+ .pipe(catchError$1(() => of(null))));
31395
29505
  // Eliminar token de FCM
31396
29506
  await this.messagingService.deleteToken();
31397
29507
  console.log('[ValtechAuth] Notifications disabled');
@@ -31448,7 +29558,7 @@ class AuthService {
31448
29558
  let token = providedToken || this.messagingService?.currentToken;
31449
29559
  // Si no hay token, intentar obtenerlo del MessagingService
31450
29560
  if (!token && this.messagingService) {
31451
- if (!await this.messagingService.isSupported()) {
29561
+ if (!(await this.messagingService.isSupported())) {
31452
29562
  return { registered: false, error: 'FCM no soportado en este navegador' };
31453
29563
  }
31454
29564
  token = await this.messagingService.getToken();
@@ -31458,7 +29568,12 @@ class AuthService {
31458
29568
  }
31459
29569
  // Registrar en backend
31460
29570
  const { platform, browser, os } = this.detectPlatformInfo();
31461
- const response = await firstValueFrom(this.http.post(`${this.config.apiUrl}/v2/users/me/devices`, { token, platform, browser, os }));
29571
+ const response = await firstValueFrom(this.http.post(`${this.config.apiUrl}/v2/users/me/devices`, {
29572
+ token,
29573
+ platform,
29574
+ browser,
29575
+ os,
29576
+ }));
31462
29577
  console.log('[ValtechAuth] Device registered manually:', response.device.deviceId);
31463
29578
  return { registered: true, deviceId: response.device.deviceId, token };
31464
29579
  }
@@ -31466,7 +29581,7 @@ class AuthService {
31466
29581
  console.warn('[ValtechAuth] Manual device registration failed:', error);
31467
29582
  return {
31468
29583
  registered: false,
31469
- error: error?.error?.message || error?.message || 'Error al registrar dispositivo'
29584
+ error: error?.error?.message || error?.message || 'Error al registrar dispositivo',
31470
29585
  };
31471
29586
  }
31472
29587
  }
@@ -31481,7 +29596,7 @@ class AuthService {
31481
29596
  }
31482
29597
  try {
31483
29598
  // Verificar si FCM está soportado
31484
- if (!await this.messagingService.isSupported()) {
29599
+ if (!(await this.messagingService.isSupported())) {
31485
29600
  return false;
31486
29601
  }
31487
29602
  // Verificar si ya tiene permisos
@@ -31496,7 +29611,12 @@ class AuthService {
31496
29611
  }
31497
29612
  // Registrar en backend
31498
29613
  const { platform, browser, os } = this.detectPlatformInfo();
31499
- await firstValueFrom(this.http.post(`${this.config.apiUrl}/v2/users/me/devices`, { token, platform, browser, os }));
29614
+ await firstValueFrom(this.http.post(`${this.config.apiUrl}/v2/users/me/devices`, {
29615
+ token,
29616
+ platform,
29617
+ browser,
29618
+ os,
29619
+ }));
31500
29620
  console.log('[ValtechAuth] Device registered successfully');
31501
29621
  return true;
31502
29622
  }
@@ -31517,9 +29637,12 @@ class AuthService {
31517
29637
  const token = this.messagingService.currentToken;
31518
29638
  if (token) {
31519
29639
  // Delete from backend (fire and forget)
31520
- this.http.request('DELETE', `${this.config.apiUrl}/v2/users/me/devices/by-token`, {
31521
- body: { token }
31522
- }).pipe(catchError$1(() => of(null))).subscribe();
29640
+ this.http
29641
+ .request('DELETE', `${this.config.apiUrl}/v2/users/me/devices/by-token`, {
29642
+ body: { token },
29643
+ })
29644
+ .pipe(catchError$1(() => of(null)))
29645
+ .subscribe();
31523
29646
  // Delete from FCM
31524
29647
  await this.messagingService.deleteToken();
31525
29648
  console.log('[ValtechAuth] Device unregistered');
@@ -34569,23 +32692,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
34569
32692
  type: Output
34570
32693
  }] } });
34571
32694
 
34572
- class LayoutComponent {
34573
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
34574
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: LayoutComponent, isStandalone: true, selector: "val-layout", ngImport: i0, template: `
34575
- <div class="layout-container">
34576
- <ng-content></ng-content>
34577
- </div>
34578
- `, 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)}.layout-container{margin:0 auto;padding:0;width:100%;box-sizing:border-box;margin-bottom:1rem;padding-top:.5rem}@media (max-width: 768px){.layout-container{max-width:100%}}@media (min-width: 768px){.layout-container{margin:0 auto;max-width:33.75rem;margin-bottom:1.5rem}}@media (min-width: 1200px){.layout-container{margin:0 auto;max-width:45rem}}\n"] }); }
34579
- }
34580
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LayoutComponent, decorators: [{
34581
- type: Component,
34582
- args: [{ selector: 'val-layout', standalone: true, imports: [], template: `
34583
- <div class="layout-container">
34584
- <ng-content></ng-content>
34585
- </div>
34586
- `, 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)}.layout-container{margin:0 auto;padding:0;width:100%;box-sizing:border-box;margin-bottom:1rem;padding-top:.5rem}@media (max-width: 768px){.layout-container{max-width:100%}}@media (min-width: 768px){.layout-container{margin:0 auto;max-width:33.75rem;margin-bottom:1.5rem}}@media (min-width: 1200px){.layout-container{margin:0 auto;max-width:45rem}}\n"] }]
34587
- }] });
34588
-
34589
32695
  class SimpleComponent {
34590
32696
  constructor() {
34591
32697
  this.onClick = new EventEmitter();
@@ -34633,12 +32739,12 @@ class SimpleComponent {
34633
32739
  @if (props.withDivider) {
34634
32740
  <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'dark' }" />
34635
32741
  }
34636
- <val-layout>
32742
+ <div class="layout-container">
34637
32743
  <ng-content select="[inner-container]"></ng-content>
34638
- </val-layout>
32744
+ </div>
34639
32745
  </ion-content>
34640
32746
  <ng-content select="[outter-container]"></ng-content>
34641
- `, isInline: true, styles: [".description-container{padding:0 16px}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: HeaderComponent, selector: "val-header", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: LayoutComponent, selector: "val-layout" }, { kind: "component", type: DividerComponent, selector: "val-divider", inputs: ["props"] }, { kind: "component", type: LinkComponent, selector: "val-link", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: ExpandableTextComponent, selector: "val-expandable-text", inputs: ["props"] }] }); }
32747
+ `, 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)}.description-container{padding:0 16px}.layout-container{margin:0 auto;padding:0;width:100%;box-sizing:border-box;margin-bottom:1rem;padding-top:.5rem}@media (max-width: 768px){.layout-container{max-width:100%}}@media (min-width: 768px){.layout-container{margin:0 auto;max-width:33.75rem;margin-bottom:1.5rem}}@media (min-width: 1200px){.layout-container{margin:0 auto;max-width:45rem}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: HeaderComponent, selector: "val-header", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: DividerComponent, selector: "val-divider", inputs: ["props"] }, { kind: "component", type: LinkComponent, selector: "val-link", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: ExpandableTextComponent, selector: "val-expandable-text", inputs: ["props"] }] }); }
34642
32748
  }
34643
32749
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SimpleComponent, decorators: [{
34644
32750
  type: Component,
@@ -34649,7 +32755,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
34649
32755
  IonTitle,
34650
32756
  IonContent,
34651
32757
  HeaderComponent,
34652
- LayoutComponent,
34653
32758
  DividerComponent,
34654
32759
  LinkComponent,
34655
32760
  ExpandableTextComponent,
@@ -34687,12 +32792,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
34687
32792
  @if (props.withDivider) {
34688
32793
  <val-divider [props]="{ fill: 'solid', size: 'medium', color: 'dark' }" />
34689
32794
  }
34690
- <val-layout>
32795
+ <div class="layout-container">
34691
32796
  <ng-content select="[inner-container]"></ng-content>
34692
- </val-layout>
32797
+ </div>
34693
32798
  </ion-content>
34694
32799
  <ng-content select="[outter-container]"></ng-content>
34695
- `, styles: [".description-container{padding:0 16px}\n"] }]
32800
+ `, 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)}.description-container{padding:0 16px}.layout-container{margin:0 auto;padding:0;width:100%;box-sizing:border-box;margin-bottom:1rem;padding-top:.5rem}@media (max-width: 768px){.layout-container{max-width:100%}}@media (min-width: 768px){.layout-container{margin:0 auto;max-width:33.75rem;margin-bottom:1.5rem}}@media (min-width: 1200px){.layout-container{margin:0 auto;max-width:45rem}}\n"] }]
34696
32801
  }], propDecorators: { props: [{
34697
32802
  type: Input
34698
32803
  }], onClick: [{
@@ -43370,5 +41475,5 @@ function buildFooterLinks(links, t) {
43370
41475
  * Generated bundle index. Do not edit.
43371
41476
  */
43372
41477
 
43373
- export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_SPACING, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AppConfigService, ArticleBuilder, ArticleComponent, AuthBackgroundComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContentLoaderComponent, ContentReactionComponent, ContentTransformer, CountdownComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, 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_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_STATUS_COLORS, DEFAULT_STATUS_LABELS, DEFAULT_WINNER_LABELS, DataTableComponent, DateInputComponent, DateRangeInputComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FabComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FormSkeletonComponent, FunHeaderComponent, GlowCardComponent, GridSkeletonComponent, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTION, MaintenancePageComponent, MenuComponent, MessagingService, MetaService, ModalService, MultiSelectSearchComponent, NavigationService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, ParticipantCardComponent, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, RadioInputComponent, RaffleStatusCardComponent, RangeInputComponent, RatingComponent, RecapCardComponent, RefresherComponent, RightsFooterComponent, RotatingTextComponent, 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, SessionService, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketGridComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, UpdateBannerComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_DEFAULT_CONTENT, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_SOCIAL_LINKS, VERSION, WinnerDisplayComponent, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, blogPost, buildFooterLinks, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, docs, extractPathParams, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, news, permissionGuard, permissionGuardFromRoute, provideValtechAds, provideValtechAppConfig, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechPresets, provideValtechSkeleton, query, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard, toArticle };
41478
+ export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_SPACING, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AppConfigService, ArticleBuilder, ArticleComponent, AuthBackgroundComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContentLoaderComponent, ContentReactionComponent, ContentTransformer, CountdownComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FabComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FooterComponent, FooterLinksComponent, FormComponent, FormFooterComponent, FormSkeletonComponent, FunHeaderComponent, GlowCardComponent, GridSkeletonComponent, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTION, MaintenancePageComponent, MenuComponent, MessagingService, MetaService, ModalService, MultiSelectSearchComponent, NavigationService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RightsFooterComponent, RotatingTextComponent, 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, SessionService, ShareButtonsComponent, SimpleComponent, SkeletonComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, UpdateBannerComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_DEFAULT_CONTENT, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_SOCIAL_LINKS, VERSION, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, blogPost, buildFooterLinks, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, docs, extractPathParams, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, news, permissionGuard, permissionGuardFromRoute, provideValtechAds, provideValtechAppConfig, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechPresets, provideValtechSkeleton, query, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard, toArticle };
43374
41479
  //# sourceMappingURL=valtech-components.mjs.map