valtech-components 2.0.1024 → 2.0.1025

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.
@@ -25,7 +25,7 @@ import { getApps, getApp, initializeApp as initializeApp$1 } from 'firebase/app'
25
25
  import * as i2$1 from '@ionic/angular/standalone';
26
26
  import { AlertController, IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonInput, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonRippleEffect, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, IonDatetimeButton, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
27
27
  import { addIcons } from 'ionicons';
28
- import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline, shareSocialOutline, helpCircleOutline, menuOutline } from 'ionicons/icons';
28
+ import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, notificationsOffOutline, alarmOutline, chatboxEllipsesOutline, checkmarkDoneOutline, cogOutline, shareSocialOutline, helpCircleOutline, menuOutline, stopCircleOutline, videocamOffOutline } from 'ionicons/icons';
29
29
  import { Browser } from '@capacitor/browser';
30
30
  import * as i1$6 from '@angular/platform-browser';
31
31
  import { DomSanitizer, Meta, Title } from '@angular/platform-browser';
@@ -49,12 +49,13 @@ import Compressor from 'compressorjs';
49
49
  import { Capacitor } from '@capacitor/core';
50
50
  import 'prismjs/components/prism-scss';
51
51
  import 'prismjs/components/prism-json';
52
+ import { BrowserMultiFormatReader } from '@zxing/browser';
52
53
 
53
54
  /**
54
55
  * Current version of valtech-components.
55
56
  * This is automatically updated during the publish process.
56
57
  */
57
- const VERSION = '2.0.1024';
58
+ const VERSION = '2.0.1025';
58
59
 
59
60
  // Control de estado de refresco (singleton a nivel de módulo)
60
61
  let isRefreshing = false;
@@ -65334,6 +65335,533 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
65334
65335
  type: Output
65335
65336
  }] } });
65336
65337
 
65338
+ /**
65339
+ * Defaults i18n (es/en) del `val-ticket-card`. Auto-registrados en el
65340
+ * constructor del componente (namespace `TicketCard`) — el consumer NUNCA tiene
65341
+ * que registrarlos. Override pasando los labels por props o registrando el
65342
+ * namespace antes de montar el componente.
65343
+ */
65344
+ const TICKET_CARD_I18N = {
65345
+ es: {
65346
+ folio: 'Folio',
65347
+ statusSold: 'Vendida',
65348
+ statusCheckedIn: 'Canjeada',
65349
+ download: 'Descargar',
65350
+ share: 'Compartir',
65351
+ },
65352
+ en: {
65353
+ folio: 'Folio',
65354
+ statusSold: 'Sold',
65355
+ statusCheckedIn: 'Checked in',
65356
+ download: 'Download',
65357
+ share: 'Share',
65358
+ },
65359
+ };
65360
+
65361
+ /**
65362
+ * val-ticket-card
65363
+ *
65364
+ * Tarjeta presentacional de una entrada de bingo: muestra el QR escaneable
65365
+ * (generado del `qrToken` opaco firmado vía `QrGeneratorService`), el folio, el
65366
+ * nombre del comprador (si hay) y un badge de estado (vendida / canjeada).
65367
+ *
65368
+ * Es la pieza que el vendedor le entrega al comprador tras la venta y que la
65369
+ * taquilla escanea para canjear. Object-first (`input()` signal), i18n
65370
+ * auto-registrado (namespace `TicketCard`). Estados negativos/neutros en gris
65371
+ * muted (convención del factory — sin rojo de alarma).
65372
+ *
65373
+ * @example
65374
+ * ```html
65375
+ * <val-ticket-card [props]="{ qrToken: ticket.qrToken, folio: ticket.folio,
65376
+ * buyerName: ticket.compradorNombre, status: 'sold', showShare: true }" />
65377
+ * ```
65378
+ */
65379
+ class TicketCardComponent {
65380
+ constructor() {
65381
+ /** Props object-first del componente. */
65382
+ this.props = input.required();
65383
+ this.qrService = inject(QrGeneratorService);
65384
+ this.i18n = inject(I18nService);
65385
+ /** QR generado (null mientras carga o si falló). */
65386
+ this.qr = signal(null);
65387
+ /** Falló la generación del QR → fallback al token corto. */
65388
+ this.failed = signal(false);
65389
+ this.status = computed(() => this.props().status ?? 'neutral');
65390
+ this.tokenShort = computed(() => {
65391
+ const tk = this.props().qrToken ?? '';
65392
+ return tk.length > 16 ? `${tk.slice(0, 16)}…` : tk;
65393
+ });
65394
+ this.folioText = computed(() => {
65395
+ this.i18n.lang();
65396
+ const folio = this.props().folio;
65397
+ if (folio === undefined || folio === null || folio === '')
65398
+ return '';
65399
+ const label = this.props().folioLabel ?? this.t('folio');
65400
+ return `${label} #${folio}`;
65401
+ });
65402
+ this.statusLabel = computed(() => {
65403
+ this.i18n.lang();
65404
+ const status = this.status();
65405
+ if (status === 'sold') {
65406
+ return this.props().statusSoldLabel ?? this.t('statusSold');
65407
+ }
65408
+ if (status === 'checkedIn') {
65409
+ return this.props().statusCheckedInLabel ?? this.t('statusCheckedIn');
65410
+ }
65411
+ return '';
65412
+ });
65413
+ if (!this.i18n.hasNamespace('TicketCard')) {
65414
+ this.i18n.registerContent('TicketCard', TICKET_CARD_I18N);
65415
+ }
65416
+ // Regenera el QR cuando cambia el token o el tamaño.
65417
+ effect(() => {
65418
+ const token = this.props().qrToken;
65419
+ const size = this.props().qrSize ?? 200;
65420
+ if (!token) {
65421
+ this.qr.set(null);
65422
+ this.failed.set(false);
65423
+ return;
65424
+ }
65425
+ void this.generate(token, size);
65426
+ }, { allowSignalWrites: true });
65427
+ }
65428
+ async generate(data, size) {
65429
+ this.failed.set(false);
65430
+ try {
65431
+ const result = await this.qrService.generate({
65432
+ data,
65433
+ width: size,
65434
+ height: size,
65435
+ margin: 1,
65436
+ dotsStyle: 'square',
65437
+ dotsColor: '#000000',
65438
+ backgroundColor: '#ffffff',
65439
+ errorCorrectionLevel: 'M',
65440
+ format: 'png',
65441
+ });
65442
+ this.qr.set(result);
65443
+ }
65444
+ catch {
65445
+ // Sin toast/throw — el fallback muestra el token corto. El consumer
65446
+ // sigue pudiendo canjear tipeando/escaneando si hace falta.
65447
+ this.qr.set(null);
65448
+ this.failed.set(true);
65449
+ }
65450
+ }
65451
+ t(key) {
65452
+ return this.i18n.t(key, 'TicketCard');
65453
+ }
65454
+ qrProps(q) {
65455
+ const p = this.props();
65456
+ return {
65457
+ qr: q,
65458
+ displaySize: p.qrSize ?? 200,
65459
+ showDownload: p.showDownload ?? false,
65460
+ showShare: p.showShare ?? false,
65461
+ showBorder: false,
65462
+ alt: this.folioText() || 'QR',
65463
+ downloadLabel: this.t('download'),
65464
+ shareLabel: this.t('share'),
65465
+ shareTitle: p.title || this.folioText() || 'QR',
65466
+ };
65467
+ }
65468
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TicketCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
65469
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TicketCardComponent, isStandalone: true, selector: "val-ticket-card", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
65470
+ <div class="ticket-card">
65471
+ @if (props().title) {
65472
+ <div class="ticket-card__title">{{ props().title }}</div>
65473
+ }
65474
+
65475
+ <div class="ticket-card__qr">
65476
+ @if (qr(); as q) {
65477
+ <val-qr-code [props]="qrProps(q)" />
65478
+ } @else if (failed()) {
65479
+ <div class="ticket-card__qr-fallback">{{ tokenShort() }}</div>
65480
+ } @else {
65481
+ <div class="ticket-card__qr-loading">
65482
+ <ion-spinner name="crescent" />
65483
+ </div>
65484
+ }
65485
+ </div>
65486
+
65487
+ <div class="ticket-card__meta">
65488
+ @if (folioText(); as f) {
65489
+ <div class="ticket-card__folio">{{ f }}</div>
65490
+ }
65491
+ @if (props().buyerName) {
65492
+ <div class="ticket-card__buyer">{{ props().buyerName }}</div>
65493
+ }
65494
+ @if (statusLabel(); as s) {
65495
+ <span class="ticket-card__badge" [attr.data-status]="status()">{{ s }}</span>
65496
+ }
65497
+ </div>
65498
+ </div>
65499
+ `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:block}.ticket-card{display:flex;flex-direction:column;align-items:center;gap:12px;padding:20px;border:1px solid var(--ion-color-light-shade, #e0e0e0);border-radius:16px;background:var(--ion-card-background, #ffffff);max-width:320px;margin:0 auto}.ticket-card__title{font-size:1rem;font-weight:700;color:var(--ion-color-dark);text-align:center}.ticket-card__qr{display:flex;align-items:center;justify-content:center;min-height:200px}.ticket-card__qr-loading{display:flex;align-items:center;justify-content:center;width:200px;height:200px}.ticket-card__qr-fallback{font-family:monospace;font-size:.75rem;color:var(--ion-color-medium);word-break:break-all;text-align:center;padding:16px}.ticket-card__meta{display:flex;flex-direction:column;align-items:center;gap:4px;text-align:center}.ticket-card__folio{font-size:1rem;font-weight:700;color:var(--ion-color-dark)}.ticket-card__buyer{font-size:.875rem;color:var(--ion-color-medium)}.ticket-card__badge{margin-top:4px;font-size:.75rem;font-weight:600;padding:3px 12px;border-radius:999px;background:var(--ion-color-medium);color:var(--ion-color-medium-contrast, #fff);white-space:nowrap}.ticket-card__badge[data-status=sold]{background:var(--ion-color-success, #2dd36f);color:var(--ion-color-success-contrast, #fff)}.ticket-card__badge[data-status=checkedIn]{background:var(--ion-color-medium);color:var(--ion-color-medium-contrast, #fff)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: QrCodeComponent, selector: "val-qr-code", inputs: ["props"], outputs: ["actionComplete", "imageLoad", "imageError"] }] }); }
65500
+ }
65501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TicketCardComponent, decorators: [{
65502
+ type: Component,
65503
+ args: [{ selector: 'val-ticket-card', standalone: true, imports: [CommonModule, IonSpinner, QrCodeComponent], template: `
65504
+ <div class="ticket-card">
65505
+ @if (props().title) {
65506
+ <div class="ticket-card__title">{{ props().title }}</div>
65507
+ }
65508
+
65509
+ <div class="ticket-card__qr">
65510
+ @if (qr(); as q) {
65511
+ <val-qr-code [props]="qrProps(q)" />
65512
+ } @else if (failed()) {
65513
+ <div class="ticket-card__qr-fallback">{{ tokenShort() }}</div>
65514
+ } @else {
65515
+ <div class="ticket-card__qr-loading">
65516
+ <ion-spinner name="crescent" />
65517
+ </div>
65518
+ }
65519
+ </div>
65520
+
65521
+ <div class="ticket-card__meta">
65522
+ @if (folioText(); as f) {
65523
+ <div class="ticket-card__folio">{{ f }}</div>
65524
+ }
65525
+ @if (props().buyerName) {
65526
+ <div class="ticket-card__buyer">{{ props().buyerName }}</div>
65527
+ }
65528
+ @if (statusLabel(); as s) {
65529
+ <span class="ticket-card__badge" [attr.data-status]="status()">{{ s }}</span>
65530
+ }
65531
+ </div>
65532
+ </div>
65533
+ `, styles: ["@charset \"UTF-8\";:host{display:block}.ticket-card{display:flex;flex-direction:column;align-items:center;gap:12px;padding:20px;border:1px solid var(--ion-color-light-shade, #e0e0e0);border-radius:16px;background:var(--ion-card-background, #ffffff);max-width:320px;margin:0 auto}.ticket-card__title{font-size:1rem;font-weight:700;color:var(--ion-color-dark);text-align:center}.ticket-card__qr{display:flex;align-items:center;justify-content:center;min-height:200px}.ticket-card__qr-loading{display:flex;align-items:center;justify-content:center;width:200px;height:200px}.ticket-card__qr-fallback{font-family:monospace;font-size:.75rem;color:var(--ion-color-medium);word-break:break-all;text-align:center;padding:16px}.ticket-card__meta{display:flex;flex-direction:column;align-items:center;gap:4px;text-align:center}.ticket-card__folio{font-size:1rem;font-weight:700;color:var(--ion-color-dark)}.ticket-card__buyer{font-size:.875rem;color:var(--ion-color-medium)}.ticket-card__badge{margin-top:4px;font-size:.75rem;font-weight:600;padding:3px 12px;border-radius:999px;background:var(--ion-color-medium);color:var(--ion-color-medium-contrast, #fff);white-space:nowrap}.ticket-card__badge[data-status=sold]{background:var(--ion-color-success, #2dd36f);color:var(--ion-color-success-contrast, #fff)}.ticket-card__badge[data-status=checkedIn]{background:var(--ion-color-medium);color:var(--ion-color-medium-contrast, #fff)}\n"] }]
65534
+ }], ctorParameters: () => [] });
65535
+
65536
+ /**
65537
+ * Defaults i18n (es/en) del `val-qr-scanner`. Auto-registrados en el
65538
+ * constructor (namespace `QrScanner`) — el consumer NUNCA tiene que
65539
+ * registrarlos. Override por props (start/stop) o registrando el namespace.
65540
+ */
65541
+ const QR_SCANNER_I18N = {
65542
+ es: {
65543
+ start: 'Iniciar cámara',
65544
+ stop: 'Detener',
65545
+ starting: 'Iniciando cámara…',
65546
+ hint: 'Apunta la cámara al código QR de la entrada.',
65547
+ cameraLabel: 'Cámara',
65548
+ denied: 'No se pudo acceder a la cámara. Revisa los permisos del navegador e inténtalo de nuevo.',
65549
+ noCamera: 'No se encontró ninguna cámara en este dispositivo.',
65550
+ error: 'Ocurrió un problema con la cámara. Inténtalo de nuevo.',
65551
+ },
65552
+ en: {
65553
+ start: 'Start camera',
65554
+ stop: 'Stop',
65555
+ starting: 'Starting camera…',
65556
+ hint: 'Point the camera at the ticket QR code.',
65557
+ cameraLabel: 'Camera',
65558
+ denied: 'Could not access the camera. Check your browser permissions and try again.',
65559
+ noCamera: 'No camera was found on this device.',
65560
+ error: 'Something went wrong with the camera. Please try again.',
65561
+ },
65562
+ };
65563
+
65564
+ addIcons({
65565
+ cameraOutline,
65566
+ stopCircleOutline,
65567
+ videocamOffOutline,
65568
+ warningOutline,
65569
+ });
65570
+ /**
65571
+ * val-qr-scanner
65572
+ *
65573
+ * Organism: scanner de códigos QR por cámara (`@zxing/browser` +
65574
+ * `@zxing/library`). Emite el texto decodificado por `(scanned)`.
65575
+ *
65576
+ * Maneja: permiso de cámara denegado (`denied`), ausencia de cámara
65577
+ * (`no-camera`), selector cuando hay varias cámaras, y botón start/stop. Hace
65578
+ * cleanup del stream en `ngOnDestroy`. i18n auto-registrado (namespace
65579
+ * `QrScanner`).
65580
+ *
65581
+ * Object-first (`@Input() props`) + un único `@Output() scanned`.
65582
+ *
65583
+ * @example
65584
+ * ```html
65585
+ * <val-qr-scanner [props]="{ continuous: true }" (scanned)="onScan($event)" />
65586
+ * ```
65587
+ */
65588
+ class QrScannerComponent {
65589
+ constructor() {
65590
+ this.props = {};
65591
+ /** Emite el texto decodificado del QR. */
65592
+ this.scanned = new EventEmitter();
65593
+ this.i18n = inject(I18nService);
65594
+ this.state = signal('idle');
65595
+ this.devices = signal([]);
65596
+ this.activeDeviceId = signal(undefined);
65597
+ this.reader = null;
65598
+ this.controls = null;
65599
+ // Anti-rebote: ignora la misma lectura repetida dentro de `dedupeMs`.
65600
+ this.lastValue = '';
65601
+ this.lastAt = 0;
65602
+ this.viewReady = false;
65603
+ if (!this.i18n.hasNamespace('QrScanner')) {
65604
+ this.i18n.registerContent('QrScanner', QR_SCANNER_I18N);
65605
+ }
65606
+ }
65607
+ ngAfterViewInit() {
65608
+ this.viewReady = true;
65609
+ if (this.props.autoStart) {
65610
+ void this.start();
65611
+ }
65612
+ }
65613
+ ngOnDestroy() {
65614
+ this.teardown();
65615
+ }
65616
+ t(key) {
65617
+ return this.i18n.t(key, 'QrScanner');
65618
+ }
65619
+ stateMessage() {
65620
+ switch (this.state()) {
65621
+ case 'denied':
65622
+ return this.t('denied');
65623
+ case 'no-camera':
65624
+ return this.t('noCamera');
65625
+ default:
65626
+ return this.t('error');
65627
+ }
65628
+ }
65629
+ deviceLabel(d) {
65630
+ return d.label || `${this.t('cameraLabel')} ${this.devices().indexOf(d) + 1}`;
65631
+ }
65632
+ async start(deviceId) {
65633
+ if (!this.viewReady)
65634
+ return;
65635
+ this.teardown();
65636
+ this.state.set('starting');
65637
+ try {
65638
+ this.reader = new BrowserMultiFormatReader();
65639
+ // Enumerar cámaras. Algunos navegadores solo dan labels tras conceder
65640
+ // permiso, así que esto puede devolver labels vacíos la 1ª vez.
65641
+ let cams = [];
65642
+ try {
65643
+ cams = await BrowserMultiFormatReader.listVideoInputDevices();
65644
+ }
65645
+ catch {
65646
+ cams = [];
65647
+ }
65648
+ this.devices.set(cams);
65649
+ // Preferir la trasera (environment) si el label lo sugiere.
65650
+ const target = deviceId ||
65651
+ this.activeDeviceId() ||
65652
+ cams.find(c => /back|rear|environment|trasera/i.test(c.label))?.deviceId ||
65653
+ cams[0]?.deviceId;
65654
+ this.activeDeviceId.set(target);
65655
+ this.controls = await this.reader.decodeFromVideoDevice(target, this.videoRef.nativeElement, result => {
65656
+ if (result) {
65657
+ this.handleResult(result.getText());
65658
+ }
65659
+ });
65660
+ this.state.set('scanning');
65661
+ }
65662
+ catch (err) {
65663
+ this.handleStartError(err);
65664
+ }
65665
+ }
65666
+ stop() {
65667
+ this.teardown();
65668
+ this.state.set('idle');
65669
+ }
65670
+ async onSelectDevice(deviceId) {
65671
+ if (deviceId && deviceId !== this.activeDeviceId()) {
65672
+ await this.start(deviceId);
65673
+ }
65674
+ }
65675
+ handleResult(text) {
65676
+ const now = Date.now();
65677
+ const dedupe = this.props.dedupeMs ?? 1500;
65678
+ if (text === this.lastValue && now - this.lastAt < dedupe) {
65679
+ return;
65680
+ }
65681
+ this.lastValue = text;
65682
+ this.lastAt = now;
65683
+ this.scanned.emit(text);
65684
+ // Modo no continuo: detener tras el primer match (la página reanuda si
65685
+ // quiere). `continuous` default true → seguir escaneando.
65686
+ if (this.props.continuous === false) {
65687
+ this.stop();
65688
+ }
65689
+ }
65690
+ handleStartError(err) {
65691
+ const name = err?.name ?? '';
65692
+ if (name === 'NotAllowedError' || name === 'SecurityError') {
65693
+ this.state.set('denied');
65694
+ }
65695
+ else if (name === 'NotFoundError' || name === 'OverconstrainedError') {
65696
+ this.state.set('no-camera');
65697
+ }
65698
+ else {
65699
+ this.state.set('error');
65700
+ }
65701
+ this.teardown(false);
65702
+ }
65703
+ /** Detiene el decode + libera el stream de la cámara. */
65704
+ teardown(resetState = true) {
65705
+ try {
65706
+ this.controls?.stop();
65707
+ }
65708
+ catch {
65709
+ // ignore
65710
+ }
65711
+ this.controls = null;
65712
+ const video = this.videoRef?.nativeElement;
65713
+ const stream = video?.srcObject;
65714
+ if (stream) {
65715
+ stream.getTracks().forEach(track => track.stop());
65716
+ video.srcObject = null;
65717
+ }
65718
+ this.reader = null;
65719
+ if (resetState) {
65720
+ this.lastValue = '';
65721
+ this.lastAt = 0;
65722
+ }
65723
+ }
65724
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: QrScannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
65725
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: QrScannerComponent, isStandalone: true, selector: "val-qr-scanner", inputs: { props: "props" }, outputs: { scanned: "scanned" }, viewQueries: [{ propertyName: "videoRef", first: true, predicate: ["video"], descendants: true }], ngImport: i0, template: `
65726
+ <div class="qr-scanner">
65727
+ <div class="qr-scanner__viewport" [class.is-active]="state() === 'scanning'">
65728
+ <video #video class="qr-scanner__video" muted playsinline></video>
65729
+
65730
+ @if (state() === 'idle') {
65731
+ <div class="qr-scanner__overlay">
65732
+ <ion-icon name="camera-outline" class="qr-scanner__overlay-icon" />
65733
+ </div>
65734
+ }
65735
+
65736
+ @if (state() === 'starting') {
65737
+ <div class="qr-scanner__overlay">
65738
+ <ion-spinner name="crescent" />
65739
+ <p>{{ t('starting') }}</p>
65740
+ </div>
65741
+ }
65742
+
65743
+ @if (state() === 'scanning') {
65744
+ <div class="qr-scanner__frame"></div>
65745
+ }
65746
+ </div>
65747
+
65748
+ @if (state() === 'denied' || state() === 'no-camera' || state() === 'error') {
65749
+ <div class="qr-scanner__message">
65750
+ <ion-icon [name]="state() === 'no-camera' ? 'videocam-off-outline' : 'warning-outline'" />
65751
+ <span>{{ stateMessage() }}</span>
65752
+ </div>
65753
+ }
65754
+
65755
+ @if (state() === 'scanning' || state() === 'starting') {
65756
+ <p class="qr-scanner__hint">{{ t('hint') }}</p>
65757
+ }
65758
+
65759
+ @if (devices().length > 1 && state() === 'scanning') {
65760
+ <ion-select
65761
+ class="qr-scanner__select"
65762
+ [label]="t('cameraLabel')"
65763
+ labelPlacement="stacked"
65764
+ interface="popover"
65765
+ [value]="activeDeviceId()"
65766
+ (ionChange)="onSelectDevice($any($event).detail.value)"
65767
+ >
65768
+ @for (d of devices(); track d.deviceId) {
65769
+ <ion-select-option [value]="d.deviceId">{{ deviceLabel(d) }}</ion-select-option>
65770
+ }
65771
+ </ion-select>
65772
+ }
65773
+
65774
+ <div class="qr-scanner__actions">
65775
+ @if (state() === 'scanning' || state() === 'starting') {
65776
+ <ion-button fill="outline" color="dark" (click)="stop()">
65777
+ <ion-icon name="stop-circle-outline" slot="start" />
65778
+ {{ props.stopLabel || t('stop') }}
65779
+ </ion-button>
65780
+ } @else {
65781
+ <ion-button color="dark" (click)="start()">
65782
+ <ion-icon name="camera-outline" slot="start" />
65783
+ {{ props.startLabel || t('start') }}
65784
+ </ion-button>
65785
+ }
65786
+ </div>
65787
+ </div>
65788
+ `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:block}.qr-scanner{display:flex;flex-direction:column;align-items:stretch;gap:12px;max-width:420px;margin:0 auto}.qr-scanner__viewport{position:relative;width:100%;aspect-ratio:1/1;border-radius:16px;overflow:hidden;background:var(--ion-color-dark, #1c1c1e);display:flex;align-items:center;justify-content:center}.qr-scanner__video{width:100%;height:100%;object-fit:cover;display:block}.qr-scanner__overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--ion-color-light, #f4f5f8)}.qr-scanner__overlay p{margin:0;font-size:.875rem}.qr-scanner__overlay-icon{font-size:3rem;opacity:.6}.qr-scanner__frame{position:absolute;inset:18%;border:3px solid var(--ion-color-primary, #ff00b2);border-radius:12px;box-shadow:0 0 0 9999px #00000040;pointer-events:none}.qr-scanner__message{display:flex;align-items:center;gap:8px;padding:12px 14px;border-radius:12px;background:var(--ion-color-light, #f4f5f8);color:var(--ion-color-medium, #6b6675);font-size:.875rem}.qr-scanner__message ion-icon{font-size:1.25rem;flex-shrink:0}.qr-scanner__hint{margin:0;text-align:center;font-size:.8125rem;color:var(--ion-color-medium, #6b6675)}.qr-scanner__select{--padding-start: 0}.qr-scanner__actions{display:flex;justify-content:center}.qr-scanner__actions ion-button{--border-radius: 999px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }] }); }
65789
+ }
65790
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: QrScannerComponent, decorators: [{
65791
+ type: Component,
65792
+ args: [{ selector: 'val-qr-scanner', standalone: true, imports: [CommonModule, IonButton, IonIcon, IonSpinner, IonSelect, IonSelectOption], template: `
65793
+ <div class="qr-scanner">
65794
+ <div class="qr-scanner__viewport" [class.is-active]="state() === 'scanning'">
65795
+ <video #video class="qr-scanner__video" muted playsinline></video>
65796
+
65797
+ @if (state() === 'idle') {
65798
+ <div class="qr-scanner__overlay">
65799
+ <ion-icon name="camera-outline" class="qr-scanner__overlay-icon" />
65800
+ </div>
65801
+ }
65802
+
65803
+ @if (state() === 'starting') {
65804
+ <div class="qr-scanner__overlay">
65805
+ <ion-spinner name="crescent" />
65806
+ <p>{{ t('starting') }}</p>
65807
+ </div>
65808
+ }
65809
+
65810
+ @if (state() === 'scanning') {
65811
+ <div class="qr-scanner__frame"></div>
65812
+ }
65813
+ </div>
65814
+
65815
+ @if (state() === 'denied' || state() === 'no-camera' || state() === 'error') {
65816
+ <div class="qr-scanner__message">
65817
+ <ion-icon [name]="state() === 'no-camera' ? 'videocam-off-outline' : 'warning-outline'" />
65818
+ <span>{{ stateMessage() }}</span>
65819
+ </div>
65820
+ }
65821
+
65822
+ @if (state() === 'scanning' || state() === 'starting') {
65823
+ <p class="qr-scanner__hint">{{ t('hint') }}</p>
65824
+ }
65825
+
65826
+ @if (devices().length > 1 && state() === 'scanning') {
65827
+ <ion-select
65828
+ class="qr-scanner__select"
65829
+ [label]="t('cameraLabel')"
65830
+ labelPlacement="stacked"
65831
+ interface="popover"
65832
+ [value]="activeDeviceId()"
65833
+ (ionChange)="onSelectDevice($any($event).detail.value)"
65834
+ >
65835
+ @for (d of devices(); track d.deviceId) {
65836
+ <ion-select-option [value]="d.deviceId">{{ deviceLabel(d) }}</ion-select-option>
65837
+ }
65838
+ </ion-select>
65839
+ }
65840
+
65841
+ <div class="qr-scanner__actions">
65842
+ @if (state() === 'scanning' || state() === 'starting') {
65843
+ <ion-button fill="outline" color="dark" (click)="stop()">
65844
+ <ion-icon name="stop-circle-outline" slot="start" />
65845
+ {{ props.stopLabel || t('stop') }}
65846
+ </ion-button>
65847
+ } @else {
65848
+ <ion-button color="dark" (click)="start()">
65849
+ <ion-icon name="camera-outline" slot="start" />
65850
+ {{ props.startLabel || t('start') }}
65851
+ </ion-button>
65852
+ }
65853
+ </div>
65854
+ </div>
65855
+ `, styles: ["@charset \"UTF-8\";:host{display:block}.qr-scanner{display:flex;flex-direction:column;align-items:stretch;gap:12px;max-width:420px;margin:0 auto}.qr-scanner__viewport{position:relative;width:100%;aspect-ratio:1/1;border-radius:16px;overflow:hidden;background:var(--ion-color-dark, #1c1c1e);display:flex;align-items:center;justify-content:center}.qr-scanner__video{width:100%;height:100%;object-fit:cover;display:block}.qr-scanner__overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--ion-color-light, #f4f5f8)}.qr-scanner__overlay p{margin:0;font-size:.875rem}.qr-scanner__overlay-icon{font-size:3rem;opacity:.6}.qr-scanner__frame{position:absolute;inset:18%;border:3px solid var(--ion-color-primary, #ff00b2);border-radius:12px;box-shadow:0 0 0 9999px #00000040;pointer-events:none}.qr-scanner__message{display:flex;align-items:center;gap:8px;padding:12px 14px;border-radius:12px;background:var(--ion-color-light, #f4f5f8);color:var(--ion-color-medium, #6b6675);font-size:.875rem}.qr-scanner__message ion-icon{font-size:1.25rem;flex-shrink:0}.qr-scanner__hint{margin:0;text-align:center;font-size:.8125rem;color:var(--ion-color-medium, #6b6675)}.qr-scanner__select{--padding-start: 0}.qr-scanner__actions{display:flex;justify-content:center}.qr-scanner__actions ion-button{--border-radius: 999px}\n"] }]
65856
+ }], ctorParameters: () => [], propDecorators: { props: [{
65857
+ type: Input
65858
+ }], scanned: [{
65859
+ type: Output
65860
+ }], videoRef: [{
65861
+ type: ViewChild,
65862
+ args: ['video']
65863
+ }] } });
65864
+
65337
65865
  /*
65338
65866
  * Public API Surface of valtech-components
65339
65867
  */
@@ -65343,5 +65871,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
65343
65871
  * Generated bundle index. Do not edit.
65344
65872
  */
65345
65873
 
65346
- export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionSelectorComponent, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createPermissionLabeler, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
65874
+ export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionSelectorComponent, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketCardComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createPermissionLabeler, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
65347
65875
  //# sourceMappingURL=valtech-components.mjs.map