valtech-components 2.0.302 → 2.0.304

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 (32) hide show
  1. package/esm2022/lib/components/atoms/button/button.component.mjs +103 -23
  2. package/esm2022/lib/components/types.mjs +1 -1
  3. package/esm2022/lib/services/lang-provider/content.mjs +1 -55
  4. package/esm2022/lib/services/lang-provider/lang-provider.service.mjs +4 -9
  5. package/esm2022/lib/shared/utils/content.mjs +2 -8
  6. package/esm2022/public-api.mjs +1 -12
  7. package/fesm2022/valtech-components.mjs +124 -2807
  8. package/fesm2022/valtech-components.mjs.map +1 -1
  9. package/lib/components/atoms/button/button.component.d.ts +33 -2
  10. package/lib/components/types.d.ts +19 -7
  11. package/package.json +1 -1
  12. package/public-api.d.ts +0 -10
  13. package/esm2022/lib/examples/comprehensive-link-test.component.mjs +0 -208
  14. package/esm2022/lib/examples/custom-content-demo.component.mjs +0 -291
  15. package/esm2022/lib/examples/display-demo.component.mjs +0 -518
  16. package/esm2022/lib/examples/display-simple-example.component.mjs +0 -202
  17. package/esm2022/lib/examples/link-processing-example.component.mjs +0 -233
  18. package/esm2022/lib/examples/multi-language-demo.component.mjs +0 -304
  19. package/esm2022/lib/examples/reactive-components-demo.component.mjs +0 -303
  20. package/esm2022/lib/examples/reactivity-test.component.mjs +0 -200
  21. package/esm2022/lib/examples/selector-examples.component.mjs +0 -234
  22. package/esm2022/lib/examples/user-issue-test.component.mjs +0 -267
  23. package/lib/examples/comprehensive-link-test.component.d.ts +0 -23
  24. package/lib/examples/custom-content-demo.component.d.ts +0 -26
  25. package/lib/examples/display-demo.component.d.ts +0 -62
  26. package/lib/examples/display-simple-example.component.d.ts +0 -23
  27. package/lib/examples/link-processing-example.component.d.ts +0 -26
  28. package/lib/examples/multi-language-demo.component.d.ts +0 -34
  29. package/lib/examples/reactive-components-demo.component.d.ts +0 -45
  30. package/lib/examples/reactivity-test.component.d.ts +0 -27
  31. package/lib/examples/selector-examples.component.d.ts +0 -21
  32. package/lib/examples/user-issue-test.component.d.ts +0 -31
@@ -5,7 +5,7 @@ import * as i1 from '@angular/common';
5
5
  import { CommonModule, NgStyle, AsyncPipe, NgFor, NgClass } from '@angular/common';
6
6
  import { addIcons } from 'ionicons';
7
7
  import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, createOutline, trashOutline, playOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, chevronDown, language, globe, chevronBackOutline } from 'ionicons/icons';
8
- import { map, BehaviorSubject, tap, distinctUntilChanged, shareReplay, Subscription, of, combineLatest } from 'rxjs';
8
+ import { map, BehaviorSubject, distinctUntilChanged, shareReplay, Subscription, of, combineLatest } from 'rxjs';
9
9
  import { Router, RouterLink } from '@angular/router';
10
10
  import { Browser } from '@capacitor/browser';
11
11
  import * as i1$1 from '@angular/platform-browser';
@@ -472,16 +472,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
472
472
  function fromContent(langService, config) {
473
473
  // Use _global as default className if not provided
474
474
  const finalClassName = config.className || '_global';
475
- console.log(`fromContent: Creating observable for ${finalClassName}.${config.key}`);
476
475
  const contentObservable = langService.getContent(finalClassName, config.key, config.fallback);
477
476
  // If interpolation is provided, apply it
478
477
  if (config.interpolation) {
479
- console.log(`fromContent: Applying interpolation for ${finalClassName}.${config.key}`, config.interpolation);
480
- return contentObservable.pipe(map(content => {
481
- const interpolated = interpolateContent(content, config.interpolation);
482
- console.log(`fromContent: Interpolated result for ${finalClassName}.${config.key}: "${interpolated}"`);
483
- return interpolated;
484
- }));
478
+ return contentObservable.pipe(map(content => interpolateContent(content, config.interpolation)));
485
479
  }
486
480
  return contentObservable;
487
481
  }
@@ -838,8 +832,7 @@ class LangService {
838
832
  * Use this to subscribe to language changes in components.
839
833
  */
840
834
  get currentLang$() {
841
- console.log('LangService.currentLang$: Creating observable');
842
- return this.selectedLang.asObservable().pipe(tap(lang => console.log(`LangService.currentLang$: Emitting language: ${lang}`)), distinctUntilChanged(), shareReplay(1) // Ensure new subscribers get the current value
835
+ return this.selectedLang.asObservable().pipe(distinctUntilChanged(), shareReplay(1) // Ensure new subscribers get the current value
843
836
  );
844
837
  }
845
838
  /**
@@ -913,16 +906,12 @@ class LangService {
913
906
  * @returns Observable that emits the text string whenever language changes
914
907
  */
915
908
  getContent(className, key, fallback) {
916
- console.log(`LangService.getContent: Creating observable for ${className}.${key}`);
917
909
  return this.currentLang$.pipe(map(lang => {
918
- console.log(`LangService.getContent: Language changed to ${lang} for ${className}.${key}`);
919
910
  const result = this.getBestAvailableContent(className, key, lang);
920
911
  if (result.shouldWarn && result.actualLang !== lang) {
921
912
  console.warn(`LangService: Content "${className}.${key}" not available in "${lang}".`, `Using "${result.actualLang}" instead. Available languages:`, this.availableLanguages);
922
913
  }
923
- const finalResult = result.content || fallback || `[${className}.${key}]`;
924
- console.log(`LangService.getContent: Returning "${finalResult}" for ${className}.${key}`);
925
- return finalResult;
914
+ return result.content || fallback || `[${className}.${key}]`;
926
915
  }), distinctUntilChanged());
927
916
  }
928
917
  /**
@@ -1350,15 +1339,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1350
1339
  *
1351
1340
  * A customizable button supporting icons, loading state, navigation, and reactive content.
1352
1341
  * Supports both static text and reactive content from the content service.
1342
+ * Follows the same content pattern as val-text for consistency.
1353
1343
  *
1354
- * @example
1355
- * // Static text
1356
- * <val-button [props]="{ text: 'Save', color: 'primary', icon: { name: 'save', slot: 'start' } }" (onClick)="handler()"></val-button>
1344
+ * @example Static text:
1345
+ * <val-button [props]="{
1346
+ * text: 'Save',
1347
+ * color: 'primary',
1348
+ * type: 'button',
1349
+ * state: 'ENABLED',
1350
+ * icon: { name: 'save', slot: 'start' }
1351
+ * }" (onClick)="handler()"></val-button>
1357
1352
  *
1358
- * // Reactive content
1359
- * <val-button [props]="{ textConfig: { key: 'save' }, color: 'primary', icon: { name: 'save', slot: 'start' } }" (onClick)="handler()"></val-button>
1353
+ * @example Reactive content:
1354
+ * <val-button [props]="{
1355
+ * contentKey: 'save',
1356
+ * contentClass: 'MyComponent',
1357
+ * contentFallback: 'Save',
1358
+ * color: 'primary',
1359
+ * type: 'button',
1360
+ * state: 'ENABLED',
1361
+ * icon: { name: 'save', slot: 'start' }
1362
+ * }" (onClick)="handler()"></val-button>
1363
+ *
1364
+ * @example Reactive content with interpolation:
1365
+ * <val-button [props]="{
1366
+ * contentKey: 'saveCount',
1367
+ * contentClass: 'MyComponent',
1368
+ * contentInterpolation: { count: 5 },
1369
+ * contentFallback: 'Save Items',
1370
+ * color: 'primary',
1371
+ * type: 'button',
1372
+ * state: 'ENABLED'
1373
+ * }" (onClick)="handler()"></val-button>
1360
1374
  *
1361
- * @input props: ButtonMetadata - Configuration for the button (text/textConfig, color, icon, state, etc.)
1375
+ * @input props: ButtonMetadata - Configuration for the button (text/content, color, icon, state, etc.)
1362
1376
  * @output onClick - Emits when the button is clicked
1363
1377
  */
1364
1378
  class ButtonComponent {
@@ -1374,29 +1388,46 @@ class ButtonComponent {
1374
1388
  this.onClick = new EventEmitter();
1375
1389
  }
1376
1390
  ngOnInit() {
1377
- this.initializeDisplayText();
1391
+ this.setupDisplayText();
1378
1392
  }
1379
1393
  ngOnDestroy() {
1380
1394
  this.subscriptions.unsubscribe();
1381
1395
  }
1382
- initializeDisplayText() {
1383
- // Static text takes precedence
1384
- if (this.props.text !== undefined) {
1396
+ /**
1397
+ * Set up the text content observable based on the props configuration.
1398
+ * Priority: static text > reactive content with interpolation > reactive content
1399
+ * This follows the same pattern as val-text component.
1400
+ */
1401
+ setupDisplayText() {
1402
+ if (this.props.text) {
1403
+ // Static text takes precedence
1385
1404
  this.displayText$ = of(this.props.text);
1386
- return;
1387
1405
  }
1388
- // Use reactive content if configured
1389
- if (this.props.textConfig) {
1390
- this.displayText$ = this.contentService.fromContent({
1391
- className: this.props.textConfig.className || '_global',
1392
- key: this.props.textConfig.key,
1393
- fallback: this.props.textConfig.fallback || this.props.textConfig.key,
1394
- interpolation: this.props.textConfig.interpolation,
1395
- });
1396
- return;
1406
+ else if (this.props.contentKey && this.props.contentClass) {
1407
+ // Reactive content from language service
1408
+ if (this.props.contentInterpolation) {
1409
+ // With interpolation
1410
+ this.displayText$ = this.contentService.fromContentWithInterpolation({
1411
+ className: this.props.contentClass,
1412
+ key: this.props.contentKey,
1413
+ fallback: this.props.contentFallback,
1414
+ interpolation: this.props.contentInterpolation,
1415
+ });
1416
+ }
1417
+ else {
1418
+ // Simple reactive content
1419
+ this.displayText$ = this.contentService.fromContent({
1420
+ className: this.props.contentClass,
1421
+ key: this.props.contentKey,
1422
+ fallback: this.props.contentFallback,
1423
+ });
1424
+ }
1425
+ }
1426
+ else {
1427
+ // Fallback to empty string if no valid content configuration
1428
+ console.warn('val-button: No valid content configuration provided. Use either "text" for static text or "contentKey" + "contentClass" for reactive content.');
1429
+ this.displayText$ = of(this.props.contentFallback || '');
1397
1430
  }
1398
- // No content configured - use empty string
1399
- this.displayText$ = of('');
1400
1431
  }
1401
1432
  clickHandler() {
1402
1433
  if (this.props.state === this.states.DISABLED) {
@@ -1460,6 +1491,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1460
1491
  }], onClick: [{
1461
1492
  type: Output
1462
1493
  }] } });
1494
+ /**
1495
+ * Helper function to create reactive button props from content configuration.
1496
+ * This provides a convenient way to create val-button props with reactive content.
1497
+ * Follows the same pattern as createTextProps for consistency.
1498
+ *
1499
+ * @param contentConfig - Content configuration
1500
+ * @param styleConfig - Optional style and behavior configuration
1501
+ * @returns ButtonMetadata with content properties set
1502
+ *
1503
+ * @example
1504
+ * ```typescript
1505
+ * // In component
1506
+ * saveButtonProps: ButtonMetadata = createButtonProps({
1507
+ * contentKey: 'save',
1508
+ * contentClass: 'MyComponent'
1509
+ * }, {
1510
+ * color: 'primary',
1511
+ * icon: { name: 'save', slot: 'start' }
1512
+ * });
1513
+ * ```
1514
+ */
1515
+ function createButtonProps(contentConfig, styleConfig = {}) {
1516
+ return {
1517
+ contentKey: contentConfig.contentKey,
1518
+ contentClass: contentConfig.contentClass,
1519
+ contentFallback: contentConfig.contentFallback,
1520
+ contentInterpolation: contentConfig.contentInterpolation,
1521
+ color: styleConfig.color || 'primary',
1522
+ type: styleConfig.type || 'button',
1523
+ state: styleConfig.state || ComponentStates.ENABLED,
1524
+ size: styleConfig.size,
1525
+ fill: styleConfig.fill,
1526
+ icon: styleConfig.icon,
1527
+ expand: styleConfig.expand,
1528
+ shape: styleConfig.shape,
1529
+ handler: styleConfig.handler,
1530
+ };
1531
+ }
1463
1532
 
1464
1533
  const Icon = (name, slot) => {
1465
1534
  return {
@@ -7208,2723 +7277,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
7208
7277
  type: Output
7209
7278
  }] } });
7210
7279
 
7211
- /**
7212
- * ComprehensiveLinkTestComponent - Componente de prueba exhaustiva para el procesamiento de enlaces.
7213
- *
7214
- * Este componente demuestra todos los casos edge y escenarios complejos de procesamiento de enlaces,
7215
- * incluyendo puntuación, URLs complejas, y mezclas de formatos.
7216
- *
7217
- * @example Uso en template:
7218
- * ```html
7219
- * <val-comprehensive-link-test></val-comprehensive-link-test>
7220
- * ```
7221
- */
7222
- class ComprehensiveLinkTestComponent {
7223
- constructor() {
7224
- this.punctuationProps = {
7225
- content: 'Diferentes puntuaciones: https://angular.io, también https://github.com! ¿Conoces https://typescript.org? Final: https://rxjs.dev. Entre paréntesis (https://zone.js) y con comillas "https://ionic.io".',
7226
- size: 'medium',
7227
- color: 'dark',
7228
- bold: false,
7229
- processLinks: true,
7230
- linkConfig: {
7231
- openExternalInNewTab: true,
7232
- linkClass: 'test-punctuation',
7233
- externalLinkClass: 'test-external',
7234
- },
7235
- };
7236
- this.complexUrlProps = {
7237
- content: 'URLs complejas: https://api.github.com/repos/angular/angular/issues?state=open&sort=updated&per_page=50, búsqueda https://google.com/search?q=angular+ionic+components#results, y documentación https://angular.io/guide/getting-started#development-environment.',
7238
- size: 'medium',
7239
- color: 'dark',
7240
- bold: false,
7241
- processLinks: true,
7242
- linkConfig: {
7243
- openExternalInNewTab: true,
7244
- linkClass: 'test-complex',
7245
- externalLinkClass: 'test-external',
7246
- },
7247
- };
7248
- this.parenthesesProps = {
7249
- content: 'Paréntesis de contexto (ver https://docs.angular.io) vs URLs con paréntesis https://example.com/api/method(param) en el contenido. También funciona (https://ionic.io/docs).',
7250
- size: 'medium',
7251
- color: 'dark',
7252
- bold: false,
7253
- processLinks: true,
7254
- linkConfig: {
7255
- openExternalInNewTab: true,
7256
- linkClass: 'test-parentheses',
7257
- externalLinkClass: 'test-external',
7258
- },
7259
- };
7260
- this.mixedFormatsProps = {
7261
- content: 'Formatos mezclados: [Documentación oficial](https://angular.io/docs), enlace directo https://github.com/angular/angular, ruta interna /dashboard/settings, [guía de inicio](/getting-started), y API https://api.example.com/v1/users?active=true.',
7262
- size: 'medium',
7263
- color: 'dark',
7264
- bold: false,
7265
- processLinks: true,
7266
- linkConfig: {
7267
- openExternalInNewTab: true,
7268
- openInternalInNewTab: false,
7269
- processMarkdownLinks: true,
7270
- linkClass: 'test-mixed',
7271
- externalLinkClass: 'test-external',
7272
- internalLinkClass: 'test-internal',
7273
- },
7274
- };
7275
- this.edgeCasesProps = {
7276
- content: 'Casos extremos: "https://quoted-url.com", múltiple puntuación https://example.com?!!, URL al final de oración https://final-url.org. También consecutivos: https://first.com y https://second.com.',
7277
- size: 'medium',
7278
- color: 'dark',
7279
- bold: false,
7280
- processLinks: true,
7281
- linkConfig: {
7282
- openExternalInNewTab: true,
7283
- linkClass: 'test-edge',
7284
- externalLinkClass: 'test-external',
7285
- },
7286
- };
7287
- this.devUrlsProps = {
7288
- content: 'URLs de desarrollo: http://localhost:4200/dashboard, servidor local https://127.0.0.1:8080/api/status, desarrollo http://dev.example.com:3000/debug?verbose=true, y túnel https://abc123.ngrok.io/webhook.',
7289
- size: 'medium',
7290
- color: 'dark',
7291
- bold: false,
7292
- processLinks: true,
7293
- linkConfig: {
7294
- openExternalInNewTab: false, // Para desarrollo, puede ser útil no abrir en nueva pestaña
7295
- linkClass: 'test-dev',
7296
- externalLinkClass: 'test-dev-external',
7297
- },
7298
- };
7299
- }
7300
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComprehensiveLinkTestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7301
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ComprehensiveLinkTestComponent, isStandalone: true, selector: "val-comprehensive-link-test", ngImport: i0, template: `
7302
- <div class="comprehensive-test">
7303
- <h2>Prueba Exhaustiva de Procesamiento de Enlaces</h2>
7304
-
7305
- <div class="test-section">
7306
- <h3>✅ Puntuación Final - SOLUCIONADO</h3>
7307
- <val-text [props]="punctuationProps"></val-text>
7308
- <p class="note">
7309
- <strong>Esperado:</strong> Los enlaces no incluyen puntuación final (.,;!?), pero la puntuación se preserva
7310
- como texto después del enlace.
7311
- </p>
7312
- </div>
7313
-
7314
- <div class="test-section">
7315
- <h3>✅ URLs Complejas con Parámetros - SOLUCIONADO</h3>
7316
- <val-text [props]="complexUrlProps"></val-text>
7317
- <p class="note">
7318
- <strong>Esperado:</strong> URLs con query params, fragmentos y rutas complejas se preservan completamente.
7319
- </p>
7320
- </div>
7321
-
7322
- <div class="test-section">
7323
- <h3>✅ Paréntesis Inteligentes - SOLUCIONADO</h3>
7324
- <val-text [props]="parenthesesProps"></val-text>
7325
- <p class="note">
7326
- <strong>Esperado:</strong> Paréntesis de contexto (texto) vs paréntesis de URL se manejan correctamente.
7327
- </p>
7328
- </div>
7329
-
7330
- <div class="test-section">
7331
- <h3>✅ Mezcla de Formatos - SOLUCIONADO</h3>
7332
- <val-text [props]="mixedFormatsProps"></val-text>
7333
- <p class="note">
7334
- <strong>Esperado:</strong> Enlaces Markdown, URLs directas y rutas internas coexisten sin conflictos.
7335
- </p>
7336
- </div>
7337
-
7338
- <div class="test-section">
7339
- <h3>✅ Casos Extremos - SOLUCIONADO</h3>
7340
- <val-text [props]="edgeCasesProps"></val-text>
7341
- <p class="note">
7342
- <strong>Esperado:</strong> Comillas, múltiple puntuación, y URLs al final de oraciones se procesan
7343
- correctamente.
7344
- </p>
7345
- </div>
7346
-
7347
- <div class="test-section">
7348
- <h3>✅ URLs de Desarrollo - SOLUCIONADO</h3>
7349
- <val-text [props]="devUrlsProps"></val-text>
7350
- <p class="note">
7351
- <strong>Esperado:</strong> URLs de localhost, puertos, y rutas de desarrollo se detectan correctamente.
7352
- </p>
7353
- </div>
7354
- </div>
7355
- `, isInline: true, styles: [".comprehensive-test{padding:20px;max-width:1000px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.test-section{margin-bottom:32px;padding:20px;border:2px solid var(--ion-color-success, #2dd36f);border-radius:12px;background:var(--ion-color-success-tint, #42d77d) 10}h2{color:var(--ion-color-primary, #3880ff);margin-bottom:24px;text-align:center}h3{color:var(--ion-color-success, #2dd36f);margin-bottom:16px;font-size:18px;display:flex;align-items:center;gap:8px}.note{margin-top:12px;padding:12px;background:var(--ion-color-light, #f4f5f8);border-radius:8px;font-size:14px;color:var(--ion-color-medium, #92949c);border-left:4px solid var(--ion-color-primary, #3880ff)}.note strong{color:var(--ion-color-dark, #222428)}\n"], dependencies: [{ kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
7356
- }
7357
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComprehensiveLinkTestComponent, decorators: [{
7358
- type: Component,
7359
- args: [{ selector: 'val-comprehensive-link-test', standalone: true, imports: [TextComponent], template: `
7360
- <div class="comprehensive-test">
7361
- <h2>Prueba Exhaustiva de Procesamiento de Enlaces</h2>
7362
-
7363
- <div class="test-section">
7364
- <h3>✅ Puntuación Final - SOLUCIONADO</h3>
7365
- <val-text [props]="punctuationProps"></val-text>
7366
- <p class="note">
7367
- <strong>Esperado:</strong> Los enlaces no incluyen puntuación final (.,;!?), pero la puntuación se preserva
7368
- como texto después del enlace.
7369
- </p>
7370
- </div>
7371
-
7372
- <div class="test-section">
7373
- <h3>✅ URLs Complejas con Parámetros - SOLUCIONADO</h3>
7374
- <val-text [props]="complexUrlProps"></val-text>
7375
- <p class="note">
7376
- <strong>Esperado:</strong> URLs con query params, fragmentos y rutas complejas se preservan completamente.
7377
- </p>
7378
- </div>
7379
-
7380
- <div class="test-section">
7381
- <h3>✅ Paréntesis Inteligentes - SOLUCIONADO</h3>
7382
- <val-text [props]="parenthesesProps"></val-text>
7383
- <p class="note">
7384
- <strong>Esperado:</strong> Paréntesis de contexto (texto) vs paréntesis de URL se manejan correctamente.
7385
- </p>
7386
- </div>
7387
-
7388
- <div class="test-section">
7389
- <h3>✅ Mezcla de Formatos - SOLUCIONADO</h3>
7390
- <val-text [props]="mixedFormatsProps"></val-text>
7391
- <p class="note">
7392
- <strong>Esperado:</strong> Enlaces Markdown, URLs directas y rutas internas coexisten sin conflictos.
7393
- </p>
7394
- </div>
7395
-
7396
- <div class="test-section">
7397
- <h3>✅ Casos Extremos - SOLUCIONADO</h3>
7398
- <val-text [props]="edgeCasesProps"></val-text>
7399
- <p class="note">
7400
- <strong>Esperado:</strong> Comillas, múltiple puntuación, y URLs al final de oraciones se procesan
7401
- correctamente.
7402
- </p>
7403
- </div>
7404
-
7405
- <div class="test-section">
7406
- <h3>✅ URLs de Desarrollo - SOLUCIONADO</h3>
7407
- <val-text [props]="devUrlsProps"></val-text>
7408
- <p class="note">
7409
- <strong>Esperado:</strong> URLs de localhost, puertos, y rutas de desarrollo se detectan correctamente.
7410
- </p>
7411
- </div>
7412
- </div>
7413
- `, styles: [".comprehensive-test{padding:20px;max-width:1000px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.test-section{margin-bottom:32px;padding:20px;border:2px solid var(--ion-color-success, #2dd36f);border-radius:12px;background:var(--ion-color-success-tint, #42d77d) 10}h2{color:var(--ion-color-primary, #3880ff);margin-bottom:24px;text-align:center}h3{color:var(--ion-color-success, #2dd36f);margin-bottom:16px;font-size:18px;display:flex;align-items:center;gap:8px}.note{margin-top:12px;padding:12px;background:var(--ion-color-light, #f4f5f8);border-radius:8px;font-size:14px;color:var(--ion-color-medium, #92949c);border-left:4px solid var(--ion-color-primary, #3880ff)}.note strong{color:var(--ion-color-dark, #222428)}\n"] }]
7414
- }] });
7415
-
7416
- class CustomContentDemoComponent {
7417
- constructor() {
7418
- this.content = inject(ContentService);
7419
- this.currentLang = 'es';
7420
- // Contenido global predefinido (sin className)
7421
- this.saveText$ = this.content.fromContent({ key: 'save' });
7422
- this.cancelText$ = this.content.fromContent({ key: 'cancel' });
7423
- this.deleteText$ = this.content.fromContent({ key: 'delete' });
7424
- this.loadingText$ = this.content.fromContent({ key: 'loading' });
7425
- // Tu contenido global personalizado (sin className)
7426
- this.dashboardText$ = this.content.fromContent({ key: 'dashboard' });
7427
- this.profileText$ = this.content.fromContent({ key: 'profile' });
7428
- this.settingsText$ = this.content.fromContent({ key: 'settings' });
7429
- this.welcomeText$ = this.content.fromContent({
7430
- key: 'welcome',
7431
- interpolation: { appName: 'Mi Aplicación' },
7432
- });
7433
- // Contenido específico del componente Language (con className)
7434
- this.spanishText$ = this.content.fromContent({
7435
- className: 'Language',
7436
- key: 'spanish',
7437
- });
7438
- this.englishText$ = this.content.fromContent({
7439
- className: 'Language',
7440
- key: 'english',
7441
- });
7442
- this.descriptionText$ = this.content.fromContent({
7443
- className: 'Language',
7444
- key: 'description',
7445
- });
7446
- // Para debug - texto síncrono
7447
- this.saveTextSync = '';
7448
- this.dashboardTextSync = '';
7449
- this.languageDescSync = '';
7450
- }
7451
- ngOnInit() {
7452
- // Obtener idioma actual
7453
- this.content.currentLang$.subscribe(lang => {
7454
- this.currentLang = lang;
7455
- });
7456
- // Obtener textos síncronos para debug
7457
- this.updateSyncTexts();
7458
- // 🔍 DIAGNÓSTICO: Verificar configuración
7459
- this.diagnoseConfiguration();
7460
- }
7461
- switchLanguage() {
7462
- const newLang = this.currentLang === 'es' ? LANGUAGES.EN : LANGUAGES.ES;
7463
- this.content.setLang(newLang);
7464
- // Actualizar textos síncronos después del cambio
7465
- setTimeout(() => {
7466
- this.updateSyncTexts();
7467
- }, 100);
7468
- }
7469
- updateSyncTexts() {
7470
- // Contenido global predefinido
7471
- this.saveTextSync = this.content.getText('save');
7472
- // Tu contenido global personalizado
7473
- this.dashboardTextSync = this.content.getText('dashboard');
7474
- // Contenido específico del componente - SOLUCIÓN TEMPORAL
7475
- // En lugar de usar getText, acceder directamente
7476
- try {
7477
- const langService = this.content.langService;
7478
- const languageContent = langService.content['Language'];
7479
- const currentLang = langService.selectedLang?.value || 'es';
7480
- const classContent = languageContent?.Content?.[currentLang];
7481
- this.languageDescSync = classContent?.['description'] || 'No encontrado';
7482
- }
7483
- catch (error) {
7484
- this.languageDescSync = `Error: ${error}`;
7485
- }
7486
- }
7487
- diagnoseConfiguration() {
7488
- console.log('=== DIAGNÓSTICO DE CONFIGURACIÓN ===');
7489
- // Verificar acceso directo al servicio
7490
- console.log('ContentService available:', !!this.content);
7491
- console.log('Current language:', this.content.currentLang);
7492
- // 🔍 Diagnóstico detallado del contenido Language
7493
- console.log('\n--- DIAGNÓSTICO DETALLADO LANGUAGE ---');
7494
- try {
7495
- // Acceder directamente al LangService
7496
- const langService = this.content.langService;
7497
- console.log('LangService available:', !!langService);
7498
- // Verificar si existe el contenido Language
7499
- const languageContent = langService.content['Language'];
7500
- console.log('Language content exists:', !!languageContent);
7501
- if (languageContent) {
7502
- console.log('Language content structure:', languageContent);
7503
- console.log('Language content.Content:', languageContent.Content);
7504
- // Verificar contenido en español
7505
- const esContent = languageContent.Content?.es;
7506
- console.log('ES content:', esContent);
7507
- console.log('ES description:', esContent?.description);
7508
- // Verificar contenido en inglés
7509
- const enContent = languageContent.Content?.en;
7510
- console.log('EN content:', enContent);
7511
- console.log('EN description:', enContent?.description);
7512
- }
7513
- // Verificar current lang
7514
- const currentLang = langService.selectedLang?.value;
7515
- console.log('Current selected language:', currentLang);
7516
- }
7517
- catch (error) {
7518
- console.log('❌ Error accessing LangService:', error);
7519
- }
7520
- // Intentar acceso síncrono a contenido global predefinido
7521
- try {
7522
- const saveText = this.content.getText('save');
7523
- console.log('✅ Global predefinido (save):', saveText);
7524
- }
7525
- catch (error) {
7526
- console.log('❌ Error global predefinido (save):', error);
7527
- }
7528
- // Intentar acceso síncrono a contenido global personalizado
7529
- try {
7530
- const dashboardText = this.content.getText('dashboard');
7531
- console.log('✅ Global personalizado (dashboard):', dashboardText);
7532
- }
7533
- catch (error) {
7534
- console.log('❌ Error global personalizado (dashboard):', error);
7535
- }
7536
- // Intentar acceso síncrono a contenido de componente
7537
- try {
7538
- const spanishText = this.content.getText('Language', 'spanish');
7539
- console.log('✅ Componente Language (spanish):', spanishText);
7540
- // 🔍 Debug paso a paso para spanish
7541
- const langService = this.content.langService;
7542
- const languageContent = langService.content['Language'];
7543
- const currentLang = langService.selectedLang?.value;
7544
- const classContent = languageContent?.Content[currentLang];
7545
- console.log('🔍 Debug spanish - currentLang:', currentLang);
7546
- console.log('🔍 Debug spanish - classContent:', classContent);
7547
- console.log('🔍 Debug spanish - classContent["spanish"]:', classContent?.['spanish']);
7548
- }
7549
- catch (error) {
7550
- console.log('❌ Error componente Language (spanish):', error);
7551
- }
7552
- // Intentar acceso síncrono a contenido de componente
7553
- try {
7554
- const descriptionText = this.content.getText('Language', 'description');
7555
- console.log('✅ Componente Language (description):', descriptionText);
7556
- // 🔍 Debug paso a paso para description
7557
- const langService = this.content.langService;
7558
- const languageContent = langService.content['Language'];
7559
- const currentLang = langService.selectedLang?.value;
7560
- const classContent = languageContent?.Content[currentLang];
7561
- console.log('🔍 Debug description - currentLang:', currentLang);
7562
- console.log('🔍 Debug description - classContent:', classContent);
7563
- console.log('🔍 Debug description - classContent["description"]:', classContent?.['description']);
7564
- }
7565
- catch (error) {
7566
- console.log('❌ Error componente Language (description):', error);
7567
- }
7568
- }
7569
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CustomContentDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7570
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CustomContentDemoComponent, isStandalone: true, selector: "app-custom-content-demo", ngImport: i0, template: `
7571
- <ion-card>
7572
- <ion-card-header>
7573
- <ion-card-title>Demo de Contenido Personalizado</ion-card-title>
7574
- </ion-card-header>
7575
-
7576
- <ion-card-content>
7577
- <!-- Contenido global predefinido -->
7578
- <div style="margin-bottom: 20px;">
7579
- <h3>Contenido Global Predefinido:</h3>
7580
- <ion-button>{{ saveText$ | async }}</ion-button>
7581
- <ion-button color="medium">{{ cancelText$ | async }}</ion-button>
7582
- <ion-button color="danger">{{ deleteText$ | async }}</ion-button>
7583
- <p><strong>Estado:</strong> {{ loadingText$ | async }}</p>
7584
- </div>
7585
-
7586
- <!-- Tu contenido global personalizado -->
7587
- <div style="margin-bottom: 20px;">
7588
- <h3>Tu Contenido Global Personalizado:</h3>
7589
- <p><strong>Sección:</strong> {{ dashboardText$ | async }}</p>
7590
- <p><strong>Usuario:</strong> {{ profileText$ | async }}</p>
7591
- <p><strong>Config:</strong> {{ settingsText$ | async }}</p>
7592
- <p>{{ welcomeText$ | async }}</p>
7593
- </div>
7594
-
7595
- <!-- Contenido específico del componente Language -->
7596
- <div style="margin-bottom: 20px;">
7597
- <h3>Contenido del Componente Language:</h3>
7598
- <ion-item>
7599
- <ion-label> <strong>Español:</strong> {{ spanishText$ | async }} </ion-label>
7600
- </ion-item>
7601
- <ion-item>
7602
- <ion-label> <strong>Inglés:</strong> {{ englishText$ | async }} </ion-label>
7603
- </ion-item>
7604
- <p>
7605
- <em>{{ descriptionText$ | async }}</em>
7606
- </p>
7607
- </div>
7608
-
7609
- <!-- Botón para cambiar idioma -->
7610
- <div>
7611
- <h3>Control de Idioma:</h3>
7612
- <ion-button (click)="switchLanguage()" color="secondary">
7613
- Cambiar a {{ currentLang === 'es' ? 'English' : 'Español' }}
7614
- </ion-button>
7615
- <p>
7616
- <small>Idioma actual: {{ currentLang }}</small>
7617
- </p>
7618
- </div>
7619
-
7620
- <!-- Debug info -->
7621
- <div style="margin-top: 20px; padding: 10px; background: #f5f5f5; border-radius: 4px;">
7622
- <h4>Debug Info:</h4>
7623
- <p><strong>Save (sync):</strong> {{ saveTextSync }}</p>
7624
- <p><strong>Dashboard (sync):</strong> {{ dashboardTextSync }}</p>
7625
- <p><strong>Language Description (sync):</strong> {{ languageDescSync }}</p>
7626
- </div>
7627
- </ion-card-content>
7628
- </ion-card>
7629
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }] }); }
7630
- }
7631
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CustomContentDemoComponent, decorators: [{
7632
- type: Component,
7633
- args: [{
7634
- selector: 'app-custom-content-demo',
7635
- standalone: true,
7636
- imports: [CommonModule, IonCard, IonCardContent, IonCardHeader, IonCardTitle, IonButton, IonItem, IonLabel],
7637
- template: `
7638
- <ion-card>
7639
- <ion-card-header>
7640
- <ion-card-title>Demo de Contenido Personalizado</ion-card-title>
7641
- </ion-card-header>
7642
-
7643
- <ion-card-content>
7644
- <!-- Contenido global predefinido -->
7645
- <div style="margin-bottom: 20px;">
7646
- <h3>Contenido Global Predefinido:</h3>
7647
- <ion-button>{{ saveText$ | async }}</ion-button>
7648
- <ion-button color="medium">{{ cancelText$ | async }}</ion-button>
7649
- <ion-button color="danger">{{ deleteText$ | async }}</ion-button>
7650
- <p><strong>Estado:</strong> {{ loadingText$ | async }}</p>
7651
- </div>
7652
-
7653
- <!-- Tu contenido global personalizado -->
7654
- <div style="margin-bottom: 20px;">
7655
- <h3>Tu Contenido Global Personalizado:</h3>
7656
- <p><strong>Sección:</strong> {{ dashboardText$ | async }}</p>
7657
- <p><strong>Usuario:</strong> {{ profileText$ | async }}</p>
7658
- <p><strong>Config:</strong> {{ settingsText$ | async }}</p>
7659
- <p>{{ welcomeText$ | async }}</p>
7660
- </div>
7661
-
7662
- <!-- Contenido específico del componente Language -->
7663
- <div style="margin-bottom: 20px;">
7664
- <h3>Contenido del Componente Language:</h3>
7665
- <ion-item>
7666
- <ion-label> <strong>Español:</strong> {{ spanishText$ | async }} </ion-label>
7667
- </ion-item>
7668
- <ion-item>
7669
- <ion-label> <strong>Inglés:</strong> {{ englishText$ | async }} </ion-label>
7670
- </ion-item>
7671
- <p>
7672
- <em>{{ descriptionText$ | async }}</em>
7673
- </p>
7674
- </div>
7675
-
7676
- <!-- Botón para cambiar idioma -->
7677
- <div>
7678
- <h3>Control de Idioma:</h3>
7679
- <ion-button (click)="switchLanguage()" color="secondary">
7680
- Cambiar a {{ currentLang === 'es' ? 'English' : 'Español' }}
7681
- </ion-button>
7682
- <p>
7683
- <small>Idioma actual: {{ currentLang }}</small>
7684
- </p>
7685
- </div>
7686
-
7687
- <!-- Debug info -->
7688
- <div style="margin-top: 20px; padding: 10px; background: #f5f5f5; border-radius: 4px;">
7689
- <h4>Debug Info:</h4>
7690
- <p><strong>Save (sync):</strong> {{ saveTextSync }}</p>
7691
- <p><strong>Dashboard (sync):</strong> {{ dashboardTextSync }}</p>
7692
- <p><strong>Language Description (sync):</strong> {{ languageDescSync }}</p>
7693
- </div>
7694
- </ion-card-content>
7695
- </ion-card>
7696
- `,
7697
- }]
7698
- }] });
7280
+ const text = {
7281
+ es: {
7282
+ spanish: 'Español',
7283
+ english: 'Inglés',
7284
+ },
7285
+ en: {
7286
+ spanish: 'Spanish',
7287
+ english: 'English',
7288
+ },
7289
+ };
7290
+ var LangSettings = new TextContent(text);
7699
7291
 
7700
7292
  /**
7701
- * Componente de demostración para val-display con contenido reactivo.
7702
- * Muestra diferentes patrones de uso y casos de ejemplo.
7703
- */
7704
- class DisplayDemoComponent {
7705
- constructor(contentService, langService) {
7706
- this.contentService = contentService;
7707
- this.langService = langService;
7708
- // Contador para ejemplos dinámicos
7709
- this.counter = 0;
7710
- // Configuración del selector de idioma
7711
- this.languageSelectorProps = {
7712
- showLabel: true,
7713
- labelConfig: {
7714
- className: '_global',
7715
- key: 'language',
7716
- fallback: 'Idioma',
7717
- },
7718
- showFlags: true,
7719
- color: 'primary',
7720
- size: 'default',
7721
- fill: 'outline',
7722
- };
7723
- // Configuraciones de ejemplo - ESTÁTICAS
7724
- this.smallStaticDisplay = {
7725
- content: 'Texto pequeño estático',
7726
- color: 'dark',
7727
- size: 'small',
7728
- };
7729
- this.mediumStaticDisplay = {
7730
- content: 'Texto mediano estático',
7731
- color: 'dark',
7732
- size: 'medium',
7733
- };
7734
- this.largeStaticDisplay = {
7735
- content: 'Texto grande estático',
7736
- color: 'dark',
7737
- size: 'large',
7738
- };
7739
- this.xlargeStaticDisplay = {
7740
- content: 'Texto extra grande estático',
7741
- color: 'dark',
7742
- size: 'xlarge',
7743
- };
7744
- // Ejemplos de colores estáticos
7745
- this.primaryDisplay = {
7746
- content: 'Texto primario',
7747
- color: 'primary',
7748
- size: 'medium',
7749
- };
7750
- this.secondaryDisplay = {
7751
- content: 'Texto secundario',
7752
- color: 'secondary',
7753
- size: 'medium',
7754
- };
7755
- this.successDisplay = {
7756
- content: 'Texto de éxito',
7757
- color: 'success',
7758
- size: 'medium',
7759
- };
7760
- this.warningDisplay = {
7761
- content: 'Texto de advertencia',
7762
- color: 'warning',
7763
- size: 'medium',
7764
- };
7765
- this.dangerDisplay = {
7766
- content: 'Texto de peligro',
7767
- color: 'danger',
7768
- size: 'medium',
7769
- };
7770
- // Configuraciones de ejemplo - REACTIVAS
7771
- this.welcomeDisplay = {
7772
- contentConfig: {
7773
- className: 'displayDemo',
7774
- key: 'welcomeTitle',
7775
- fallback: 'Bienvenido a la aplicación',
7776
- },
7777
- color: 'primary',
7778
- size: 'xlarge',
7779
- };
7780
- this.descriptionDisplay = {
7781
- contentConfig: {
7782
- className: 'displayDemo',
7783
- key: 'welcomeDescription',
7784
- fallback: 'Esta es una descripción de ejemplo',
7785
- },
7786
- color: 'medium',
7787
- size: 'medium',
7788
- };
7789
- this.statusDisplay = {
7790
- contentConfig: {
7791
- className: 'displayDemo',
7792
- key: 'statusOnline',
7793
- fallback: 'En línea',
7794
- },
7795
- color: 'success',
7796
- size: 'small',
7797
- };
7798
- // Ejemplos con interpolación
7799
- this.userWelcomeDisplay = {
7800
- contentConfig: {
7801
- className: 'displayDemo',
7802
- key: 'welcomeUser',
7803
- fallback: 'Hola, {{userName}}!',
7804
- interpolation: {
7805
- userName: 'Juan Pérez',
7806
- },
7807
- },
7808
- color: 'tertiary',
7809
- size: 'large',
7810
- };
7811
- this.counterDisplay = {
7812
- contentConfig: {
7813
- className: 'displayDemo',
7814
- key: 'counterCurrent',
7815
- fallback: 'Contador: {{count}}',
7816
- interpolation: {
7817
- count: this.counter,
7818
- },
7819
- },
7820
- color: 'secondary',
7821
- size: 'medium',
7822
- };
7823
- // Ejemplos con claves faltantes para demostrar fallbacks
7824
- this.missingKeyDisplay = {
7825
- contentConfig: {
7826
- className: 'displayDemo',
7827
- key: 'this.key.does.not.exist',
7828
- fallback: 'Esta clave no existe, pero tengo fallback',
7829
- },
7830
- color: 'warning',
7831
- size: 'medium',
7832
- };
7833
- this.noFallbackDisplay = {
7834
- contentConfig: {
7835
- className: 'displayDemo',
7836
- key: 'another.missing.key',
7837
- // Sin fallback - usará la clave como fallback
7838
- },
7839
- color: 'danger',
7840
- size: 'small',
7841
- };
7842
- // Ejemplos mixtos
7843
- this.staticMixedDisplay = {
7844
- content: 'Este es contenido estático (no cambia con el idioma)',
7845
- color: 'dark',
7846
- size: 'medium',
7847
- };
7848
- this.reactiveMixedDisplay = {
7849
- contentConfig: {
7850
- className: 'displayDemo',
7851
- key: 'mixedReactive',
7852
- fallback: 'Este contenido sí cambia con el idioma',
7853
- },
7854
- color: 'primary',
7855
- size: 'medium',
7856
- };
7857
- // Ejemplo dinámico que se actualiza
7858
- this.dynamicCounterDisplay = {
7859
- contentConfig: {
7860
- className: 'displayDemo',
7861
- key: 'dynamicContent',
7862
- fallback: 'Clics: {{count}}',
7863
- interpolation: {
7864
- count: this.counter,
7865
- },
7866
- },
7867
- color: 'tertiary',
7868
- size: 'large',
7869
- };
7870
- }
7871
- ngOnInit() {
7872
- this.initializeContent();
7873
- this.initializeLanguageState();
7874
- }
7875
- initializeContent() {
7876
- // Contenido de la página
7877
- this.demoTitle$ = this.contentService.fromContent({
7878
- className: 'displayDemo',
7879
- key: 'pageTitle',
7880
- fallback: 'Demostración del Componente Display',
7881
- });
7882
- this.languageLabel$ = this.contentService.fromContent({
7883
- className: '_global',
7884
- key: 'language',
7885
- fallback: 'Idioma',
7886
- });
7887
- this.staticSectionTitle$ = this.contentService.fromContent({
7888
- className: 'displayDemo',
7889
- key: 'sectionsStatic',
7890
- fallback: 'Ejemplos Estáticos',
7891
- });
7892
- this.reactiveSectionTitle$ = this.contentService.fromContent({
7893
- className: 'displayDemo',
7894
- key: 'sectionsReactive',
7895
- fallback: 'Ejemplos Reactivos',
7896
- });
7897
- this.mixedSectionTitle$ = this.contentService.fromContent({
7898
- className: 'displayDemo',
7899
- key: 'sectionsMixed',
7900
- fallback: 'Ejemplos Mixtos',
7901
- });
7902
- this.dynamicSectionTitle$ = this.contentService.fromContent({
7903
- className: 'displayDemo',
7904
- key: 'sectionsDynamic',
7905
- fallback: 'Ejemplos Dinámicos',
7906
- });
7907
- this.analysisTitle$ = this.contentService.fromContent({
7908
- className: 'displayDemo',
7909
- key: 'sectionsAnalysis',
7910
- fallback: 'Análisis de Idioma',
7911
- });
7912
- this.reactiveContentTitle$ = this.contentService.fromContent({
7913
- className: 'displayDemo',
7914
- key: 'subsectionsReactiveContent',
7915
- fallback: 'Contenido reactivo básico:',
7916
- });
7917
- this.interpolationTitle$ = this.contentService.fromContent({
7918
- className: 'displayDemo',
7919
- key: 'subsectionsInterpolation',
7920
- fallback: 'Contenido con interpolación:',
7921
- });
7922
- this.fallbackTitle$ = this.contentService.fromContent({
7923
- className: 'displayDemo',
7924
- key: 'subsectionsFallback',
7925
- fallback: 'Demostración de fallbacks:',
7926
- });
7927
- this.mixedContentTitle$ = this.contentService.fromContent({
7928
- className: 'displayDemo',
7929
- key: 'subsectionsMixedContent',
7930
- fallback: 'Contenido estático vs reactivo:',
7931
- });
7932
- this.dynamicContentTitle$ = this.contentService.fromContent({
7933
- className: 'displayDemo',
7934
- key: 'subsectionsDynamicContent',
7935
- fallback: 'Contenido que se actualiza dinámicamente:',
7936
- });
7937
- this.updateButtonText$ = this.contentService.fromContent({
7938
- className: 'displayDemo',
7939
- key: 'buttonsUpdateCounter',
7940
- fallback: 'Actualizar Contador',
7941
- });
7942
- this.currentLangLabel$ = this.contentService.fromContent({
7943
- className: 'displayDemo',
7944
- key: 'analysisCurrentLanguage',
7945
- fallback: 'Idioma actual',
7946
- });
7947
- this.availableLangsLabel$ = this.contentService.fromContent({
7948
- className: 'displayDemo',
7949
- key: 'analysisAvailableLanguages',
7950
- fallback: 'Idiomas disponibles',
7951
- });
7952
- }
7953
- initializeLanguageState() {
7954
- this.currentLanguage$ = this.langService.currentLang$;
7955
- this.availableLanguages$ = this.langService.currentLang$.pipe(map$1(() => this.langService.availableLangs));
7956
- }
7957
- changeLanguage(language) {
7958
- this.langService.setLang(language);
7959
- }
7960
- onLanguageChange(language) {
7961
- console.log('Language changed to:', language);
7962
- // El language selector ya maneja el cambio de idioma internamente
7963
- // pero podemos agregar lógica adicional aquí si es necesario
7964
- }
7965
- updateCounter() {
7966
- this.counter++;
7967
- // Actualizar los displays que usan el contador
7968
- this.counterDisplay = {
7969
- ...this.counterDisplay,
7970
- contentConfig: {
7971
- ...this.counterDisplay.contentConfig,
7972
- interpolation: {
7973
- count: this.counter,
7974
- },
7975
- },
7976
- };
7977
- this.dynamicCounterDisplay = {
7978
- ...this.dynamicCounterDisplay,
7979
- contentConfig: {
7980
- ...this.dynamicCounterDisplay.contentConfig,
7981
- interpolation: {
7982
- count: this.counter,
7983
- },
7984
- },
7985
- };
7986
- }
7987
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DisplayDemoComponent, deps: [{ token: ContentService }, { token: LangService }], target: i0.ɵɵFactoryTarget.Component }); }
7988
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DisplayDemoComponent, isStandalone: true, selector: "val-display-demo", ngImport: i0, template: `
7989
- <div class="display-demo">
7990
- <ion-card>
7991
- <ion-card-header>
7992
- <ion-card-title>{{ demoTitle$ | async }}</ion-card-title>
7993
- </ion-card-header>
7994
-
7995
- <ion-card-content>
7996
- <!-- Selector de idioma -->
7997
- <div class="language-selector-container">
7998
- <val-language-selector [props]="languageSelectorProps" (languageChange)="onLanguageChange($event)">
7999
- </val-language-selector>
8000
- </div>
8001
-
8002
- <!-- Ejemplos estáticos -->
8003
- <div class="section">
8004
- <h3>{{ staticSectionTitle$ | async }}</h3>
8005
-
8006
- <div class="example-group">
8007
- <h4>Diferentes tamaños:</h4>
8008
- <val-display [props]="smallStaticDisplay"></val-display>
8009
- <val-display [props]="mediumStaticDisplay"></val-display>
8010
- <val-display [props]="largeStaticDisplay"></val-display>
8011
- <val-display [props]="xlargeStaticDisplay"></val-display>
8012
- </div>
8013
-
8014
- <div class="example-group">
8015
- <h4>Diferentes colores:</h4>
8016
- <val-display [props]="primaryDisplay"></val-display>
8017
- <val-display [props]="secondaryDisplay"></val-display>
8018
- <val-display [props]="successDisplay"></val-display>
8019
- <val-display [props]="warningDisplay"></val-display>
8020
- <val-display [props]="dangerDisplay"></val-display>
8021
- </div>
8022
- </div>
8023
-
8024
- <!-- Ejemplos reactivos -->
8025
- <div class="section">
8026
- <h3>{{ reactiveSectionTitle$ | async }}</h3>
8027
-
8028
- <div class="example-group">
8029
- <h4>{{ reactiveContentTitle$ | async }}</h4>
8030
- <val-display [props]="welcomeDisplay"></val-display>
8031
- <val-display [props]="descriptionDisplay"></val-display>
8032
- <val-display [props]="statusDisplay"></val-display>
8033
- </div>
8034
-
8035
- <div class="example-group">
8036
- <h4>{{ interpolationTitle$ | async }}</h4>
8037
- <val-display [props]="userWelcomeDisplay"></val-display>
8038
- <val-display [props]="counterDisplay"></val-display>
8039
- </div>
8040
-
8041
- <div class="example-group">
8042
- <h4>{{ fallbackTitle$ | async }}</h4>
8043
- <val-display [props]="missingKeyDisplay"></val-display>
8044
- <val-display [props]="noFallbackDisplay"></val-display>
8045
- </div>
8046
- </div>
8047
-
8048
- <!-- Ejemplos mixtos -->
8049
- <div class="section">
8050
- <h3>{{ mixedSectionTitle$ | async }}</h3>
8051
-
8052
- <div class="example-group">
8053
- <h4>{{ mixedContentTitle$ | async }}</h4>
8054
- <div class="mixed-examples">
8055
- <val-display [props]="staticMixedDisplay"></val-display>
8056
- <val-display [props]="reactiveMixedDisplay"></val-display>
8057
- </div>
8058
- </div>
8059
- </div>
8060
-
8061
- <!-- Ejemplos dinámicos -->
8062
- <div class="section">
8063
- <h3>{{ dynamicSectionTitle$ | async }}</h3>
8064
-
8065
- <div class="example-group">
8066
- <h4>{{ dynamicContentTitle$ | async }}</h4>
8067
- <ion-button (click)="updateCounter()" color="primary">
8068
- {{ updateButtonText$ | async }}
8069
- </ion-button>
8070
- <val-display [props]="dynamicCounterDisplay"></val-display>
8071
- </div>
8072
- </div>
8073
-
8074
- <!-- Análisis de contenido -->
8075
- <div class="section">
8076
- <h3>{{ analysisTitle$ | async }}</h3>
8077
- <div class="analysis-info">
8078
- <p>
8079
- <strong>{{ currentLangLabel$ | async }}:</strong> {{ currentLanguage$ | async | uppercase }}
8080
- </p>
8081
- <p>
8082
- <strong>{{ availableLangsLabel$ | async }}:</strong>
8083
- {{ (availableLanguages$ | async)?.join(', ') | uppercase }}
8084
- </p>
8085
- </div>
8086
- </div>
8087
- </ion-card-content>
8088
- </ion-card>
8089
- </div>
8090
- `, isInline: true, styles: [".display-demo{padding:16px}.language-selector-container{margin:16px 0;padding:12px;background:var(--ion-color-step-50);border-radius:8px}.section{margin:24px 0;border-bottom:1px solid var(--ion-color-light);padding-bottom:16px}.example-group{margin:16px 0;padding:12px;background:var(--ion-color-light);border-radius:8px}.example-group h4{margin:0 0 12px;color:var(--ion-color-medium)}.mixed-examples{display:flex;flex-direction:column;gap:8px}.analysis-info{background:var(--ion-color-step-50);padding:16px;border-radius:8px;margin-top:16px}val-display{display:block;margin:8px 0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: LanguageSelectorComponent, selector: "val-language-selector", inputs: ["props"], outputs: ["languageChange"] }] }); }
8091
- }
8092
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DisplayDemoComponent, decorators: [{
8093
- type: Component,
8094
- args: [{ selector: 'val-display-demo', standalone: true, imports: [
8095
- CommonModule,
8096
- IonCard,
8097
- IonCardContent,
8098
- IonCardHeader,
8099
- IonCardTitle,
8100
- IonButton,
8101
- DisplayComponent,
8102
- LanguageSelectorComponent,
8103
- ], template: `
8104
- <div class="display-demo">
8105
- <ion-card>
8106
- <ion-card-header>
8107
- <ion-card-title>{{ demoTitle$ | async }}</ion-card-title>
8108
- </ion-card-header>
8109
-
8110
- <ion-card-content>
8111
- <!-- Selector de idioma -->
8112
- <div class="language-selector-container">
8113
- <val-language-selector [props]="languageSelectorProps" (languageChange)="onLanguageChange($event)">
8114
- </val-language-selector>
8115
- </div>
8116
-
8117
- <!-- Ejemplos estáticos -->
8118
- <div class="section">
8119
- <h3>{{ staticSectionTitle$ | async }}</h3>
8120
-
8121
- <div class="example-group">
8122
- <h4>Diferentes tamaños:</h4>
8123
- <val-display [props]="smallStaticDisplay"></val-display>
8124
- <val-display [props]="mediumStaticDisplay"></val-display>
8125
- <val-display [props]="largeStaticDisplay"></val-display>
8126
- <val-display [props]="xlargeStaticDisplay"></val-display>
8127
- </div>
8128
-
8129
- <div class="example-group">
8130
- <h4>Diferentes colores:</h4>
8131
- <val-display [props]="primaryDisplay"></val-display>
8132
- <val-display [props]="secondaryDisplay"></val-display>
8133
- <val-display [props]="successDisplay"></val-display>
8134
- <val-display [props]="warningDisplay"></val-display>
8135
- <val-display [props]="dangerDisplay"></val-display>
8136
- </div>
8137
- </div>
8138
-
8139
- <!-- Ejemplos reactivos -->
8140
- <div class="section">
8141
- <h3>{{ reactiveSectionTitle$ | async }}</h3>
8142
-
8143
- <div class="example-group">
8144
- <h4>{{ reactiveContentTitle$ | async }}</h4>
8145
- <val-display [props]="welcomeDisplay"></val-display>
8146
- <val-display [props]="descriptionDisplay"></val-display>
8147
- <val-display [props]="statusDisplay"></val-display>
8148
- </div>
8149
-
8150
- <div class="example-group">
8151
- <h4>{{ interpolationTitle$ | async }}</h4>
8152
- <val-display [props]="userWelcomeDisplay"></val-display>
8153
- <val-display [props]="counterDisplay"></val-display>
8154
- </div>
8155
-
8156
- <div class="example-group">
8157
- <h4>{{ fallbackTitle$ | async }}</h4>
8158
- <val-display [props]="missingKeyDisplay"></val-display>
8159
- <val-display [props]="noFallbackDisplay"></val-display>
8160
- </div>
8161
- </div>
8162
-
8163
- <!-- Ejemplos mixtos -->
8164
- <div class="section">
8165
- <h3>{{ mixedSectionTitle$ | async }}</h3>
8166
-
8167
- <div class="example-group">
8168
- <h4>{{ mixedContentTitle$ | async }}</h4>
8169
- <div class="mixed-examples">
8170
- <val-display [props]="staticMixedDisplay"></val-display>
8171
- <val-display [props]="reactiveMixedDisplay"></val-display>
8172
- </div>
8173
- </div>
8174
- </div>
8175
-
8176
- <!-- Ejemplos dinámicos -->
8177
- <div class="section">
8178
- <h3>{{ dynamicSectionTitle$ | async }}</h3>
8179
-
8180
- <div class="example-group">
8181
- <h4>{{ dynamicContentTitle$ | async }}</h4>
8182
- <ion-button (click)="updateCounter()" color="primary">
8183
- {{ updateButtonText$ | async }}
8184
- </ion-button>
8185
- <val-display [props]="dynamicCounterDisplay"></val-display>
8186
- </div>
8187
- </div>
8188
-
8189
- <!-- Análisis de contenido -->
8190
- <div class="section">
8191
- <h3>{{ analysisTitle$ | async }}</h3>
8192
- <div class="analysis-info">
8193
- <p>
8194
- <strong>{{ currentLangLabel$ | async }}:</strong> {{ currentLanguage$ | async | uppercase }}
8195
- </p>
8196
- <p>
8197
- <strong>{{ availableLangsLabel$ | async }}:</strong>
8198
- {{ (availableLanguages$ | async)?.join(', ') | uppercase }}
8199
- </p>
8200
- </div>
8201
- </div>
8202
- </ion-card-content>
8203
- </ion-card>
8204
- </div>
8205
- `, styles: [".display-demo{padding:16px}.language-selector-container{margin:16px 0;padding:12px;background:var(--ion-color-step-50);border-radius:8px}.section{margin:24px 0;border-bottom:1px solid var(--ion-color-light);padding-bottom:16px}.example-group{margin:16px 0;padding:12px;background:var(--ion-color-light);border-radius:8px}.example-group h4{margin:0 0 12px;color:var(--ion-color-medium)}.mixed-examples{display:flex;flex-direction:column;gap:8px}.analysis-info{background:var(--ion-color-step-50);padding:16px;border-radius:8px;margin-top:16px}val-display{display:block;margin:8px 0}\n"] }]
8206
- }], ctorParameters: () => [{ type: ContentService }, { type: LangService }] });
8207
-
8208
- /**
8209
- * Ejemplo rápido de uso del componente val-display con contenido reactivo
8210
- */
8211
- class DisplayExampleComponent {
8212
- constructor() {
8213
- // ✅ Ejemplos de contenido estático
8214
- this.staticTitle = {
8215
- content: 'Este es un título estático',
8216
- color: 'primary',
8217
- size: 'xlarge',
8218
- };
8219
- this.staticSubtitle = {
8220
- content: 'Este es un subtítulo que no cambia',
8221
- color: 'medium',
8222
- size: 'large',
8223
- };
8224
- // ✅ Ejemplos de contenido reactivo (requiere configuración de i18n)
8225
- this.reactiveWelcome = {
8226
- contentConfig: {
8227
- className: 'displayExample',
8228
- key: 'welcome.title',
8229
- fallback: 'Bienvenido a la aplicación',
8230
- },
8231
- color: 'primary',
8232
- size: 'xlarge',
8233
- };
8234
- this.reactiveDescription = {
8235
- contentConfig: {
8236
- className: 'displayExample',
8237
- key: 'welcome.description',
8238
- fallback: 'Esta descripción cambia según el idioma',
8239
- },
8240
- color: 'dark',
8241
- size: 'medium',
8242
- };
8243
- // ✅ Ejemplos con interpolación de variables
8244
- this.userGreeting = {
8245
- contentConfig: {
8246
- className: 'displayExample',
8247
- key: 'user.greeting',
8248
- fallback: 'Hola, {{name}}! Tienes {{messages}} mensajes.',
8249
- interpolation: {
8250
- name: 'María',
8251
- messages: 5,
8252
- },
8253
- },
8254
- color: 'tertiary',
8255
- size: 'large',
8256
- };
8257
- this.statusMessage = {
8258
- contentConfig: {
8259
- className: 'displayExample',
8260
- key: 'status.online',
8261
- fallback: 'Estado: {{status}} desde {{time}}',
8262
- interpolation: {
8263
- status: 'En línea',
8264
- time: '10:30 AM',
8265
- },
8266
- },
8267
- color: 'success',
8268
- size: 'small',
8269
- };
8270
- // ✅ Ejemplos de diferentes tamaños
8271
- this.smallText = {
8272
- content: 'Texto pequeño (small)',
8273
- color: 'dark',
8274
- size: 'small',
8275
- };
8276
- this.mediumText = {
8277
- content: 'Texto mediano (medium)',
8278
- color: 'dark',
8279
- size: 'medium',
8280
- };
8281
- this.largeText = {
8282
- content: 'Texto grande (large)',
8283
- color: 'dark',
8284
- size: 'large',
8285
- };
8286
- this.xlargeText = {
8287
- content: 'Texto extra grande (xlarge)',
8288
- color: 'dark',
8289
- size: 'xlarge',
8290
- };
8291
- // ✅ Ejemplos de diferentes colores
8292
- this.primaryText = {
8293
- content: 'Texto color primary',
8294
- color: 'primary',
8295
- size: 'medium',
8296
- };
8297
- this.successText = {
8298
- content: 'Texto color success',
8299
- color: 'success',
8300
- size: 'medium',
8301
- };
8302
- this.warningText = {
8303
- content: 'Texto color warning',
8304
- color: 'warning',
8305
- size: 'medium',
8306
- };
8307
- this.dangerText = {
8308
- content: 'Texto color danger',
8309
- color: 'danger',
8310
- size: 'medium',
8311
- };
8312
- }
8313
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DisplayExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8314
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DisplayExampleComponent, isStandalone: true, selector: "app-display-example", ngImport: i0, template: `
8315
- <div class="display-examples">
8316
- <h2>Ejemplos de val-display</h2>
8317
-
8318
- <!-- Contenido estático -->
8319
- <div class="section">
8320
- <h3>Contenido Estático</h3>
8321
- <val-display [props]="staticTitle"></val-display>
8322
- <val-display [props]="staticSubtitle"></val-display>
8323
- </div>
8324
-
8325
- <!-- Contenido reactivo -->
8326
- <div class="section">
8327
- <h3>Contenido Reactivo</h3>
8328
- <val-display [props]="reactiveWelcome"></val-display>
8329
- <val-display [props]="reactiveDescription"></val-display>
8330
- </div>
8331
-
8332
- <!-- Contenido con interpolación -->
8333
- <div class="section">
8334
- <h3>Contenido con Variables</h3>
8335
- <val-display [props]="userGreeting"></val-display>
8336
- <val-display [props]="statusMessage"></val-display>
8337
- </div>
8338
-
8339
- <!-- Diferentes tamaños -->
8340
- <div class="section">
8341
- <h3>Diferentes Tamaños</h3>
8342
- <val-display [props]="smallText"></val-display>
8343
- <val-display [props]="mediumText"></val-display>
8344
- <val-display [props]="largeText"></val-display>
8345
- <val-display [props]="xlargeText"></val-display>
8346
- </div>
8347
-
8348
- <!-- Diferentes colores -->
8349
- <div class="section">
8350
- <h3>Diferentes Colores</h3>
8351
- <val-display [props]="primaryText"></val-display>
8352
- <val-display [props]="successText"></val-display>
8353
- <val-display [props]="warningText"></val-display>
8354
- <val-display [props]="dangerText"></val-display>
8355
- </div>
8356
- </div>
8357
- `, isInline: true, styles: [".display-examples{padding:20px;max-width:800px;margin:0 auto}.section{margin:30px 0;padding:20px;border:1px solid var(--ion-color-light);border-radius:8px;background:var(--ion-color-step-50)}.section h3{margin:0 0 15px;color:var(--ion-color-primary)}val-display{display:block;margin:10px 0}\n"], dependencies: [{ kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }] }); }
8358
- }
8359
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DisplayExampleComponent, decorators: [{
8360
- type: Component,
8361
- args: [{ selector: 'app-display-example', standalone: true, imports: [DisplayComponent], template: `
8362
- <div class="display-examples">
8363
- <h2>Ejemplos de val-display</h2>
8364
-
8365
- <!-- Contenido estático -->
8366
- <div class="section">
8367
- <h3>Contenido Estático</h3>
8368
- <val-display [props]="staticTitle"></val-display>
8369
- <val-display [props]="staticSubtitle"></val-display>
8370
- </div>
8371
-
8372
- <!-- Contenido reactivo -->
8373
- <div class="section">
8374
- <h3>Contenido Reactivo</h3>
8375
- <val-display [props]="reactiveWelcome"></val-display>
8376
- <val-display [props]="reactiveDescription"></val-display>
8377
- </div>
8378
-
8379
- <!-- Contenido con interpolación -->
8380
- <div class="section">
8381
- <h3>Contenido con Variables</h3>
8382
- <val-display [props]="userGreeting"></val-display>
8383
- <val-display [props]="statusMessage"></val-display>
8384
- </div>
8385
-
8386
- <!-- Diferentes tamaños -->
8387
- <div class="section">
8388
- <h3>Diferentes Tamaños</h3>
8389
- <val-display [props]="smallText"></val-display>
8390
- <val-display [props]="mediumText"></val-display>
8391
- <val-display [props]="largeText"></val-display>
8392
- <val-display [props]="xlargeText"></val-display>
8393
- </div>
8394
-
8395
- <!-- Diferentes colores -->
8396
- <div class="section">
8397
- <h3>Diferentes Colores</h3>
8398
- <val-display [props]="primaryText"></val-display>
8399
- <val-display [props]="successText"></val-display>
8400
- <val-display [props]="warningText"></val-display>
8401
- <val-display [props]="dangerText"></val-display>
8402
- </div>
8403
- </div>
8404
- `, styles: [".display-examples{padding:20px;max-width:800px;margin:0 auto}.section{margin:30px 0;padding:20px;border:1px solid var(--ion-color-light);border-radius:8px;background:var(--ion-color-step-50)}.section h3{margin:0 0 15px;color:var(--ion-color-primary)}val-display{display:block;margin:10px 0}\n"] }]
8405
- }] });
8406
-
8407
- /**
8408
- * LinkProcessingExampleComponent - Componente de ejemplo que demuestra el procesamiento automático de enlaces.
8409
- *
8410
- * Este componente muestra diferentes casos de uso para el procesamiento automático de enlaces
8411
- * en el componente val-text, incluyendo enlaces externos, rutas internas y configuraciones personalizadas.
8412
- *
8413
- * @example Uso en template:
8414
- * ```html
8415
- * <val-link-processing-example></val-link-processing-example>
8416
- * ```
8417
- */
8418
- class LinkProcessingExampleComponent {
8419
- constructor() {
8420
- this.basicTextProps = {
8421
- content: 'Este texto contiene https://angular.io y /dashboard pero no se procesan como enlaces.',
8422
- size: 'medium',
8423
- color: 'dark',
8424
- bold: false,
8425
- processLinks: false,
8426
- };
8427
- this.basicLinksProps = {
8428
- content: 'Visita https://angular.io para documentación o ve a /dashboard para el panel principal.',
8429
- size: 'medium',
8430
- color: 'dark',
8431
- bold: false,
8432
- processLinks: true,
8433
- };
8434
- this.customLinksProps = {
8435
- content: 'Enlaces personalizados: https://github.com/angular/angular y /profile/settings',
8436
- size: 'medium',
8437
- color: 'dark',
8438
- bold: false,
8439
- processLinks: true,
8440
- linkConfig: {
8441
- openExternalInNewTab: true,
8442
- openInternalInNewTab: false,
8443
- linkClass: 'custom-link-style',
8444
- externalLinkClass: 'external-custom',
8445
- internalLinkClass: 'internal-custom',
8446
- },
8447
- };
8448
- this.mixedLinksProps = {
8449
- content: 'Consulta la documentación en https://ionicframework.com/docs, revisa el código en https://github.com/ionic-team/ionic-framework, o navega a /components/buttons para ejemplos internos.',
8450
- size: 'medium',
8451
- color: 'dark',
8452
- bold: false,
8453
- processLinks: true,
8454
- linkConfig: {
8455
- openExternalInNewTab: true,
8456
- openInternalInNewTab: false,
8457
- linkClass: 'processed-link',
8458
- externalLinkClass: 'external-link',
8459
- internalLinkClass: 'internal-link',
8460
- },
8461
- };
8462
- this.sameTabLinksProps = {
8463
- content: 'Estos enlaces no abren en nueva pestaña: https://example.com y /home',
8464
- size: 'medium',
8465
- color: 'dark',
8466
- bold: false,
8467
- processLinks: true,
8468
- linkConfig: {
8469
- openExternalInNewTab: false,
8470
- openInternalInNewTab: false,
8471
- linkClass: 'same-tab-link',
8472
- externalLinkClass: 'external-same-tab',
8473
- internalLinkClass: 'internal-same-tab',
8474
- },
8475
- };
8476
- this.markdownLinksProps = {
8477
- content: 'Consulta [la documentación de Angular](https://angular.io/docs) y ve a [configuración del perfil](/profile/settings) para más opciones.',
8478
- size: 'medium',
8479
- color: 'dark',
8480
- bold: false,
8481
- processLinks: true,
8482
- linkConfig: {
8483
- openExternalInNewTab: true,
8484
- openInternalInNewTab: false,
8485
- processMarkdownLinks: true,
8486
- linkClass: 'markdown-link',
8487
- externalLinkClass: 'markdown-external',
8488
- internalLinkClass: 'markdown-internal',
8489
- },
8490
- };
8491
- this.mixedFormatsProps = {
8492
- content: 'Aquí hay [documentación oficial](https://angular.io/docs), un enlace directo https://github.com/angular/angular, y una ruta interna /dashboard/analytics. ¡Todos funcionan!',
8493
- size: 'medium',
8494
- color: 'dark',
8495
- bold: false,
8496
- processLinks: true,
8497
- linkConfig: {
8498
- openExternalInNewTab: true,
8499
- openInternalInNewTab: false,
8500
- processMarkdownLinks: true,
8501
- linkClass: 'mixed-link',
8502
- externalLinkClass: 'mixed-external',
8503
- internalLinkClass: 'mixed-internal',
8504
- },
8505
- };
8506
- this.punctuationTestProps = {
8507
- content: 'URLs con puntuación final: https://ionicframework.com/docs, también https://angular.io! Pregunta sobre https://github.com/angular? Y punto final: https://typescript.org. Paréntesis (https://rxjs.dev) y comillas "https://zone.js". ¡Todos funcionan!',
8508
- size: 'medium',
8509
- color: 'dark',
8510
- bold: false,
8511
- processLinks: true,
8512
- linkConfig: {
8513
- openExternalInNewTab: true,
8514
- linkClass: 'punctuation-test',
8515
- externalLinkClass: 'external-punct',
8516
- },
8517
- };
8518
- this.complexUrlsProps = {
8519
- content: 'URLs complejas: https://example.com/path?param=value&other=123#section, búsqueda en https://google.com/search?q=angular+components, y API https://api.github.com/repos/owner/repo/issues?state=open. Todos con parámetros y fragmentos.',
8520
- size: 'medium',
8521
- color: 'dark',
8522
- bold: false,
8523
- processLinks: true,
8524
- linkConfig: {
8525
- openExternalInNewTab: true,
8526
- linkClass: 'complex-url',
8527
- externalLinkClass: 'complex-external',
8528
- },
8529
- };
8530
- }
8531
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkProcessingExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8532
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LinkProcessingExampleComponent, isStandalone: true, selector: "val-link-processing-example", ngImport: i0, template: `
8533
- <div class="link-examples">
8534
- <h2>Ejemplos de Procesamiento de Enlaces</h2>
8535
-
8536
- <div class="example-section">
8537
- <h3>Texto sin procesamiento de enlaces:</h3>
8538
- <val-text [props]="basicTextProps"></val-text>
8539
- </div>
8540
-
8541
- <div class="example-section">
8542
- <h3>Texto con procesamiento básico de enlaces:</h3>
8543
- <val-text [props]="basicLinksProps"></val-text>
8544
- </div>
8545
-
8546
- <div class="example-section">
8547
- <h3>Enlaces con configuración personalizada:</h3>
8548
- <val-text [props]="customLinksProps"></val-text>
8549
- </div>
8550
-
8551
- <div class="example-section">
8552
- <h3>Enlaces internos y externos mezclados:</h3>
8553
- <val-text [props]="mixedLinksProps"></val-text>
8554
- </div>
8555
-
8556
- <div class="example-section">
8557
- <h3>Enlaces sin abrir en nueva pestaña:</h3>
8558
- <val-text [props]="sameTabLinksProps"></val-text>
8559
- </div>
8560
-
8561
- <div class="example-section">
8562
- <h3>Enlaces estilo Markdown [texto](url):</h3>
8563
- <val-text [props]="markdownLinksProps"></val-text>
8564
- </div>
8565
-
8566
- <div class="example-section">
8567
- <h3>Mezcla de enlaces directos y Markdown:</h3>
8568
- <val-text [props]="mixedFormatsProps"></val-text>
8569
- </div>
8570
-
8571
- <div class="example-section">
8572
- <h3>Corrección de puntuación en URLs:</h3>
8573
- <val-text [props]="punctuationTestProps"></val-text>
8574
- </div>
8575
-
8576
- <div class="example-section">
8577
- <h3>URLs complejas con parámetros y fragmentos:</h3>
8578
- <val-text [props]="complexUrlsProps"></val-text>
8579
- </div>
8580
- </div>
8581
- `, isInline: true, styles: [".example-section{margin-bottom:24px;padding:16px;border:1px solid var(--ion-color-light, #f4f5f8);border-radius:8px;background:var(--ion-color-light-tint, #f5f6f9)}h2{color:var(--ion-color-primary, #3880ff);margin-bottom:20px}h3{color:var(--ion-color-dark, #222428);margin-bottom:10px;font-size:16px}\n"], dependencies: [{ kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
8582
- }
8583
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkProcessingExampleComponent, decorators: [{
8584
- type: Component,
8585
- args: [{ selector: 'val-link-processing-example', standalone: true, imports: [TextComponent], template: `
8586
- <div class="link-examples">
8587
- <h2>Ejemplos de Procesamiento de Enlaces</h2>
8588
-
8589
- <div class="example-section">
8590
- <h3>Texto sin procesamiento de enlaces:</h3>
8591
- <val-text [props]="basicTextProps"></val-text>
8592
- </div>
8593
-
8594
- <div class="example-section">
8595
- <h3>Texto con procesamiento básico de enlaces:</h3>
8596
- <val-text [props]="basicLinksProps"></val-text>
8597
- </div>
8598
-
8599
- <div class="example-section">
8600
- <h3>Enlaces con configuración personalizada:</h3>
8601
- <val-text [props]="customLinksProps"></val-text>
8602
- </div>
8603
-
8604
- <div class="example-section">
8605
- <h3>Enlaces internos y externos mezclados:</h3>
8606
- <val-text [props]="mixedLinksProps"></val-text>
8607
- </div>
8608
-
8609
- <div class="example-section">
8610
- <h3>Enlaces sin abrir en nueva pestaña:</h3>
8611
- <val-text [props]="sameTabLinksProps"></val-text>
8612
- </div>
8613
-
8614
- <div class="example-section">
8615
- <h3>Enlaces estilo Markdown [texto](url):</h3>
8616
- <val-text [props]="markdownLinksProps"></val-text>
8617
- </div>
8618
-
8619
- <div class="example-section">
8620
- <h3>Mezcla de enlaces directos y Markdown:</h3>
8621
- <val-text [props]="mixedFormatsProps"></val-text>
8622
- </div>
8623
-
8624
- <div class="example-section">
8625
- <h3>Corrección de puntuación en URLs:</h3>
8626
- <val-text [props]="punctuationTestProps"></val-text>
8627
- </div>
8628
-
8629
- <div class="example-section">
8630
- <h3>URLs complejas con parámetros y fragmentos:</h3>
8631
- <val-text [props]="complexUrlsProps"></val-text>
8632
- </div>
8633
- </div>
8634
- `, styles: [".example-section{margin-bottom:24px;padding:16px;border:1px solid var(--ion-color-light, #f4f5f8);border-radius:8px;background:var(--ion-color-light-tint, #f5f6f9)}h2{color:var(--ion-color-primary, #3880ff);margin-bottom:20px}h3{color:var(--ion-color-dark, #222428);margin-bottom:10px;font-size:16px}\n"] }]
8635
- }] });
8636
-
8637
- /**
8638
- * MultiLanguageDemoComponent - Demuestra el sistema de idiomas flexible.
8639
- *
8640
- * Este componente muestra cómo el sistema maneja múltiples idiomas,
8641
- * fallbacks automáticos y warnings por traducciones faltantes.
8642
- */
8643
- class MultiLanguageDemoComponent {
8644
- constructor(content, langService) {
8645
- this.content = content;
8646
- this.langService = langService;
8647
- this.availableLanguages = [];
8648
- this.analysisResults = null;
8649
- // Global content observables
8650
- this.okButton$ = this.content.fromContent({ key: 'ok' });
8651
- this.cancelButton$ = this.content.fromContent({ key: 'cancel' });
8652
- this.saveButton$ = this.content.fromContent({ key: 'save' });
8653
- this.deleteButton$ = this.content.fromContent({ key: 'delete' });
8654
- // Content that might have missing translations
8655
- this.nextButton$ = this.content.fromContent({ key: 'next', fallback: 'Next' });
8656
- this.finishButton$ = this.content.fromContent({ key: 'finish', fallback: 'Finish' });
8657
- this.searchPlaceholder$ = this.content.fromContent({ key: 'searchPlaceholder', fallback: 'Search...' });
8658
- this.noDataMessage$ = this.content.fromContent({ key: 'noData', fallback: 'No data available' });
8659
- }
8660
- ngOnInit() {
8661
- this.availableLanguages = this.langService.availableLangs;
8662
- }
8663
- switchLanguage(lang) {
8664
- console.log(`Switching to language: ${lang}`);
8665
- this.langService.setLang(lang);
8666
- this.analysisResults = null; // Reset analysis when language changes
8667
- }
8668
- getLanguageName(lang) {
8669
- const names = {
8670
- [LANGUAGES.ES]: 'Español',
8671
- [LANGUAGES.EN]: 'English',
8672
- [LANGUAGES.FR]: 'Français',
8673
- [LANGUAGES.DE]: 'Deutsch',
8674
- pt: 'Português',
8675
- };
8676
- return names[lang] || lang.toUpperCase();
8677
- }
8678
- analyzeCurrentComponent() {
8679
- const componentName = '_global'; // Analyzing global content for this demo
8680
- const availableLanguages = this.langService.getAvailableLanguagesForComponent(componentName);
8681
- const missingKeys = this.langService.getMissingContentKeys(componentName, this.langService.currentLang);
8682
- this.analysisResults = {
8683
- availableLanguages,
8684
- missingKeys,
8685
- };
8686
- console.log('Component analysis results:', this.analysisResults);
8687
- }
8688
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiLanguageDemoComponent, deps: [{ token: ContentService }, { token: LangService }], target: i0.ɵɵFactoryTarget.Component }); }
8689
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MultiLanguageDemoComponent, isStandalone: true, selector: "val-multi-language-demo", ngImport: i0, template: `
8690
- <div class="multi-lang-demo">
8691
- <h2>Sistema de Idiomas Flexible</h2>
8692
-
8693
- <div class="language-info">
8694
- <h3>Información del Sistema:</h3>
8695
- <p><strong>Idioma actual:</strong> {{ langService.currentLang }}</p>
8696
- <p><strong>Idioma por defecto:</strong> {{ langService.defaultLanguage }}</p>
8697
- <p><strong>Idiomas disponibles:</strong> {{ langService.availableLangs.join(', ') }}</p>
8698
- </div>
8699
-
8700
- <div class="language-switcher">
8701
- <h3>Cambiar Idioma:</h3>
8702
- <div class="button-group">
8703
- <button
8704
- *ngFor="let lang of availableLanguages"
8705
- [class.active]="lang === langService.currentLang"
8706
- (click)="switchLanguage(lang)"
8707
- >
8708
- {{ getLanguageName(lang) }}
8709
- </button>
8710
- <!-- Ejemplo de idioma no disponible -->
8711
- <button (click)="switchLanguage('pt')">Português (no disponible)</button>
8712
- </div>
8713
- </div>
8714
-
8715
- <div class="content-examples">
8716
- <h3>Contenido Global:</h3>
8717
- <div class="example-grid">
8718
- <val-text
8719
- [props]="{ content: okButton$ | async, size: 'medium', color: 'dark', bold: false, processLinks: false }"
8720
- ></val-text>
8721
- <val-text
8722
- [props]="{
8723
- content: cancelButton$ | async,
8724
- size: 'medium',
8725
- color: 'dark',
8726
- bold: false,
8727
- processLinks: false,
8728
- }"
8729
- ></val-text>
8730
- <val-text
8731
- [props]="{ content: saveButton$ | async, size: 'medium', color: 'dark', bold: false, processLinks: false }"
8732
- ></val-text>
8733
- <val-text
8734
- [props]="{
8735
- content: deleteButton$ | async,
8736
- size: 'medium',
8737
- color: 'dark',
8738
- bold: false,
8739
- processLinks: false,
8740
- }"
8741
- ></val-text>
8742
- </div>
8743
-
8744
- <h3>Contenido con Fallback (algunas traducciones faltantes):</h3>
8745
- <div class="example-grid">
8746
- <val-text
8747
- [props]="{ content: nextButton$ | async, size: 'medium', color: 'dark', bold: false, processLinks: false }"
8748
- ></val-text>
8749
- <val-text
8750
- [props]="{
8751
- content: finishButton$ | async,
8752
- size: 'medium',
8753
- color: 'dark',
8754
- bold: false,
8755
- processLinks: false,
8756
- }"
8757
- ></val-text>
8758
- <val-text
8759
- [props]="{
8760
- content: searchPlaceholder$ | async,
8761
- size: 'medium',
8762
- color: 'dark',
8763
- bold: false,
8764
- processLinks: false,
8765
- }"
8766
- ></val-text>
8767
- <val-text
8768
- [props]="{
8769
- content: noDataMessage$ | async,
8770
- size: 'medium',
8771
- color: 'dark',
8772
- bold: false,
8773
- processLinks: false,
8774
- }"
8775
- ></val-text>
8776
- </div>
8777
- </div>
8778
-
8779
- <div class="warning-info">
8780
- <h3>Información de Warnings:</h3>
8781
- <p>
8782
- Abre la consola del navegador para ver los warnings cuando cambies a idiomas con traducciones incompletas
8783
- (francés, alemán).
8784
- </p>
8785
- <p>El sistema automáticamente usará el idioma por defecto o el primer idioma disponible como fallback.</p>
8786
- </div>
8787
-
8788
- <div class="component-analysis">
8789
- <h3>Análisis del Componente:</h3>
8790
- <button (click)="analyzeCurrentComponent()">Analizar Contenido</button>
8791
- <div *ngIf="analysisResults" class="analysis-results">
8792
- <p>
8793
- <strong>Idiomas disponibles para este componente:</strong>
8794
- {{ analysisResults.availableLanguages.join(', ') }}
8795
- </p>
8796
- <div *ngIf="analysisResults.missingKeys.length > 0">
8797
- <p>
8798
- <strong>Claves faltantes en {{ langService.currentLang }}:</strong>
8799
- </p>
8800
- <ul>
8801
- <li *ngFor="let key of analysisResults.missingKeys">{{ key }}</li>
8802
- </ul>
8803
- </div>
8804
- </div>
8805
- </div>
8806
- </div>
8807
- `, isInline: true, styles: [".multi-lang-demo{padding:20px;max-width:800px}.language-info,.content-examples,.warning-info,.component-analysis{margin:20px 0;padding:15px;border:1px solid var(--ion-color-light, #f4f5f8);border-radius:8px;background:var(--ion-color-light-tint, #f5f6f9)}.button-group{display:flex;gap:10px;flex-wrap:wrap}.button-group button{padding:8px 16px;border:1px solid var(--ion-color-primary, #3880ff);background:#fff;color:var(--ion-color-primary, #3880ff);border-radius:4px;cursor:pointer;transition:all .2s}.button-group button:hover{background:var(--ion-color-primary-tint, #4992ff);color:#fff}.button-group button.active{background:var(--ion-color-primary, #3880ff);color:#fff}.example-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin-top:10px}.analysis-results{margin-top:10px;padding:10px;background:#fff;border-radius:4px}h2{color:var(--ion-color-primary, #3880ff)}h3{color:var(--ion-color-dark, #222428);margin-bottom:10px}\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: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
8808
- }
8809
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiLanguageDemoComponent, decorators: [{
8810
- type: Component,
8811
- args: [{ selector: 'val-multi-language-demo', standalone: true, imports: [CommonModule, TextComponent, ButtonComponent], template: `
8812
- <div class="multi-lang-demo">
8813
- <h2>Sistema de Idiomas Flexible</h2>
8814
-
8815
- <div class="language-info">
8816
- <h3>Información del Sistema:</h3>
8817
- <p><strong>Idioma actual:</strong> {{ langService.currentLang }}</p>
8818
- <p><strong>Idioma por defecto:</strong> {{ langService.defaultLanguage }}</p>
8819
- <p><strong>Idiomas disponibles:</strong> {{ langService.availableLangs.join(', ') }}</p>
8820
- </div>
8821
-
8822
- <div class="language-switcher">
8823
- <h3>Cambiar Idioma:</h3>
8824
- <div class="button-group">
8825
- <button
8826
- *ngFor="let lang of availableLanguages"
8827
- [class.active]="lang === langService.currentLang"
8828
- (click)="switchLanguage(lang)"
8829
- >
8830
- {{ getLanguageName(lang) }}
8831
- </button>
8832
- <!-- Ejemplo de idioma no disponible -->
8833
- <button (click)="switchLanguage('pt')">Português (no disponible)</button>
8834
- </div>
8835
- </div>
8836
-
8837
- <div class="content-examples">
8838
- <h3>Contenido Global:</h3>
8839
- <div class="example-grid">
8840
- <val-text
8841
- [props]="{ content: okButton$ | async, size: 'medium', color: 'dark', bold: false, processLinks: false }"
8842
- ></val-text>
8843
- <val-text
8844
- [props]="{
8845
- content: cancelButton$ | async,
8846
- size: 'medium',
8847
- color: 'dark',
8848
- bold: false,
8849
- processLinks: false,
8850
- }"
8851
- ></val-text>
8852
- <val-text
8853
- [props]="{ content: saveButton$ | async, size: 'medium', color: 'dark', bold: false, processLinks: false }"
8854
- ></val-text>
8855
- <val-text
8856
- [props]="{
8857
- content: deleteButton$ | async,
8858
- size: 'medium',
8859
- color: 'dark',
8860
- bold: false,
8861
- processLinks: false,
8862
- }"
8863
- ></val-text>
8864
- </div>
8865
-
8866
- <h3>Contenido con Fallback (algunas traducciones faltantes):</h3>
8867
- <div class="example-grid">
8868
- <val-text
8869
- [props]="{ content: nextButton$ | async, size: 'medium', color: 'dark', bold: false, processLinks: false }"
8870
- ></val-text>
8871
- <val-text
8872
- [props]="{
8873
- content: finishButton$ | async,
8874
- size: 'medium',
8875
- color: 'dark',
8876
- bold: false,
8877
- processLinks: false,
8878
- }"
8879
- ></val-text>
8880
- <val-text
8881
- [props]="{
8882
- content: searchPlaceholder$ | async,
8883
- size: 'medium',
8884
- color: 'dark',
8885
- bold: false,
8886
- processLinks: false,
8887
- }"
8888
- ></val-text>
8889
- <val-text
8890
- [props]="{
8891
- content: noDataMessage$ | async,
8892
- size: 'medium',
8893
- color: 'dark',
8894
- bold: false,
8895
- processLinks: false,
8896
- }"
8897
- ></val-text>
8898
- </div>
8899
- </div>
8900
-
8901
- <div class="warning-info">
8902
- <h3>Información de Warnings:</h3>
8903
- <p>
8904
- Abre la consola del navegador para ver los warnings cuando cambies a idiomas con traducciones incompletas
8905
- (francés, alemán).
8906
- </p>
8907
- <p>El sistema automáticamente usará el idioma por defecto o el primer idioma disponible como fallback.</p>
8908
- </div>
8909
-
8910
- <div class="component-analysis">
8911
- <h3>Análisis del Componente:</h3>
8912
- <button (click)="analyzeCurrentComponent()">Analizar Contenido</button>
8913
- <div *ngIf="analysisResults" class="analysis-results">
8914
- <p>
8915
- <strong>Idiomas disponibles para este componente:</strong>
8916
- {{ analysisResults.availableLanguages.join(', ') }}
8917
- </p>
8918
- <div *ngIf="analysisResults.missingKeys.length > 0">
8919
- <p>
8920
- <strong>Claves faltantes en {{ langService.currentLang }}:</strong>
8921
- </p>
8922
- <ul>
8923
- <li *ngFor="let key of analysisResults.missingKeys">{{ key }}</li>
8924
- </ul>
8925
- </div>
8926
- </div>
8927
- </div>
8928
- </div>
8929
- `, styles: [".multi-lang-demo{padding:20px;max-width:800px}.language-info,.content-examples,.warning-info,.component-analysis{margin:20px 0;padding:15px;border:1px solid var(--ion-color-light, #f4f5f8);border-radius:8px;background:var(--ion-color-light-tint, #f5f6f9)}.button-group{display:flex;gap:10px;flex-wrap:wrap}.button-group button{padding:8px 16px;border:1px solid var(--ion-color-primary, #3880ff);background:#fff;color:var(--ion-color-primary, #3880ff);border-radius:4px;cursor:pointer;transition:all .2s}.button-group button:hover{background:var(--ion-color-primary-tint, #4992ff);color:#fff}.button-group button.active{background:var(--ion-color-primary, #3880ff);color:#fff}.example-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin-top:10px}.analysis-results{margin-top:10px;padding:10px;background:#fff;border-radius:4px}h2{color:var(--ion-color-primary, #3880ff)}h3{color:var(--ion-color-dark, #222428);margin-bottom:10px}\n"] }]
8930
- }], ctorParameters: () => [{ type: ContentService }, { type: LangService }] });
8931
-
8932
- /**
8933
- * Simple demo component showcasing reactive content patterns
8934
- * for buttons and alert boxes.
8935
- *
8936
- * Demonstrates:
8937
- * - Button components with reactive text
8938
- * - Alert boxes with reactive content
8939
- * - Language switching
8940
- * - Static vs reactive content patterns
8941
- */
8942
- class ReactiveComponentsDemoComponent {
8943
- constructor(contentService, langService) {
8944
- this.contentService = contentService;
8945
- this.langService = langService;
8946
- this.subscriptions = new Subscription();
8947
- }
8948
- ngOnInit() {
8949
- this.initializeContent();
8950
- this.initializeComponents();
8951
- }
8952
- ngOnDestroy() {
8953
- this.subscriptions.unsubscribe();
8954
- }
8955
- initializeContent() {
8956
- // Page-level content
8957
- this.pageTitle$ = this.contentService.fromContent({
8958
- className: 'reactiveDemo',
8959
- key: 'title',
8960
- fallback: 'Reactive Components Demo',
8961
- });
8962
- this.languageLabel$ = this.contentService.fromContent({
8963
- className: '_global',
8964
- key: 'language',
8965
- fallback: 'Language',
8966
- });
8967
- this.buttonSectionTitle$ = this.contentService.fromContent({
8968
- className: 'reactiveDemo',
8969
- key: 'buttons.title',
8970
- fallback: 'Reactive Buttons',
8971
- });
8972
- this.alertSectionTitle$ = this.contentService.fromContent({
8973
- className: 'reactiveDemo',
8974
- key: 'alerts.title',
8975
- fallback: 'Reactive Alerts',
8976
- });
8977
- // Language state
8978
- this.currentLanguage$ = this.langService.currentLang$;
8979
- this.availableLanguages$ = this.langService.currentLang$.pipe(map(() => this.langService.availableLangs));
8980
- }
8981
- initializeComponents() {
8982
- // Reactive buttons with common actions
8983
- this.saveButton = {
8984
- color: 'primary',
8985
- fill: 'solid',
8986
- type: 'button',
8987
- state: ComponentStates.ENABLED,
8988
- textConfig: {
8989
- className: '_global',
8990
- key: 'save',
8991
- fallback: 'Save',
8992
- },
8993
- handler: () => this.handleSave(),
8994
- };
8995
- this.cancelButton = {
8996
- color: 'medium',
8997
- fill: 'outline',
8998
- type: 'button',
8999
- state: ComponentStates.ENABLED,
9000
- textConfig: {
9001
- className: '_global',
9002
- key: 'cancel',
9003
- fallback: 'Cancel',
9004
- },
9005
- handler: () => this.handleCancel(),
9006
- };
9007
- // Static button for comparison
9008
- this.staticButton = {
9009
- color: 'tertiary',
9010
- fill: 'outline',
9011
- type: 'button',
9012
- state: ComponentStates.ENABLED,
9013
- text: 'Static Button', // Static text
9014
- handler: () => this.handleStatic(),
9015
- };
9016
- // Reactive alert boxes
9017
- this.warningAlert = {
9018
- box: {
9019
- color: 'warning',
9020
- rounded: true,
9021
- bordered: false,
9022
- icon: 'warning',
9023
- },
9024
- icon: {
9025
- name: 'warning',
9026
- color: 'warning',
9027
- size: 'medium',
9028
- },
9029
- textConfig: {
9030
- className: 'reactiveDemo',
9031
- key: 'alerts.warning',
9032
- fallback: 'This is a warning message',
9033
- },
9034
- textStyle: {
9035
- size: 'medium',
9036
- bold: false,
9037
- },
9038
- };
9039
- this.successAlert = {
9040
- box: {
9041
- color: 'success',
9042
- rounded: true,
9043
- bordered: false,
9044
- icon: 'checkmark-circle',
9045
- },
9046
- icon: {
9047
- name: 'checkmark-circle',
9048
- color: 'success',
9049
- size: 'medium',
9050
- },
9051
- textConfig: {
9052
- className: 'reactiveDemo',
9053
- key: 'alerts.success',
9054
- fallback: 'Operation completed successfully!',
9055
- },
9056
- textStyle: {
9057
- size: 'medium',
9058
- bold: true,
9059
- },
9060
- };
9061
- // Static alert for comparison
9062
- this.staticAlert = {
9063
- box: {
9064
- color: 'dark',
9065
- rounded: true,
9066
- bordered: false,
9067
- icon: 'information-circle',
9068
- },
9069
- icon: {
9070
- name: 'information-circle',
9071
- color: 'dark',
9072
- size: 'medium',
9073
- },
9074
- text: 'This is a static alert message', // Static text
9075
- textStyle: {
9076
- size: 'medium',
9077
- bold: false,
9078
- },
9079
- };
9080
- }
9081
- // Event handlers
9082
- changeLanguage(language) {
9083
- this.langService.setLang(language);
9084
- }
9085
- handleSave() {
9086
- console.log('Save button clicked');
9087
- }
9088
- handleCancel() {
9089
- console.log('Cancel button clicked');
9090
- }
9091
- handleStatic() {
9092
- console.log('Static button clicked');
9093
- }
9094
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ReactiveComponentsDemoComponent, deps: [{ token: ContentService }, { token: LangService }], target: i0.ɵɵFactoryTarget.Component }); }
9095
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ReactiveComponentsDemoComponent, isStandalone: true, selector: "val-reactive-components-demo", ngImport: i0, template: `
9096
- <div class="reactive-components-demo">
9097
- <ion-card>
9098
- <ion-card-header>
9099
- <ion-card-title>{{ pageTitle$ | async }}</ion-card-title>
9100
- </ion-card-header>
9101
-
9102
- <ion-card-content>
9103
- <!-- Language Selector -->
9104
- <ion-item>
9105
- <ion-label>{{ languageLabel$ | async }}</ion-label>
9106
- <ion-select
9107
- interface="popover"
9108
- [value]="currentLanguage$ | async"
9109
- (ionChange)="changeLanguage($event.detail.value)"
9110
- >
9111
- <ion-select-option *ngFor="let lang of availableLanguages$ | async" [value]="lang">
9112
- {{ lang | uppercase }}
9113
- </ion-select-option>
9114
- </ion-select>
9115
- </ion-item>
9116
-
9117
- <!-- Reactive Buttons Demo -->
9118
- <div class="section">
9119
- <h3>{{ buttonSectionTitle$ | async }}</h3>
9120
-
9121
- <!-- Common action buttons with reactive text -->
9122
- <div class="button-grid">
9123
- <val-button [props]="saveButton"></val-button>
9124
- <val-button [props]="cancelButton"></val-button>
9125
- <val-button [props]="staticButton"></val-button>
9126
- </div>
9127
- </div>
9128
-
9129
- <!-- Reactive Alert Boxes Demo -->
9130
- <div class="section">
9131
- <h3>{{ alertSectionTitle$ | async }}</h3>
9132
-
9133
- <!-- Alert with reactive content -->
9134
- <val-alert-box [props]="warningAlert"></val-alert-box>
9135
- <val-alert-box [props]="successAlert"></val-alert-box>
9136
- <val-alert-box [props]="staticAlert"></val-alert-box>
9137
- </div>
9138
-
9139
- <!-- Analysis -->
9140
- <div class="section">
9141
- <h3>Analysis</h3>
9142
- <div class="analysis-info">
9143
- <p><strong>Current Language:</strong> {{ currentLanguage$ | async | uppercase }}</p>
9144
- <p><strong>Available Languages:</strong> {{ (availableLanguages$ | async)?.join(', ') | uppercase }}</p>
9145
- </div>
9146
- </div>
9147
- </ion-card-content>
9148
- </ion-card>
9149
- </div>
9150
- `, isInline: true, styles: [".reactive-components-demo{padding:16px}.section{margin:24px 0}.button-grid{display:flex;gap:12px;flex-wrap:wrap;margin:16px 0}.analysis-info{background:var(--ion-color-light);padding:16px;border-radius:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "expandedIcon", "fill", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: AlertBoxComponent, selector: "val-alert-box", inputs: ["props"] }] }); }
9151
- }
9152
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ReactiveComponentsDemoComponent, decorators: [{
9153
- type: Component,
9154
- args: [{ selector: 'val-reactive-components-demo', standalone: true, imports: [
9155
- CommonModule,
9156
- IonCard,
9157
- IonCardContent,
9158
- IonCardHeader,
9159
- IonCardTitle,
9160
- IonSelect,
9161
- IonSelectOption,
9162
- IonItem,
9163
- IonLabel,
9164
- ButtonComponent,
9165
- AlertBoxComponent,
9166
- ], template: `
9167
- <div class="reactive-components-demo">
9168
- <ion-card>
9169
- <ion-card-header>
9170
- <ion-card-title>{{ pageTitle$ | async }}</ion-card-title>
9171
- </ion-card-header>
9172
-
9173
- <ion-card-content>
9174
- <!-- Language Selector -->
9175
- <ion-item>
9176
- <ion-label>{{ languageLabel$ | async }}</ion-label>
9177
- <ion-select
9178
- interface="popover"
9179
- [value]="currentLanguage$ | async"
9180
- (ionChange)="changeLanguage($event.detail.value)"
9181
- >
9182
- <ion-select-option *ngFor="let lang of availableLanguages$ | async" [value]="lang">
9183
- {{ lang | uppercase }}
9184
- </ion-select-option>
9185
- </ion-select>
9186
- </ion-item>
9187
-
9188
- <!-- Reactive Buttons Demo -->
9189
- <div class="section">
9190
- <h3>{{ buttonSectionTitle$ | async }}</h3>
9191
-
9192
- <!-- Common action buttons with reactive text -->
9193
- <div class="button-grid">
9194
- <val-button [props]="saveButton"></val-button>
9195
- <val-button [props]="cancelButton"></val-button>
9196
- <val-button [props]="staticButton"></val-button>
9197
- </div>
9198
- </div>
9199
-
9200
- <!-- Reactive Alert Boxes Demo -->
9201
- <div class="section">
9202
- <h3>{{ alertSectionTitle$ | async }}</h3>
9203
-
9204
- <!-- Alert with reactive content -->
9205
- <val-alert-box [props]="warningAlert"></val-alert-box>
9206
- <val-alert-box [props]="successAlert"></val-alert-box>
9207
- <val-alert-box [props]="staticAlert"></val-alert-box>
9208
- </div>
9209
-
9210
- <!-- Analysis -->
9211
- <div class="section">
9212
- <h3>Analysis</h3>
9213
- <div class="analysis-info">
9214
- <p><strong>Current Language:</strong> {{ currentLanguage$ | async | uppercase }}</p>
9215
- <p><strong>Available Languages:</strong> {{ (availableLanguages$ | async)?.join(', ') | uppercase }}</p>
9216
- </div>
9217
- </div>
9218
- </ion-card-content>
9219
- </ion-card>
9220
- </div>
9221
- `, styles: [".reactive-components-demo{padding:16px}.section{margin:24px 0}.button-grid{display:flex;gap:12px;flex-wrap:wrap;margin:16px 0}.analysis-info{background:var(--ion-color-light);padding:16px;border-radius:8px}\n"] }]
9222
- }], ctorParameters: () => [{ type: ContentService }, { type: LangService }] });
9223
-
9224
- /**
9225
- * Test component to diagnose reactive content behavior.
9226
- * Compares fromContent vs fromMultipleContent reactivity.
9227
- */
9228
- class ReactivityTestComponent {
9229
- constructor() {
9230
- this.contentService = inject(ContentService);
9231
- this.langService = inject(LangService);
9232
- // Observable for current language
9233
- this.currentLang$ = this.langService.currentLang$;
9234
- // Single key content observables (using fromContent)
9235
- this.singleWelcome$ = this.contentService.fromContent({
9236
- className: 'testReactivity',
9237
- key: 'welcomeMessage',
9238
- fallback: 'Welcome',
9239
- });
9240
- this.singleSave$ = this.contentService.fromContent({
9241
- className: 'testReactivity',
9242
- key: 'saveButton',
9243
- fallback: 'Save',
9244
- });
9245
- this.singleCancel$ = this.contentService.fromContent({
9246
- className: 'testReactivity',
9247
- key: 'cancelButton',
9248
- fallback: 'Cancel',
9249
- });
9250
- // Multiple keys content observable (using fromMultipleContent)
9251
- this.multipleContent$ = this.contentService.fromMultipleContent('testReactivity', [
9252
- 'welcomeMessage',
9253
- 'saveButton',
9254
- 'cancelButton',
9255
- ]);
9256
- // Direct LangService tests
9257
- this.directSingle$ = this.langService.getContent('testReactivity', 'welcomeMessage', 'Welcome');
9258
- this.directMultiple$ = this.langService.getMultipleContent('testReactivity', ['welcomeMessage']);
9259
- // Update counters
9260
- this.singleUpdateCount = 0;
9261
- this.multipleUpdateCount = 0;
9262
- this.directSingleUpdateCount = 0;
9263
- this.directMultipleUpdateCount = 0;
9264
- }
9265
- ngOnInit() {
9266
- // Subscribe to observables to count updates
9267
- this.singleWelcome$.subscribe(() => {
9268
- this.singleUpdateCount++;
9269
- console.log('Single key updated:', this.singleUpdateCount);
9270
- });
9271
- this.multipleContent$.subscribe(() => {
9272
- this.multipleUpdateCount++;
9273
- console.log('Multiple keys updated:', this.multipleUpdateCount);
9274
- });
9275
- this.directSingle$.subscribe(() => {
9276
- this.directSingleUpdateCount++;
9277
- console.log('Direct single updated:', this.directSingleUpdateCount);
9278
- });
9279
- this.directMultiple$.subscribe(() => {
9280
- this.directMultipleUpdateCount++;
9281
- console.log('Direct multiple updated:', this.directMultipleUpdateCount);
9282
- });
9283
- }
9284
- switchToSpanish() {
9285
- this.langService.setLang('es');
9286
- }
9287
- switchToEnglish() {
9288
- this.langService.setLang('en');
9289
- }
9290
- switchToFrench() {
9291
- this.langService.setLang('fr');
9292
- }
9293
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ReactivityTestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9294
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ReactivityTestComponent, isStandalone: true, selector: "val-reactivity-test", ngImport: i0, template: `
9295
- <div style="padding: 20px; border: 1px solid #ccc; margin: 10px;">
9296
- <h3>Reactivity Test Component</h3>
9297
-
9298
- <!-- Current Language -->
9299
- <div style="margin-bottom: 20px;"><strong>Current Language:</strong> {{ currentLang$ | async }}</div>
9300
-
9301
- <!-- Language Switch Buttons -->
9302
- <div style="margin-bottom: 20px;">
9303
- <button (click)="switchToSpanish()" style="margin-right: 10px;">Switch to ES</button>
9304
- <button (click)="switchToEnglish()" style="margin-right: 10px;">Switch to EN</button>
9305
- <button (click)="switchToFrench()">Switch to FR</button>
9306
- </div>
9307
-
9308
- <!-- Single Key Tests -->
9309
- <div style="margin-bottom: 20px;">
9310
- <h4>Single Key Tests (fromContent)</h4>
9311
- <div><strong>welcomeMessage (fromContent):</strong> {{ singleWelcome$ | async }}</div>
9312
- <div><strong>saveButton (fromContent):</strong> {{ singleSave$ | async }}</div>
9313
- <div><strong>cancelButton (fromContent):</strong> {{ singleCancel$ | async }}</div>
9314
- </div>
9315
-
9316
- <!-- Multiple Keys Test -->
9317
- <div style="margin-bottom: 20px;">
9318
- <h4>Multiple Keys Test (fromMultipleContent)</h4>
9319
- <div>
9320
- <strong>welcomeMessage (multiple):</strong>
9321
- {{ (multipleContent$ | async)?.['welcomeMessage'] || 'Loading...' }}
9322
- </div>
9323
- <div>
9324
- <strong>saveButton (multiple):</strong> {{ (multipleContent$ | async)?.['saveButton'] || 'Loading...' }}
9325
- </div>
9326
- <div>
9327
- <strong>cancelButton (multiple):</strong> {{ (multipleContent$ | async)?.['cancelButton'] || 'Loading...' }}
9328
- </div>
9329
- </div>
9330
-
9331
- <!-- Direct LangService Tests -->
9332
- <div style="margin-bottom: 20px;">
9333
- <h4>Direct LangService Tests</h4>
9334
- <div><strong>welcomeMessage (direct single):</strong> {{ directSingle$ | async }}</div>
9335
- <div>
9336
- <strong>welcomeMessage (direct multiple):</strong>
9337
- {{ (directMultiple$ | async)?.['welcomeMessage'] || 'Loading...' }}
9338
- </div>
9339
- </div>
9340
-
9341
- <!-- Update Counter -->
9342
- <div>
9343
- <h4>Update Counters</h4>
9344
- <div><strong>Single key updates:</strong> {{ singleUpdateCount }}</div>
9345
- <div><strong>Multiple keys updates:</strong> {{ multipleUpdateCount }}</div>
9346
- <div><strong>Direct single updates:</strong> {{ directSingleUpdateCount }}</div>
9347
- <div><strong>Direct multiple updates:</strong> {{ directMultipleUpdateCount }}</div>
9348
- </div>
9349
- </div>
9350
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); }
9351
- }
9352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ReactivityTestComponent, decorators: [{
9353
- type: Component,
9354
- args: [{
9355
- selector: 'val-reactivity-test',
9356
- standalone: true,
9357
- imports: [CommonModule],
9358
- template: `
9359
- <div style="padding: 20px; border: 1px solid #ccc; margin: 10px;">
9360
- <h3>Reactivity Test Component</h3>
9361
-
9362
- <!-- Current Language -->
9363
- <div style="margin-bottom: 20px;"><strong>Current Language:</strong> {{ currentLang$ | async }}</div>
9364
-
9365
- <!-- Language Switch Buttons -->
9366
- <div style="margin-bottom: 20px;">
9367
- <button (click)="switchToSpanish()" style="margin-right: 10px;">Switch to ES</button>
9368
- <button (click)="switchToEnglish()" style="margin-right: 10px;">Switch to EN</button>
9369
- <button (click)="switchToFrench()">Switch to FR</button>
9370
- </div>
9371
-
9372
- <!-- Single Key Tests -->
9373
- <div style="margin-bottom: 20px;">
9374
- <h4>Single Key Tests (fromContent)</h4>
9375
- <div><strong>welcomeMessage (fromContent):</strong> {{ singleWelcome$ | async }}</div>
9376
- <div><strong>saveButton (fromContent):</strong> {{ singleSave$ | async }}</div>
9377
- <div><strong>cancelButton (fromContent):</strong> {{ singleCancel$ | async }}</div>
9378
- </div>
9379
-
9380
- <!-- Multiple Keys Test -->
9381
- <div style="margin-bottom: 20px;">
9382
- <h4>Multiple Keys Test (fromMultipleContent)</h4>
9383
- <div>
9384
- <strong>welcomeMessage (multiple):</strong>
9385
- {{ (multipleContent$ | async)?.['welcomeMessage'] || 'Loading...' }}
9386
- </div>
9387
- <div>
9388
- <strong>saveButton (multiple):</strong> {{ (multipleContent$ | async)?.['saveButton'] || 'Loading...' }}
9389
- </div>
9390
- <div>
9391
- <strong>cancelButton (multiple):</strong> {{ (multipleContent$ | async)?.['cancelButton'] || 'Loading...' }}
9392
- </div>
9393
- </div>
9394
-
9395
- <!-- Direct LangService Tests -->
9396
- <div style="margin-bottom: 20px;">
9397
- <h4>Direct LangService Tests</h4>
9398
- <div><strong>welcomeMessage (direct single):</strong> {{ directSingle$ | async }}</div>
9399
- <div>
9400
- <strong>welcomeMessage (direct multiple):</strong>
9401
- {{ (directMultiple$ | async)?.['welcomeMessage'] || 'Loading...' }}
9402
- </div>
9403
- </div>
9404
-
9405
- <!-- Update Counter -->
9406
- <div>
9407
- <h4>Update Counters</h4>
9408
- <div><strong>Single key updates:</strong> {{ singleUpdateCount }}</div>
9409
- <div><strong>Multiple keys updates:</strong> {{ multipleUpdateCount }}</div>
9410
- <div><strong>Direct single updates:</strong> {{ directSingleUpdateCount }}</div>
9411
- <div><strong>Direct multiple updates:</strong> {{ directMultipleUpdateCount }}</div>
9412
- </div>
9413
- </div>
9414
- `,
9415
- }]
9416
- }] });
9417
-
9418
- /**
9419
- * Ejemplo de uso de los componentes popover-selector y language-selector
9420
- */
9421
- class SelectorExamplesComponent {
9422
- constructor() {
9423
- // ✅ Ejemplos de Popover Selector Genérico
9424
- this.categorySelector = {
9425
- options: [
9426
- { value: 'work', label: 'Trabajo', icon: 'briefcase' },
9427
- { value: 'personal', label: 'Personal', icon: 'person' },
9428
- { value: 'travel', label: 'Viajes', icon: 'airplane' },
9429
- { value: 'health', label: 'Salud', icon: 'fitness' },
9430
- ],
9431
- selectedValue: 'work',
9432
- label: 'Categoría',
9433
- icon: 'folder',
9434
- color: 'primary',
9435
- size: 'default',
9436
- fill: 'outline',
9437
- };
9438
- this.prioritySelector = {
9439
- options: [
9440
- { value: 'low', label: 'Baja', icon: 'arrow-down', disabled: false },
9441
- { value: 'medium', label: 'Media', icon: 'remove' },
9442
- { value: 'high', label: 'Alta', icon: 'arrow-up' },
9443
- { value: 'urgent', label: 'Urgente', icon: 'warning' },
9444
- ],
9445
- selectedValue: 'medium',
9446
- label: 'Prioridad',
9447
- icon: 'flag',
9448
- color: 'warning',
9449
- size: 'large',
9450
- fill: 'solid',
9451
- shape: 'round',
9452
- };
9453
- this.multipleSelector = {
9454
- options: [
9455
- { value: 'email', label: 'Email', icon: 'mail' },
9456
- { value: 'sms', label: 'SMS', icon: 'chatbox' },
9457
- { value: 'push', label: 'Push', icon: 'notifications' },
9458
- { value: 'in-app', label: 'In-App', icon: 'apps' },
9459
- ],
9460
- selectedValue: ['email', 'push'],
9461
- label: 'Notificaciones',
9462
- icon: 'notifications-circle',
9463
- multiple: true,
9464
- color: 'tertiary',
9465
- size: 'default',
9466
- fill: 'outline',
9467
- showCheckmark: true,
9468
- };
9469
- // ✅ Ejemplos de Language Selector (con soporte multiidioma)
9470
- // Los nombres de idiomas se obtienen automáticamente del sistema de contenido
9471
- // y se muestran traducidos según el idioma actual de la aplicación
9472
- this.basicLanguageSelector = {
9473
- showLabel: true,
9474
- label: 'Idioma',
9475
- color: 'medium',
9476
- size: 'default',
9477
- fill: 'outline',
9478
- };
9479
- // Con banderas y nombres traducidos automáticamente
9480
- this.flagLanguageSelector = {
9481
- showLabel: true,
9482
- label: 'Language / Idioma',
9483
- showFlags: true,
9484
- color: 'primary',
9485
- size: 'large',
9486
- fill: 'solid',
9487
- };
9488
- // Con nombres personalizados (sobrescribe las traducciones automáticas)
9489
- this.customLanguageSelector = {
9490
- showLabel: true,
9491
- labelConfig: {
9492
- className: '_global',
9493
- key: 'language',
9494
- fallback: 'Idioma',
9495
- },
9496
- showFlags: true,
9497
- color: 'secondary',
9498
- size: 'default',
9499
- fill: 'outline',
9500
- shape: 'round',
9501
- customLanguageNames: {
9502
- es: 'Español (España)',
9503
- en: 'English (US)',
9504
- fr: 'Français',
9505
- de: 'Deutsch',
9506
- },
9507
- };
9508
- // Compacto sin etiqueta, solo banderas y nombres traducidos
9509
- this.compactLanguageSelector = {
9510
- showLabel: false,
9511
- showFlags: true,
9512
- color: 'tertiary',
9513
- size: 'small',
9514
- fill: 'clear',
9515
- };
9516
- }
9517
- // ✅ Event Handlers
9518
- onCategoryChange(category) {
9519
- console.log('Category changed:', category);
9520
- }
9521
- onPriorityChange(priority) {
9522
- console.log('Priority changed:', priority);
9523
- }
9524
- onMultipleChange(notifications) {
9525
- console.log('Notifications changed:', notifications);
9526
- }
9527
- onLanguageChange(language) {
9528
- console.log('Language changed to:', language);
9529
- // La aplicación automáticamente actualizará todos los nombres de idiomas
9530
- // según la nueva configuración de idioma seleccionada
9531
- }
9532
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectorExamplesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9533
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SelectorExamplesComponent, isStandalone: true, selector: "app-selector-examples", ngImport: i0, template: `
9534
- <div class="selector-examples">
9535
- <h2>Ejemplos de Selectores</h2>
9536
-
9537
- <!-- Popover Selector Genérico -->
9538
- <div class="section">
9539
- <h3>Popover Selector Genérico</h3>
9540
-
9541
- <div class="example-group">
9542
- <h4>Selector de Categorías:</h4>
9543
- <val-popover-selector [props]="categorySelector" (selectionChange)="onCategoryChange($event)">
9544
- </val-popover-selector>
9545
- </div>
9546
-
9547
- <div class="example-group">
9548
- <h4>Selector de Prioridad:</h4>
9549
- <val-popover-selector [props]="prioritySelector" (selectionChange)="onPriorityChange($event)">
9550
- </val-popover-selector>
9551
- </div>
9552
-
9553
- <div class="example-group">
9554
- <h4>Selector Múltiple:</h4>
9555
- <val-popover-selector [props]="multipleSelector" (selectionChange)="onMultipleChange($event)">
9556
- </val-popover-selector>
9557
- </div>
9558
- </div>
9559
-
9560
- <!-- Language Selector -->
9561
- <div class="section">
9562
- <h3>Selector de Idioma (Multiidioma)</h3>
9563
- <p>Los nombres de idiomas se muestran traducidos según el idioma actual:</p>
9564
-
9565
- <div class="example-group">
9566
- <h4>Selector Básico (nombres traducidos):</h4>
9567
- <val-language-selector [props]="basicLanguageSelector"> </val-language-selector>
9568
- </div>
9569
-
9570
- <div class="example-group">
9571
- <h4>Selector con Banderas (nombres traducidos):</h4>
9572
- <val-language-selector [props]="flagLanguageSelector"> </val-language-selector>
9573
- </div>
9574
-
9575
- <div class="example-group">
9576
- <h4>Selector Personalizado (nombres propios):</h4>
9577
- <val-language-selector [props]="customLanguageSelector" (languageChange)="onLanguageChange($event)">
9578
- </val-language-selector>
9579
- </div>
9580
-
9581
- <div class="example-group">
9582
- <h4>Selector Compacto:</h4>
9583
- <val-language-selector [props]="compactLanguageSelector"> </val-language-selector>
9584
- </div>
9585
- </div>
9586
- </div>
9587
- `, isInline: true, styles: [".selector-examples{padding:20px;max-width:800px;margin:0 auto}.section{margin:30px 0;padding:20px;border:1px solid var(--ion-color-light);border-radius:8px;background:var(--ion-color-step-50)}.section h3{margin:0 0 20px;color:var(--ion-color-primary)}.example-group{margin:20px 0;padding:15px;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.example-group h4{margin:0 0 15px;color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "component", type: PopoverSelectorComponent, selector: "val-popover-selector", inputs: ["props"], outputs: ["selectionChange"] }, { kind: "component", type: LanguageSelectorComponent, selector: "val-language-selector", inputs: ["props"], outputs: ["languageChange"] }] }); }
9588
- }
9589
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectorExamplesComponent, decorators: [{
9590
- type: Component,
9591
- args: [{ selector: 'app-selector-examples', standalone: true, imports: [PopoverSelectorComponent, LanguageSelectorComponent], template: `
9592
- <div class="selector-examples">
9593
- <h2>Ejemplos de Selectores</h2>
9594
-
9595
- <!-- Popover Selector Genérico -->
9596
- <div class="section">
9597
- <h3>Popover Selector Genérico</h3>
9598
-
9599
- <div class="example-group">
9600
- <h4>Selector de Categorías:</h4>
9601
- <val-popover-selector [props]="categorySelector" (selectionChange)="onCategoryChange($event)">
9602
- </val-popover-selector>
9603
- </div>
9604
-
9605
- <div class="example-group">
9606
- <h4>Selector de Prioridad:</h4>
9607
- <val-popover-selector [props]="prioritySelector" (selectionChange)="onPriorityChange($event)">
9608
- </val-popover-selector>
9609
- </div>
9610
-
9611
- <div class="example-group">
9612
- <h4>Selector Múltiple:</h4>
9613
- <val-popover-selector [props]="multipleSelector" (selectionChange)="onMultipleChange($event)">
9614
- </val-popover-selector>
9615
- </div>
9616
- </div>
9617
-
9618
- <!-- Language Selector -->
9619
- <div class="section">
9620
- <h3>Selector de Idioma (Multiidioma)</h3>
9621
- <p>Los nombres de idiomas se muestran traducidos según el idioma actual:</p>
9622
-
9623
- <div class="example-group">
9624
- <h4>Selector Básico (nombres traducidos):</h4>
9625
- <val-language-selector [props]="basicLanguageSelector"> </val-language-selector>
9626
- </div>
9627
-
9628
- <div class="example-group">
9629
- <h4>Selector con Banderas (nombres traducidos):</h4>
9630
- <val-language-selector [props]="flagLanguageSelector"> </val-language-selector>
9631
- </div>
9632
-
9633
- <div class="example-group">
9634
- <h4>Selector Personalizado (nombres propios):</h4>
9635
- <val-language-selector [props]="customLanguageSelector" (languageChange)="onLanguageChange($event)">
9636
- </val-language-selector>
9637
- </div>
9638
-
9639
- <div class="example-group">
9640
- <h4>Selector Compacto:</h4>
9641
- <val-language-selector [props]="compactLanguageSelector"> </val-language-selector>
9642
- </div>
9643
- </div>
9644
- </div>
9645
- `, styles: [".selector-examples{padding:20px;max-width:800px;margin:0 auto}.section{margin:30px 0;padding:20px;border:1px solid var(--ion-color-light);border-radius:8px;background:var(--ion-color-step-50)}.section h3{margin:0 0 20px;color:var(--ion-color-primary)}.example-group{margin:20px 0;padding:15px;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.example-group h4{margin:0 0 15px;color:var(--ion-color-medium)}\n"] }]
9646
- }] });
9647
-
9648
- /**
9649
- * Simple test component to diagnose the user's specific issue.
9650
- * Tests the exact pattern the user is using.
9651
- */
9652
- class UserIssueTestComponent {
9653
- constructor() {
9654
- this.contentService = inject(ContentService);
9655
- this.langService = inject(LangService);
9656
- // Current language observable
9657
- this.currentLang$ = this.langService.currentLang$;
9658
- // Direct ContentService pattern (what user is trying)
9659
- this.saveButtonDirect$ = this.contentService.fromContent({ key: 'save' });
9660
- this.cancelButtonDirect$ = this.contentService.fromContent({ key: 'cancel' });
9661
- // ContentHelper pattern (user's alternative)
9662
- this.contentHelper = this.contentService.forComponent('_global');
9663
- this.saveButtonHelper$ = this.contentHelper.get('save');
9664
- this.cancelButtonHelper$ = this.contentHelper.get('cancel');
9665
- // Direct LangService for comparison
9666
- this.saveButtonLang$ = this.langService.getContent('_global', 'save');
9667
- this.cancelButtonLang$ = this.langService.getContent('_global', 'cancel');
9668
- // Update counters
9669
- this.directUpdateCount = 0;
9670
- this.helperUpdateCount = 0;
9671
- this.langServiceUpdateCount = 0;
9672
- }
9673
- ngOnInit() {
9674
- console.log('UserIssueTestComponent: Initializing...');
9675
- // Subscribe to count updates
9676
- this.saveButtonDirect$.subscribe(value => {
9677
- this.directUpdateCount++;
9678
- console.log('Direct fromContent updated:', value, 'Count:', this.directUpdateCount);
9679
- });
9680
- this.saveButtonHelper$.subscribe(value => {
9681
- this.helperUpdateCount++;
9682
- console.log('Helper updated:', value, 'Count:', this.helperUpdateCount);
9683
- });
9684
- this.saveButtonLang$.subscribe(value => {
9685
- this.langServiceUpdateCount++;
9686
- console.log('LangService updated:', value, 'Count:', this.langServiceUpdateCount);
9687
- });
9688
- // Log initial state
9689
- console.log('Current language:', this.langService.currentLang);
9690
- console.log('Available languages:', this.langService.availableLangs);
9691
- console.log('Has save content:', this.langService.hasContent('_global', 'save'));
9692
- console.log('Has cancel content:', this.langService.hasContent('_global', 'cancel'));
9693
- }
9694
- switchToSpanish() {
9695
- console.log('Switching to Spanish...');
9696
- this.langService.setLang('es');
9697
- }
9698
- switchToEnglish() {
9699
- console.log('Switching to English...');
9700
- this.langService.setLang('en');
9701
- }
9702
- // Synchronous methods for debugging
9703
- getSaveTextSync() {
9704
- return this.contentService.getText('save', 'Save (fallback)');
9705
- }
9706
- getCancelTextSync() {
9707
- return this.contentService.getText('cancel', 'Cancel (fallback)');
9708
- }
9709
- getAvailableLanguages() {
9710
- return this.langService.availableLangs.join(', ');
9711
- }
9712
- hasContentSave() {
9713
- return this.langService.hasContent('_global', 'save');
9714
- }
9715
- hasContentCancel() {
9716
- return this.langService.hasContent('_global', 'cancel');
9717
- }
9718
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserIssueTestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9719
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: UserIssueTestComponent, isStandalone: true, selector: "val-user-issue-test", ngImport: i0, template: `
9720
- <div style="padding: 20px; border: 2px solid #007bff; margin: 10px; border-radius: 8px;">
9721
- <h3>User Issue Test - Exact Pattern</h3>
9722
-
9723
- <!-- Current Language Display -->
9724
- <div style="margin-bottom: 20px; padding: 10px; background: #f0f8ff; border-radius: 4px;">
9725
- <strong>Current Language:</strong> {{ currentLang$ | async }}
9726
- </div>
9727
-
9728
- <!-- Language Switch Buttons -->
9729
- <div style="margin-bottom: 20px;">
9730
- <button
9731
- (click)="switchToSpanish()"
9732
- style="margin-right: 10px; padding: 8px 16px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;"
9733
- >
9734
- Switch to ES
9735
- </button>
9736
- <button
9737
- (click)="switchToEnglish()"
9738
- style="margin-right: 10px; padding: 8px 16px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;"
9739
- >
9740
- Switch to EN
9741
- </button>
9742
- </div>
9743
-
9744
- <!-- Direct ContentService Tests -->
9745
- <div style="margin-bottom: 20px; padding: 10px; background: #fff3cd; border-radius: 4px;">
9746
- <h4>Direct ContentService fromContent (user's pattern)</h4>
9747
- <div>
9748
- <strong>Save Button:</strong>
9749
- <ng-container *ngIf="saveButtonDirect$ | async as save; else loading">{{ save }}</ng-container>
9750
- </div>
9751
- <div>
9752
- <strong>Cancel Button:</strong>
9753
- <ng-container *ngIf="cancelButtonDirect$ | async as cancel; else loading">{{ cancel }}</ng-container>
9754
- </div>
9755
- </div>
9756
-
9757
- <!-- ContentHelper Tests -->
9758
- <div style="margin-bottom: 20px; padding: 10px; background: #d1ecf1; border-radius: 4px;">
9759
- <h4>ContentHelper forComponent (user's helper)</h4>
9760
- <div>
9761
- <strong>Save Button:</strong>
9762
- <ng-container *ngIf="saveButtonHelper$ | async as save; else loading">{{ save }}</ng-container>
9763
- </div>
9764
- <div>
9765
- <strong>Cancel Button:</strong>
9766
- <ng-container *ngIf="cancelButtonHelper$ | async as cancel; else loading">{{ cancel }}</ng-container>
9767
- </div>
9768
- </div>
9769
-
9770
- <!-- Direct LangService Tests -->
9771
- <div style="margin-bottom: 20px; padding: 10px; background: '#d4edda'; border-radius: 4px;">
9772
- <h4>Direct LangService (for comparison)</h4>
9773
- <div>
9774
- <strong>Save Button:</strong>
9775
- <ng-container *ngIf="saveButtonLang$ | async as save; else loading">{{ save }}</ng-container>
9776
- </div>
9777
- <div>
9778
- <strong>Cancel Button:</strong>
9779
- <ng-container *ngIf="cancelButtonLang$ | async as cancel; else loading">{{ cancel }}</ng-container>
9780
- </div>
9781
- </div>
9782
-
9783
- <ng-template #loading>Loading...</ng-template>
9784
-
9785
- <!-- Synchronous Tests -->
9786
- <div style="margin-bottom: 20px; padding: 10px; background: #f8d7da; border-radius: 4px;">
9787
- <h4>Synchronous getText (for reference)</h4>
9788
- <div><strong>Save Button (sync):</strong> {{ getSaveTextSync() }}</div>
9789
- <div><strong>Cancel Button (sync):</strong> {{ getCancelTextSync() }}</div>
9790
- </div>
9791
-
9792
- <!-- Debug Information -->
9793
- <div style="margin-bottom: 20px; padding: 10px; background: #e2e3e5; border-radius: 4px;">
9794
- <h4>Debug Info</h4>
9795
- <div><strong>Available Languages:</strong> {{ getAvailableLanguages() }}</div>
9796
- <div><strong>Has 'save' content:</strong> {{ hasContentSave() }}</div>
9797
- <div><strong>Has 'cancel' content:</strong> {{ hasContentCancel() }}</div>
9798
- </div>
9799
-
9800
- <!-- Update Counters -->
9801
- <div style="padding: 10px; background: #fff; border: 1px solid #dee2e6; border-radius: 4px;">
9802
- <h4>Update Counters (should increment on language change)</h4>
9803
- <div><strong>Direct fromContent updates:</strong> {{ directUpdateCount }}</div>
9804
- <div><strong>Helper updates:</strong> {{ helperUpdateCount }}</div>
9805
- <div><strong>LangService updates:</strong> {{ langServiceUpdateCount }}</div>
9806
- </div>
9807
- </div>
9808
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); }
9809
- }
9810
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserIssueTestComponent, decorators: [{
9811
- type: Component,
9812
- args: [{
9813
- selector: 'val-user-issue-test',
9814
- standalone: true,
9815
- imports: [CommonModule],
9816
- template: `
9817
- <div style="padding: 20px; border: 2px solid #007bff; margin: 10px; border-radius: 8px;">
9818
- <h3>User Issue Test - Exact Pattern</h3>
9819
-
9820
- <!-- Current Language Display -->
9821
- <div style="margin-bottom: 20px; padding: 10px; background: #f0f8ff; border-radius: 4px;">
9822
- <strong>Current Language:</strong> {{ currentLang$ | async }}
9823
- </div>
9824
-
9825
- <!-- Language Switch Buttons -->
9826
- <div style="margin-bottom: 20px;">
9827
- <button
9828
- (click)="switchToSpanish()"
9829
- style="margin-right: 10px; padding: 8px 16px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;"
9830
- >
9831
- Switch to ES
9832
- </button>
9833
- <button
9834
- (click)="switchToEnglish()"
9835
- style="margin-right: 10px; padding: 8px 16px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;"
9836
- >
9837
- Switch to EN
9838
- </button>
9839
- </div>
9840
-
9841
- <!-- Direct ContentService Tests -->
9842
- <div style="margin-bottom: 20px; padding: 10px; background: #fff3cd; border-radius: 4px;">
9843
- <h4>Direct ContentService fromContent (user's pattern)</h4>
9844
- <div>
9845
- <strong>Save Button:</strong>
9846
- <ng-container *ngIf="saveButtonDirect$ | async as save; else loading">{{ save }}</ng-container>
9847
- </div>
9848
- <div>
9849
- <strong>Cancel Button:</strong>
9850
- <ng-container *ngIf="cancelButtonDirect$ | async as cancel; else loading">{{ cancel }}</ng-container>
9851
- </div>
9852
- </div>
9853
-
9854
- <!-- ContentHelper Tests -->
9855
- <div style="margin-bottom: 20px; padding: 10px; background: #d1ecf1; border-radius: 4px;">
9856
- <h4>ContentHelper forComponent (user's helper)</h4>
9857
- <div>
9858
- <strong>Save Button:</strong>
9859
- <ng-container *ngIf="saveButtonHelper$ | async as save; else loading">{{ save }}</ng-container>
9860
- </div>
9861
- <div>
9862
- <strong>Cancel Button:</strong>
9863
- <ng-container *ngIf="cancelButtonHelper$ | async as cancel; else loading">{{ cancel }}</ng-container>
9864
- </div>
9865
- </div>
9866
-
9867
- <!-- Direct LangService Tests -->
9868
- <div style="margin-bottom: 20px; padding: 10px; background: '#d4edda'; border-radius: 4px;">
9869
- <h4>Direct LangService (for comparison)</h4>
9870
- <div>
9871
- <strong>Save Button:</strong>
9872
- <ng-container *ngIf="saveButtonLang$ | async as save; else loading">{{ save }}</ng-container>
9873
- </div>
9874
- <div>
9875
- <strong>Cancel Button:</strong>
9876
- <ng-container *ngIf="cancelButtonLang$ | async as cancel; else loading">{{ cancel }}</ng-container>
9877
- </div>
9878
- </div>
9879
-
9880
- <ng-template #loading>Loading...</ng-template>
9881
-
9882
- <!-- Synchronous Tests -->
9883
- <div style="margin-bottom: 20px; padding: 10px; background: #f8d7da; border-radius: 4px;">
9884
- <h4>Synchronous getText (for reference)</h4>
9885
- <div><strong>Save Button (sync):</strong> {{ getSaveTextSync() }}</div>
9886
- <div><strong>Cancel Button (sync):</strong> {{ getCancelTextSync() }}</div>
9887
- </div>
9888
-
9889
- <!-- Debug Information -->
9890
- <div style="margin-bottom: 20px; padding: 10px; background: #e2e3e5; border-radius: 4px;">
9891
- <h4>Debug Info</h4>
9892
- <div><strong>Available Languages:</strong> {{ getAvailableLanguages() }}</div>
9893
- <div><strong>Has 'save' content:</strong> {{ hasContentSave() }}</div>
9894
- <div><strong>Has 'cancel' content:</strong> {{ hasContentCancel() }}</div>
9895
- </div>
9896
-
9897
- <!-- Update Counters -->
9898
- <div style="padding: 10px; background: #fff; border: 1px solid #dee2e6; border-radius: 4px;">
9899
- <h4>Update Counters (should increment on language change)</h4>
9900
- <div><strong>Direct fromContent updates:</strong> {{ directUpdateCount }}</div>
9901
- <div><strong>Helper updates:</strong> {{ helperUpdateCount }}</div>
9902
- <div><strong>LangService updates:</strong> {{ langServiceUpdateCount }}</div>
9903
- </div>
9904
- </div>
9905
- `,
9906
- }]
9907
- }] });
9908
-
9909
- const text = {
9910
- es: {
9911
- spanish: 'Español',
9912
- english: 'Inglés',
9913
- },
9914
- en: {
9915
- spanish: 'Spanish',
9916
- english: 'English',
9917
- },
9918
- };
9919
- var LangSettings = new TextContent(text);
9920
-
9921
- /**
9922
- * Global content that can be used across all components.
9923
- * These are common texts like buttons, actions, states, etc.
9924
- * Structure: {es: {key1: 'value1', key2: 'value2'}, en: {key1: 'value1', key2: 'value2'}, fr: {...}}
9925
- *
9926
- * Note: You can add any language code. The system will automatically detect available languages
9927
- * and provide intelligent fallbacks with warnings for missing translations.
7293
+ * Global content that can be used across all components.
7294
+ * These are common texts like buttons, actions, states, etc.
7295
+ * Structure: {es: {key1: 'value1', key2: 'value2'}, en: {key1: 'value1', key2: 'value2'}, fr: {...}}
7296
+ *
7297
+ * Note: You can add any language code. The system will automatically detect available languages
7298
+ * and provide intelligent fallbacks with warnings for missing translations.
9928
7299
  */
9929
7300
  const globalContentData = {
9930
7301
  es: {
@@ -10021,60 +7392,6 @@ const globalContentData = {
10021
7392
  // Common placeholders
10022
7393
  searchPlaceholder: 'Search...',
10023
7394
  },
10024
- fr: {
10025
- // Common buttons - Example of partial translation (missing some keys intentionally)
10026
- ok: 'OK',
10027
- cancel: 'Annuler',
10028
- save: 'Sauvegarder',
10029
- delete: 'Supprimer',
10030
- edit: 'Modifier',
10031
- close: 'Fermer',
10032
- back: 'Retour',
10033
- // Common states and messages (intentionally incomplete to show fallback behavior)
10034
- loading: 'Chargement...',
10035
- error: 'Erreur',
10036
- success: 'Succès',
10037
- // Common confirmations
10038
- areYouSure: 'Êtes-vous sûr?',
10039
- // Language names (translated) - flat keys for type compatibility
10040
- languageName_es: 'Espagnol',
10041
- languageName_en: 'Anglais',
10042
- languageName_fr: 'Français',
10043
- languageName_de: 'Allemand',
10044
- languageName_pt: 'Portugais',
10045
- languageName_it: 'Italien',
10046
- languageName_zh: 'Chinois',
10047
- languageName_ja: 'Japonais',
10048
- languageName_ko: 'Coréen',
10049
- languageName_ru: 'Russe',
10050
- languageName_ar: 'Arabe',
10051
- language: 'Langue',
10052
- },
10053
- de: {
10054
- // Common buttons - Another example of partial translation
10055
- ok: 'OK',
10056
- cancel: 'Abbrechen',
10057
- save: 'Speichern',
10058
- delete: 'Löschen',
10059
- // Common states and messages
10060
- loading: 'Laden...',
10061
- error: 'Fehler',
10062
- // Common confirmations
10063
- areYouSure: 'Sind Sie sicher?',
10064
- // Language names (translated) - flat keys for type compatibility
10065
- languageName_es: 'Spanisch',
10066
- languageName_en: 'Englisch',
10067
- languageName_fr: 'Französisch',
10068
- languageName_de: 'Deutsch',
10069
- languageName_pt: 'Portugiesisch',
10070
- languageName_it: 'Italienisch',
10071
- languageName_zh: 'Chinesisch',
10072
- languageName_ja: 'Japanisch',
10073
- languageName_ko: 'Koreanisch',
10074
- languageName_ru: 'Russisch',
10075
- languageName_ar: 'Arabisch',
10076
- language: 'Sprache',
10077
- },
10078
7395
  };
10079
7396
  const GlobalContent = new TextContent(globalContentData);
10080
7397
  const content = {
@@ -10154,5 +7471,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
10154
7471
  * Generated bundle index. Do not edit.
10155
7472
  */
10156
7473
 
10157
- export { ActionType, AlertBoxComponent, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, ButtonComponent, ButtonGroupComponent, CardComponent, CardSection, CardType, CheckInputComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CommentInputComponent, ComponentContentHelper, ComponentStates, ComprehensiveLinkTestComponent, ContentLoaderComponent, ContentService, CustomContentDemoComponent, DateInputComponent, DisplayComponent, DisplayDemoComponent, DisplayExampleComponent, DividerComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FileInputComponent, FooterComponent, FormComponent, FormFooterComponent, GlobalContent, HeaderComponent, HintComponent, HourInputComponent, HrefComponent, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InputType, ItemListComponent, LANGUAGES, LangService, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessingExampleComponent, LinkProcessorService, LinksCakeComponent, ListContentHelper, LocalStorageService, MOTION, MultiLanguageDemoComponent, NavigationService, NoContentComponent, NotesBoxComponent, NumberInputComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PasswordInputComponent, PinInputComponent, PopoverSelectorComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProgressBarComponent, ProgressStatusComponent, PrompterComponent, RadioInputComponent, ReactiveComponentsDemoComponent, ReactivityTestComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SelectSearchComponent, SelectorExamplesComponent, SimpleComponent, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, TextComponent, TextContent, TextInputComponent, ThemeOption, ThemeService, TitleBlockComponent, TitleComponent, ToastService, ToolbarActionType, ToolbarComponent, UserIssueTestComponent, ValtechConfigService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, content, createComponentContentHelper, createContentHelper, createReactiveProps, createTextProps, createTitleProps, fromContent, fromContentWithInterpolation, fromMultipleContent, globalContentData, goToTop, interpolateContent, isAtEnd, maxLength, replaceSpecialChars, resolveColor, resolveInputDefaultValue, shouldUseReactiveContent };
7474
+ export { ActionType, AlertBoxComponent, AvatarComponent, BannerComponent, BaseDefault, BoxComponent, ButtonComponent, ButtonGroupComponent, CardComponent, CardSection, CardType, CheckInputComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CommentInputComponent, ComponentContentHelper, ComponentStates, ContentLoaderComponent, ContentService, DateInputComponent, DisplayComponent, DividerComponent, DownloadService, EmailInputComponent, ExpandableTextComponent, FileInputComponent, FooterComponent, FormComponent, FormFooterComponent, GlobalContent, HeaderComponent, HintComponent, HourInputComponent, HrefComponent, Icon, IconComponent, IconService, ImageComponent, InAppBrowserService, InputType, ItemListComponent, LANGUAGES, LangService, LanguageSelectorComponent, LayeredCardComponent, LayoutComponent, LinkComponent, LinkProcessorService, LinksCakeComponent, ListContentHelper, LocalStorageService, MOTION, NavigationService, NoContentComponent, NotesBoxComponent, NumberInputComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PasswordInputComponent, PinInputComponent, PopoverSelectorComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProgressBarComponent, ProgressStatusComponent, PrompterComponent, RadioInputComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SelectSearchComponent, SimpleComponent, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, TextComponent, TextContent, TextInputComponent, ThemeOption, ThemeService, TitleBlockComponent, TitleComponent, ToastService, ToolbarActionType, ToolbarComponent, ValtechConfigService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, content, createButtonProps, createComponentContentHelper, createContentHelper, createReactiveProps, createTextProps, createTitleProps, fromContent, fromContentWithInterpolation, fromMultipleContent, globalContentData, goToTop, interpolateContent, isAtEnd, maxLength, replaceSpecialChars, resolveColor, resolveInputDefaultValue, shouldUseReactiveContent };
10158
7475
  //# sourceMappingURL=valtech-components.mjs.map