valtech-components 4.0.13 → 4.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/esm2022/lib/components/organisms/invite-member-modal/invite-member-modal.component.mjs +3 -9
  2. package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.component.mjs +159 -66
  3. package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.i18n.mjs +17 -9
  4. package/esm2022/lib/components/organisms/organization-view/organization-view.component.mjs +2 -2
  5. package/esm2022/lib/services/app-version/app-version.service.mjs +10 -4
  6. package/esm2022/lib/services/app-version/config.mjs +6 -1
  7. package/esm2022/lib/services/app-version/index.mjs +2 -2
  8. package/esm2022/lib/services/app-version/types.mjs +1 -1
  9. package/esm2022/lib/services/org/types.mjs +9 -2
  10. package/esm2022/lib/version.mjs +2 -2
  11. package/esm2022/public-api.mjs +1 -1
  12. package/fesm2022/valtech-components.mjs +196 -84
  13. package/fesm2022/valtech-components.mjs.map +1 -1
  14. package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +1 -1
  15. package/lib/components/molecules/features-list/features-list.component.d.ts +1 -1
  16. package/lib/components/organisms/article/article.component.d.ts +4 -4
  17. package/lib/components/organisms/landing-steps/landing-steps.component.d.ts +1 -1
  18. package/lib/components/organisms/member-import-modal/member-import-modal.component.d.ts +5 -3
  19. package/lib/services/app-version/app-version.service.d.ts +4 -2
  20. package/lib/services/app-version/config.d.ts +6 -1
  21. package/lib/services/app-version/index.d.ts +1 -1
  22. package/lib/services/app-version/types.d.ts +20 -0
  23. package/lib/services/org/types.d.ts +12 -1
  24. package/lib/version.d.ts +1 -1
  25. package/package.json +1 -1
  26. package/public-api.d.ts +1 -1
  27. package/src/lib/components/styles/overrides.scss +8 -0
@@ -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.13';
59
+ const VERSION = '4.0.15';
60
60
 
61
61
  // Control de estado de refresco (singleton a nivel de módulo)
62
62
  let isRefreshing = false;
@@ -26975,6 +26975,11 @@ const DEFAULT_APP_VERSION_SERVICE_CONFIG = {
26975
26975
  * Token de inyección para la configuración de AppVersionService.
26976
26976
  */
26977
26977
  const VALTECH_APP_VERSION = new InjectionToken('ValtechAppVersion');
26978
+ /**
26979
+ * Token de inyección para el plugin de plataforma nativa.
26980
+ * Provisto opcionalmente por apps que corren en iOS/Android vía Capacitor.
26981
+ */
26982
+ const APP_VERSION_PLATFORM_PLUGIN = new InjectionToken('AppVersionPlatformPlugin');
26978
26983
  /**
26979
26984
  * Provee el servicio de verificación de versión a la aplicación Angular.
26980
26985
  *
@@ -27054,6 +27059,8 @@ class AppVersionService {
27054
27059
  this.serviceConfig = inject(VALTECH_APP_VERSION, {
27055
27060
  optional: true,
27056
27061
  });
27062
+ /** Plugin nativo opcional: provisto por apps Capacitor para Play Store / App Store. */
27063
+ this.platformPlugin = inject(APP_VERSION_PLATFORM_PLUGIN, { optional: true });
27057
27064
  this.document = inject(DOCUMENT);
27058
27065
  this.destroyRef = inject(DestroyRef);
27059
27066
  /** True cuando el SW reportó un bundle nuevo listo (`VERSION_READY`). */
@@ -27107,10 +27114,14 @@ class AppVersionService {
27107
27114
  /**
27108
27115
  * Aplica la actualización pendiente.
27109
27116
  *
27110
- * Si el SW está habilitado, activa la versión descargada y recarga; si no,
27111
- * solo recarga la página (la web obtiene el bundle nuevo del servidor).
27117
+ * Si hay un plugin de plataforma (nativo/Capacitor), delega en él (ej. Play Store).
27118
+ * Si no, activa la versión SW si está disponible y recarga la página.
27112
27119
  */
27113
27120
  async applyUpdate() {
27121
+ if (this.platformPlugin) {
27122
+ await this.platformPlugin.applyUpdate();
27123
+ return;
27124
+ }
27114
27125
  try {
27115
27126
  if (this.swUpdate?.isEnabled) {
27116
27127
  await this.swUpdate.activateUpdate();
@@ -48690,6 +48701,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
48690
48701
  type: Input
48691
48702
  }] } });
48692
48703
 
48704
+ /**
48705
+ * Resuelve el label legible de un rol para el idioma dado.
48706
+ * Fallback: displayName en otro idioma → role.name (snake_case).
48707
+ */
48708
+ function resolveRoleLabel(role, lang) {
48709
+ const label = role.displayName?.[lang] ?? role.displayName?.['es'] ?? role.displayName?.['en'];
48710
+ return label ?? role.name;
48711
+ }
48712
+
48693
48713
  /**
48694
48714
  * Defaults i18n (es/en) embebidos en `val-invite-member-modal`. Auto-registrados
48695
48715
  * en el constructor del componente si el consumer no proveyó el namespace
@@ -48900,14 +48920,7 @@ class InviteMemberModalComponent {
48900
48920
  });
48901
48921
  }
48902
48922
  roleDisplayName(role) {
48903
- const keyMap = {
48904
- viewer: 'roleViewer',
48905
- editor: 'roleEditor',
48906
- admin: 'roleAdmin',
48907
- };
48908
- const key = keyMap[role.name] ?? role.name;
48909
- const label = this.t(key);
48910
- return label && !label.startsWith('[') ? label : role.name;
48923
+ return resolveRoleLabel(role, this.i18n.lang());
48911
48924
  }
48912
48925
  async onInviteByEmail() {
48913
48926
  const email = this.query().trim();
@@ -50078,14 +50091,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
50078
50091
  const MEMBER_IMPORT_MODAL_I18N = {
50079
50092
  es: {
50080
50093
  title: 'Importar miembros',
50081
- hint: 'Pega un CSV con columnas: email, nombre, rol (una fila por persona).',
50094
+ subtitle: 'Carga un archivo CSV o pega el contenido directamente. Cada fila debe tener email, nombre y rol. Los cambios se aplican al instante.',
50082
50095
  csvPlaceholder: 'email,nombre,rol\nana@x.com,Ana,editor\nbeto@x.com,Beto,viewer',
50096
+ importMethodLabel: '¿Cómo deseas importar?',
50097
+ importMethodFile: 'Por archivo',
50098
+ importMethodFileHint: 'Sube un archivo .csv desde tu equipo',
50099
+ importMethodPaste: 'Pegar contenido',
50100
+ importMethodPasteHint: 'Escribe o pega el CSV directamente',
50083
50101
  uploadFile: 'Subir archivo CSV',
50084
- orPaste: 'o pega el CSV abajo',
50085
50102
  fileLoaded: 'Archivo cargado: {name}',
50086
50103
  fileReadError: 'No se pudo leer el archivo.',
50087
50104
  rolesAvailable: 'Roles disponibles:',
50088
- onConflictLabel: 'Si el email ya existe',
50105
+ onConflictLabel: '¿Qué hacer si el email ya existe?',
50089
50106
  conflictAssign: 'Asignar el rol',
50090
50107
  conflictSkip: 'Omitir',
50091
50108
  conflictError: 'Marcar error',
@@ -50093,7 +50110,7 @@ const MEMBER_IMPORT_MODAL_I18N = {
50093
50110
  submit: 'Importar',
50094
50111
  submitting: 'Importando...',
50095
50112
  parseError: 'No se pudo interpretar el CSV. Revisa el formato.',
50096
- noRows: 'Pega al menos una fila válida (email y rol).',
50113
+ noRows: 'Agrega al menos una fila válida (email y rol).',
50097
50114
  summary: 'Resumen',
50098
50115
  created: 'creados',
50099
50116
  assigned: 'asignados',
@@ -50110,14 +50127,18 @@ const MEMBER_IMPORT_MODAL_I18N = {
50110
50127
  },
50111
50128
  en: {
50112
50129
  title: 'Import members',
50113
- hint: 'Paste a CSV with columns: email, name, role (one row per person).',
50130
+ subtitle: 'Upload a CSV file or paste the content directly. Each row must include email, name and role. Changes are applied immediately.',
50114
50131
  csvPlaceholder: 'email,name,role\nana@x.com,Ana,editor\nbeto@x.com,Beto,viewer',
50132
+ importMethodLabel: 'How do you want to import?',
50133
+ importMethodFile: 'From file',
50134
+ importMethodFileHint: 'Upload a .csv file from your device',
50135
+ importMethodPaste: 'Paste content',
50136
+ importMethodPasteHint: 'Type or paste the CSV directly',
50115
50137
  uploadFile: 'Upload CSV file',
50116
- orPaste: 'or paste the CSV below',
50117
50138
  fileLoaded: 'File loaded: {name}',
50118
50139
  fileReadError: "Couldn't read the file.",
50119
50140
  rolesAvailable: 'Available roles:',
50120
- onConflictLabel: 'If the email already exists',
50141
+ onConflictLabel: 'What to do if the email already exists?',
50121
50142
  conflictAssign: 'Assign the role',
50122
50143
  conflictSkip: 'Skip',
50123
50144
  conflictError: 'Mark as error',
@@ -50125,7 +50146,7 @@ const MEMBER_IMPORT_MODAL_I18N = {
50125
50146
  submit: 'Import',
50126
50147
  submitting: 'Importing...',
50127
50148
  parseError: "Couldn't parse the CSV. Check the format.",
50128
- noRows: 'Paste at least one valid row (email and role).',
50149
+ noRows: 'Add at least one valid row (email and role).',
50129
50150
  summary: 'Summary',
50130
50151
  created: 'created',
50131
50152
  assigned: 'assigned',
@@ -50143,7 +50164,7 @@ const MEMBER_IMPORT_MODAL_I18N = {
50143
50164
  };
50144
50165
 
50145
50166
  const DEFAULT_NAMESPACE$8 = 'Settings.ImportModal';
50146
- addIcons({ cloudUploadOutline });
50167
+ addIcons({ cloudUploadOutline, documentTextOutline });
50147
50168
  /**
50148
50169
  * `val-member-import-modal` — panel de carga masiva de miembros (ADR-023 fase 6).
50149
50170
  *
@@ -50164,8 +50185,9 @@ class MemberImportModalComponent {
50164
50185
  /** Namespace i18n. */
50165
50186
  this.i18nNamespace = DEFAULT_NAMESPACE$8;
50166
50187
  this.csv = '';
50167
- this.sendActivation = true;
50188
+ this.importMode = signal('file');
50168
50189
  this.onConflictControl = new FormControl('assignRole');
50190
+ this.sendActivationControl = new FormControl(true);
50169
50191
  this.conflictSelectProps = computed(() => ({
50170
50192
  control: this.onConflictControl,
50171
50193
  label: '',
@@ -50178,12 +50200,25 @@ class MemberImportModalComponent {
50178
50200
  { id: 'error', name: this.t('conflictError'), order: 2 },
50179
50201
  ],
50180
50202
  }));
50203
+ this.sendActivationProps = computed(() => ({
50204
+ control: this.sendActivationControl,
50205
+ label: this.t('sendActivation'),
50206
+ type: InputType.CHECK,
50207
+ state: ComponentStates.ENABLED,
50208
+ labelPlacement: 'end',
50209
+ }));
50181
50210
  this.submitting = signal(false);
50182
50211
  this.errorMsg = signal('');
50183
50212
  this.results = signal(null);
50184
50213
  /** Nombre del archivo CSV cargado (vacío si se pegó manualmente). */
50185
50214
  this.fileName = signal('');
50186
- this.rolesHint = computed(() => this.availableRoles.length ? `${this.t('rolesAvailable')} ${this.availableRoles.join(', ')}` : '');
50215
+ this.rolesHint = computed(() => {
50216
+ if (!this.availableRoles.length)
50217
+ return '';
50218
+ const lang = this.i18n.lang();
50219
+ const names = this.availableRoles.map(r => resolveRoleLabel(r, lang)).join(', ');
50220
+ return `${this.t('rolesAvailable')} ${names}`;
50221
+ });
50187
50222
  this.summaryLabel = computed(() => {
50188
50223
  const s = this.results()?.summary;
50189
50224
  if (!s)
@@ -50248,7 +50283,7 @@ class MemberImportModalComponent {
50248
50283
  .importMembers(this.orgId, {
50249
50284
  users,
50250
50285
  onConflict: (this.onConflictControl.value ?? 'assignRole'),
50251
- sendActivation: this.sendActivation,
50286
+ sendActivation: this.sendActivationControl.value ?? true,
50252
50287
  })
50253
50288
  .subscribe({
50254
50289
  next: res => {
@@ -50277,6 +50312,7 @@ class MemberImportModalComponent {
50277
50312
  this.fileName.set('');
50278
50313
  this.errorMsg.set('');
50279
50314
  this.results.set(null);
50315
+ this.importMode.set('file');
50280
50316
  }
50281
50317
  dismiss() {
50282
50318
  this._modalRef?.dismiss(null, 'cancel');
@@ -50298,10 +50334,9 @@ class MemberImportModalComponent {
50298
50334
 
50299
50335
  <ion-content class="ion-padding">
50300
50336
  <val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
50337
+ <val-title [props]="{ content: t('subtitle'), size: 'large', color: '', bold: false }" />
50301
50338
 
50302
50339
  @if (!results()) {
50303
- <val-title [props]="{ content: t('hint'), size: 'large', color: '', bold: false }" />
50304
-
50305
50340
  @if (rolesHint()) {
50306
50341
  <val-text
50307
50342
  class="import-roles-hint"
@@ -50309,40 +50344,79 @@ class MemberImportModalComponent {
50309
50344
  />
50310
50345
  }
50311
50346
 
50312
- <!-- Subida de archivo: label nativo envuelve el input (label trick, igual
50313
- que val-attachment-uploader) → gesto confiable en iOS/PWA. -->
50314
- <div class="import-upload">
50315
- <label class="import-upload__btn">
50316
- <ion-icon name="cloud-upload-outline" />
50317
- <span>{{ t('uploadFile') }}</span>
50318
- <input type="file" accept=".csv,text/csv,text/plain" (change)="onFileSelected($event)" />
50319
- </label>
50320
- <span class="import-upload__hint">{{ t('orPaste') }}</span>
50347
+ <!-- Selector de método de importación -->
50348
+ <div class="import-section">
50349
+ <val-title [props]="{ content: t('importMethodLabel'), size: 'small', color: 'dark', bold: true }" />
50350
+ <div class="import-method-cards">
50351
+ <button
50352
+ type="button"
50353
+ class="import-method-card"
50354
+ [class.import-method-card--active]="importMode() === 'file'"
50355
+ (click)="importMode.set('file')"
50356
+ >
50357
+ <ion-icon name="cloud-upload-outline" class="import-method-card__icon" />
50358
+ <span class="import-method-card__title">{{ t('importMethodFile') }}</span>
50359
+ <span class="import-method-card__hint">{{ t('importMethodFileHint') }}</span>
50360
+ </button>
50361
+ <button
50362
+ type="button"
50363
+ class="import-method-card"
50364
+ [class.import-method-card--active]="importMode() === 'paste'"
50365
+ (click)="importMode.set('paste')"
50366
+ >
50367
+ <ion-icon name="document-text-outline" class="import-method-card__icon" />
50368
+ <span class="import-method-card__title">{{ t('importMethodPaste') }}</span>
50369
+ <span class="import-method-card__hint">{{ t('importMethodPasteHint') }}</span>
50370
+ </button>
50371
+ </div>
50321
50372
  </div>
50322
50373
 
50323
- @if (fileName()) {
50324
- <p class="import-file-loaded">
50325
- {{ t('fileLoaded').replace('{name}', fileName()) }}
50326
- </p>
50374
+ <!-- Subida de archivo (label trick — gesto confiable en iOS/PWA) -->
50375
+ @if (importMode() === 'file') {
50376
+ <div class="import-section">
50377
+ <label class="import-upload__btn">
50378
+ <ion-icon name="cloud-upload-outline" />
50379
+ <span>{{ t('uploadFile') }}</span>
50380
+ <input type="file" accept=".csv,text/csv,text/plain" (change)="onFileSelected($event)" />
50381
+ </label>
50382
+ @if (fileName()) {
50383
+ <p class="import-file-loaded">
50384
+ {{ t('fileLoaded').replace('{name}', fileName()) }}
50385
+ </p>
50386
+ }
50387
+ </div>
50327
50388
  }
50328
50389
 
50329
- <ion-textarea
50330
- class="import-csv"
50331
- [autoGrow]="true"
50332
- [rows]="6"
50333
- [placeholder]="t('csvPlaceholder')"
50334
- [(ngModel)]="csv"
50335
- />
50390
+ <!-- Pegar CSV -->
50391
+ @if (importMode() === 'paste') {
50392
+ <div class="import-section">
50393
+ <ion-textarea
50394
+ class="import-csv"
50395
+ [autoGrow]="true"
50396
+ [rows]="6"
50397
+ [placeholder]="t('csvPlaceholder')"
50398
+ [(ngModel)]="csv"
50399
+ />
50400
+ </div>
50401
+ }
50402
+
50403
+ <!-- Si hubo carga de archivo, mostrar textarea de solo lectura para revisar -->
50404
+ @if (importMode() === 'file' && csv) {
50405
+ <div class="import-section">
50406
+ <ion-textarea class="import-csv" [autoGrow]="true" [rows]="4" [readonly]="true" [value]="csv" />
50407
+ </div>
50408
+ }
50336
50409
 
50337
- <!-- Selector de conflicto: val-title + val-select-input (mismo patrón que invite modal) -->
50338
- <div class="conflict-select-wrap">
50339
- <val-title [props]="{ content: t('onConflictLabel'), size: 'small', color: 'dark', bold: false }" />
50410
+ <!-- Conflicto: select -->
50411
+ <div class="import-section">
50412
+ <val-title [props]="{ content: t('onConflictLabel'), size: 'small', color: 'dark', bold: true }" />
50340
50413
  <val-select-input [props]="conflictSelectProps()" />
50341
50414
  </div>
50342
50415
 
50343
- <ion-checkbox class="import-activation" labelPlacement="end" [(ngModel)]="sendActivation">
50344
- {{ t('sendActivation') }}
50345
- </ion-checkbox>
50416
+ <!-- Activación: val-check-input -->
50417
+ <div class="import-section">
50418
+ <val-check-input [props]="sendActivationProps()" />
50419
+ </div>
50346
50420
 
50347
50421
  @if (errorMsg()) {
50348
50422
  <p class="import-error">{{ errorMsg() }}</p>
@@ -50379,7 +50453,7 @@ class MemberImportModalComponent {
50379
50453
  </div>
50380
50454
  }
50381
50455
  </ion-content>
50382
- `, isInline: true, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:16px}.import-roles-hint{display:block;margin-bottom:16px}.import-upload{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:16px}.import-upload__btn{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:1px solid var(--ion-color-medium, #92949c);border-radius:10px;background:var(--ion-color-light);color:var(--ion-color-dark);font-size:.875rem;font-weight:600;cursor:pointer;transition:border-color .15s ease}.import-upload__btn:hover{border-color:var(--ion-color-primary, #7026df)}.import-upload__btn ion-icon{font-size:1.25rem}.import-upload__btn input[type=file]{display:none}.import-upload__hint{font-size:.8125rem;color:var(--ion-color-medium)}.import-file-loaded{margin:0 0 16px;font-size:.8125rem;color:var(--ion-color-medium-shade, #6b6e76)}.import-csv{--background: var(--ion-color-light);border-radius:10px;margin-bottom:20px;font-family:monospace;font-size:.8125rem}.conflict-select-wrap{margin-bottom:20px}.conflict-select-wrap val-title{display:block;margin-bottom:6px}.import-activation{display:block;margin-bottom:20px;font-size:.875rem}.import-error{margin:0 0 12px;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.import-actions{margin-top:8px}.import-results{display:flex;flex-direction:column;gap:6px;margin:12px 0}.import-row{display:grid;grid-template-columns:1fr auto;grid-row-gap:2px;align-items:center;padding:10px 12px;border-radius:8px;border-left:3px solid var(--ion-color-medium);background:var(--ion-color-light);font-size:14px}.import-row--created{border-left-color:var(--ion-color-success, #2dd36f)}.import-row--assigned{border-left-color:var(--ion-color-primary, #7026df)}.import-row--skipped{border-left-color:var(--ion-color-medium, #92949c)}.import-row--error{border-left-color:var(--ion-color-danger, #c0392b)}.import-row__email{font-weight:600;color:var(--ion-color-dark)}.import-row__status{text-align:right;color:var(--ion-color-medium-shade, #6b6e76)}.import-row__reason{grid-column:1 / -1;font-size:12px;color:var(--ion-color-danger, #c0392b)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { 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: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["preset", "props"] }] }); }
50456
+ `, isInline: true, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:8px}.import-roles-hint{display:block;margin-bottom:24px}.import-section{margin-bottom:28px}.import-section val-title{margin-bottom:10px}.import-method-cards{display:grid;grid-template-columns:1fr 1fr;gap:12px}.import-method-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:14px 16px;border:1.5px solid var(--ion-color-light-shade, #d7d8da);border-radius:12px;background:var(--ion-color-light);cursor:pointer;text-align:left;transition:border-color .15s ease,background .15s ease}.import-method-card:hover{border-color:var(--ion-color-medium, #92949c)}.import-method-card--active{border-color:var(--ion-color-primary, #7026df);background:color-mix(in srgb,var(--ion-color-primary, #7026df) 6%,var(--ion-color-light))}.import-method-card__icon{font-size:1.375rem;color:var(--ion-color-medium-shade, #6b6e76);margin-bottom:4px}.import-method-card--active .import-method-card__icon{color:var(--ion-color-primary, #7026df)}.import-method-card__title{font-size:.875rem;font-weight:600;color:var(--ion-color-dark)}.import-method-card__hint{font-size:.75rem;color:var(--ion-color-medium, #92949c);line-height:1.3}.import-upload__btn{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:1px solid var(--ion-color-medium, #92949c);border-radius:10px;background:var(--ion-color-light);color:var(--ion-color-dark);font-size:.875rem;font-weight:600;cursor:pointer;transition:border-color .15s ease}.import-upload__btn:hover{border-color:var(--ion-color-primary, #7026df)}.import-upload__btn ion-icon{font-size:1.25rem}.import-upload__btn input[type=file]{display:none}.import-file-loaded{margin:10px 0 0;font-size:.8125rem;color:var(--ion-color-medium-shade, #6b6e76)}.import-csv{--background: transparent;border-radius:10px;font-family:monospace;font-size:.8125rem}.import-error{margin:0 0 12px;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.import-actions{margin-top:8px}.import-results{display:flex;flex-direction:column;gap:6px;margin:12px 0}.import-row{display:grid;grid-template-columns:1fr auto;grid-row-gap:2px;align-items:center;padding:10px 12px;border-radius:8px;border-left:3px solid var(--ion-color-medium);background:var(--ion-color-light);font-size:.875rem}.import-row--created{border-left-color:var(--ion-color-success, #2dd36f)}.import-row--assigned{border-left-color:var(--ion-color-primary, #7026df)}.import-row--skipped{border-left-color:var(--ion-color-medium, #92949c)}.import-row--error{border-left-color:var(--ion-color-danger, #c0392b)}.import-row__email{font-weight:600;color:var(--ion-color-dark)}.import-row__status{text-align:right;color:var(--ion-color-medium-shade, #6b6e76)}.import-row__reason{grid-column:1 / -1;font-size:.75rem;color:var(--ion-color-danger, #c0392b)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { 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: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["preset", "props"] }, { kind: "component", type: CheckInputComponent, selector: "val-check-input", inputs: ["preset", "props"] }] }); }
50383
50457
  }
50384
50458
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MemberImportModalComponent, decorators: [{
50385
50459
  type: Component,
@@ -50392,13 +50466,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
50392
50466
  IonButton,
50393
50467
  IonContent,
50394
50468
  IonTextarea,
50395
- IonCheckbox,
50396
50469
  IonSpinner,
50397
50470
  IonIcon,
50398
50471
  DisplayComponent,
50399
50472
  TextComponent,
50400
50473
  TitleComponent,
50401
50474
  SearchSelectorComponent,
50475
+ CheckInputComponent,
50402
50476
  ], template: `
50403
50477
  <ion-header>
50404
50478
  <ion-toolbar>
@@ -50412,10 +50486,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
50412
50486
 
50413
50487
  <ion-content class="ion-padding">
50414
50488
  <val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
50489
+ <val-title [props]="{ content: t('subtitle'), size: 'large', color: '', bold: false }" />
50415
50490
 
50416
50491
  @if (!results()) {
50417
- <val-title [props]="{ content: t('hint'), size: 'large', color: '', bold: false }" />
50418
-
50419
50492
  @if (rolesHint()) {
50420
50493
  <val-text
50421
50494
  class="import-roles-hint"
@@ -50423,40 +50496,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
50423
50496
  />
50424
50497
  }
50425
50498
 
50426
- <!-- Subida de archivo: label nativo envuelve el input (label trick, igual
50427
- que val-attachment-uploader) → gesto confiable en iOS/PWA. -->
50428
- <div class="import-upload">
50429
- <label class="import-upload__btn">
50430
- <ion-icon name="cloud-upload-outline" />
50431
- <span>{{ t('uploadFile') }}</span>
50432
- <input type="file" accept=".csv,text/csv,text/plain" (change)="onFileSelected($event)" />
50433
- </label>
50434
- <span class="import-upload__hint">{{ t('orPaste') }}</span>
50499
+ <!-- Selector de método de importación -->
50500
+ <div class="import-section">
50501
+ <val-title [props]="{ content: t('importMethodLabel'), size: 'small', color: 'dark', bold: true }" />
50502
+ <div class="import-method-cards">
50503
+ <button
50504
+ type="button"
50505
+ class="import-method-card"
50506
+ [class.import-method-card--active]="importMode() === 'file'"
50507
+ (click)="importMode.set('file')"
50508
+ >
50509
+ <ion-icon name="cloud-upload-outline" class="import-method-card__icon" />
50510
+ <span class="import-method-card__title">{{ t('importMethodFile') }}</span>
50511
+ <span class="import-method-card__hint">{{ t('importMethodFileHint') }}</span>
50512
+ </button>
50513
+ <button
50514
+ type="button"
50515
+ class="import-method-card"
50516
+ [class.import-method-card--active]="importMode() === 'paste'"
50517
+ (click)="importMode.set('paste')"
50518
+ >
50519
+ <ion-icon name="document-text-outline" class="import-method-card__icon" />
50520
+ <span class="import-method-card__title">{{ t('importMethodPaste') }}</span>
50521
+ <span class="import-method-card__hint">{{ t('importMethodPasteHint') }}</span>
50522
+ </button>
50523
+ </div>
50435
50524
  </div>
50436
50525
 
50437
- @if (fileName()) {
50438
- <p class="import-file-loaded">
50439
- {{ t('fileLoaded').replace('{name}', fileName()) }}
50440
- </p>
50526
+ <!-- Subida de archivo (label trick — gesto confiable en iOS/PWA) -->
50527
+ @if (importMode() === 'file') {
50528
+ <div class="import-section">
50529
+ <label class="import-upload__btn">
50530
+ <ion-icon name="cloud-upload-outline" />
50531
+ <span>{{ t('uploadFile') }}</span>
50532
+ <input type="file" accept=".csv,text/csv,text/plain" (change)="onFileSelected($event)" />
50533
+ </label>
50534
+ @if (fileName()) {
50535
+ <p class="import-file-loaded">
50536
+ {{ t('fileLoaded').replace('{name}', fileName()) }}
50537
+ </p>
50538
+ }
50539
+ </div>
50441
50540
  }
50442
50541
 
50443
- <ion-textarea
50444
- class="import-csv"
50445
- [autoGrow]="true"
50446
- [rows]="6"
50447
- [placeholder]="t('csvPlaceholder')"
50448
- [(ngModel)]="csv"
50449
- />
50542
+ <!-- Pegar CSV -->
50543
+ @if (importMode() === 'paste') {
50544
+ <div class="import-section">
50545
+ <ion-textarea
50546
+ class="import-csv"
50547
+ [autoGrow]="true"
50548
+ [rows]="6"
50549
+ [placeholder]="t('csvPlaceholder')"
50550
+ [(ngModel)]="csv"
50551
+ />
50552
+ </div>
50553
+ }
50554
+
50555
+ <!-- Si hubo carga de archivo, mostrar textarea de solo lectura para revisar -->
50556
+ @if (importMode() === 'file' && csv) {
50557
+ <div class="import-section">
50558
+ <ion-textarea class="import-csv" [autoGrow]="true" [rows]="4" [readonly]="true" [value]="csv" />
50559
+ </div>
50560
+ }
50450
50561
 
50451
- <!-- Selector de conflicto: val-title + val-select-input (mismo patrón que invite modal) -->
50452
- <div class="conflict-select-wrap">
50453
- <val-title [props]="{ content: t('onConflictLabel'), size: 'small', color: 'dark', bold: false }" />
50562
+ <!-- Conflicto: select -->
50563
+ <div class="import-section">
50564
+ <val-title [props]="{ content: t('onConflictLabel'), size: 'small', color: 'dark', bold: true }" />
50454
50565
  <val-select-input [props]="conflictSelectProps()" />
50455
50566
  </div>
50456
50567
 
50457
- <ion-checkbox class="import-activation" labelPlacement="end" [(ngModel)]="sendActivation">
50458
- {{ t('sendActivation') }}
50459
- </ion-checkbox>
50568
+ <!-- Activación: val-check-input -->
50569
+ <div class="import-section">
50570
+ <val-check-input [props]="sendActivationProps()" />
50571
+ </div>
50460
50572
 
50461
50573
  @if (errorMsg()) {
50462
50574
  <p class="import-error">{{ errorMsg() }}</p>
@@ -50493,7 +50605,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
50493
50605
  </div>
50494
50606
  }
50495
50607
  </ion-content>
50496
- `, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:16px}.import-roles-hint{display:block;margin-bottom:16px}.import-upload{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:16px}.import-upload__btn{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:1px solid var(--ion-color-medium, #92949c);border-radius:10px;background:var(--ion-color-light);color:var(--ion-color-dark);font-size:.875rem;font-weight:600;cursor:pointer;transition:border-color .15s ease}.import-upload__btn:hover{border-color:var(--ion-color-primary, #7026df)}.import-upload__btn ion-icon{font-size:1.25rem}.import-upload__btn input[type=file]{display:none}.import-upload__hint{font-size:.8125rem;color:var(--ion-color-medium)}.import-file-loaded{margin:0 0 16px;font-size:.8125rem;color:var(--ion-color-medium-shade, #6b6e76)}.import-csv{--background: var(--ion-color-light);border-radius:10px;margin-bottom:20px;font-family:monospace;font-size:.8125rem}.conflict-select-wrap{margin-bottom:20px}.conflict-select-wrap val-title{display:block;margin-bottom:6px}.import-activation{display:block;margin-bottom:20px;font-size:.875rem}.import-error{margin:0 0 12px;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.import-actions{margin-top:8px}.import-results{display:flex;flex-direction:column;gap:6px;margin:12px 0}.import-row{display:grid;grid-template-columns:1fr auto;grid-row-gap:2px;align-items:center;padding:10px 12px;border-radius:8px;border-left:3px solid var(--ion-color-medium);background:var(--ion-color-light);font-size:14px}.import-row--created{border-left-color:var(--ion-color-success, #2dd36f)}.import-row--assigned{border-left-color:var(--ion-color-primary, #7026df)}.import-row--skipped{border-left-color:var(--ion-color-medium, #92949c)}.import-row--error{border-left-color:var(--ion-color-danger, #c0392b)}.import-row__email{font-weight:600;color:var(--ion-color-dark)}.import-row__status{text-align:right;color:var(--ion-color-medium-shade, #6b6e76)}.import-row__reason{grid-column:1 / -1;font-size:12px;color:var(--ion-color-danger, #c0392b)}\n"] }]
50608
+ `, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:8px}.import-roles-hint{display:block;margin-bottom:24px}.import-section{margin-bottom:28px}.import-section val-title{margin-bottom:10px}.import-method-cards{display:grid;grid-template-columns:1fr 1fr;gap:12px}.import-method-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:14px 16px;border:1.5px solid var(--ion-color-light-shade, #d7d8da);border-radius:12px;background:var(--ion-color-light);cursor:pointer;text-align:left;transition:border-color .15s ease,background .15s ease}.import-method-card:hover{border-color:var(--ion-color-medium, #92949c)}.import-method-card--active{border-color:var(--ion-color-primary, #7026df);background:color-mix(in srgb,var(--ion-color-primary, #7026df) 6%,var(--ion-color-light))}.import-method-card__icon{font-size:1.375rem;color:var(--ion-color-medium-shade, #6b6e76);margin-bottom:4px}.import-method-card--active .import-method-card__icon{color:var(--ion-color-primary, #7026df)}.import-method-card__title{font-size:.875rem;font-weight:600;color:var(--ion-color-dark)}.import-method-card__hint{font-size:.75rem;color:var(--ion-color-medium, #92949c);line-height:1.3}.import-upload__btn{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:1px solid var(--ion-color-medium, #92949c);border-radius:10px;background:var(--ion-color-light);color:var(--ion-color-dark);font-size:.875rem;font-weight:600;cursor:pointer;transition:border-color .15s ease}.import-upload__btn:hover{border-color:var(--ion-color-primary, #7026df)}.import-upload__btn ion-icon{font-size:1.25rem}.import-upload__btn input[type=file]{display:none}.import-file-loaded{margin:10px 0 0;font-size:.8125rem;color:var(--ion-color-medium-shade, #6b6e76)}.import-csv{--background: transparent;border-radius:10px;font-family:monospace;font-size:.8125rem}.import-error{margin:0 0 12px;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.import-actions{margin-top:8px}.import-results{display:flex;flex-direction:column;gap:6px;margin:12px 0}.import-row{display:grid;grid-template-columns:1fr auto;grid-row-gap:2px;align-items:center;padding:10px 12px;border-radius:8px;border-left:3px solid var(--ion-color-medium);background:var(--ion-color-light);font-size:.875rem}.import-row--created{border-left-color:var(--ion-color-success, #2dd36f)}.import-row--assigned{border-left-color:var(--ion-color-primary, #7026df)}.import-row--skipped{border-left-color:var(--ion-color-medium, #92949c)}.import-row--error{border-left-color:var(--ion-color-danger, #c0392b)}.import-row__email{font-weight:600;color:var(--ion-color-dark)}.import-row__status{text-align:right;color:var(--ion-color-medium-shade, #6b6e76)}.import-row__reason{grid-column:1 / -1;font-size:.75rem;color:var(--ion-color-danger, #c0392b)}\n"] }]
50497
50609
  }], ctorParameters: () => [], propDecorators: { orgId: [{
50498
50610
  type: Input
50499
50611
  }], availableRoles: [{
@@ -50996,7 +51108,7 @@ class OrganizationViewComponent {
50996
51108
  component: MemberImportModalComponent,
50997
51109
  componentProps: {
50998
51110
  orgId: this.activeOrgId(),
50999
- availableRoles: this.availableRoles().map(r => r.name),
51111
+ availableRoles: this.availableRoles(),
51000
51112
  onSuccess: () => {
51001
51113
  this.loadMembers();
51002
51114
  this.resolvedConfig().onMemberInvited?.();
@@ -66927,5 +67039,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
66927
67039
  * Generated bundle index. Do not edit.
66928
67040
  */
66929
67041
 
66930
- export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionSelectorComponent, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketCardComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, button, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createPageState, createPermissionLabeler, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
67042
+ export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, APP_VERSION_PLATFORM_PLUGIN, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AboutViewComponent, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, ApiKeyCreateModalComponent, ApiKeyService, ApiKeysModalComponent, ApiKeysViewComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_BUTTON_PRESETS, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_PRESETS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DatePickerComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FieldListComponent, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, IONIC_COLORS$5 as IONIC_COLORS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PermissionCatalogService, PermissionSelectorComponent, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QrScannerComponent, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TicketCardComponent, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SETTINGS_MENU_LINKS, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, button, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createPageState, createPermissionLabeler, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, iconButton, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isIonicColor, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAboutRoutes, provideValtechAccountRoutes, provideValtechAds, provideValtechApiKeysRoutes, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor, resolveInputDefaultValue, resolveIonicColor, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
66931
67043
  //# sourceMappingURL=valtech-components.mjs.map