valtech-components 4.0.179 → 4.0.181

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.
@@ -56,7 +56,7 @@ import { BrowserMultiFormatReader } from '@zxing/browser';
56
56
  * Current version of valtech-components.
57
57
  * This is automatically updated during the publish process.
58
58
  */
59
- const VERSION = '4.0.179';
59
+ const VERSION = '4.0.181';
60
60
 
61
61
  // Control de estado de refresco (singleton a nivel de módulo)
62
62
  let isRefreshing = false;
@@ -6587,145 +6587,21 @@ class OAuthService {
6587
6587
  this.clearLocalStorageFallback();
6588
6588
  const nonce = this.generateNonce();
6589
6589
  this.expectedNonce = nonce;
6590
- // popup=true sobrevive el bounce cross-origin (Google/MS borran window.name
6591
- // por privacidad). El backend lo reenvía en el redirect final vía appendParams.
6592
- const redirectUri = `${window.location.origin}/auth/oauth/callback?popup=true`;
6590
+ // Flujo REDIRECT (sin popup). El popup quedaba COLGADO bajo COOP: Google
6591
+ // setea Cross-Origin-Opener-Policy window.opener queda severado (el
6592
+ // postMessage del popup no llega), BroadcastChannel/localStorage no siempre
6593
+ // entregan, y popup.closed queda bloqueado ("COOP policy would block the
6594
+ // window.closed call") → ni siquiera dispara el cancel: la ventana principal
6595
+ // espera para siempre sin redirigir. Navegamos la VENTANA COMPLETA al /start;
6596
+ // al volver, OAuthCallbackComponent corre como ventana principal (redirect_uri
6597
+ // SIN popup=true) y completa la sesión vía completeInMainWindow → navega al
6598
+ // home. Sin popup = sin COOP = sin cuelgue. (El link-flow sigue por popup.)
6599
+ const redirectUri = `${window.location.origin}/auth/oauth/callback`;
6593
6600
  const startUrl = `${this.config?.apiUrl}/v2/auth/oauth/${provider}/start?redirect_uri=${encodeURIComponent(redirectUri)}&client_nonce=${encodeURIComponent(nonce)}`;
6594
- // Abrir popup centrado
6595
- const width = 500;
6596
- const height = 600;
6597
- const left = window.screenX + (window.outerWidth - width) / 2;
6598
- const top = window.screenY + (window.outerHeight - height) / 2;
6599
- const features = `width=${width},height=${height},left=${left},top=${top},popup=yes`;
6600
- this.popup = window.open(startUrl, 'oauth', features);
6601
- if (!this.popup) {
6602
- observer.error({
6603
- code: 'POPUP_BLOCKED',
6604
- message: 'El navegador bloqueó la ventana emergente. Por favor, permite popups para este sitio.',
6605
- });
6606
- return () => { };
6607
- }
6608
- // Escuchar mensajes del popup
6609
- this.messageHandler = (event) => {
6610
- // Validar origen
6611
- if (event.origin !== window.location.origin) {
6612
- return;
6613
- }
6614
- // Validar tipo de mensaje
6615
- const data = event.data;
6616
- if (data?.type !== 'oauth-callback') {
6617
- return;
6618
- }
6619
- // Verificar el nonce del flujo (M-07): si no coincide, no es nuestro
6620
- // callback → ignorar (no consumir el observable).
6621
- if (!this.isNonceValid(data)) {
6622
- return;
6623
- }
6624
- // Limpiar
6625
- this.cleanup();
6626
- // Emitir resultado dentro de NgZone para trigger change detection
6627
- this.ngZone.run(() => {
6628
- if (data.error) {
6629
- observer.error(data.error);
6630
- }
6631
- else if (data.tokens) {
6632
- observer.next(data.tokens);
6633
- observer.complete();
6634
- }
6635
- else {
6636
- observer.error({
6637
- code: 'INVALID_RESPONSE',
6638
- message: 'Respuesta inválida del servidor de autenticación',
6639
- });
6640
- }
6641
- });
6642
- };
6643
- window.addEventListener('message', this.messageHandler);
6644
- // BroadcastChannel: canal adicional immune a COOP (funciona entre misma
6645
- // origin sin importar el browsing context group). Es el canal más fiable
6646
- // cuando COOP sever el link opener→popup al pasar por Google/MS.
6647
- try {
6648
- this.broadcastChannel = new BroadcastChannel('valtech-oauth-callback');
6649
- this.broadcastChannel.onmessage = (event) => {
6650
- const data = event.data;
6651
- if (data?.type !== 'oauth-callback')
6652
- return;
6653
- if (!this.isNonceValid(data))
6654
- return;
6655
- this.clearLocalStorageFallback();
6656
- this.cleanup();
6657
- this.ngZone.run(() => {
6658
- if (data.error) {
6659
- observer.error(data.error);
6660
- }
6661
- else if (data.tokens) {
6662
- observer.next(data.tokens);
6663
- observer.complete();
6664
- }
6665
- else {
6666
- observer.error({
6667
- code: 'INVALID_RESPONSE',
6668
- message: 'Respuesta inválida del servidor de autenticación',
6669
- });
6670
- }
6671
- });
6672
- };
6673
- }
6674
- catch {
6675
- // BroadcastChannel no disponible (contextos muy restringidos) — ignorar
6676
- }
6677
- // Polling de localStorage (COOP workaround - no podemos detectar popup.closed)
6678
- // También verifica si el popup se cerró manualmente
6679
- this.checkClosedInterval = setInterval(() => {
6680
- // Primero verificar localStorage (funciona aunque COOP bloquee todo)
6681
- const storedData = this.checkLocalStorageFallback();
6682
- if (storedData) {
6683
- this.cleanup();
6684
- this.ngZone.run(() => {
6685
- if (storedData.error) {
6686
- observer.error(storedData.error);
6687
- }
6688
- else if (storedData.tokens) {
6689
- // Gate de diagnóstico: la metadata de tokens (keys, presencia y
6690
- // longitud del firebaseToken) no debe filtrarse a la consola en
6691
- // producción (L4 del audit). Solo en dev.
6692
- if (isDevMode()) {
6693
- console.log('[OAuthService] Retrieved tokens from localStorage fallback', {
6694
- keys: Object.keys(storedData.tokens),
6695
- hasFirebaseToken: !!storedData.tokens.firebaseToken,
6696
- firebaseTokenLength: storedData.tokens.firebaseToken?.length ?? 0,
6697
- });
6698
- }
6699
- observer.next(storedData.tokens);
6700
- observer.complete();
6701
- }
6702
- else {
6703
- observer.error({
6704
- code: 'INVALID_RESPONSE',
6705
- message: 'Respuesta inválida del servidor de autenticación',
6706
- });
6707
- }
6708
- });
6709
- return;
6710
- }
6711
- // Intentar verificar si popup se cerró (puede fallar por COOP)
6712
- try {
6713
- if (this.popup?.closed) {
6714
- this.cleanup();
6715
- this.ngZone.run(() => {
6716
- observer.error({
6717
- code: 'POPUP_CLOSED',
6718
- message: 'Se cerró la ventana de autenticación',
6719
- });
6720
- });
6721
- }
6722
- }
6723
- catch {
6724
- // COOP bloquea acceso a popup.closed - ignorar y seguir con polling
6725
- }
6726
- }, 300);
6727
- // Cleanup cuando el observable se destruye
6728
- return () => this.cleanup();
6601
+ window.location.assign(startUrl);
6602
+ // La página se descarga acá; el observable no emite (la finalización ocurre
6603
+ // en el callback, ya como ventana principal). Sin listeners ni polling.
6604
+ return () => { };
6729
6605
  });
6730
6606
  }
6731
6607
  /**
@@ -28487,7 +28363,7 @@ class UpdateBannerComponent {
28487
28363
  </div>
28488
28364
  </div>
28489
28365
  }
28490
- `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:contents}.val-update-banner{position:fixed;top:0;left:0;right:0;z-index:1100;display:flex;justify-content:center;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;pointer-events:none}.val-update-banner__backdrop{position:fixed;inset:0;z-index:-1;background:#0000008c;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);pointer-events:auto}.val-update-banner__panel{pointer-events:auto;display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;max-width:640px;padding:12px 16px;background:var(--ion-background-color, #fff);border:1px solid var(--val-border-color, rgba(0, 0, 0, .08));border-radius:var(--val-border-radius, 12px);box-shadow:0 4px 24px #0000001f;animation:val-update-banner-in .25s ease-out}.val-update-banner--required{align-items:center;height:100%}.val-update-banner--required .val-update-banner__panel{flex-direction:column;text-align:center;max-width:420px}.val-update-banner__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;background:color-mix(in srgb,var(--ion-color-primary) 14%,transparent);font-size:22px}.val-update-banner__icon val-icon{display:flex;line-height:0}.val-update-banner__icon ::ng-deep ion-icon{display:block}.val-update-banner--required .val-update-banner__icon{background:color-mix(in srgb,var(--ion-color-warning) 16%,transparent)}.val-update-banner__body{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.val-update-banner__actions{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:4px}.val-update-banner--required .val-update-banner__actions{margin-top:8px}@keyframes val-update-banner-in{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 540px){.val-update-banner__panel{flex-direction:column;text-align:center}.val-update-banner__actions{width:100%;justify-content:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: IconComponent, selector: "val-icon", inputs: ["props"] }] }); }
28366
+ `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:contents}.val-update-banner{position:fixed;top:0;left:0;right:0;z-index:1100;display:flex;justify-content:center;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;pointer-events:none}.val-update-banner__backdrop{position:fixed;inset:0;z-index:-1;background:#0000008c;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);pointer-events:auto}.val-update-banner__panel{pointer-events:auto;display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;max-width:640px;padding:12px 16px;background:var(--ion-background-color, #fff);border:1px solid var(--val-border-color, rgba(0, 0, 0, .08));border-radius:var(--val-border-radius, 12px);box-shadow:0 4px 24px #0000001f;animation:val-update-banner-in .25s ease-out}.val-update-banner--required{align-items:center;height:100%}.val-update-banner--required .val-update-banner__panel{flex-direction:column;text-align:center;max-width:420px}.val-update-banner__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;background:color-mix(in srgb,var(--ion-color-primary) 14%,transparent);font-size:22px}.val-update-banner__icon val-icon{display:flex;line-height:0}.val-update-banner__icon ::ng-deep ion-icon{display:block}.val-update-banner--required .val-update-banner__icon{background:color-mix(in srgb,var(--ion-color-warning) 16%,transparent)}.val-update-banner__body{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.val-update-banner__actions{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:4px}.val-update-banner__actions val-button:first-child ::ng-deep ion-button{min-width:100px}.val-update-banner--required .val-update-banner__actions{margin-top:8px}@keyframes val-update-banner-in{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 540px){.val-update-banner__panel{flex-direction:column;text-align:center}.val-update-banner__actions{width:100%;justify-content:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: IconComponent, selector: "val-icon", inputs: ["props"] }] }); }
28491
28367
  }
28492
28368
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UpdateBannerComponent, decorators: [{
28493
28369
  type: Component,
@@ -28562,7 +28438,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
28562
28438
  </div>
28563
28439
  </div>
28564
28440
  }
28565
- `, styles: ["@charset \"UTF-8\";:host{display:contents}.val-update-banner{position:fixed;top:0;left:0;right:0;z-index:1100;display:flex;justify-content:center;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;pointer-events:none}.val-update-banner__backdrop{position:fixed;inset:0;z-index:-1;background:#0000008c;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);pointer-events:auto}.val-update-banner__panel{pointer-events:auto;display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;max-width:640px;padding:12px 16px;background:var(--ion-background-color, #fff);border:1px solid var(--val-border-color, rgba(0, 0, 0, .08));border-radius:var(--val-border-radius, 12px);box-shadow:0 4px 24px #0000001f;animation:val-update-banner-in .25s ease-out}.val-update-banner--required{align-items:center;height:100%}.val-update-banner--required .val-update-banner__panel{flex-direction:column;text-align:center;max-width:420px}.val-update-banner__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;background:color-mix(in srgb,var(--ion-color-primary) 14%,transparent);font-size:22px}.val-update-banner__icon val-icon{display:flex;line-height:0}.val-update-banner__icon ::ng-deep ion-icon{display:block}.val-update-banner--required .val-update-banner__icon{background:color-mix(in srgb,var(--ion-color-warning) 16%,transparent)}.val-update-banner__body{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.val-update-banner__actions{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:4px}.val-update-banner--required .val-update-banner__actions{margin-top:8px}@keyframes val-update-banner-in{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 540px){.val-update-banner__panel{flex-direction:column;text-align:center}.val-update-banner__actions{width:100%;justify-content:center}}\n"] }]
28441
+ `, styles: ["@charset \"UTF-8\";:host{display:contents}.val-update-banner{position:fixed;top:0;left:0;right:0;z-index:1100;display:flex;justify-content:center;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;pointer-events:none}.val-update-banner__backdrop{position:fixed;inset:0;z-index:-1;background:#0000008c;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);pointer-events:auto}.val-update-banner__panel{pointer-events:auto;display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;max-width:640px;padding:12px 16px;background:var(--ion-background-color, #fff);border:1px solid var(--val-border-color, rgba(0, 0, 0, .08));border-radius:var(--val-border-radius, 12px);box-shadow:0 4px 24px #0000001f;animation:val-update-banner-in .25s ease-out}.val-update-banner--required{align-items:center;height:100%}.val-update-banner--required .val-update-banner__panel{flex-direction:column;text-align:center;max-width:420px}.val-update-banner__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;background:color-mix(in srgb,var(--ion-color-primary) 14%,transparent);font-size:22px}.val-update-banner__icon val-icon{display:flex;line-height:0}.val-update-banner__icon ::ng-deep ion-icon{display:block}.val-update-banner--required .val-update-banner__icon{background:color-mix(in srgb,var(--ion-color-warning) 16%,transparent)}.val-update-banner__body{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.val-update-banner__actions{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:4px}.val-update-banner__actions val-button:first-child ::ng-deep ion-button{min-width:100px}.val-update-banner--required .val-update-banner__actions{margin-top:8px}@keyframes val-update-banner-in{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 540px){.val-update-banner__panel{flex-direction:column;text-align:center}.val-update-banner__actions{width:100%;justify-content:center}}\n"] }]
28566
28442
  }], ctorParameters: () => [] });
28567
28443
 
28568
28444
  /**
@@ -54370,7 +54246,7 @@ const ORGANIZATION_VIEW_I18N = {
54370
54246
  },
54371
54247
  };
54372
54248
 
54373
- addIcons({ warningOutline });
54249
+ addIcons({ warningOutline, swapHorizontalOutline });
54374
54250
  const DEFAULT_NAMESPACE$6 = 'Settings.Organization';
54375
54251
  const DEFAULT_VIEW_PERMISSIONS_ROUTE = '/app/settings/permissions';
54376
54252
  const DEFAULT_API_KEYS_ROUTE = '/app/settings/api-keys';
@@ -54524,9 +54400,10 @@ class OrganizationViewComponent {
54524
54400
  return this.tt('planFree');
54525
54401
  });
54526
54402
  this.switchOrgSectionProps = computed(() => ({
54527
- title: this.tt('activeOrgTitle'),
54403
+ title: this.pageTitle(),
54528
54404
  action: {
54529
54405
  text: this.tt('switchOrgCta'),
54406
+ icon: { name: 'swap-horizontal-outline', slot: 'start' },
54530
54407
  color: 'dark',
54531
54408
  fill: 'outline',
54532
54409
  size: 'small',
@@ -54535,6 +54412,7 @@ class OrganizationViewComponent {
54535
54412
  token: 'org-switch',
54536
54413
  state: ComponentStates.ENABLED,
54537
54414
  },
54415
+ infoLink: { label: this.tt('orgsMoreInfo'), token: 'org-more-info' },
54538
54416
  }));
54539
54417
  this.editButtonProps = computed(() => ({
54540
54418
  text: this.tt('editCta'),
@@ -54778,6 +54656,12 @@ class OrganizationViewComponent {
54778
54656
  this.nav.navigateByUrl(this.resolvedConfig().apiKeysRoute);
54779
54657
  }
54780
54658
  // "Más información" sobre organizaciones — mismo sheet explicativo que muestra
54659
+ onHeaderAction(token) {
54660
+ if (token === 'org-switch')
54661
+ this.onSwitchOrg();
54662
+ else if (token === 'org-more-info')
54663
+ this.onOrgInfo();
54664
+ }
54781
54665
  // account-view sin org, pero disponible siempre (todo user tiene org por defecto).
54782
54666
  onSwitchOrg() {
54783
54667
  void this.modalService.open({
@@ -55044,17 +54928,7 @@ class OrganizationViewComponent {
55044
54928
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OrganizationViewComponent, isStandalone: true, selector: "val-organization-view", inputs: { config: "config" }, ngImport: i0, template: `
55045
54929
  <div class="page">
55046
54930
  <header class="page-header">
55047
- <val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
55048
- <val-title
55049
- [props]="{
55050
- size: 'large',
55051
- color: 'dark',
55052
- bold: false,
55053
- content: pageDescription(),
55054
- }"
55055
- />
55056
- <!-- Sección "Organización activa" con botón Cambiar a la derecha. -->
55057
- <val-section-header [props]="switchOrgSectionProps()" (actionClick)="onSwitchOrg()" />
54931
+ <val-section-header [props]="switchOrgSectionProps()" (actionClick)="onHeaderAction($event)" />
55058
54932
  </header>
55059
54933
 
55060
54934
  @if (resolvedConfig().showInfo) {
@@ -55356,7 +55230,7 @@ class OrganizationViewComponent {
55356
55230
  (created)="onOrgCreated($event)"
55357
55231
  />
55358
55232
  </div>
55359
- `, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.org-more-info-link{background:none;border:none;padding:4px 0;margin-top:4px;font-size:13px;font-weight:600;color:var(--ion-color-primary, #7026df);cursor:pointer;text-align:left}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;gap:8px}.invite-cta{display:flex;flex-direction:column;gap:16px}.invite-cta__text{display:flex;flex-direction:column;gap:4px}.invite-cta__actions{display:flex;gap:12px;flex-wrap:wrap}.org-info-card{border-radius:14px;background:var(--ion-color-light, #f4f5f8);overflow:hidden}.org-info-logo{display:flex;justify-content:center;padding:8px 0 16px}.org-logo-img{width:80px;height:80px;border-radius:50%;object-fit:cover;border:2px solid var(--ion-color-light)}:host-context(body.dark) .org-info-card,:host-context(html.ion-palette-dark) .org-info-card,:host-context([data-theme=\"dark\"]) .org-info-card{background:#ffffff0d}.org-info-field{padding:12px 16px;display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-field:last-child{border-bottom:none}.org-info-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.org-info-value{font-size:.95rem;font-weight:500;color:var(--ion-color-dark)}.org-info-value--muted{color:var(--ion-color-medium);font-weight:400}.plan-badge{display:inline-block;font-size:.78rem;font-weight:700;padding:3px 10px;border-radius:20px;width:fit-content}.plan-badge--free{background:var(--ion-color-light-shade, #d7d8da);color:var(--ion-color-dark)}.plan-badge--pro{background:var(--ion-color-primary);color:#fff}.plan-badge--enterprise{background:#f5c542;color:#222}.members-list{display:flex;flex-direction:column;gap:8px}.members-show-more{background:none;border:none;color:var(--ion-color-primary);font-size:14px;font-weight:500;cursor:pointer;padding:8px 0}.rbac-debug{opacity:.7}.rbac-debug__body{display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:.78rem}.rbac-debug__row{display:flex;gap:8px;align-items:flex-start}.rbac-debug__label{color:var(--ion-color-medium);min-width:72px;flex-shrink:0}.rbac-debug__value{color:var(--ion-color-dark);word-break:break-all}.rbac-debug__value--perms{color:var(--ion-color-medium)}.section-title-danger{display:flex;align-items:center;gap:8px;margin-bottom:12px}.section-title-danger val-title{display:block;margin:0}.danger-icon{display:block;font-size:1.125rem;color:var(--ion-color-warning-shade, #d4a017);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: CreateOrgModalComponent, selector: "val-create-org-modal", inputs: ["i18nNamespace", "isOpen"], outputs: ["dismissed", "created"] }, { kind: "component", type: CtaCardComponent, selector: "val-cta-card", inputs: ["props"], outputs: ["onAction"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "directive", type: HasPermissionDirective, selector: "[valHasPermission]", inputs: ["valHasPermission"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: MemberCardComponent, selector: "val-member-card", inputs: ["props"], outputs: ["onAction"] }, { kind: "component", type: PermissionsModalComponent, selector: "val-permissions-modal", inputs: ["isOpen", "config"], outputs: ["dismissed"] }, { kind: "component", type: SectionHeaderComponent, selector: "val-section-header", inputs: ["props"], outputs: ["actionClick"] }] }); }
55233
+ `, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.org-more-info-link{background:none;border:none;padding:4px 0;margin-top:4px;font-size:13px;font-weight:600;color:var(--ion-color-primary, #7026df);cursor:pointer;text-align:left}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;gap:8px}.invite-cta{display:flex;flex-direction:column;gap:16px}.invite-cta__text{display:flex;flex-direction:column;gap:4px}.invite-cta__actions{display:flex;gap:12px;flex-wrap:wrap}.org-info-card{border-radius:14px;background:var(--ion-color-light, #f4f5f8);overflow:hidden}.org-info-logo{display:flex;justify-content:center;padding:8px 0 16px}.org-logo-img{width:80px;height:80px;border-radius:50%;object-fit:cover;border:2px solid var(--ion-color-light)}:host-context(body.dark) .org-info-card,:host-context(html.ion-palette-dark) .org-info-card,:host-context([data-theme=\"dark\"]) .org-info-card{background:#ffffff0d}.org-info-field{padding:12px 16px;display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-field:last-child{border-bottom:none}.org-info-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.org-info-value{font-size:.95rem;font-weight:500;color:var(--ion-color-dark)}.org-info-value--muted{color:var(--ion-color-medium);font-weight:400}.plan-badge{display:inline-block;font-size:.78rem;font-weight:700;padding:3px 10px;border-radius:20px;width:fit-content}.plan-badge--free{background:var(--ion-color-light-shade, #d7d8da);color:var(--ion-color-dark)}.plan-badge--pro{background:var(--ion-color-primary);color:#fff}.plan-badge--enterprise{background:#f5c542;color:#222}.members-list{display:flex;flex-direction:column;gap:8px}.members-show-more{background:none;border:none;color:var(--ion-color-primary);font-size:14px;font-weight:500;cursor:pointer;padding:8px 0}.rbac-debug{opacity:.7}.rbac-debug__body{display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:.78rem}.rbac-debug__row{display:flex;gap:8px;align-items:flex-start}.rbac-debug__label{color:var(--ion-color-medium);min-width:72px;flex-shrink:0}.rbac-debug__value{color:var(--ion-color-dark);word-break:break-all}.rbac-debug__value--perms{color:var(--ion-color-medium)}.section-title-danger{display:flex;align-items:center;gap:8px;margin-bottom:12px}.section-title-danger val-title{display:block;margin:0}.danger-icon{display:block;font-size:1.125rem;color:var(--ion-color-warning-shade, #d4a017);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: CreateOrgModalComponent, selector: "val-create-org-modal", inputs: ["i18nNamespace", "isOpen"], outputs: ["dismissed", "created"] }, { kind: "component", type: CtaCardComponent, selector: "val-cta-card", inputs: ["props"], outputs: ["onAction"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "directive", type: HasPermissionDirective, selector: "[valHasPermission]", inputs: ["valHasPermission"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: MemberCardComponent, selector: "val-member-card", inputs: ["props"], outputs: ["onAction"] }, { kind: "component", type: PermissionsModalComponent, selector: "val-permissions-modal", inputs: ["isOpen", "config"], outputs: ["dismissed"] }, { kind: "component", type: SectionHeaderComponent, selector: "val-section-header", inputs: ["props"], outputs: ["actionClick"] }] }); }
55360
55234
  }
55361
55235
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrganizationViewComponent, decorators: [{
55362
55236
  type: Component,
@@ -55381,17 +55255,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
55381
55255
  ], template: `
55382
55256
  <div class="page">
55383
55257
  <header class="page-header">
55384
- <val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
55385
- <val-title
55386
- [props]="{
55387
- size: 'large',
55388
- color: 'dark',
55389
- bold: false,
55390
- content: pageDescription(),
55391
- }"
55392
- />
55393
- <!-- Sección "Organización activa" con botón Cambiar a la derecha. -->
55394
- <val-section-header [props]="switchOrgSectionProps()" (actionClick)="onSwitchOrg()" />
55258
+ <val-section-header [props]="switchOrgSectionProps()" (actionClick)="onHeaderAction($event)" />
55395
55259
  </header>
55396
55260
 
55397
55261
  @if (resolvedConfig().showInfo) {