valtech-components 2.0.779 → 2.0.780

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.
@@ -52,7 +52,7 @@ import 'prismjs/components/prism-json';
52
52
  * Current version of valtech-components.
53
53
  * This is automatically updated during the publish process.
54
54
  */
55
- const VERSION = '2.0.779';
55
+ const VERSION = '2.0.780';
56
56
 
57
57
  /**
58
58
  * Servicio para gestionar presets de componentes.
@@ -6268,6 +6268,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6268
6268
  type: Input
6269
6269
  }] } });
6270
6270
 
6271
+ addIcons({ personOutline });
6272
+ /**
6273
+ * `val-user-avatar`
6274
+ *
6275
+ * Avatar **smart** con cadena de fallback automática:
6276
+ *
6277
+ * foto (`avatarUrl`) → iniciales (de `name`/`email`) → icono persona.
6278
+ *
6279
+ * Si la imagen falla en cargar (404, CORS, etc.), automáticamente cae a las
6280
+ * iniciales sin que el caller tenga que hacer nada. Color de fondo derivado
6281
+ * deterministicamente del user para que el mismo user tenga siempre el mismo
6282
+ * color (a menos que `background` se sobrescriba).
6283
+ *
6284
+ * @example
6285
+ * ```html
6286
+ * <val-user-avatar [props]="{ user: auth.user() }" (onClick)="goProfile()" />
6287
+ * ```
6288
+ */
6289
+ class UserAvatarComponent {
6290
+ constructor() {
6291
+ this.props_ = signal({});
6292
+ this.imageFailed = signal(false);
6293
+ this.onClick = new EventEmitter();
6294
+ this.resolvedProps = computed(() => this.props_());
6295
+ /** Resuelve los campos del user (user prop > campos sueltos). */
6296
+ this.resolvedUser = computed(() => {
6297
+ const p = this.resolvedProps();
6298
+ return {
6299
+ name: p.user?.name?.trim() || p.name?.trim() || '',
6300
+ email: p.user?.email?.trim() || p.email?.trim() || '',
6301
+ avatarUrl: p.user?.avatarUrl?.trim() || p.avatarUrl?.trim() || '',
6302
+ };
6303
+ });
6304
+ /** URL de imagen — empty si no hay o si la carga falló. */
6305
+ this.imageUrl = computed(() => this.resolvedUser().avatarUrl);
6306
+ this.showImage = computed(() => !!this.imageUrl() && !this.imageFailed());
6307
+ /** Iniciales — 1-2 chars derivados de name (preferred) o email prefix. */
6308
+ this.initials = computed(() => {
6309
+ const { name, email } = this.resolvedUser();
6310
+ if (name) {
6311
+ const parts = name.split(/\s+/).filter(Boolean);
6312
+ if (parts.length >= 2)
6313
+ return parts[0][0] + parts[1][0];
6314
+ if (parts.length === 1 && parts[0].length >= 2) {
6315
+ return parts[0].slice(0, 2);
6316
+ }
6317
+ return parts[0]?.[0] ?? '';
6318
+ }
6319
+ if (email) {
6320
+ const prefix = email.split('@')[0] ?? '';
6321
+ // Tomar 1-2 chars del prefix
6322
+ if (prefix.length >= 2)
6323
+ return prefix.slice(0, 2);
6324
+ return prefix[0] ?? '';
6325
+ }
6326
+ return '';
6327
+ });
6328
+ this.sizeClass = computed(() => this.resolvedProps().size || 'small');
6329
+ this.shapeClass = computed(() => this.resolvedProps().shape || 'circle');
6330
+ /** Background — explicito o derivado deterministicamente del user. */
6331
+ this.bgColor = computed(() => {
6332
+ const p = this.resolvedProps();
6333
+ if (p.background)
6334
+ return p.background;
6335
+ const { name, email } = this.resolvedUser();
6336
+ const seed = name || email || 'val';
6337
+ return this.colorFromSeed(seed);
6338
+ });
6339
+ this.ariaLabel = computed(() => {
6340
+ const { name, email } = this.resolvedUser();
6341
+ return name || email || 'User avatar';
6342
+ });
6343
+ }
6344
+ set props(value) {
6345
+ this.props_.set(value ?? {});
6346
+ this.imageFailed.set(false);
6347
+ }
6348
+ /** Subscribers — usado para condicionar cursor/aria. */
6349
+ get hasClick() {
6350
+ return this.onClick.observed;
6351
+ }
6352
+ onImageError() {
6353
+ this.imageFailed.set(true);
6354
+ }
6355
+ onImageLoad() {
6356
+ this.imageFailed.set(false);
6357
+ }
6358
+ /**
6359
+ * Hash determinista string → HSL color del rango Valtech (purples/blues).
6360
+ * Mismo seed → mismo color (consistencia entre sessions).
6361
+ */
6362
+ colorFromSeed(seed) {
6363
+ let hash = 0;
6364
+ for (let i = 0; i < seed.length; i++) {
6365
+ hash = (hash * 31 + seed.charCodeAt(i)) >>> 0;
6366
+ }
6367
+ // Restringir a rango violet/blue (240-290°) para coherencia con palette
6368
+ const hue = 240 + (hash % 50);
6369
+ const sat = 55 + ((hash >>> 8) % 20); // 55-75%
6370
+ const light = 38 + ((hash >>> 16) % 12); // 38-50% — siempre legible con fg blanco
6371
+ return `hsl(${hue}, ${sat}%, ${light}%)`;
6372
+ }
6373
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UserAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6374
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: UserAvatarComponent, isStandalone: true, selector: "val-user-avatar", inputs: { props: "props" }, outputs: { onClick: "onClick" }, ngImport: i0, template: `
6375
+ <button
6376
+ type="button"
6377
+ class="val-user-avatar"
6378
+ [class.bordered]="resolvedProps().bordered"
6379
+ [class.grayscale]="resolvedProps().grayscale"
6380
+ [class.has-click]="hasClick"
6381
+ [class]="shapeClass() + ' ' + sizeClass() + ' ' + (resolvedProps().cssClass || '')"
6382
+ [style.background]="!showImage() ? bgColor() : 'transparent'"
6383
+ [style.color]="resolvedProps().foreground || '#fff'"
6384
+ [attr.aria-label]="ariaLabel()"
6385
+ (click)="onClick.emit()"
6386
+ >
6387
+ @if (showImage()) {
6388
+ <img class="val-user-avatar__img" [src]="imageUrl()" alt="" (error)="onImageError()" (load)="onImageLoad()" />
6389
+ } @else if (initials()) {
6390
+ <span class="val-user-avatar__initials">{{ initials() }}</span>
6391
+ } @else {
6392
+ <ion-icon name="person-outline" class="val-user-avatar__icon" aria-hidden="true" />
6393
+ }
6394
+ </button>
6395
+ `, isInline: true, styles: [":host{display:inline-flex}.val-user-avatar{position:relative;display:inline-flex;align-items:center;justify-content:center;overflow:hidden;padding:0;margin:0;border:none;background:var(--ion-color-medium, #92949c);color:#fff;font-weight:600;font-family:inherit;line-height:1;-webkit-user-select:none;user-select:none;cursor:default;transition:transform .15s ease,box-shadow .15s ease}.val-user-avatar.has-click{cursor:pointer}.val-user-avatar.has-click:hover{transform:scale(1.04)}.val-user-avatar.has-click:active{transform:scale(.96)}.val-user-avatar.circle{border-radius:50%}.val-user-avatar.square{border-radius:8px}.val-user-avatar.xsmall{width:24px;height:24px;font-size:.625rem}.val-user-avatar.small{width:32px;height:32px;font-size:.75rem}.val-user-avatar.medium{width:48px;height:48px;font-size:1rem}.val-user-avatar.large{width:72px;height:72px;font-size:1.5rem}.val-user-avatar.xlarge{width:96px;height:96px;font-size:2rem}.val-user-avatar.bordered{box-shadow:0 0 0 2px var(--ion-background-color, #fff)}.val-user-avatar.grayscale{filter:grayscale(100%)}.val-user-avatar__img{width:100%;height:100%;object-fit:cover;display:block}.val-user-avatar__initials{text-transform:uppercase;letter-spacing:.02em}.val-user-avatar__icon{font-size:60%}\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"] }] }); }
6396
+ }
6397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UserAvatarComponent, decorators: [{
6398
+ type: Component,
6399
+ args: [{ selector: 'val-user-avatar', standalone: true, imports: [CommonModule, IonIcon], template: `
6400
+ <button
6401
+ type="button"
6402
+ class="val-user-avatar"
6403
+ [class.bordered]="resolvedProps().bordered"
6404
+ [class.grayscale]="resolvedProps().grayscale"
6405
+ [class.has-click]="hasClick"
6406
+ [class]="shapeClass() + ' ' + sizeClass() + ' ' + (resolvedProps().cssClass || '')"
6407
+ [style.background]="!showImage() ? bgColor() : 'transparent'"
6408
+ [style.color]="resolvedProps().foreground || '#fff'"
6409
+ [attr.aria-label]="ariaLabel()"
6410
+ (click)="onClick.emit()"
6411
+ >
6412
+ @if (showImage()) {
6413
+ <img class="val-user-avatar__img" [src]="imageUrl()" alt="" (error)="onImageError()" (load)="onImageLoad()" />
6414
+ } @else if (initials()) {
6415
+ <span class="val-user-avatar__initials">{{ initials() }}</span>
6416
+ } @else {
6417
+ <ion-icon name="person-outline" class="val-user-avatar__icon" aria-hidden="true" />
6418
+ }
6419
+ </button>
6420
+ `, styles: [":host{display:inline-flex}.val-user-avatar{position:relative;display:inline-flex;align-items:center;justify-content:center;overflow:hidden;padding:0;margin:0;border:none;background:var(--ion-color-medium, #92949c);color:#fff;font-weight:600;font-family:inherit;line-height:1;-webkit-user-select:none;user-select:none;cursor:default;transition:transform .15s ease,box-shadow .15s ease}.val-user-avatar.has-click{cursor:pointer}.val-user-avatar.has-click:hover{transform:scale(1.04)}.val-user-avatar.has-click:active{transform:scale(.96)}.val-user-avatar.circle{border-radius:50%}.val-user-avatar.square{border-radius:8px}.val-user-avatar.xsmall{width:24px;height:24px;font-size:.625rem}.val-user-avatar.small{width:32px;height:32px;font-size:.75rem}.val-user-avatar.medium{width:48px;height:48px;font-size:1rem}.val-user-avatar.large{width:72px;height:72px;font-size:1.5rem}.val-user-avatar.xlarge{width:96px;height:96px;font-size:2rem}.val-user-avatar.bordered{box-shadow:0 0 0 2px var(--ion-background-color, #fff)}.val-user-avatar.grayscale{filter:grayscale(100%)}.val-user-avatar__img{width:100%;height:100%;object-fit:cover;display:block}.val-user-avatar__initials{text-transform:uppercase;letter-spacing:.02em}.val-user-avatar__icon{font-size:60%}\n"] }]
6421
+ }], propDecorators: { props: [{
6422
+ type: Input
6423
+ }], onClick: [{
6424
+ type: Output
6425
+ }] } });
6426
+
6271
6427
  /**
6272
6428
  * val-alert-box
6273
6429
  *
@@ -8489,95 +8645,90 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8489
8645
  }] } });
8490
8646
 
8491
8647
  /**
8492
- * val-notes-box
8648
+ * `val-notes-box` — callout / admonition para resaltar información dentro de un
8649
+ * flujo de texto.
8493
8650
  *
8494
- * Displays a styled notes/info box with optional prefix and configurable color, size, and padding.
8651
+ * Diseño tipo GitHub/Docusaurus: fondo tintado suave, accent en el borde
8652
+ * izquierdo, prefijo en mayúsculas pequeñas. Funciona en light & dark.
8495
8653
  *
8496
- * @example
8497
- * <val-notes-box [props]="{ text: 'Note', prefix: 'Info', color: 'primary', textColor: 'dark', size: 'medium', rounded: true, padding: '8px' }"></val-notes-box>
8654
+ * El color es un Ionic Color (primary, success, warning, danger, tertiary, …).
8655
+ * No usa `ion-card` ni `ion-color="X"` como background sino una mezcla
8656
+ * `rgba(--ion-color-X-rgb, 0.08)` para no asfixiar el contenido.
8657
+ *
8658
+ * Renderiza inline HTML (`<strong>`, links via `processLinks`) cuando los
8659
+ * flags están activos.
8498
8660
  *
8499
- * @input props: NotesBoxMetadata - Configuration for the notes box (text, prefix, color, textColor, size, rounded, padding)
8661
+ * @example
8662
+ * <val-notes-box [props]="{
8663
+ * text: 'Recordá guardar tus cambios antes de salir.',
8664
+ * prefix: 'Tip',
8665
+ * color: 'tertiary',
8666
+ * textColor: 'dark',
8667
+ * size: 'medium',
8668
+ * rounded: true,
8669
+ * allowPartialBold: true,
8670
+ * }"></val-notes-box>
8500
8671
  */
8501
8672
  class NotesBoxComponent {
8502
- constructor() { }
8503
- ngOnInit() { }
8504
8673
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NotesBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8505
8674
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: NotesBoxComponent, isStandalone: true, selector: "val-notes-box", inputs: { props: "props" }, ngImport: i0, template: `
8506
8675
  <div
8507
- [class.notes-box-compact]="props.compact"
8508
- [class.notes-box-align-center]="props.align === 'center'"
8509
- [class.notes-box-align-right]="props.align === 'right'"
8676
+ class="val-notes-box"
8677
+ [class.is-compact]="props.compact"
8678
+ [class.is-rounded]="props.rounded"
8679
+ [class.align-center]="props.align === 'center'"
8680
+ [class.align-right]="props.align === 'right'"
8681
+ [attr.data-color]="props.color || 'primary'"
8682
+ role="note"
8510
8683
  >
8511
- <val-box
8512
- [props]="{
8513
- icon: '',
8514
- bordered: false,
8515
- color: props.color,
8516
- leftBorder: !props.compact,
8517
- rounded: props.rounded,
8518
- padding: props.padding || (props.compact ? '6px 12px' : undefined),
8519
- }"
8520
- >
8521
- <div [ngClass]="['content-container', props.size]" body>
8522
- @if (props.prefix) {
8523
- <val-text
8524
- [props]="{ content: props.prefix, color: props.textColor, bold: true, size: props.size }"
8525
- ></val-text>
8526
- }
8527
- <val-text
8528
- [props]="{
8529
- content: props.text,
8530
- color: props.textColor,
8531
- bold: false,
8532
- size: props.size,
8533
- allowPartialBold: props.allowPartialBold,
8534
- processLinks: props.processLinks,
8535
- }"
8536
- ></val-text>
8537
- </div>
8538
- </val-box>
8684
+ @if (props.prefix) {
8685
+ <div class="val-notes-box__header">{{ props.prefix }}</div>
8686
+ }
8687
+ <div class="val-notes-box__body" [class]="'size-' + (props.size || 'medium')">
8688
+ <val-text
8689
+ [props]="{
8690
+ content: props.text,
8691
+ color: props.textColor,
8692
+ bold: false,
8693
+ size: props.size,
8694
+ allowPartialBold: props.allowPartialBold,
8695
+ processLinks: props.processLinks,
8696
+ }"
8697
+ ></val-text>
8698
+ </div>
8539
8699
  </div>
8540
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.content-container{display:inline-grid}.notes-box-compact{display:inline-block;width:fit-content;max-width:100%}.notes-box-compact ::ng-deep val-box ion-card{margin:0;box-shadow:none}.notes-box-align-center{text-align:center}.notes-box-align-center:not(.notes-box-compact){display:flex;justify-content:center}.notes-box-align-right{text-align:right}.notes-box-align-right:not(.notes-box-compact){display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: BoxComponent, selector: "val-box", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
8700
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{display:block}.val-notes-box{--notes-rgb: var(--ion-color-primary-rgb, 112, 38, 223);--notes-bg: rgba(var(--notes-rgb), .07);--notes-border: rgba(var(--notes-rgb), .18);--notes-accent: rgb(var(--notes-rgb));--notes-text: var(--ion-color-dark, #0a0612);--notes-link: rgb(var(--notes-rgb));position:relative;display:block;padding:14px 18px 14px 20px;background:var(--notes-bg);border:1px solid var(--notes-border);border-left:4px solid var(--notes-accent);border-radius:10px;color:var(--notes-text);margin:0;line-height:1.55}.val-notes-box.is-rounded{border-radius:12px}.val-notes-box[data-color=primary]{--notes-rgb: var(--ion-color-primary-rgb)}.val-notes-box[data-color=secondary]{--notes-rgb: var(--ion-color-secondary-rgb)}.val-notes-box[data-color=tertiary]{--notes-rgb: var(--ion-color-tertiary-rgb)}.val-notes-box[data-color=success]{--notes-rgb: var(--ion-color-success-rgb)}.val-notes-box[data-color=warning]{--notes-rgb: var(--ion-color-warning-rgb)}.val-notes-box[data-color=danger]{--notes-rgb: var(--ion-color-danger-rgb)}.val-notes-box[data-color=medium]{--notes-rgb: var(--ion-color-medium-rgb)}.val-notes-box[data-color=dark]{--notes-rgb: var(--ion-color-dark-rgb)}.val-notes-box[data-color=light]{--notes-rgb: var(--ion-color-medium-rgb)}.val-notes-box__header{display:block;margin:0 0 6px;font-weight:700;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--notes-accent);font-family:var(--ion-font-family, inherit)}.val-notes-box__body{display:block;color:var(--notes-text);font-size:14px;line-height:1.6}.val-notes-box__body.size-small{font-size:13px;line-height:1.55}.val-notes-box__body.size-large{font-size:15px;line-height:1.6}.val-notes-box__body.size-xlarge{font-size:16px;line-height:1.55}.val-notes-box__body ::ng-deep val-text{display:block;color:var(--notes-text)}.val-notes-box__body ::ng-deep val-text p{margin:0;color:inherit}.val-notes-box__body ::ng-deep val-text ion-text{color:var(--notes-text)!important}.val-notes-box__body ::ng-deep val-text strong,.val-notes-box__body ::ng-deep val-text b,.val-notes-box__body ::ng-deep .partial-bold{color:var(--notes-text);font-weight:700}.val-notes-box__body ::ng-deep val-text a{color:var(--notes-link);text-decoration:underline;text-underline-offset:2px;font-weight:600}.val-notes-box__body ::ng-deep val-text a:hover{opacity:.85}.val-notes-box.align-center,.val-notes-box.align-center .val-notes-box__header{text-align:center}.val-notes-box.align-right,.val-notes-box.align-right .val-notes-box__header{text-align:right}.val-notes-box.is-compact{display:inline-block;width:fit-content;max-width:100%;padding:5px 12px;border-left-width:1px;border-radius:999px;font-size:12px;line-height:1.3}.val-notes-box.is-compact .val-notes-box__header{display:inline;margin:0 6px 0 0;font-size:11px;letter-spacing:.06em}.val-notes-box.is-compact .val-notes-box__body{display:inline;font-size:12px}.val-notes-box.is-compact ::ng-deep val-text{display:inline}.val-notes-box.is-compact ::ng-deep val-text p{display:inline}@media (prefers-color-scheme: dark){:host-context(body:not(.light)) .val-notes-box{--notes-bg: rgba(var(--notes-rgb), .16);--notes-border: rgba(var(--notes-rgb), .3);--notes-text: var(--ion-color-light, #f4f5f8)}}:host-context(body.dark) .val-notes-box,:host-context(.theme-dark) .val-notes-box,:host-context([data-theme=dark]) .val-notes-box{--notes-bg: rgba(var(--notes-rgb), .16);--notes-border: rgba(var(--notes-rgb), .3);--notes-text: var(--ion-color-light, #f4f5f8)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8541
8701
  }
8542
8702
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NotesBoxComponent, decorators: [{
8543
8703
  type: Component,
8544
- args: [{ selector: 'val-notes-box', standalone: true, imports: [CommonModule, BoxComponent, TextComponent], template: `
8704
+ args: [{ selector: 'val-notes-box', standalone: true, imports: [CommonModule, TextComponent], template: `
8545
8705
  <div
8546
- [class.notes-box-compact]="props.compact"
8547
- [class.notes-box-align-center]="props.align === 'center'"
8548
- [class.notes-box-align-right]="props.align === 'right'"
8706
+ class="val-notes-box"
8707
+ [class.is-compact]="props.compact"
8708
+ [class.is-rounded]="props.rounded"
8709
+ [class.align-center]="props.align === 'center'"
8710
+ [class.align-right]="props.align === 'right'"
8711
+ [attr.data-color]="props.color || 'primary'"
8712
+ role="note"
8549
8713
  >
8550
- <val-box
8551
- [props]="{
8552
- icon: '',
8553
- bordered: false,
8554
- color: props.color,
8555
- leftBorder: !props.compact,
8556
- rounded: props.rounded,
8557
- padding: props.padding || (props.compact ? '6px 12px' : undefined),
8558
- }"
8559
- >
8560
- <div [ngClass]="['content-container', props.size]" body>
8561
- @if (props.prefix) {
8562
- <val-text
8563
- [props]="{ content: props.prefix, color: props.textColor, bold: true, size: props.size }"
8564
- ></val-text>
8565
- }
8566
- <val-text
8567
- [props]="{
8568
- content: props.text,
8569
- color: props.textColor,
8570
- bold: false,
8571
- size: props.size,
8572
- allowPartialBold: props.allowPartialBold,
8573
- processLinks: props.processLinks,
8574
- }"
8575
- ></val-text>
8576
- </div>
8577
- </val-box>
8714
+ @if (props.prefix) {
8715
+ <div class="val-notes-box__header">{{ props.prefix }}</div>
8716
+ }
8717
+ <div class="val-notes-box__body" [class]="'size-' + (props.size || 'medium')">
8718
+ <val-text
8719
+ [props]="{
8720
+ content: props.text,
8721
+ color: props.textColor,
8722
+ bold: false,
8723
+ size: props.size,
8724
+ allowPartialBold: props.allowPartialBold,
8725
+ processLinks: props.processLinks,
8726
+ }"
8727
+ ></val-text>
8728
+ </div>
8578
8729
  </div>
8579
- `, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.content-container{display:inline-grid}.notes-box-compact{display:inline-block;width:fit-content;max-width:100%}.notes-box-compact ::ng-deep val-box ion-card{margin:0;box-shadow:none}.notes-box-align-center{text-align:center}.notes-box-align-center:not(.notes-box-compact){display:flex;justify-content:center}.notes-box-align-right{text-align:right}.notes-box-align-right:not(.notes-box-compact){display:flex;justify-content:flex-end}\n"] }]
8580
- }], ctorParameters: () => [], propDecorators: { props: [{
8730
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{display:block}.val-notes-box{--notes-rgb: var(--ion-color-primary-rgb, 112, 38, 223);--notes-bg: rgba(var(--notes-rgb), .07);--notes-border: rgba(var(--notes-rgb), .18);--notes-accent: rgb(var(--notes-rgb));--notes-text: var(--ion-color-dark, #0a0612);--notes-link: rgb(var(--notes-rgb));position:relative;display:block;padding:14px 18px 14px 20px;background:var(--notes-bg);border:1px solid var(--notes-border);border-left:4px solid var(--notes-accent);border-radius:10px;color:var(--notes-text);margin:0;line-height:1.55}.val-notes-box.is-rounded{border-radius:12px}.val-notes-box[data-color=primary]{--notes-rgb: var(--ion-color-primary-rgb)}.val-notes-box[data-color=secondary]{--notes-rgb: var(--ion-color-secondary-rgb)}.val-notes-box[data-color=tertiary]{--notes-rgb: var(--ion-color-tertiary-rgb)}.val-notes-box[data-color=success]{--notes-rgb: var(--ion-color-success-rgb)}.val-notes-box[data-color=warning]{--notes-rgb: var(--ion-color-warning-rgb)}.val-notes-box[data-color=danger]{--notes-rgb: var(--ion-color-danger-rgb)}.val-notes-box[data-color=medium]{--notes-rgb: var(--ion-color-medium-rgb)}.val-notes-box[data-color=dark]{--notes-rgb: var(--ion-color-dark-rgb)}.val-notes-box[data-color=light]{--notes-rgb: var(--ion-color-medium-rgb)}.val-notes-box__header{display:block;margin:0 0 6px;font-weight:700;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--notes-accent);font-family:var(--ion-font-family, inherit)}.val-notes-box__body{display:block;color:var(--notes-text);font-size:14px;line-height:1.6}.val-notes-box__body.size-small{font-size:13px;line-height:1.55}.val-notes-box__body.size-large{font-size:15px;line-height:1.6}.val-notes-box__body.size-xlarge{font-size:16px;line-height:1.55}.val-notes-box__body ::ng-deep val-text{display:block;color:var(--notes-text)}.val-notes-box__body ::ng-deep val-text p{margin:0;color:inherit}.val-notes-box__body ::ng-deep val-text ion-text{color:var(--notes-text)!important}.val-notes-box__body ::ng-deep val-text strong,.val-notes-box__body ::ng-deep val-text b,.val-notes-box__body ::ng-deep .partial-bold{color:var(--notes-text);font-weight:700}.val-notes-box__body ::ng-deep val-text a{color:var(--notes-link);text-decoration:underline;text-underline-offset:2px;font-weight:600}.val-notes-box__body ::ng-deep val-text a:hover{opacity:.85}.val-notes-box.align-center,.val-notes-box.align-center .val-notes-box__header{text-align:center}.val-notes-box.align-right,.val-notes-box.align-right .val-notes-box__header{text-align:right}.val-notes-box.is-compact{display:inline-block;width:fit-content;max-width:100%;padding:5px 12px;border-left-width:1px;border-radius:999px;font-size:12px;line-height:1.3}.val-notes-box.is-compact .val-notes-box__header{display:inline;margin:0 6px 0 0;font-size:11px;letter-spacing:.06em}.val-notes-box.is-compact .val-notes-box__body{display:inline;font-size:12px}.val-notes-box.is-compact ::ng-deep val-text{display:inline}.val-notes-box.is-compact ::ng-deep val-text p{display:inline}@media (prefers-color-scheme: dark){:host-context(body:not(.light)) .val-notes-box{--notes-bg: rgba(var(--notes-rgb), .16);--notes-border: rgba(var(--notes-rgb), .3);--notes-text: var(--ion-color-light, #f4f5f8)}}:host-context(body.dark) .val-notes-box,:host-context(.theme-dark) .val-notes-box,:host-context([data-theme=dark]) .val-notes-box{--notes-bg: rgba(var(--notes-rgb), .16);--notes-border: rgba(var(--notes-rgb), .3);--notes-text: var(--ion-color-light, #f4f5f8)}\n"] }]
8731
+ }], propDecorators: { props: [{
8581
8732
  type: Input
8582
8733
  }] } });
8583
8734
 
@@ -19890,6 +20041,10 @@ class AuthStateService {
19890
20041
  return {
19891
20042
  userId: state.userId,
19892
20043
  email: state.email || '',
20044
+ name: state.name ?? undefined,
20045
+ handle: state.handle ?? undefined,
20046
+ avatarUrl: state.avatarUrl ?? undefined,
20047
+ phone: state.phone ?? undefined,
19893
20048
  roles: state.roles,
19894
20049
  permissions: state.permissions,
19895
20050
  isSuperAdmin: state.isSuperAdmin,
@@ -19903,7 +20058,7 @@ class AuthStateService {
19903
20058
  * Establece el estado de carga.
19904
20059
  */
19905
20060
  setLoading(isLoading) {
19906
- this._state.update((s) => ({ ...s, isLoading }));
20061
+ this._state.update(s => ({ ...s, isLoading }));
19907
20062
  }
19908
20063
  /**
19909
20064
  * Establece el estado de autenticación exitosa.
@@ -19929,7 +20084,7 @@ class AuthStateService {
19929
20084
  */
19930
20085
  updateAccessToken(accessToken, expiresIn) {
19931
20086
  const expiresAt = Date.now() + expiresIn * 1000;
19932
- this._state.update((s) => ({
20087
+ this._state.update(s => ({
19933
20088
  ...s,
19934
20089
  accessToken,
19935
20090
  expiresAt,
@@ -19939,7 +20094,7 @@ class AuthStateService {
19939
20094
  * Actualiza el refresh token (token rotation).
19940
20095
  */
19941
20096
  updateRefreshToken(refreshToken) {
19942
- this._state.update((s) => ({
20097
+ this._state.update(s => ({
19943
20098
  ...s,
19944
20099
  refreshToken,
19945
20100
  }));
@@ -19948,7 +20103,7 @@ class AuthStateService {
19948
20103
  * Actualiza los permisos.
19949
20104
  */
19950
20105
  updatePermissions(roles, permissions, isSuperAdmin) {
19951
- this._state.update((s) => ({
20106
+ this._state.update(s => ({
19952
20107
  ...s,
19953
20108
  roles,
19954
20109
  permissions,
@@ -19959,7 +20114,7 @@ class AuthStateService {
19959
20114
  * Establece un error de autenticación.
19960
20115
  */
19961
20116
  setError(error) {
19962
- this._state.update((s) => ({
20117
+ this._state.update(s => ({
19963
20118
  ...s,
19964
20119
  error,
19965
20120
  isLoading: false,
@@ -19969,7 +20124,7 @@ class AuthStateService {
19969
20124
  * Limpia el error.
19970
20125
  */
19971
20126
  clearError() {
19972
- this._state.update((s) => ({
20127
+ this._state.update(s => ({
19973
20128
  ...s,
19974
20129
  error: null,
19975
20130
  }));
@@ -20018,12 +20173,29 @@ class AuthStateService {
20018
20173
  * Actualiza el userId y email (después de parsear el token).
20019
20174
  */
20020
20175
  updateUserInfo(userId, email) {
20021
- this._state.update((s) => ({
20176
+ this._state.update(s => ({
20022
20177
  ...s,
20023
20178
  userId,
20024
20179
  email,
20025
20180
  }));
20026
20181
  }
20182
+ /**
20183
+ * Hidrata el state con campos del profile (nombre, handle, avatar, phone).
20184
+ * Invocado tras `getProfile()` o `updateProfile()` para que consumers de
20185
+ * `auth.user()` vean los campos enriched automáticamente.
20186
+ *
20187
+ * Cualquier campo `undefined` se ignora (no sobrescribe con null). Campos
20188
+ * `null` explícitos se persisten (signal de "limpiado").
20189
+ */
20190
+ updateProfileFields(fields) {
20191
+ this._state.update(s => ({
20192
+ ...s,
20193
+ ...(fields.name !== undefined && { name: fields.name }),
20194
+ ...(fields.handle !== undefined && { handle: fields.handle }),
20195
+ ...(fields.avatarUrl !== undefined && { avatarUrl: fields.avatarUrl }),
20196
+ ...(fields.phone !== undefined && { phone: fields.phone }),
20197
+ }));
20198
+ }
20027
20199
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
20028
20200
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthStateService, providedIn: 'root' }); }
20029
20201
  }
@@ -24086,29 +24258,32 @@ class AuthService {
24086
24258
  // =============================================
24087
24259
  /**
24088
24260
  * Obtiene el perfil del usuario autenticado.
24089
- * Incluye información de MFA y teléfono.
24261
+ * Incluye información de MFA y teléfono. Hidrata el state automáticamente
24262
+ * con `name/handle/avatarUrl/phone` para que `auth.user()` los retorne.
24090
24263
  */
24091
24264
  getProfile() {
24092
- return this.http
24093
- .get(`${this.baseUrl}/profile`)
24094
- .pipe(catchError(error => this.handleAuthError(error)));
24265
+ return this.http.get(`${this.baseUrl}/profile`).pipe(tap(profile => this.stateService.updateProfileFields({
24266
+ name: profile.name,
24267
+ handle: profile.handle ?? null,
24268
+ avatarUrl: profile.avatarUrl ?? null,
24269
+ phone: profile.phone ?? null,
24270
+ })), catchError(error => this.handleAuthError(error)));
24095
24271
  }
24096
24272
  /**
24097
- * Actualiza el perfil del usuario.
24273
+ * Actualiza el perfil del usuario. Sincroniza state con los nuevos values
24274
+ * (name/phone) — el backend response no los echo'a pero el caller ya tiene
24275
+ * los valores que mandó.
24098
24276
  */
24099
24277
  updateProfile(request) {
24100
- return this.http
24101
- .put(`${this.baseUrl}/profile`, request)
24102
- .pipe(catchError(error => this.handleAuthError(error)));
24278
+ return this.http.put(`${this.baseUrl}/profile`, request).pipe(tap(() => this.stateService.updateProfileFields(request)), catchError(error => this.handleAuthError(error)));
24103
24279
  }
24104
24280
  /**
24105
- * Actualiza el avatar del usuario en el backend.
24106
- * Nota: El estado local del avatar se maneja a través de getProfile().
24281
+ * Actualiza el avatar del usuario en el backend. Sincroniza state con el
24282
+ * `avatarUrl` retornado para que el header / dashboard se refresquen sin
24283
+ * necesidad de un getProfile adicional.
24107
24284
  */
24108
24285
  updateAvatar(request) {
24109
- return this.http
24110
- .put(`${this.baseUrl}/profile/avatar`, request)
24111
- .pipe(catchError(error => this.handleAuthError(error)));
24286
+ return this.http.put(`${this.baseUrl}/profile/avatar`, request).pipe(tap(res => this.stateService.updateProfileFields({ avatarUrl: res.avatarUrl })), catchError(error => this.handleAuthError(error)));
24112
24287
  }
24113
24288
  // =============================================
24114
24289
  // RECUPERACIÓN DE CONTRASEÑA
@@ -24231,9 +24406,7 @@ class AuthService {
24231
24406
  * @param handle - Nuevo handle (sin @, ej: "victorv")
24232
24407
  */
24233
24408
  updateHandle(handle) {
24234
- return this.http
24235
- .put(`${this.baseUrl}/profile/handle`, { handle })
24236
- .pipe(catchError(error => this.handleAuthError(error)));
24409
+ return this.http.put(`${this.baseUrl}/profile/handle`, { handle }).pipe(tap(() => this.stateService.updateProfileFields({ handle })), catchError(error => this.handleAuthError(error)));
24237
24410
  }
24238
24411
  /**
24239
24412
  * Verifica si un handle está disponible.
@@ -26415,11 +26588,15 @@ class ToolbarComponent {
26415
26588
  <ion-button *ngIf="action.type === actionTypes.ICON" (click)="clickHandler(action.token)">
26416
26589
  <ion-icon slot="icon-only" [name]="action.description" [color]="props.textColor"></ion-icon>
26417
26590
  </ion-button>
26418
- <val-avatar
26591
+ <val-user-avatar
26419
26592
  *ngIf="action.type === actionTypes.AVATAR"
26420
- [props]="{ size: 'small', image: action.description, default: '' }"
26593
+ [props]="{
26594
+ user: action.user,
26595
+ avatarUrl: action.description,
26596
+ size: 'small',
26597
+ }"
26421
26598
  (onClick)="clickHandler(action.token)"
26422
- ></val-avatar>
26599
+ ></val-user-avatar>
26423
26600
  <val-image
26424
26601
  *ngIf="action.type === actionTypes.IMAGE"
26425
26602
  [props]="action.image"
@@ -26444,11 +26621,15 @@ class ToolbarComponent {
26444
26621
  <ion-button *ngIf="action.type === actionTypes.ICON" (click)="clickHandler(action.token)">
26445
26622
  <ion-icon slot="icon-only" [name]="action.description" [color]="props.textColor"></ion-icon>
26446
26623
  </ion-button>
26447
- <val-avatar
26624
+ <val-user-avatar
26448
26625
  *ngIf="action.type === actionTypes.AVATAR"
26449
- [props]="{ size: 'small', image: action.description, default: '' }"
26626
+ [props]="{
26627
+ user: action.user,
26628
+ avatarUrl: action.description,
26629
+ size: 'small',
26630
+ }"
26450
26631
  (onClick)="clickHandler(action.token)"
26451
- ></val-avatar>
26632
+ ></val-user-avatar>
26452
26633
  <val-image
26453
26634
  *ngIf="action.type === actionTypes.IMAGE"
26454
26635
  [props]="action.image"
@@ -26464,7 +26645,7 @@ class ToolbarComponent {
26464
26645
  <!-- experimental -->
26465
26646
  <ng-content select="[toolbar-bottom]"></ng-content>
26466
26647
  </ion-toolbar>
26467
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif}.left-buttons{margin-left:-1rem}.background{background:var(--ion-background-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: LanguageSelectorComponent, selector: "val-language-selector", inputs: ["props"], outputs: ["languageChange"] }] }); }
26648
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif}.left-buttons{margin-left:-1rem}.background{background:var(--ion-background-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }, { kind: "component", type: UserAvatarComponent, selector: "val-user-avatar", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: LanguageSelectorComponent, selector: "val-language-selector", inputs: ["props"], outputs: ["languageChange"] }] }); }
26468
26649
  }
26469
26650
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ToolbarComponent, decorators: [{
26470
26651
  type: Component,
@@ -26478,6 +26659,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
26478
26659
  IonTitle,
26479
26660
  AvatarComponent,
26480
26661
  ImageComponent,
26662
+ UserAvatarComponent,
26481
26663
  IonMenuButton,
26482
26664
  LanguageSelectorComponent,
26483
26665
  ], template: `
@@ -26496,11 +26678,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
26496
26678
  <ion-button *ngIf="action.type === actionTypes.ICON" (click)="clickHandler(action.token)">
26497
26679
  <ion-icon slot="icon-only" [name]="action.description" [color]="props.textColor"></ion-icon>
26498
26680
  </ion-button>
26499
- <val-avatar
26681
+ <val-user-avatar
26500
26682
  *ngIf="action.type === actionTypes.AVATAR"
26501
- [props]="{ size: 'small', image: action.description, default: '' }"
26683
+ [props]="{
26684
+ user: action.user,
26685
+ avatarUrl: action.description,
26686
+ size: 'small',
26687
+ }"
26502
26688
  (onClick)="clickHandler(action.token)"
26503
- ></val-avatar>
26689
+ ></val-user-avatar>
26504
26690
  <val-image
26505
26691
  *ngIf="action.type === actionTypes.IMAGE"
26506
26692
  [props]="action.image"
@@ -26525,11 +26711,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
26525
26711
  <ion-button *ngIf="action.type === actionTypes.ICON" (click)="clickHandler(action.token)">
26526
26712
  <ion-icon slot="icon-only" [name]="action.description" [color]="props.textColor"></ion-icon>
26527
26713
  </ion-button>
26528
- <val-avatar
26714
+ <val-user-avatar
26529
26715
  *ngIf="action.type === actionTypes.AVATAR"
26530
- [props]="{ size: 'small', image: action.description, default: '' }"
26716
+ [props]="{
26717
+ user: action.user,
26718
+ avatarUrl: action.description,
26719
+ size: 'small',
26720
+ }"
26531
26721
  (onClick)="clickHandler(action.token)"
26532
- ></val-avatar>
26722
+ ></val-user-avatar>
26533
26723
  <val-image
26534
26724
  *ngIf="action.type === actionTypes.IMAGE"
26535
26725
  [props]="action.image"
@@ -43619,5 +43809,5 @@ function buildFooterLinks(links, t, resolver) {
43619
43809
  * Generated bundle index. Do not edit.
43620
43810
  */
43621
43811
 
43622
- 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, CHEV_KEYS, 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, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentTransformer, CookieBannerComponent, 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, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, 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, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MenuComponent, MessagingService, MetaService, ModalService, MultiSelectSearchComponent, NavigationService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, 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, SHAPE_KEYS, SKELETON_PRESETS, SOLID_KEYS, 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, TRI_KEYS, 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_LEGAL_CONFIG, VALTECH_SOCIAL_LINKS, VERSION, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, blogPost, buildFooterLinks, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, docs, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideValtechAds, provideValtechAppConfig, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPresets, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard, toArticle };
43812
+ 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, CHEV_KEYS, 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, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentTransformer, CookieBannerComponent, 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, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, 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, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginComponent, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MenuComponent, MessagingService, MetaService, ModalService, MultiSelectSearchComponent, NavigationService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PLATFORM_CONFIGS, PageContentComponent, PageTemplateComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, 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, SHAPE_KEYS, SKELETON_PRESETS, SOLID_KEYS, 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, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, UpdateBannerComponent, UserAvatarComponent, 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_LEGAL_CONFIG, VALTECH_SOCIAL_LINKS, VERSION, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, blogPost, buildFooterLinks, buildPath, collections, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createTitleProps, docs, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideValtechAds, provideValtechAppConfig, provideValtechAuth, provideValtechAuthInterceptor, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPresets, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor, resolveInputDefaultValue, roleGuard, storagePaths, superAdminGuard, toArticle };
43623
43813
  //# sourceMappingURL=valtech-components.mjs.map