@propbinder/mobile-design 0.2.16 → 0.2.21

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.
@@ -788,7 +788,7 @@ class MobilePageBase {
788
788
  ngOnDestroy() {
789
789
  // Clean up Capacitor listener if it exists
790
790
  if (this.networkListenerId) {
791
- Network.removeAllListeners().catch(err => {
791
+ Network.removeAllListeners().catch((err) => {
792
792
  console.warn('Failed to remove network listeners', err);
793
793
  });
794
794
  }
@@ -2888,7 +2888,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2888
2888
  * Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.
2889
2889
  * Opens as a full-screen modal similar to post details.
2890
2890
  */
2891
- class WhitelabelDemoModalComponent {
2891
+ let WhitelabelDemoModalComponent$1 = class WhitelabelDemoModalComponent {
2892
2892
  whitelabelService = inject(WhitelabelService);
2893
2893
  modalController = inject(ModalController);
2894
2894
  // Current active theme
@@ -3509,8 +3509,8 @@ class WhitelabelDemoModalComponent {
3509
3509
  </div>
3510
3510
  </ion-content>
3511
3511
  `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;background:var(--color-background-neutral-primary, #ffffff)}.modal-header{flex-shrink:0;background:var(--color-background-neutral-primary, #ffffff);border-bottom:1px solid var(--border-color-default, #e0e0e0);padding:0 16px}ion-content,.modal-content{--background: #ffffff;flex:1;width:100%}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:56px}.header-title{font-family:Brockmann,sans-serif;font-size:17px;font-weight:600;color:var(--color-text-primary, #1a1a1a);flex:1}.close-button{flex-shrink:0;border-radius:50%}.close-button::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important;background:var(--color-background-neutral-secondary, #f5f5f5)!important;color:var(--color-text-primary, #1a1a1a)!important}.demo-container{padding:20px;max-width:600px;margin:0 auto;width:100%}.demo-section{margin-bottom:32px}.demo-section h2{margin-bottom:16px;font-size:18px;font-weight:600;color:#333}.theme-buttons{display:flex;gap:12px;flex-wrap:wrap}.theme-btn{padding:8px 16px;border-radius:8px;font-size:14px;font-weight:500;border:none;cursor:pointer;transition:all .2s ease;background:#e0e0e0;color:#333}.theme-btn:active{transform:scale(.98)}.theme-btn.active{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.logo-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:var(--color-brand-secondary);border-radius:12px;min-height:80px}.logomark-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:#fff;border:1px solid #e0e0e0;border-radius:12px;min-height:80px}.preview-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.preview-tile{background:#fff;border-radius:12px}.preview-tile h3{font-size:13px;font-weight:600;color:#666;margin-top:0;margin-bottom:12px}.app-icon-sizes{display:flex;gap:24px;align-items:flex-end;justify-content:center;padding:24px;background:#fff;border-radius:12px;border:1px solid var(--border-color-default, #e0e0e0);flex-wrap:wrap}.app-icon-demo{display:flex;flex-direction:column;align-items:center;gap:12px;--app-icon-background: var(--color-app-icon-surface)}.app-icon-demo span{font-size:12px;color:#666;font-family:monospace}.color-section{background:#fff;border-radius:12px}.color-swatches{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}.swatch{padding:16px;border-radius:8px;text-align:center}.swatch-label{font-size:12px;font-weight:600;margin-bottom:4px}.swatch-value{font-size:11px;opacity:.8;font-family:monospace}.swatch--app-icon-surface{background:var(--color-app-icon-surface);color:var(--color-app-icon-content)}.swatch--app-icon-content{background:var(--color-app-icon-content);color:var(--color-app-icon-surface);border:1px solid #e0e0e0}.swatch--accent{background:var(--color-accent);color:var(--color-on-accent)}.swatch--on-accent{background:var(--color-on-accent);color:var(--color-accent);border:1px solid #e0e0e0}.swatch--header-surface{background:var(--color-header-surface);color:var(--color-header-content)}.swatch--header-content{background:var(--color-header-content);color:var(--color-header-surface);border:1px solid #e0e0e0}.color-inputs{display:flex;flex-direction:column;gap:12px}.color-group-label{font-size:13px;font-weight:600;color:#333;margin-top:8px}.color-row{display:flex;align-items:center;gap:12px}.color-row label{min-width:70px;font-size:13px;color:#666}.color-row input[type=color]{width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;padding:0}.color-row input[type=text]{flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-family:monospace;font-size:13px}.toggle-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0}.toggle-row label{font-size:14px;color:#333;font-weight:500}.toggle-row input[type=checkbox]{width:48px;height:28px;-webkit-appearance:none;appearance:none;background:#ddd;border-radius:14px;position:relative;cursor:pointer;transition:background .2s ease;flex-shrink:0}.toggle-row input[type=checkbox]:checked{background:var(--color-accent)}.toggle-row input[type=checkbox]:before{content:\"\";position:absolute;width:24px;height:24px;border-radius:50%;background:#fff;top:2px;left:2px;transition:transform .2s ease;box-shadow:0 1px 3px #0003}.toggle-row input[type=checkbox]:checked:before{transform:translate(20px)}.radio-group{display:flex;gap:16px;margin-bottom:16px}.radio-option{display:flex;align-items:center;gap:8px;cursor:pointer}.radio-option input[type=radio]{width:18px;height:18px;cursor:pointer;accent-color:var(--color-accent)}.radio-option label{font-size:14px;color:#333;cursor:pointer;font-weight:500}.bg-preview{height:80px;border-radius:8px;margin-bottom:16px;border:1px solid #e0e0e0;position:relative;overflow:hidden}.bg-preview:after{content:\"Preview\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:12px;font-weight:600;color:#0000004d;text-shadow:0 1px 2px rgba(255,255,255,.5)}@supports (padding: env(safe-area-inset-bottom)){.demo-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: DsLogoComponent, selector: "ds-logo", inputs: ["variant", "size", "customHeight", "customWidth"] }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsAppIconComponent, selector: "ds-app-icon", inputs: ["size"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
3512
- }
3513
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalComponent, decorators: [{
3512
+ };
3513
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalComponent$1, decorators: [{
3514
3514
  type: Component,
3515
3515
  args: [{ selector: 'ds-whitelabel-demo-modal', standalone: true, imports: [
3516
3516
  CommonModule,
@@ -3907,7 +3907,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3907
3907
  * }
3908
3908
  * ```
3909
3909
  */
3910
- class WhitelabelDemoModalService {
3910
+ let WhitelabelDemoModalService$1 = class WhitelabelDemoModalService {
3911
3911
  modalController;
3912
3912
  constructor(modalController) {
3913
3913
  this.modalController = modalController;
@@ -3921,7 +3921,7 @@ class WhitelabelDemoModalService {
3921
3921
  try {
3922
3922
  // console.log('[WhitelabelDemoModal] Opening...');
3923
3923
  const modal = await this.modalController.create({
3924
- component: WhitelabelDemoModalComponent,
3924
+ component: WhitelabelDemoModalComponent$1,
3925
3925
  cssClass: 'ds-whitelabel-demo-modal',
3926
3926
  mode: 'ios',
3927
3927
  presentingElement: document.querySelector('ion-router-outlet') || undefined,
@@ -3961,8 +3961,8 @@ class WhitelabelDemoModalService {
3961
3961
  }
3962
3962
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
3963
3963
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService, providedIn: 'root' });
3964
- }
3965
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService, decorators: [{
3964
+ };
3965
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService$1, decorators: [{
3966
3966
  type: Injectable,
3967
3967
  args: [{
3968
3968
  providedIn: 'root',
@@ -4015,7 +4015,7 @@ class DsMobilePageMainComponent extends MobilePageBase {
4015
4015
  modalController = inject(ModalController);
4016
4016
  router = inject(Router);
4017
4017
  userService = inject(UserService);
4018
- whitelabelDemoModal = inject(WhitelabelDemoModalService);
4018
+ whitelabelDemoModal = inject(WhitelabelDemoModalService$1);
4019
4019
  // Computed property to check if running on native platform
4020
4020
  isNativePlatform = computed(() => this.platform.is('ios') || this.platform.is('android') || this.platform.is('capacitor'), ...(ngDevMode ? [{ debugName: "isNativePlatform" }] : []));
4021
4021
  // Inputs - Title
@@ -5322,6 +5322,200 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5322
5322
  args: [{ selector: 'tile-value', standalone: true, template: `<ng-content />`, styles: [":host{font-family:Brockmann,sans-serif;font-size:var(--font-size-lg);font-weight:600;line-height:26px;letter-spacing:-.72px;color:var(--color-header-content, #ffffff);display:block}\n"] }]
5323
5323
  }] });
5324
5324
 
5325
+ /**
5326
+ * DsMobileSystemMessageBannerComponent
5327
+ *
5328
+ * Full-width centered banner component for displaying system messages in chat conversations.
5329
+ * Uses the same text styling as message bubbles for consistency.
5330
+ *
5331
+ * Features:
5332
+ * - Full-width centered layout
5333
+ * - Subtle background with theming support
5334
+ * - Same typography as message bubbles
5335
+ * - Optional icon support
5336
+ *
5337
+ * Common use cases:
5338
+ * - Inquiry status updates ("Your inquiry has been assigned to...")
5339
+ * - System notifications ("This inquiry is marked as resolved")
5340
+ * - Auto-replies ("We aim to respond within 24 hours...")
5341
+ * - Time/date separators
5342
+ *
5343
+ * @example
5344
+ * ```html
5345
+ * <!-- Simple system message -->
5346
+ * <ds-mobile-system-message-banner
5347
+ * [message]="'Ricki Meihlen har overtaget din henvendelse og vil kontakte dig snart.'">
5348
+ * </ds-mobile-system-message-banner>
5349
+ *
5350
+ * <!-- With icon -->
5351
+ * <ds-mobile-system-message-banner
5352
+ * [message]="'Vi bestræber os på at svare inden for 24 timer på hverdage.'"
5353
+ * [iconName]="'remixInformationLine'">
5354
+ * </ds-mobile-system-message-banner>
5355
+ * ```
5356
+ */
5357
+ class DsMobileSystemMessageBannerComponent {
5358
+ /**
5359
+ * System message text to display
5360
+ */
5361
+ message = input.required(...(ngDevMode ? [{ debugName: "message" }] : []));
5362
+ /**
5363
+ * Optional icon name (currently using inline SVG for info icon)
5364
+ * Can be extended to support full icon library integration
5365
+ */
5366
+ iconName = input('', ...(ngDevMode ? [{ debugName: "iconName" }] : []));
5367
+ /**
5368
+ * Whether this system message appears directly after a timestamp
5369
+ * When true, removes top padding to reduce spacing
5370
+ */
5371
+ afterTimestamp = input(false, ...(ngDevMode ? [{ debugName: "afterTimestamp" }] : []));
5372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileSystemMessageBannerComponent, isStandalone: true, selector: "ds-mobile-system-message-banner", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, afterTimestamp: { classPropertyName: "afterTimestamp", publicName: "afterTimestamp", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.after-timestamp": "afterTimestamp()" } }, ngImport: i0, template: `
5374
+ <div class="system-message-container">
5375
+ <div class="system-message-content">
5376
+ @if (iconName()) {
5377
+ <span class="system-message-icon">
5378
+ <!-- Icon slot - you can add ds-icon component here if needed -->
5379
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
5380
+ <path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
5381
+ </svg>
5382
+ </span>
5383
+ }
5384
+ <p class="system-message-text">{{ message() }}</p>
5385
+ </div>
5386
+ </div>
5387
+ `, isInline: true, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
5388
+ }
5389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, decorators: [{
5390
+ type: Component,
5391
+ args: [{ selector: 'ds-mobile-system-message-banner', standalone: true, imports: [CommonModule], host: {
5392
+ '[class.after-timestamp]': 'afterTimestamp()'
5393
+ }, template: `
5394
+ <div class="system-message-container">
5395
+ <div class="system-message-content">
5396
+ @if (iconName()) {
5397
+ <span class="system-message-icon">
5398
+ <!-- Icon slot - you can add ds-icon component here if needed -->
5399
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
5400
+ <path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
5401
+ </svg>
5402
+ </span>
5403
+ }
5404
+ <p class="system-message-text">{{ message() }}</p>
5405
+ </div>
5406
+ </div>
5407
+ `, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"] }]
5408
+ }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], afterTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterTimestamp", required: false }] }] } });
5409
+
5410
+ /**
5411
+ * DsMobileFileAttachmentComponent
5412
+ *
5413
+ * File attachment display for various document types.
5414
+ * Shows file info card with icon, filename, and file size.
5415
+ * Supports PDF and generic document formats.
5416
+ * Emits click event to open file in viewer.
5417
+ *
5418
+ * @example
5419
+ * ```html
5420
+ * <ds-mobile-file-attachment
5421
+ * [fileName]="'Document.pdf'"
5422
+ * [fileSize]="'1.2 MB'"
5423
+ * [variant]="'pdf'"
5424
+ * (fileClick)="openFile()">
5425
+ * </ds-mobile-file-attachment>
5426
+ * ```
5427
+ */
5428
+ class DsMobileFileAttachmentComponent {
5429
+ /**
5430
+ * File name
5431
+ */
5432
+ fileName = input('Document', ...(ngDevMode ? [{ debugName: "fileName" }] : []));
5433
+ /**
5434
+ * File size display (e.g., "1.2 MB")
5435
+ */
5436
+ fileSize = input('', ...(ngDevMode ? [{ debugName: "fileSize" }] : []));
5437
+ /**
5438
+ * File type variant
5439
+ * - 'pdf' - PDF document (red icon)
5440
+ * - 'doc' - Generic document (blue icon)
5441
+ */
5442
+ variant = input('doc', ...(ngDevMode ? [{ debugName: "variant" }] : []));
5443
+ /**
5444
+ * Emits when the file attachment is clicked
5445
+ */
5446
+ fileClick = output();
5447
+ /**
5448
+ * Get the appropriate icon name based on variant
5449
+ */
5450
+ getIconName() {
5451
+ return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';
5452
+ }
5453
+ /**
5454
+ * Get the file type label based on variant
5455
+ */
5456
+ getFileTypeLabel() {
5457
+ return this.variant() === 'pdf' ? 'PDF' : 'DOC';
5458
+ }
5459
+ handleClick(event) {
5460
+ event.stopPropagation();
5461
+ this.fileClick.emit();
5462
+ }
5463
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileFileAttachmentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5464
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileFileAttachmentComponent, isStandalone: true, selector: "ds-mobile-file-attachment", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, host: { listeners: { "click": "handleClick($event)" } }, ngImport: i0, template: `
5465
+ <div class="file-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
5466
+ <ds-avatar
5467
+ type="icon"
5468
+ [iconName]="getIconName()"
5469
+ size="lg"
5470
+ />
5471
+ </div>
5472
+
5473
+ <div class="file-info">
5474
+ <div class="file-name">{{ fileName() }}</div>
5475
+ @if (fileSize()) {
5476
+ <div class="file-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
5477
+ } @else {
5478
+ <div class="file-meta">{{ getFileTypeLabel() }}</div>
5479
+ }
5480
+ </div>
5481
+
5482
+ <ds-icon
5483
+ name="remixArrowRightSLine"
5484
+ size="20px"
5485
+ class="open-icon"
5486
+ />
5487
+ `, isInline: true, styles: [":host{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease}:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host:active{transform:scale(.98)}.file-avatar{flex-shrink:0}.file-avatar.pdf::ng-deep .avatar--icon{background-color:#ff5757!important}.file-avatar.doc::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}.file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.file-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.open-icon{color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
5488
+ }
5489
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileFileAttachmentComponent, decorators: [{
5490
+ type: Component,
5491
+ args: [{ selector: 'ds-mobile-file-attachment', standalone: true, imports: [CommonModule, DsAvatarComponent, DsIconComponent], host: {
5492
+ '(click)': 'handleClick($event)'
5493
+ }, template: `
5494
+ <div class="file-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
5495
+ <ds-avatar
5496
+ type="icon"
5497
+ [iconName]="getIconName()"
5498
+ size="lg"
5499
+ />
5500
+ </div>
5501
+
5502
+ <div class="file-info">
5503
+ <div class="file-name">{{ fileName() }}</div>
5504
+ @if (fileSize()) {
5505
+ <div class="file-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
5506
+ } @else {
5507
+ <div class="file-meta">{{ getFileTypeLabel() }}</div>
5508
+ }
5509
+ </div>
5510
+
5511
+ <ds-icon
5512
+ name="remixArrowRightSLine"
5513
+ size="20px"
5514
+ class="open-icon"
5515
+ />
5516
+ `, styles: [":host{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease}:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host:active{transform:scale(.98)}.file-avatar{flex-shrink:0}.file-avatar.pdf::ng-deep .avatar--icon{background-color:#ff5757!important}.file-avatar.doc::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}.file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.file-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.open-icon{color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"] }]
5517
+ }], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
5518
+
5325
5519
  /**
5326
5520
  * DsMobileCommentComponent
5327
5521
  *
@@ -9703,107 +9897,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
9703
9897
  }] } });
9704
9898
 
9705
9899
  /**
9706
- * DsMobileSystemMessageBannerComponent
9707
- *
9708
- * Full-width centered banner component for displaying system messages in chat conversations.
9709
- * Uses the same text styling as message bubbles for consistency.
9710
- *
9711
- * Features:
9712
- * - Full-width centered layout
9713
- * - Subtle background with theming support
9714
- * - Same typography as message bubbles
9715
- * - Optional icon support
9716
- *
9717
- * Common use cases:
9718
- * - Inquiry status updates ("Your inquiry has been assigned to...")
9719
- * - System notifications ("This inquiry is marked as resolved")
9720
- * - Auto-replies ("We aim to respond within 24 hours...")
9721
- * - Time/date separators
9722
- *
9723
- * @example
9724
- * ```html
9725
- * <!-- Simple system message -->
9726
- * <ds-mobile-system-message-banner
9727
- * [message]="'Ricki Meihlen har overtaget din henvendelse og vil kontakte dig snart.'">
9728
- * </ds-mobile-system-message-banner>
9900
+ * DsMobileLightboxHeaderComponent
9729
9901
  *
9730
- * <!-- With icon -->
9731
- * <ds-mobile-system-message-banner
9732
- * [message]="'Vi bestræber os på at svare inden for 24 timer på hverdage.'"
9733
- * [iconName]="'remixInformationLine'">
9734
- * </ds-mobile-system-message-banner>
9735
- * ```
9902
+ * Shared header component for all lightbox types (image, PDF, etc.)
9903
+ * Displays author information and close button with consistent styling.
9736
9904
  */
9737
- class DsMobileSystemMessageBannerComponent {
9905
+ class DsMobileLightboxHeaderComponent {
9738
9906
  /**
9739
- * System message text to display
9907
+ * Author information to display
9740
9908
  */
9741
- message = input.required(...(ngDevMode ? [{ debugName: "message" }] : []));
9909
+ author = input(...(ngDevMode ? [undefined, { debugName: "author" }] : []));
9742
9910
  /**
9743
- * Optional icon name (currently using inline SVG for info icon)
9744
- * Can be extended to support full icon library integration
9911
+ * Emitted when close button is clicked
9745
9912
  */
9746
- iconName = input('', ...(ngDevMode ? [{ debugName: "iconName" }] : []));
9913
+ closeClick = output();
9747
9914
  /**
9748
- * Whether this system message appears directly after a timestamp
9749
- * When true, removes top padding to reduce spacing
9750
- */
9751
- afterTimestamp = input(false, ...(ngDevMode ? [{ debugName: "afterTimestamp" }] : []));
9752
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9753
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileSystemMessageBannerComponent, isStandalone: true, selector: "ds-mobile-system-message-banner", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, afterTimestamp: { classPropertyName: "afterTimestamp", publicName: "afterTimestamp", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.after-timestamp": "afterTimestamp()" } }, ngImport: i0, template: `
9754
- <div class="system-message-container">
9755
- <div class="system-message-content">
9756
- @if (iconName()) {
9757
- <span class="system-message-icon">
9758
- <!-- Icon slot - you can add ds-icon component here if needed -->
9759
- <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
9760
- <path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
9761
- </svg>
9762
- </span>
9763
- }
9764
- <p class="system-message-text">{{ message() }}</p>
9765
- </div>
9766
- </div>
9767
- `, isInline: true, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
9768
- }
9769
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, decorators: [{
9770
- type: Component,
9771
- args: [{ selector: 'ds-mobile-system-message-banner', standalone: true, imports: [CommonModule], host: {
9772
- '[class.after-timestamp]': 'afterTimestamp()'
9773
- }, template: `
9774
- <div class="system-message-container">
9775
- <div class="system-message-content">
9776
- @if (iconName()) {
9777
- <span class="system-message-icon">
9778
- <!-- Icon slot - you can add ds-icon component here if needed -->
9779
- <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
9780
- <path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
9781
- </svg>
9782
- </span>
9783
- }
9784
- <p class="system-message-text">{{ message() }}</p>
9785
- </div>
9786
- </div>
9787
- `, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"] }]
9788
- }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], afterTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterTimestamp", required: false }] }] } });
9789
-
9790
- /**
9791
- * DsMobileLightboxHeaderComponent
9792
- *
9793
- * Shared header component for all lightbox types (image, PDF, etc.)
9794
- * Displays author information and close button with consistent styling.
9795
- */
9796
- class DsMobileLightboxHeaderComponent {
9797
- /**
9798
- * Author information to display
9799
- */
9800
- author = input(...(ngDevMode ? [undefined, { debugName: "author" }] : []));
9801
- /**
9802
- * Emitted when close button is clicked
9803
- */
9804
- closeClick = output();
9805
- /**
9806
- * Emitted when share button is clicked
9915
+ * Emitted when share button is clicked
9807
9916
  */
9808
9917
  shareClick = output();
9809
9918
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -16351,115 +16460,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
16351
16460
  `, styles: [":host{display:block;width:100%}.text-input-wrapper{position:relative;width:100%}.text-input{width:100%;height:48px;padding:0 16px;box-sizing:border-box;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-base);font-weight:400;line-height:1.4;color:var(--text-color-default-primary);background-color:var(--color-background-neutral-primary);border:1px solid var(--border-color-default);border-radius:8px;transition:border-color var(--transition-duration-fast) var(--ease-smooth),background-color var(--transition-duration-fast) var(--ease-smooth),box-shadow var(--transition-duration-fast) var(--ease-smooth);outline:none;-webkit-appearance:none;appearance:none}.text-input::placeholder{color:var(--text-color-default-tertiary)}.text-input:hover:not(:disabled):not(:focus){border-color:var(--border-color-default);background-color:var(--color-background-neutral-primary-hover)}.text-input:focus{border-color:var(--color-accent);background-color:var(--color-background-neutral-primary);box-shadow:0 0 0 3px var(--outline-color-default)}.text-input.error{border-color:var(--color-destructive-base)}.text-input.error:focus{border-color:var(--color-destructive-base);box-shadow:0 0 0 3px #dc26261a}.text-input:disabled{background-color:var(--color-background-neutral-disabled);border-color:var(--border-color-default);color:var(--text-color-default-disabled);cursor:not-allowed}.text-input:disabled::placeholder{color:var(--text-color-default-disabled)}.error-message{margin-top:8px;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-destructive-base)}\n"] }]
16352
16461
  }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], inputmode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputmode", required: false }] }], autoClearError: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClearError", required: false }] }], validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "validator", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], blur: [{ type: i0.Output, args: ["blur"] }], focus: [{ type: i0.Output, args: ["focus"] }], errorCleared: [{ type: i0.Output, args: ["errorCleared"] }] } });
16353
16462
 
16354
- /**
16355
- * DsMobileFileAttachmentComponent
16356
- *
16357
- * File attachment display for various document types.
16358
- * Shows file info card with icon, filename, and file size.
16359
- * Supports PDF and generic document formats.
16360
- * Emits click event to open file in viewer.
16361
- *
16362
- * @example
16363
- * ```html
16364
- * <ds-mobile-file-attachment
16365
- * [fileName]="'Document.pdf'"
16366
- * [fileSize]="'1.2 MB'"
16367
- * [variant]="'pdf'"
16368
- * (fileClick)="openFile()">
16369
- * </ds-mobile-file-attachment>
16370
- * ```
16371
- */
16372
- class DsMobileFileAttachmentComponent {
16373
- /**
16374
- * File name
16375
- */
16376
- fileName = input('Document', ...(ngDevMode ? [{ debugName: "fileName" }] : []));
16377
- /**
16378
- * File size display (e.g., "1.2 MB")
16379
- */
16380
- fileSize = input('', ...(ngDevMode ? [{ debugName: "fileSize" }] : []));
16381
- /**
16382
- * File type variant
16383
- * - 'pdf' - PDF document (red icon)
16384
- * - 'doc' - Generic document (blue icon)
16385
- */
16386
- variant = input('doc', ...(ngDevMode ? [{ debugName: "variant" }] : []));
16387
- /**
16388
- * Emits when the file attachment is clicked
16389
- */
16390
- fileClick = output();
16391
- /**
16392
- * Get the appropriate icon name based on variant
16393
- */
16394
- getIconName() {
16395
- return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';
16396
- }
16397
- /**
16398
- * Get the file type label based on variant
16399
- */
16400
- getFileTypeLabel() {
16401
- return this.variant() === 'pdf' ? 'PDF' : 'DOC';
16402
- }
16403
- handleClick(event) {
16404
- event.stopPropagation();
16405
- this.fileClick.emit();
16406
- }
16407
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileFileAttachmentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16408
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileFileAttachmentComponent, isStandalone: true, selector: "ds-mobile-file-attachment", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, host: { listeners: { "click": "handleClick($event)" } }, ngImport: i0, template: `
16409
- <div class="file-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
16410
- <ds-avatar
16411
- type="icon"
16412
- [iconName]="getIconName()"
16413
- size="lg"
16414
- />
16415
- </div>
16416
-
16417
- <div class="file-info">
16418
- <div class="file-name">{{ fileName() }}</div>
16419
- @if (fileSize()) {
16420
- <div class="file-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
16421
- } @else {
16422
- <div class="file-meta">{{ getFileTypeLabel() }}</div>
16423
- }
16424
- </div>
16425
-
16426
- <ds-icon
16427
- name="remixArrowRightSLine"
16428
- size="20px"
16429
- class="open-icon"
16430
- />
16431
- `, isInline: true, styles: [":host{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease}:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host:active{transform:scale(.98)}.file-avatar{flex-shrink:0}.file-avatar.pdf::ng-deep .avatar--icon{background-color:#ff5757!important}.file-avatar.doc::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}.file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.file-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.open-icon{color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
16432
- }
16433
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileFileAttachmentComponent, decorators: [{
16434
- type: Component,
16435
- args: [{ selector: 'ds-mobile-file-attachment', standalone: true, imports: [CommonModule, DsAvatarComponent, DsIconComponent], host: {
16436
- '(click)': 'handleClick($event)'
16437
- }, template: `
16438
- <div class="file-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
16439
- <ds-avatar
16440
- type="icon"
16441
- [iconName]="getIconName()"
16442
- size="lg"
16443
- />
16444
- </div>
16445
-
16446
- <div class="file-info">
16447
- <div class="file-name">{{ fileName() }}</div>
16448
- @if (fileSize()) {
16449
- <div class="file-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
16450
- } @else {
16451
- <div class="file-meta">{{ getFileTypeLabel() }}</div>
16452
- }
16453
- </div>
16454
-
16455
- <ds-icon
16456
- name="remixArrowRightSLine"
16457
- size="20px"
16458
- class="open-icon"
16459
- />
16460
- `, styles: [":host{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease}:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host:active{transform:scale(.98)}.file-avatar{flex-shrink:0}.file-avatar.pdf::ng-deep .avatar--icon{background-color:#ff5757!important}.file-avatar.doc::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}.file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.file-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.open-icon{color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"] }]
16461
- }], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
16462
-
16463
16463
  /**
16464
16464
  * DsMobileFabComponent
16465
16465
  *
@@ -19644,6 +19644,1093 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
19644
19644
  `, styles: [".activity-list{display:flex;flex-direction:column;gap:12px;position:relative}.activity-list ds-mobile-list-item:not(:last-child) [content-leading]:after{content:\"\";position:absolute;top:40px;left:50%;transform:translate(-50%);width:1px;height:calc(100% - 2px);background:var(--border-color-default, #e5e5e5);z-index:0}.activity-icon-wrapper{width:100%;height:100%;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:1}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:100%;height:100%;z-index:1}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-value.description-text{padding:0 0 8px}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}.photo-add{width:100%;aspect-ratio:1;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer}.photo-item{width:100%;aspect-ratio:1;border-radius:12px;-o-object-fit:cover;object-fit:cover}\n"] }]
19645
19645
  }], ctorParameters: () => [{ type: UserService }, { type: DsMobileLightboxService }, { type: DsMobileChatModalService }] });
19646
19646
 
19647
+ /**
19648
+ * Whitelabel Demo Modal Component
19649
+ *
19650
+ * Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.
19651
+ * Opens as a full-screen modal similar to post details.
19652
+ */
19653
+ class WhitelabelDemoModalComponent {
19654
+ whitelabelService = inject(WhitelabelService);
19655
+ modalController = inject(ModalController);
19656
+ // Current active theme
19657
+ currentTheme = 'default';
19658
+ // Custom color inputs
19659
+ customAppIconSurface = '#6B5FF5';
19660
+ customAppIconContent = '#FFFFFF';
19661
+ customAccent = '#6B5FF5';
19662
+ customOnAccent = '#FFFFFF';
19663
+ customHeaderSurface = '#221a4c';
19664
+ customHeaderContent = '#FFFFFF';
19665
+ customHeaderAccent = 'rgba(255, 255, 255, 0.15)';
19666
+ customOnHeaderAccent = '#FFFFFF';
19667
+ // Sign-in background inputs
19668
+ customSignInBgSolid = '#D6C7FF';
19669
+ customSignInBgGradientStart = '#D6C7FF';
19670
+ customSignInBgGradientEnd = '#8A9BFF';
19671
+ customSignInContentColor = '#1a1a1a';
19672
+ ngOnInit() {
19673
+ this.updateCustomColorInputs();
19674
+ this.updateSignInBgInputs();
19675
+ this.updateSignInContentColorInput();
19676
+ this.detectCurrentTheme();
19677
+ }
19678
+ /**
19679
+ * Detect the current active theme based on colors
19680
+ */
19681
+ detectCurrentTheme() {
19682
+ const headerSurface = this.whitelabelService.headerSurface().toUpperCase();
19683
+ if (headerSurface === '#A70923') {
19684
+ this.currentTheme = 'cej';
19685
+ }
19686
+ else if (headerSurface === '#660036') {
19687
+ this.currentTheme = 'pka';
19688
+ }
19689
+ else if (headerSurface === '#262424') {
19690
+ this.currentTheme = 'clave';
19691
+ }
19692
+ else if (headerSurface === '#1D4A49') {
19693
+ this.currentTheme = 'freedom';
19694
+ }
19695
+ else {
19696
+ this.currentTheme = 'default';
19697
+ }
19698
+ }
19699
+ /**
19700
+ * Close the modal
19701
+ */
19702
+ close() {
19703
+ this.modalController.dismiss();
19704
+ }
19705
+ applyDefaultTheme() {
19706
+ this.currentTheme = 'default';
19707
+ this.whitelabelService.updateConfig({
19708
+ logoUrl: '/Assets/logos/propbinder-logomark.svg',
19709
+ logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',
19710
+ logoAlt: 'Propbinder',
19711
+ logoSize: 'md',
19712
+ appIconSurface: '#6B5FF5',
19713
+ appIconContent: '#FFFFFF',
19714
+ accent: '#6B5FF5',
19715
+ onAccent: '#FFFFFF',
19716
+ headerSurface: '#221a4c',
19717
+ headerContent: '#FFFFFF',
19718
+ headerAccent: '#6B5FF5',
19719
+ onHeaderAccent: '#FFFFFF',
19720
+ showCityIllustration: true,
19721
+ signInBgType: 'gradient',
19722
+ signInBgSolid: '#D6C7FF',
19723
+ signInBgGradientStart: '#D6C7FF',
19724
+ signInBgGradientEnd: '#8A9BFF',
19725
+ signInContentColor: '#1a1a1a',
19726
+ organizationName: 'Propbinder',
19727
+ organizationId: 'default'
19728
+ });
19729
+ this.updateCustomColorInputs();
19730
+ this.updateSignInBgInputs();
19731
+ this.updateSignInContentColorInput();
19732
+ }
19733
+ applyCejTheme() {
19734
+ this.currentTheme = 'cej';
19735
+ this.whitelabelService.updateConfig({
19736
+ logoUrl: '/Assets/logos/cej-logo.png',
19737
+ logoMarkUrl: '/Assets/logos/cej-logo.png',
19738
+ logoAlt: 'CEJ',
19739
+ logoSize: 'xl',
19740
+ appIconSurface: '#A70923',
19741
+ appIconContent: '#FFFFFF',
19742
+ accent: '#dc092c',
19743
+ onAccent: '#FFFFFF',
19744
+ headerSurface: '#A70923',
19745
+ headerContent: '#FFFFFF',
19746
+ headerAccent: '#dc092c',
19747
+ onHeaderAccent: '#FFFFFF',
19748
+ showCityIllustration: false,
19749
+ signInBgType: 'gradient',
19750
+ signInBgSolid: '#FFE5E8',
19751
+ signInBgGradientStart: '#FFE5E8',
19752
+ signInBgGradientEnd: '#FFC7CE',
19753
+ signInContentColor: '#1a1a1a',
19754
+ organizationName: 'CEJ',
19755
+ organizationId: 'cej'
19756
+ });
19757
+ this.updateCustomColorInputs();
19758
+ this.updateSignInBgInputs();
19759
+ this.updateSignInContentColorInput();
19760
+ }
19761
+ applyPkaTheme() {
19762
+ this.currentTheme = 'pka';
19763
+ this.whitelabelService.updateConfig({
19764
+ logoUrl: '/Assets/logos/pka-logo.svg',
19765
+ logoMarkUrl: '/Assets/logos/pka-logo.svg',
19766
+ logoAlt: 'PKA',
19767
+ logoSize: 'md',
19768
+ appIconSurface: '#CC006C',
19769
+ appIconContent: '#FFFFFF',
19770
+ accent: '#CC006C',
19771
+ onAccent: '#FFFFFF',
19772
+ headerSurface: '#660036',
19773
+ headerContent: '#FFFFFF',
19774
+ headerAccent: '#CC006C',
19775
+ onHeaderAccent: '#FFFFFF',
19776
+ showCityIllustration: false,
19777
+ signInBgType: 'gradient',
19778
+ signInBgSolid: '#FFE0F0',
19779
+ signInBgGradientStart: '#FFE0F0',
19780
+ signInBgGradientEnd: '#FFB3D9',
19781
+ signInContentColor: '#1a1a1a',
19782
+ organizationName: 'PKA',
19783
+ organizationId: 'pka'
19784
+ });
19785
+ this.updateCustomColorInputs();
19786
+ this.updateSignInBgInputs();
19787
+ this.updateSignInContentColorInput();
19788
+ }
19789
+ applyClaveTheme() {
19790
+ this.currentTheme = 'clave';
19791
+ this.whitelabelService.updateConfig({
19792
+ logoUrl: '/Assets/logos/clave-logo.svg',
19793
+ logoMarkUrl: '/Assets/logos/clave-logo.svg',
19794
+ logoAlt: 'Clave',
19795
+ logoSize: 'lg',
19796
+ appIconSurface: '#262424',
19797
+ appIconContent: '#FFFFFF',
19798
+ accent: '#868764',
19799
+ onAccent: '#FFFFFF',
19800
+ headerSurface: '#262424',
19801
+ headerContent: '#FFFFFF',
19802
+ headerAccent: '#868764',
19803
+ onHeaderAccent: '#FFFFFF',
19804
+ showCityIllustration: false,
19805
+ signInBgType: 'gradient',
19806
+ signInBgSolid: '#E8E8E0',
19807
+ signInBgGradientStart: '#E8E8E0',
19808
+ signInBgGradientEnd: '#D4D4C3',
19809
+ signInContentColor: '#1a1a1a',
19810
+ organizationName: 'Clave',
19811
+ organizationId: 'clave'
19812
+ });
19813
+ this.updateCustomColorInputs();
19814
+ this.updateSignInBgInputs();
19815
+ this.updateSignInContentColorInput();
19816
+ }
19817
+ applyFreedomTheme() {
19818
+ this.currentTheme = 'freedom';
19819
+ this.whitelabelService.updateConfig({
19820
+ logoUrl: '/Assets/logos/freedom-logo.svg',
19821
+ logoMarkUrl: '/Assets/logos/freedom-logomark.svg',
19822
+ logoAlt: 'Freedom',
19823
+ logoSize: 'md',
19824
+ appIconSurface: '#1D4A49',
19825
+ appIconContent: '#FFFFFF',
19826
+ accent: '#1D4A49',
19827
+ onAccent: '#FFFFFF',
19828
+ headerSurface: '#1D4A49',
19829
+ headerContent: '#FFFFFF',
19830
+ headerAccent: '#AACFC3',
19831
+ onHeaderAccent: '#1D4A49',
19832
+ showCityIllustration: false,
19833
+ signInBgType: 'gradient',
19834
+ signInBgSolid: '#D5E8E6',
19835
+ signInBgGradientStart: '#D5E8E6',
19836
+ signInBgGradientEnd: '#AACFC3',
19837
+ signInContentColor: '#FFFFFF',
19838
+ organizationName: 'Freedom',
19839
+ organizationId: 'freedom'
19840
+ });
19841
+ this.updateCustomColorInputs();
19842
+ this.updateSignInBgInputs();
19843
+ this.updateSignInContentColorInput();
19844
+ }
19845
+ applyCustomColors() {
19846
+ this.whitelabelService.updateColors({
19847
+ appIconSurface: this.customAppIconSurface,
19848
+ appIconContent: this.customAppIconContent,
19849
+ accent: this.customAccent,
19850
+ onAccent: this.customOnAccent,
19851
+ headerSurface: this.customHeaderSurface,
19852
+ headerContent: this.customHeaderContent,
19853
+ headerAccent: this.customHeaderAccent,
19854
+ onHeaderAccent: this.customOnHeaderAccent
19855
+ });
19856
+ }
19857
+ toggleCityIllustration() {
19858
+ this.whitelabelService.updateConfig({
19859
+ showCityIllustration: !this.whitelabelService.showCityIllustration()
19860
+ });
19861
+ }
19862
+ updateSignInBgType(type) {
19863
+ this.whitelabelService.updateConfig({
19864
+ signInBgType: type
19865
+ });
19866
+ }
19867
+ updateLogoSize(size) {
19868
+ this.whitelabelService.updateConfig({
19869
+ logoSize: size,
19870
+ logoHeight: undefined // Clear custom height to use size-based calculation
19871
+ });
19872
+ }
19873
+ applySignInBackground() {
19874
+ this.whitelabelService.updateConfig({
19875
+ signInBgSolid: this.customSignInBgSolid,
19876
+ signInBgGradientStart: this.customSignInBgGradientStart,
19877
+ signInBgGradientEnd: this.customSignInBgGradientEnd
19878
+ });
19879
+ }
19880
+ applySignInContentColor() {
19881
+ this.whitelabelService.updateConfig({
19882
+ signInContentColor: this.customSignInContentColor
19883
+ });
19884
+ }
19885
+ updateSignInBgInputs() {
19886
+ this.customSignInBgSolid = this.whitelabelService.signInBgSolid();
19887
+ this.customSignInBgGradientStart = this.whitelabelService.signInBgGradientStart();
19888
+ this.customSignInBgGradientEnd = this.whitelabelService.signInBgGradientEnd();
19889
+ }
19890
+ updateSignInContentColorInput() {
19891
+ this.customSignInContentColor = this.whitelabelService.signInContentColor();
19892
+ }
19893
+ updateCustomColorInputs() {
19894
+ this.customAppIconSurface = this.whitelabelService.appIconSurface();
19895
+ this.customAppIconContent = this.whitelabelService.appIconContent();
19896
+ this.customAccent = this.whitelabelService.accent();
19897
+ this.customOnAccent = this.whitelabelService.onAccent();
19898
+ this.customHeaderSurface = this.whitelabelService.headerSurface();
19899
+ this.customHeaderContent = this.whitelabelService.headerContent();
19900
+ this.customHeaderAccent = this.whitelabelService.headerAccent();
19901
+ this.customOnHeaderAccent = this.whitelabelService.onHeaderAccent();
19902
+ }
19903
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19904
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: WhitelabelDemoModalComponent, isStandalone: true, selector: "ds-whitelabel-demo-modal", ngImport: i0, template: `
19905
+ <!-- Fixed Header -->
19906
+ <div class="modal-header">
19907
+ <div class="header-content">
19908
+ <span class="header-title">Whitelabel</span>
19909
+ <ds-icon-button
19910
+ icon="remixCloseLine"
19911
+ variant="secondary"
19912
+ size="lg"
19913
+ (click)="close()"
19914
+ class="close-button"
19915
+ aria-label="Close">
19916
+ </ds-icon-button>
19917
+ </div>
19918
+ </div>
19919
+
19920
+ <!-- Scrollable Content -->
19921
+ <ion-content [scrollY]="true" class="modal-content">
19922
+ <div class="demo-container">
19923
+ <!-- Theme Selection -->
19924
+ <div class="demo-section">
19925
+ <h2>Theme</h2>
19926
+ <div class="theme-buttons">
19927
+ <button class="theme-btn" (click)="applyDefaultTheme()" [class.active]="currentTheme === 'default'">
19928
+ Propbinder
19929
+ </button>
19930
+ <button class="theme-btn" (click)="applyCejTheme()" [class.active]="currentTheme === 'cej'">
19931
+ CEJ
19932
+ </button>
19933
+ <button class="theme-btn" (click)="applyPkaTheme()" [class.active]="currentTheme === 'pka'">
19934
+ PKA
19935
+ </button>
19936
+ <button class="theme-btn" (click)="applyClaveTheme()" [class.active]="currentTheme === 'clave'">
19937
+ Clave
19938
+ </button>
19939
+ <button class="theme-btn" (click)="applyFreedomTheme()" [class.active]="currentTheme === 'freedom'">
19940
+ Freedom
19941
+ </button>
19942
+ </div>
19943
+ </div>
19944
+
19945
+ <!-- Sign-in Page Options -->
19946
+ <div class="demo-section">
19947
+ <h2>Sign-in Page</h2>
19948
+ <div class="color-section">
19949
+ <div class="toggle-row">
19950
+ <label>Show City Illustration</label>
19951
+ <input
19952
+ type="checkbox"
19953
+ [checked]="whitelabelService.showCityIllustration()"
19954
+ [disabled]="currentTheme !== 'default'"
19955
+ (change)="toggleCityIllustration()"
19956
+ [style.opacity]="currentTheme !== 'default' ? '0.5' : '1'"
19957
+ [style.cursor]="currentTheme !== 'default' ? 'not-allowed' : 'pointer'"
19958
+ />
19959
+ </div>
19960
+
19961
+ <div style="margin-top: 24px;">
19962
+ <h3 style="font-size: 14px; font-weight: 600; color: #333; margin: 0 0 12px 0;">Background</h3>
19963
+
19964
+ <!-- Background type selector -->
19965
+ <div class="radio-group">
19966
+ <div class="radio-option">
19967
+ <input
19968
+ type="radio"
19969
+ id="bg-solid"
19970
+ name="bgType"
19971
+ value="solid"
19972
+ [checked]="whitelabelService.signInBgType() === 'solid'"
19973
+ (change)="updateSignInBgType('solid')"
19974
+ />
19975
+ <label for="bg-solid">Solid</label>
19976
+ </div>
19977
+ <div class="radio-option">
19978
+ <input
19979
+ type="radio"
19980
+ id="bg-gradient"
19981
+ name="bgType"
19982
+ value="gradient"
19983
+ [checked]="whitelabelService.signInBgType() === 'gradient'"
19984
+ (change)="updateSignInBgType('gradient')"
19985
+ />
19986
+ <label for="bg-gradient">Gradient</label>
19987
+ </div>
19988
+ </div>
19989
+
19990
+ <!-- Background preview -->
19991
+ <div class="bg-preview" [style.background]="whitelabelService.signInBgStyle()"></div>
19992
+
19993
+ <!-- Solid color input -->
19994
+ @if (whitelabelService.signInBgType() === 'solid') {
19995
+ <div class="color-row">
19996
+ <label>Color</label>
19997
+ <input
19998
+ type="color"
19999
+ [(ngModel)]="customSignInBgSolid"
20000
+ (change)="applySignInBackground()"
20001
+ />
20002
+ <input
20003
+ type="text"
20004
+ [(ngModel)]="customSignInBgSolid"
20005
+ (change)="applySignInBackground()"
20006
+ />
20007
+ </div>
20008
+ }
20009
+
20010
+ <!-- Gradient color inputs -->
20011
+ @if (whitelabelService.signInBgType() === 'gradient') {
20012
+ <div class="color-row">
20013
+ <label>Start</label>
20014
+ <input
20015
+ type="color"
20016
+ [(ngModel)]="customSignInBgGradientStart"
20017
+ (change)="applySignInBackground()"
20018
+ />
20019
+ <input
20020
+ type="text"
20021
+ [(ngModel)]="customSignInBgGradientStart"
20022
+ (change)="applySignInBackground()"
20023
+ />
20024
+ </div>
20025
+ <div class="color-row">
20026
+ <label>End</label>
20027
+ <input
20028
+ type="color"
20029
+ [(ngModel)]="customSignInBgGradientEnd"
20030
+ (change)="applySignInBackground()"
20031
+ />
20032
+ <input
20033
+ type="text"
20034
+ [(ngModel)]="customSignInBgGradientEnd"
20035
+ (change)="applySignInBackground()"
20036
+ />
20037
+ </div>
20038
+ }
20039
+
20040
+ <!-- Sign-in content color -->
20041
+ <div style="margin-top: 24px;">
20042
+ <h3 style="font-size: 14px; font-weight: 600; color: #333; margin: 0 0 12px 0;">Content Color</h3>
20043
+ <div class="color-row">
20044
+ <label>Text</label>
20045
+ <input
20046
+ type="color"
20047
+ [(ngModel)]="customSignInContentColor"
20048
+ (change)="applySignInContentColor()"
20049
+ />
20050
+ <input
20051
+ type="text"
20052
+ [(ngModel)]="customSignInContentColor"
20053
+ (change)="applySignInContentColor()"
20054
+ />
20055
+ </div>
20056
+ </div>
20057
+ </div>
20058
+ </div>
20059
+ </div>
20060
+
20061
+ <!-- Logo & Logomark Preview -->
20062
+ <div class="demo-section">
20063
+ <h2>Logo Preview</h2>
20064
+
20065
+ <!-- Logo Size Selector -->
20066
+ <div style="margin-bottom: 16px;">
20067
+ <h3 style="font-size: 14px; font-weight: 600; color: #333; margin: 0 0 12px 0;">Header Logo Size</h3>
20068
+ <div class="theme-buttons">
20069
+ <button
20070
+ class="theme-btn"
20071
+ (click)="updateLogoSize('sm')"
20072
+ [class.active]="whitelabelService.logoSize() === 'sm'">
20073
+ Small (24px)
20074
+ </button>
20075
+ <button
20076
+ class="theme-btn"
20077
+ (click)="updateLogoSize('md')"
20078
+ [class.active]="whitelabelService.logoSize() === 'md'">
20079
+ Medium (28px)
20080
+ </button>
20081
+ <button
20082
+ class="theme-btn"
20083
+ (click)="updateLogoSize('lg')"
20084
+ [class.active]="whitelabelService.logoSize() === 'lg'">
20085
+ Large (32px)
20086
+ </button>
20087
+ <button
20088
+ class="theme-btn"
20089
+ (click)="updateLogoSize('xl')"
20090
+ [class.active]="whitelabelService.logoSize() === 'xl'">
20091
+ XLarge (36px)
20092
+ </button>
20093
+ </div>
20094
+ </div>
20095
+
20096
+ <div class="preview-grid">
20097
+ <div class="preview-tile">
20098
+ <h3>Logo</h3>
20099
+ <div class="logo-preview">
20100
+ <ds-logo variant="full" />
20101
+ </div>
20102
+ </div>
20103
+ <div class="preview-tile">
20104
+ <h3>Logomark</h3>
20105
+ <div class="logomark-preview">
20106
+ <ds-avatar-with-badge
20107
+ [type]="'initials'"
20108
+ [initials]="'KN'"
20109
+ [size]="'md'"
20110
+ [badgePosition]="'bottom-right'"
20111
+ />
20112
+ </div>
20113
+ </div>
20114
+ </div>
20115
+ </div>
20116
+
20117
+ <!-- App Icon -->
20118
+ <div class="demo-section">
20119
+ <h2>App Icon</h2>
20120
+ <div class="app-icon-sizes">
20121
+ <div class="app-icon-demo">
20122
+ <ds-app-icon size="xl" />
20123
+ </div>
20124
+ </div>
20125
+ </div>
20126
+
20127
+ <!-- Brand Colors -->
20128
+ <div class="demo-section">
20129
+ <h2>Brand Colors</h2>
20130
+ <div class="color-section">
20131
+ <div class="color-swatches">
20132
+ <div class="swatch swatch--app-icon-surface">
20133
+ <div class="swatch-label">App Icon Surface</div>
20134
+ <div class="swatch-value">{{ whitelabelService.appIconSurface() }}</div>
20135
+ </div>
20136
+ <div class="swatch swatch--app-icon-content">
20137
+ <div class="swatch-label">App Icon Content</div>
20138
+ <div class="swatch-value">{{ whitelabelService.appIconContent() }}</div>
20139
+ </div>
20140
+ <div class="swatch swatch--accent">
20141
+ <div class="swatch-label">Accent</div>
20142
+ <div class="swatch-value">{{ whitelabelService.accent() }}</div>
20143
+ </div>
20144
+ <div class="swatch swatch--on-accent">
20145
+ <div class="swatch-label">On Accent</div>
20146
+ <div class="swatch-value">{{ whitelabelService.onAccent() }}</div>
20147
+ </div>
20148
+ <div class="swatch swatch--header-surface">
20149
+ <div class="swatch-label">Header Surface</div>
20150
+ <div class="swatch-value">{{ whitelabelService.headerSurface() }}</div>
20151
+ </div>
20152
+ <div class="swatch swatch--header-content">
20153
+ <div class="swatch-label">Header Content</div>
20154
+ <div class="swatch-value">{{ whitelabelService.headerContent() }}</div>
20155
+ </div>
20156
+ </div>
20157
+
20158
+ <div class="color-inputs">
20159
+ <div class="color-group-label">App Icon</div>
20160
+ <div class="color-row">
20161
+ <label>Surface</label>
20162
+ <input
20163
+ type="color"
20164
+ [(ngModel)]="customAppIconSurface"
20165
+ (change)="applyCustomColors()"
20166
+ />
20167
+ <input
20168
+ type="text"
20169
+ [(ngModel)]="customAppIconSurface"
20170
+ (change)="applyCustomColors()"
20171
+ />
20172
+ </div>
20173
+ <div class="color-row">
20174
+ <label>Content</label>
20175
+ <input
20176
+ type="color"
20177
+ [(ngModel)]="customAppIconContent"
20178
+ (change)="applyCustomColors()"
20179
+ />
20180
+ <input
20181
+ type="text"
20182
+ [(ngModel)]="customAppIconContent"
20183
+ (change)="applyCustomColors()"
20184
+ />
20185
+ </div>
20186
+
20187
+ <div class="color-group-label">Accent</div>
20188
+ <div class="color-row">
20189
+ <label>Base</label>
20190
+ <input
20191
+ type="color"
20192
+ [(ngModel)]="customAccent"
20193
+ (change)="applyCustomColors()"
20194
+ />
20195
+ <input
20196
+ type="text"
20197
+ [(ngModel)]="customAccent"
20198
+ (change)="applyCustomColors()"
20199
+ />
20200
+ </div>
20201
+ <div class="color-row">
20202
+ <label>On Accent</label>
20203
+ <input
20204
+ type="color"
20205
+ [(ngModel)]="customOnAccent"
20206
+ (change)="applyCustomColors()"
20207
+ />
20208
+ <input
20209
+ type="text"
20210
+ [(ngModel)]="customOnAccent"
20211
+ (change)="applyCustomColors()"
20212
+ />
20213
+ </div>
20214
+
20215
+ <div class="color-group-label">Header</div>
20216
+ <div class="color-row">
20217
+ <label>Surface</label>
20218
+ <input
20219
+ type="color"
20220
+ [(ngModel)]="customHeaderSurface"
20221
+ (change)="applyCustomColors()"
20222
+ />
20223
+ <input
20224
+ type="text"
20225
+ [(ngModel)]="customHeaderSurface"
20226
+ (change)="applyCustomColors()"
20227
+ />
20228
+ </div>
20229
+ <div class="color-row">
20230
+ <label>Content</label>
20231
+ <input
20232
+ type="color"
20233
+ [(ngModel)]="customHeaderContent"
20234
+ (change)="applyCustomColors()"
20235
+ />
20236
+ <input
20237
+ type="text"
20238
+ [(ngModel)]="customHeaderContent"
20239
+ (change)="applyCustomColors()"
20240
+ />
20241
+ </div>
20242
+ <div class="color-row">
20243
+ <label>Accent</label>
20244
+ <input
20245
+ type="color"
20246
+ [(ngModel)]="customHeaderAccent"
20247
+ (change)="applyCustomColors()"
20248
+ />
20249
+ <input
20250
+ type="text"
20251
+ [(ngModel)]="customHeaderAccent"
20252
+ (change)="applyCustomColors()"
20253
+ />
20254
+ </div>
20255
+ <div class="color-row">
20256
+ <label>On Accent</label>
20257
+ <input
20258
+ type="color"
20259
+ [(ngModel)]="customOnHeaderAccent"
20260
+ (change)="applyCustomColors()"
20261
+ />
20262
+ <input
20263
+ type="text"
20264
+ [(ngModel)]="customOnHeaderAccent"
20265
+ (change)="applyCustomColors()"
20266
+ />
20267
+ </div>
20268
+ </div>
20269
+ </div>
20270
+ </div>
20271
+ </div>
20272
+ </ion-content>
20273
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;background:var(--color-background-neutral-primary, #ffffff)}.modal-header{flex-shrink:0;background:var(--color-background-neutral-primary, #ffffff);border-bottom:1px solid var(--border-color-default, #e0e0e0);padding:0 16px}ion-content,.modal-content{--background: #ffffff;flex:1;width:100%}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:56px}.header-title{font-family:Brockmann,sans-serif;font-size:17px;font-weight:600;color:var(--color-text-primary, #1a1a1a);flex:1}.close-button{flex-shrink:0;border-radius:50%}.close-button::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important;background:var(--color-background-neutral-secondary, #f5f5f5)!important;color:var(--color-text-primary, #1a1a1a)!important}.demo-container{padding:20px;max-width:600px;margin:0 auto;width:100%}.demo-section{margin-bottom:32px}.demo-section h2{margin-bottom:16px;font-size:18px;font-weight:600;color:#333}.theme-buttons{display:flex;gap:12px;flex-wrap:wrap}.theme-btn{padding:8px 16px;border-radius:8px;font-size:14px;font-weight:500;border:none;cursor:pointer;transition:all .2s ease;background:#e0e0e0;color:#333}.theme-btn:active{transform:scale(.98)}.theme-btn.active{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.logo-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:var(--color-brand-secondary);border-radius:12px;min-height:80px}.logomark-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:#fff;border:1px solid #e0e0e0;border-radius:12px;min-height:80px}.preview-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.preview-tile{background:#fff;border-radius:12px}.preview-tile h3{font-size:13px;font-weight:600;color:#666;margin-top:0;margin-bottom:12px}.app-icon-sizes{display:flex;gap:24px;align-items:flex-end;justify-content:center;padding:24px;background:#fff;border-radius:12px;border:1px solid var(--border-color-default, #e0e0e0);flex-wrap:wrap}.app-icon-demo{display:flex;flex-direction:column;align-items:center;gap:12px;--app-icon-background: var(--color-app-icon-surface)}.app-icon-demo span{font-size:12px;color:#666;font-family:monospace}.color-section{background:#fff;border-radius:12px}.color-swatches{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}.swatch{padding:16px;border-radius:8px;text-align:center}.swatch-label{font-size:12px;font-weight:600;margin-bottom:4px}.swatch-value{font-size:11px;opacity:.8;font-family:monospace}.swatch--app-icon-surface{background:var(--color-app-icon-surface);color:var(--color-app-icon-content)}.swatch--app-icon-content{background:var(--color-app-icon-content);color:var(--color-app-icon-surface);border:1px solid #e0e0e0}.swatch--accent{background:var(--color-accent);color:var(--color-on-accent)}.swatch--on-accent{background:var(--color-on-accent);color:var(--color-accent);border:1px solid #e0e0e0}.swatch--header-surface{background:var(--color-header-surface);color:var(--color-header-content)}.swatch--header-content{background:var(--color-header-content);color:var(--color-header-surface);border:1px solid #e0e0e0}.color-inputs{display:flex;flex-direction:column;gap:12px}.color-group-label{font-size:13px;font-weight:600;color:#333;margin-top:8px}.color-row{display:flex;align-items:center;gap:12px}.color-row label{min-width:70px;font-size:13px;color:#666}.color-row input[type=color]{width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;padding:0}.color-row input[type=text]{flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-family:monospace;font-size:13px}.toggle-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0}.toggle-row label{font-size:14px;color:#333;font-weight:500}.toggle-row input[type=checkbox]{width:48px;height:28px;-webkit-appearance:none;appearance:none;background:#ddd;border-radius:14px;position:relative;cursor:pointer;transition:background .2s ease;flex-shrink:0}.toggle-row input[type=checkbox]:checked{background:var(--color-accent)}.toggle-row input[type=checkbox]:before{content:\"\";position:absolute;width:24px;height:24px;border-radius:50%;background:#fff;top:2px;left:2px;transition:transform .2s ease;box-shadow:0 1px 3px #0003}.toggle-row input[type=checkbox]:checked:before{transform:translate(20px)}.radio-group{display:flex;gap:16px;margin-bottom:16px}.radio-option{display:flex;align-items:center;gap:8px;cursor:pointer}.radio-option input[type=radio]{width:18px;height:18px;cursor:pointer;accent-color:var(--color-accent)}.radio-option label{font-size:14px;color:#333;cursor:pointer;font-weight:500}.bg-preview{height:80px;border-radius:8px;margin-bottom:16px;border:1px solid #e0e0e0;position:relative;overflow:hidden}.bg-preview:after{content:\"Preview\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:12px;font-weight:600;color:#0000004d;text-shadow:0 1px 2px rgba(255,255,255,.5)}@supports (padding: env(safe-area-inset-bottom)){.demo-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: DsLogoComponent, selector: "ds-logo", inputs: ["variant", "size", "customHeight", "customWidth"] }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsAppIconComponent, selector: "ds-app-icon", inputs: ["size"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
20274
+ }
20275
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalComponent, decorators: [{
20276
+ type: Component,
20277
+ args: [{ selector: 'ds-whitelabel-demo-modal', standalone: true, imports: [
20278
+ CommonModule,
20279
+ FormsModule,
20280
+ IonContent,
20281
+ DsLogoComponent,
20282
+ DsAvatarWithBadgeComponent,
20283
+ DsAppIconComponent,
20284
+ DsIconButtonComponent
20285
+ ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
20286
+ <!-- Fixed Header -->
20287
+ <div class="modal-header">
20288
+ <div class="header-content">
20289
+ <span class="header-title">Whitelabel</span>
20290
+ <ds-icon-button
20291
+ icon="remixCloseLine"
20292
+ variant="secondary"
20293
+ size="lg"
20294
+ (click)="close()"
20295
+ class="close-button"
20296
+ aria-label="Close">
20297
+ </ds-icon-button>
20298
+ </div>
20299
+ </div>
20300
+
20301
+ <!-- Scrollable Content -->
20302
+ <ion-content [scrollY]="true" class="modal-content">
20303
+ <div class="demo-container">
20304
+ <!-- Theme Selection -->
20305
+ <div class="demo-section">
20306
+ <h2>Theme</h2>
20307
+ <div class="theme-buttons">
20308
+ <button class="theme-btn" (click)="applyDefaultTheme()" [class.active]="currentTheme === 'default'">
20309
+ Propbinder
20310
+ </button>
20311
+ <button class="theme-btn" (click)="applyCejTheme()" [class.active]="currentTheme === 'cej'">
20312
+ CEJ
20313
+ </button>
20314
+ <button class="theme-btn" (click)="applyPkaTheme()" [class.active]="currentTheme === 'pka'">
20315
+ PKA
20316
+ </button>
20317
+ <button class="theme-btn" (click)="applyClaveTheme()" [class.active]="currentTheme === 'clave'">
20318
+ Clave
20319
+ </button>
20320
+ <button class="theme-btn" (click)="applyFreedomTheme()" [class.active]="currentTheme === 'freedom'">
20321
+ Freedom
20322
+ </button>
20323
+ </div>
20324
+ </div>
20325
+
20326
+ <!-- Sign-in Page Options -->
20327
+ <div class="demo-section">
20328
+ <h2>Sign-in Page</h2>
20329
+ <div class="color-section">
20330
+ <div class="toggle-row">
20331
+ <label>Show City Illustration</label>
20332
+ <input
20333
+ type="checkbox"
20334
+ [checked]="whitelabelService.showCityIllustration()"
20335
+ [disabled]="currentTheme !== 'default'"
20336
+ (change)="toggleCityIllustration()"
20337
+ [style.opacity]="currentTheme !== 'default' ? '0.5' : '1'"
20338
+ [style.cursor]="currentTheme !== 'default' ? 'not-allowed' : 'pointer'"
20339
+ />
20340
+ </div>
20341
+
20342
+ <div style="margin-top: 24px;">
20343
+ <h3 style="font-size: 14px; font-weight: 600; color: #333; margin: 0 0 12px 0;">Background</h3>
20344
+
20345
+ <!-- Background type selector -->
20346
+ <div class="radio-group">
20347
+ <div class="radio-option">
20348
+ <input
20349
+ type="radio"
20350
+ id="bg-solid"
20351
+ name="bgType"
20352
+ value="solid"
20353
+ [checked]="whitelabelService.signInBgType() === 'solid'"
20354
+ (change)="updateSignInBgType('solid')"
20355
+ />
20356
+ <label for="bg-solid">Solid</label>
20357
+ </div>
20358
+ <div class="radio-option">
20359
+ <input
20360
+ type="radio"
20361
+ id="bg-gradient"
20362
+ name="bgType"
20363
+ value="gradient"
20364
+ [checked]="whitelabelService.signInBgType() === 'gradient'"
20365
+ (change)="updateSignInBgType('gradient')"
20366
+ />
20367
+ <label for="bg-gradient">Gradient</label>
20368
+ </div>
20369
+ </div>
20370
+
20371
+ <!-- Background preview -->
20372
+ <div class="bg-preview" [style.background]="whitelabelService.signInBgStyle()"></div>
20373
+
20374
+ <!-- Solid color input -->
20375
+ @if (whitelabelService.signInBgType() === 'solid') {
20376
+ <div class="color-row">
20377
+ <label>Color</label>
20378
+ <input
20379
+ type="color"
20380
+ [(ngModel)]="customSignInBgSolid"
20381
+ (change)="applySignInBackground()"
20382
+ />
20383
+ <input
20384
+ type="text"
20385
+ [(ngModel)]="customSignInBgSolid"
20386
+ (change)="applySignInBackground()"
20387
+ />
20388
+ </div>
20389
+ }
20390
+
20391
+ <!-- Gradient color inputs -->
20392
+ @if (whitelabelService.signInBgType() === 'gradient') {
20393
+ <div class="color-row">
20394
+ <label>Start</label>
20395
+ <input
20396
+ type="color"
20397
+ [(ngModel)]="customSignInBgGradientStart"
20398
+ (change)="applySignInBackground()"
20399
+ />
20400
+ <input
20401
+ type="text"
20402
+ [(ngModel)]="customSignInBgGradientStart"
20403
+ (change)="applySignInBackground()"
20404
+ />
20405
+ </div>
20406
+ <div class="color-row">
20407
+ <label>End</label>
20408
+ <input
20409
+ type="color"
20410
+ [(ngModel)]="customSignInBgGradientEnd"
20411
+ (change)="applySignInBackground()"
20412
+ />
20413
+ <input
20414
+ type="text"
20415
+ [(ngModel)]="customSignInBgGradientEnd"
20416
+ (change)="applySignInBackground()"
20417
+ />
20418
+ </div>
20419
+ }
20420
+
20421
+ <!-- Sign-in content color -->
20422
+ <div style="margin-top: 24px;">
20423
+ <h3 style="font-size: 14px; font-weight: 600; color: #333; margin: 0 0 12px 0;">Content Color</h3>
20424
+ <div class="color-row">
20425
+ <label>Text</label>
20426
+ <input
20427
+ type="color"
20428
+ [(ngModel)]="customSignInContentColor"
20429
+ (change)="applySignInContentColor()"
20430
+ />
20431
+ <input
20432
+ type="text"
20433
+ [(ngModel)]="customSignInContentColor"
20434
+ (change)="applySignInContentColor()"
20435
+ />
20436
+ </div>
20437
+ </div>
20438
+ </div>
20439
+ </div>
20440
+ </div>
20441
+
20442
+ <!-- Logo & Logomark Preview -->
20443
+ <div class="demo-section">
20444
+ <h2>Logo Preview</h2>
20445
+
20446
+ <!-- Logo Size Selector -->
20447
+ <div style="margin-bottom: 16px;">
20448
+ <h3 style="font-size: 14px; font-weight: 600; color: #333; margin: 0 0 12px 0;">Header Logo Size</h3>
20449
+ <div class="theme-buttons">
20450
+ <button
20451
+ class="theme-btn"
20452
+ (click)="updateLogoSize('sm')"
20453
+ [class.active]="whitelabelService.logoSize() === 'sm'">
20454
+ Small (24px)
20455
+ </button>
20456
+ <button
20457
+ class="theme-btn"
20458
+ (click)="updateLogoSize('md')"
20459
+ [class.active]="whitelabelService.logoSize() === 'md'">
20460
+ Medium (28px)
20461
+ </button>
20462
+ <button
20463
+ class="theme-btn"
20464
+ (click)="updateLogoSize('lg')"
20465
+ [class.active]="whitelabelService.logoSize() === 'lg'">
20466
+ Large (32px)
20467
+ </button>
20468
+ <button
20469
+ class="theme-btn"
20470
+ (click)="updateLogoSize('xl')"
20471
+ [class.active]="whitelabelService.logoSize() === 'xl'">
20472
+ XLarge (36px)
20473
+ </button>
20474
+ </div>
20475
+ </div>
20476
+
20477
+ <div class="preview-grid">
20478
+ <div class="preview-tile">
20479
+ <h3>Logo</h3>
20480
+ <div class="logo-preview">
20481
+ <ds-logo variant="full" />
20482
+ </div>
20483
+ </div>
20484
+ <div class="preview-tile">
20485
+ <h3>Logomark</h3>
20486
+ <div class="logomark-preview">
20487
+ <ds-avatar-with-badge
20488
+ [type]="'initials'"
20489
+ [initials]="'KN'"
20490
+ [size]="'md'"
20491
+ [badgePosition]="'bottom-right'"
20492
+ />
20493
+ </div>
20494
+ </div>
20495
+ </div>
20496
+ </div>
20497
+
20498
+ <!-- App Icon -->
20499
+ <div class="demo-section">
20500
+ <h2>App Icon</h2>
20501
+ <div class="app-icon-sizes">
20502
+ <div class="app-icon-demo">
20503
+ <ds-app-icon size="xl" />
20504
+ </div>
20505
+ </div>
20506
+ </div>
20507
+
20508
+ <!-- Brand Colors -->
20509
+ <div class="demo-section">
20510
+ <h2>Brand Colors</h2>
20511
+ <div class="color-section">
20512
+ <div class="color-swatches">
20513
+ <div class="swatch swatch--app-icon-surface">
20514
+ <div class="swatch-label">App Icon Surface</div>
20515
+ <div class="swatch-value">{{ whitelabelService.appIconSurface() }}</div>
20516
+ </div>
20517
+ <div class="swatch swatch--app-icon-content">
20518
+ <div class="swatch-label">App Icon Content</div>
20519
+ <div class="swatch-value">{{ whitelabelService.appIconContent() }}</div>
20520
+ </div>
20521
+ <div class="swatch swatch--accent">
20522
+ <div class="swatch-label">Accent</div>
20523
+ <div class="swatch-value">{{ whitelabelService.accent() }}</div>
20524
+ </div>
20525
+ <div class="swatch swatch--on-accent">
20526
+ <div class="swatch-label">On Accent</div>
20527
+ <div class="swatch-value">{{ whitelabelService.onAccent() }}</div>
20528
+ </div>
20529
+ <div class="swatch swatch--header-surface">
20530
+ <div class="swatch-label">Header Surface</div>
20531
+ <div class="swatch-value">{{ whitelabelService.headerSurface() }}</div>
20532
+ </div>
20533
+ <div class="swatch swatch--header-content">
20534
+ <div class="swatch-label">Header Content</div>
20535
+ <div class="swatch-value">{{ whitelabelService.headerContent() }}</div>
20536
+ </div>
20537
+ </div>
20538
+
20539
+ <div class="color-inputs">
20540
+ <div class="color-group-label">App Icon</div>
20541
+ <div class="color-row">
20542
+ <label>Surface</label>
20543
+ <input
20544
+ type="color"
20545
+ [(ngModel)]="customAppIconSurface"
20546
+ (change)="applyCustomColors()"
20547
+ />
20548
+ <input
20549
+ type="text"
20550
+ [(ngModel)]="customAppIconSurface"
20551
+ (change)="applyCustomColors()"
20552
+ />
20553
+ </div>
20554
+ <div class="color-row">
20555
+ <label>Content</label>
20556
+ <input
20557
+ type="color"
20558
+ [(ngModel)]="customAppIconContent"
20559
+ (change)="applyCustomColors()"
20560
+ />
20561
+ <input
20562
+ type="text"
20563
+ [(ngModel)]="customAppIconContent"
20564
+ (change)="applyCustomColors()"
20565
+ />
20566
+ </div>
20567
+
20568
+ <div class="color-group-label">Accent</div>
20569
+ <div class="color-row">
20570
+ <label>Base</label>
20571
+ <input
20572
+ type="color"
20573
+ [(ngModel)]="customAccent"
20574
+ (change)="applyCustomColors()"
20575
+ />
20576
+ <input
20577
+ type="text"
20578
+ [(ngModel)]="customAccent"
20579
+ (change)="applyCustomColors()"
20580
+ />
20581
+ </div>
20582
+ <div class="color-row">
20583
+ <label>On Accent</label>
20584
+ <input
20585
+ type="color"
20586
+ [(ngModel)]="customOnAccent"
20587
+ (change)="applyCustomColors()"
20588
+ />
20589
+ <input
20590
+ type="text"
20591
+ [(ngModel)]="customOnAccent"
20592
+ (change)="applyCustomColors()"
20593
+ />
20594
+ </div>
20595
+
20596
+ <div class="color-group-label">Header</div>
20597
+ <div class="color-row">
20598
+ <label>Surface</label>
20599
+ <input
20600
+ type="color"
20601
+ [(ngModel)]="customHeaderSurface"
20602
+ (change)="applyCustomColors()"
20603
+ />
20604
+ <input
20605
+ type="text"
20606
+ [(ngModel)]="customHeaderSurface"
20607
+ (change)="applyCustomColors()"
20608
+ />
20609
+ </div>
20610
+ <div class="color-row">
20611
+ <label>Content</label>
20612
+ <input
20613
+ type="color"
20614
+ [(ngModel)]="customHeaderContent"
20615
+ (change)="applyCustomColors()"
20616
+ />
20617
+ <input
20618
+ type="text"
20619
+ [(ngModel)]="customHeaderContent"
20620
+ (change)="applyCustomColors()"
20621
+ />
20622
+ </div>
20623
+ <div class="color-row">
20624
+ <label>Accent</label>
20625
+ <input
20626
+ type="color"
20627
+ [(ngModel)]="customHeaderAccent"
20628
+ (change)="applyCustomColors()"
20629
+ />
20630
+ <input
20631
+ type="text"
20632
+ [(ngModel)]="customHeaderAccent"
20633
+ (change)="applyCustomColors()"
20634
+ />
20635
+ </div>
20636
+ <div class="color-row">
20637
+ <label>On Accent</label>
20638
+ <input
20639
+ type="color"
20640
+ [(ngModel)]="customOnHeaderAccent"
20641
+ (change)="applyCustomColors()"
20642
+ />
20643
+ <input
20644
+ type="text"
20645
+ [(ngModel)]="customOnHeaderAccent"
20646
+ (change)="applyCustomColors()"
20647
+ />
20648
+ </div>
20649
+ </div>
20650
+ </div>
20651
+ </div>
20652
+ </div>
20653
+ </ion-content>
20654
+ `, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;background:var(--color-background-neutral-primary, #ffffff)}.modal-header{flex-shrink:0;background:var(--color-background-neutral-primary, #ffffff);border-bottom:1px solid var(--border-color-default, #e0e0e0);padding:0 16px}ion-content,.modal-content{--background: #ffffff;flex:1;width:100%}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:56px}.header-title{font-family:Brockmann,sans-serif;font-size:17px;font-weight:600;color:var(--color-text-primary, #1a1a1a);flex:1}.close-button{flex-shrink:0;border-radius:50%}.close-button::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important;background:var(--color-background-neutral-secondary, #f5f5f5)!important;color:var(--color-text-primary, #1a1a1a)!important}.demo-container{padding:20px;max-width:600px;margin:0 auto;width:100%}.demo-section{margin-bottom:32px}.demo-section h2{margin-bottom:16px;font-size:18px;font-weight:600;color:#333}.theme-buttons{display:flex;gap:12px;flex-wrap:wrap}.theme-btn{padding:8px 16px;border-radius:8px;font-size:14px;font-weight:500;border:none;cursor:pointer;transition:all .2s ease;background:#e0e0e0;color:#333}.theme-btn:active{transform:scale(.98)}.theme-btn.active{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.logo-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:var(--color-brand-secondary);border-radius:12px;min-height:80px}.logomark-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:#fff;border:1px solid #e0e0e0;border-radius:12px;min-height:80px}.preview-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.preview-tile{background:#fff;border-radius:12px}.preview-tile h3{font-size:13px;font-weight:600;color:#666;margin-top:0;margin-bottom:12px}.app-icon-sizes{display:flex;gap:24px;align-items:flex-end;justify-content:center;padding:24px;background:#fff;border-radius:12px;border:1px solid var(--border-color-default, #e0e0e0);flex-wrap:wrap}.app-icon-demo{display:flex;flex-direction:column;align-items:center;gap:12px;--app-icon-background: var(--color-app-icon-surface)}.app-icon-demo span{font-size:12px;color:#666;font-family:monospace}.color-section{background:#fff;border-radius:12px}.color-swatches{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}.swatch{padding:16px;border-radius:8px;text-align:center}.swatch-label{font-size:12px;font-weight:600;margin-bottom:4px}.swatch-value{font-size:11px;opacity:.8;font-family:monospace}.swatch--app-icon-surface{background:var(--color-app-icon-surface);color:var(--color-app-icon-content)}.swatch--app-icon-content{background:var(--color-app-icon-content);color:var(--color-app-icon-surface);border:1px solid #e0e0e0}.swatch--accent{background:var(--color-accent);color:var(--color-on-accent)}.swatch--on-accent{background:var(--color-on-accent);color:var(--color-accent);border:1px solid #e0e0e0}.swatch--header-surface{background:var(--color-header-surface);color:var(--color-header-content)}.swatch--header-content{background:var(--color-header-content);color:var(--color-header-surface);border:1px solid #e0e0e0}.color-inputs{display:flex;flex-direction:column;gap:12px}.color-group-label{font-size:13px;font-weight:600;color:#333;margin-top:8px}.color-row{display:flex;align-items:center;gap:12px}.color-row label{min-width:70px;font-size:13px;color:#666}.color-row input[type=color]{width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;padding:0}.color-row input[type=text]{flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-family:monospace;font-size:13px}.toggle-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0}.toggle-row label{font-size:14px;color:#333;font-weight:500}.toggle-row input[type=checkbox]{width:48px;height:28px;-webkit-appearance:none;appearance:none;background:#ddd;border-radius:14px;position:relative;cursor:pointer;transition:background .2s ease;flex-shrink:0}.toggle-row input[type=checkbox]:checked{background:var(--color-accent)}.toggle-row input[type=checkbox]:before{content:\"\";position:absolute;width:24px;height:24px;border-radius:50%;background:#fff;top:2px;left:2px;transition:transform .2s ease;box-shadow:0 1px 3px #0003}.toggle-row input[type=checkbox]:checked:before{transform:translate(20px)}.radio-group{display:flex;gap:16px;margin-bottom:16px}.radio-option{display:flex;align-items:center;gap:8px;cursor:pointer}.radio-option input[type=radio]{width:18px;height:18px;cursor:pointer;accent-color:var(--color-accent)}.radio-option label{font-size:14px;color:#333;cursor:pointer;font-weight:500}.bg-preview{height:80px;border-radius:8px;margin-bottom:16px;border:1px solid #e0e0e0;position:relative;overflow:hidden}.bg-preview:after{content:\"Preview\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:12px;font-weight:600;color:#0000004d;text-shadow:0 1px 2px rgba(255,255,255,.5)}@supports (padding: env(safe-area-inset-bottom)){.demo-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"] }]
20655
+ }] });
20656
+
20657
+ /**
20658
+ * WhitelabelDemoModalService
20659
+ *
20660
+ * Service for displaying the whitelabel demo in a full-screen modal.
20661
+ * Built on Ionic's modal system with native gestures and animations.
20662
+ *
20663
+ * @example
20664
+ * ```typescript
20665
+ * constructor(private whitelabelModal: WhitelabelDemoModalService) {}
20666
+ *
20667
+ * async openDemo() {
20668
+ * await this.whitelabelModal.open();
20669
+ * }
20670
+ * ```
20671
+ */
20672
+ class WhitelabelDemoModalService {
20673
+ modalController;
20674
+ constructor(modalController) {
20675
+ this.modalController = modalController;
20676
+ }
20677
+ /**
20678
+ * Open the whitelabel demo modal
20679
+ *
20680
+ * @returns Promise that resolves when the modal is presented
20681
+ */
20682
+ async open() {
20683
+ try {
20684
+ // console.log('[WhitelabelDemoModal] Opening...');
20685
+ const modal = await this.modalController.create({
20686
+ component: WhitelabelDemoModalComponent,
20687
+ cssClass: 'ds-whitelabel-demo-modal',
20688
+ mode: 'ios',
20689
+ presentingElement: document.querySelector('ion-router-outlet') || undefined,
20690
+ backdropDismiss: true,
20691
+ showBackdrop: true,
20692
+ animated: true,
20693
+ keyboardClose: true,
20694
+ // Control the presenting element animation
20695
+ enterAnimation: undefined, // Use default
20696
+ leaveAnimation: undefined, // Use default
20697
+ });
20698
+ // console.log('[WhitelabelDemoModal] Modal created, presenting...');
20699
+ await modal.present();
20700
+ // console.log('[WhitelabelDemoModal] Modal presented');
20701
+ }
20702
+ catch (error) {
20703
+ // console.error('[WhitelabelDemoModal] Error opening modal:', error);
20704
+ throw error;
20705
+ }
20706
+ }
20707
+ /**
20708
+ * Close the currently open whitelabel demo modal
20709
+ *
20710
+ * @param data Optional data to pass back when dismissing
20711
+ * @returns Promise that resolves when the modal is dismissed
20712
+ */
20713
+ async close(data) {
20714
+ return this.modalController.dismiss(data);
20715
+ }
20716
+ /**
20717
+ * Get the top-most modal if one exists
20718
+ *
20719
+ * @returns Promise that resolves to the modal element or undefined
20720
+ */
20721
+ async getTop() {
20722
+ return this.modalController.getTop();
20723
+ }
20724
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
20725
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService, providedIn: 'root' });
20726
+ }
20727
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: WhitelabelDemoModalService, decorators: [{
20728
+ type: Injectable,
20729
+ args: [{
20730
+ providedIn: 'root',
20731
+ }]
20732
+ }], ctorParameters: () => [{ type: i1.ModalController }] });
20733
+
19647
20734
  /**
19648
20735
  * MobileTabsExampleComponent
19649
20736
  *