@propbinder/mobile-design 0.2.0 → 0.2.2
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propbinder-mobile-design.mjs","sources":["../../../projects/mobile-design-lib/src/services/whitelabel.service.ts","../../../projects/mobile-design-lib/src/components/logo/ds-logo.ts","../../../projects/mobile-design-lib/src/components/shared/mobile-page-base.ts","../../../projects/mobile-design-lib/src/components/shared/directives/long-press.directive.ts","../../../projects/mobile-design-lib/src/components/list-item/ds-mobile-list-item.ts","../../../projects/mobile-design-lib/src/components/action-list-item/ds-mobile-action-list-item.ts","../../../projects/mobile-design-lib/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts","../../../projects/mobile-design-lib/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts","../../../projects/mobile-design-lib/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts","../../../projects/mobile-design-lib/src/services/user.service.ts","../../../projects/mobile-design-lib/src/components/avatar-with-badge/ds-avatar-with-badge.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo-modal.component.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo-modal.service.ts","../../../projects/mobile-design-lib/src/components/page-main/ds-mobile-page-main.ts","../../../projects/mobile-design-lib/src/components/page-details/ds-mobile-page-details.ts","../../../projects/mobile-design-lib/src/components/content/ds-mobile-content.ts","../../../projects/mobile-design-lib/src/components/header-content/ds-mobile-header-content.ts","../../../projects/mobile-design-lib/src/components/comment/ds-mobile-comment.ts","../../../projects/mobile-design-lib/src/components/post-composer/ds-mobile-post-composer.ts","../../../projects/mobile-design-lib/src/components/message-composer/ds-mobile-message-composer.ts","../../../projects/mobile-design-lib/src/components/message-bubble/ds-mobile-message-bubble.ts","../../../projects/mobile-design-lib/src/components/list-item-static/ds-mobile-list-item-static.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-post/index.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts","../../../projects/mobile-design-lib/src/components/contact-list-item/ds-mobile-contact-list-item.ts","../../../projects/mobile-design-lib/src/components/tab-bar/ds-mobile-tab-bar.ts","../../../projects/mobile-design-lib/src/components/tabs/ds-mobile-tabs.ts","../../../projects/mobile-design-lib/src/components/inline-tabs/ds-mobile-inline-tabs.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-header.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-footer.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-image.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-pdf.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox.service.ts","../../../projects/mobile-design-lib/src/components/lightbox/index.ts","../../../projects/mobile-design-lib/src/components/inline-photo/ds-mobile-inline-photo.ts","../../../projects/mobile-design-lib/src/components/modal/ds-mobile-modal.service.ts","../../../projects/mobile-design-lib/src/components/modal/index.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/index.ts","../../../projects/mobile-design-lib/src/components/chat-modal/ds-mobile-chat-modal.ts","../../../projects/mobile-design-lib/src/components/chat-modal/ds-mobile-chat-modal.service.ts","../../../projects/mobile-design-lib/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts","../../../projects/mobile-design-lib/src/components/card-inline/ds-mobile-card-inline.ts","../../../projects/mobile-design-lib/src/components/card-inline-file/ds-mobile-card-inline-file.ts","../../../projects/mobile-design-lib/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts","../../../projects/mobile-design-lib/src/components/swiper/ds-mobile-swiper.ts","../../../projects/mobile-design-lib/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts","../../../projects/mobile-design-lib/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts","../../../projects/mobile-design-lib/src/components/handbook-folder/ds-mobile-handbook-folder.ts","../../../projects/mobile-design-lib/src/components/text-input/ds-text-input.ts","../../../projects/mobile-design-lib/src/components/index.ts","../../../projects/mobile-design-lib/src/pages/community.page.ts","../../../projects/mobile-design-lib/src/pages/handbook.page.ts","../../../projects/mobile-design-lib/src/pages/home.page.ts","../../../projects/mobile-design-lib/src/animations/page-transitions.ts","../../../projects/mobile-design-lib/src/pages/inquiries.example.ts","../../../projects/mobile-design-lib/src/pages/inquiry-detail.example.ts","../../../projects/mobile-design-lib/src/pages/mobile-tabs-example.component.ts","../../../projects/mobile-design-lib/src/pages/post-create.page.ts","../../../projects/mobile-design-lib/src/pages/post-detail.page.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo.page.ts","../../../projects/mobile-design-lib/src/public-api.ts","../../../projects/mobile-design-lib/src/propbinder-mobile-design.ts"],"sourcesContent":["import { Injectable, signal, effect, computed } from '@angular/core';\r\nimport { StatusBar } from '@capacitor/status-bar';\r\n\r\nexport interface WhitelabelConfig {\r\n // Logo assets\r\n logoUrl: string; // Full logo for header (typically horizontal)\r\n logoMarkUrl: string; // Compact logo mark for avatars/badges\r\n logoAlt: string; // Alt text for accessibility\r\n \r\n // Logo dimensions (optional, for optimization)\r\n logoWidth?: number;\r\n logoHeight?: number;\r\n logoMarkWidth?: number;\r\n logoMarkHeight?: number;\r\n \r\n // Brand colors - these will update CSS custom properties\r\n primarySurface: string; // Background for primary elements (buttons, active states)\r\n primaryContent: string; // Text/icon color on primary surfaces\r\n secondarySurface: string; // Background for secondary elements (headers)\r\n secondaryContent: string; // Text/icon color on secondary surfaces (titles, active tabs)\r\n \r\n // Organization info\r\n organizationName: string;\r\n organizationId: string;\r\n}\r\n\r\nconst DEFAULT_CONFIG: WhitelabelConfig = {\r\n logoUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoAlt: 'Propbinder',\r\n logoHeight: 28, // Default logo height in pixels\r\n primarySurface: '#6B5FF5', // Propbinder brand purple - buttons, active states\r\n primaryContent: '#FFFFFF', // White text on primary surfaces\r\n secondarySurface: '#221a4c', // Propbinder dark purple - headers\r\n secondaryContent: '#FFFFFF', // White text on secondary surfaces (titles, active tabs)\r\n organizationName: 'Propbinder',\r\n organizationId: 'default'\r\n};\r\n\r\n/**\r\n * WhitelabelService\r\n * \r\n * Manages whitelabel configuration including logos and brand colors.\r\n * Automatically updates CSS custom properties when colors change.\r\n * \r\n * @example\r\n * Initialize with custom config:\r\n * ```typescript\r\n * whitelabelService.initialize({\r\n * logoUrl: '/Assets/logos/acme-logo.svg',\r\n * logoMarkUrl: '/Assets/logos/acme-mark.svg',\r\n * primaryColor: '#2563eb',\r\n * secondaryColor: '#3b82f6',\r\n * organizationName: 'Acme Corp'\r\n * });\r\n * ```\r\n * \r\n * Load from API:\r\n * ```typescript\r\n * await whitelabelService.loadFromApi('acme-corp');\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WhitelabelService {\r\n private _config = signal<WhitelabelConfig>(DEFAULT_CONFIG);\r\n \r\n // Readonly computed signals for accessing config values\r\n readonly logoUrl = computed(() => this._config().logoUrl);\r\n readonly logoMarkUrl = computed(() => this._config().logoMarkUrl);\r\n readonly logoAlt = computed(() => this._config().logoAlt);\r\n readonly logoHeight = computed(() => this._config().logoHeight ?? 32);\r\n readonly primarySurface = computed(() => this._config().primarySurface);\r\n readonly primaryContent = computed(() => this._config().primaryContent);\r\n readonly secondarySurface = computed(() => this._config().secondarySurface);\r\n readonly secondaryContent = computed(() => this._config().secondaryContent);\r\n readonly organizationName = computed(() => this._config().organizationName);\r\n readonly organizationId = computed(() => this._config().organizationId);\r\n \r\n // Full config accessor\r\n readonly config = this._config.asReadonly();\r\n \r\n constructor() {\r\n // Apply default colors on initialization\r\n this.applyColors(DEFAULT_CONFIG);\r\n \r\n // Watch for config changes and update CSS custom properties\r\n effect(() => {\r\n const config = this._config();\r\n this.applyColors(config);\r\n });\r\n }\r\n \r\n /**\r\n * Initialize whitelabel configuration\r\n * Call this early in app initialization (app.config.ts or app.component.ts)\r\n */\r\n initialize(config: Partial<WhitelabelConfig>) {\r\n this._config.update(current => ({\r\n ...current,\r\n ...config\r\n }));\r\n }\r\n \r\n /**\r\n * Load whitelabel config from API\r\n * Typically called on app startup based on subdomain, user tenant, etc.\r\n * \r\n * @param organizationId - The organization identifier (subdomain, tenant ID, etc.)\r\n */\r\n async loadFromApi(organizationId?: string): Promise<void> {\r\n try {\r\n // Example API call structure\r\n // const response = await fetch(`/api/whitelabel/${organizationId || 'default'}`);\r\n // const config = await response.json();\r\n // this.initialize(config);\r\n \r\n console.log('Loading whitelabel config from API for:', organizationId);\r\n \r\n // Example: Different configs for different organizations\r\n if (organizationId === 'demo-client') {\r\n this.initialize({\r\n logoUrl: '/Assets/logos/demo-logo.svg',\r\n logoMarkUrl: '/Assets/logos/demo-mark.svg',\r\n logoAlt: 'Demo Client',\r\n primarySurface: '#2563eb', // Blue\r\n primaryContent: '#FFFFFF', // White text on blue\r\n secondarySurface: '#3b82f6', // Lighter blue\r\n secondaryContent: '#FFFFFF', // White text on header\r\n organizationName: 'Demo Client',\r\n organizationId: 'demo-client'\r\n });\r\n }\r\n // Add more organization-specific configs as needed\r\n \r\n } catch (error) {\r\n console.error('Failed to load whitelabel config:', error);\r\n // Fallback to defaults already set\r\n }\r\n }\r\n \r\n /**\r\n * Update config dynamically (e.g., when user switches organizations)\r\n */\r\n updateConfig(updates: Partial<WhitelabelConfig>) {\r\n this.initialize(updates);\r\n }\r\n \r\n /**\r\n * Update only the brand colors\r\n */\r\n updateColors(colors: {\r\n primarySurface?: string;\r\n primaryContent?: string;\r\n secondarySurface?: string;\r\n secondaryContent?: string;\r\n }) {\r\n this._config.update(current => ({\r\n ...current,\r\n ...colors\r\n }));\r\n }\r\n \r\n /**\r\n * Reset to default configuration\r\n */\r\n resetToDefault() {\r\n this._config.set(DEFAULT_CONFIG);\r\n }\r\n \r\n /**\r\n * Convert hex color to RGB values\r\n */\r\n private hexToRgb(hex: string): { r: number; g: number; b: number } | null {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n return result ? {\r\n r: parseInt(result[1], 16),\r\n g: parseInt(result[2], 16),\r\n b: parseInt(result[3], 16)\r\n } : null;\r\n }\r\n \r\n /**\r\n * Apply colors to CSS custom properties and native StatusBar\r\n * This updates the actual CSS variables used throughout the app\r\n * and the native status bar color on mobile devices\r\n */\r\n private applyColors(config: WhitelabelConfig) {\r\n if (typeof document !== 'undefined') {\r\n const { primarySurface, primaryContent, secondarySurface, secondaryContent } = config;\r\n const root = document.documentElement;\r\n const body = document.body;\r\n const ionApp = document.querySelector('ion-app');\r\n \r\n // Primary surface color - used for buttons, selected states, accents background\r\n root.style.setProperty('--color-background-brand', primarySurface);\r\n root.style.setProperty('--color-brand-base', primarySurface);\r\n root.style.setProperty('--color-primary-surface', primarySurface);\r\n body.style.setProperty('--color-background-brand', primarySurface);\r\n body.style.setProperty('--color-brand-base', primarySurface);\r\n body.style.setProperty('--color-primary-surface', primarySurface);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--color-background-brand', primarySurface);\r\n (ionApp as HTMLElement).style.setProperty('--color-brand-base', primarySurface);\r\n (ionApp as HTMLElement).style.setProperty('--color-primary-surface', primarySurface);\r\n }\r\n \r\n // Primary content color - text/icon color on primary surfaces\r\n root.style.setProperty('--color-primary-content', primaryContent);\r\n body.style.setProperty('--color-primary-content', primaryContent);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--color-primary-content', primaryContent);\r\n }\r\n \r\n // Update tab button selected color directly\r\n // CSS variable inheritance doesn't always work dynamically with Ionic components\r\n document.querySelectorAll('ion-tab-button').forEach(tabButton => {\r\n (tabButton as HTMLElement).style.setProperty('--color-selected', primarySurface);\r\n });\r\n \r\n // Secondary surface color - used for headers, status bar background\r\n root.style.setProperty('--color-brand-secondary', secondarySurface);\r\n root.style.setProperty('--color-secondary-surface', secondarySurface);\r\n body.style.setProperty('--color-brand-secondary', secondarySurface);\r\n body.style.setProperty('--color-secondary-surface', secondarySurface);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--color-brand-secondary', secondarySurface);\r\n (ionApp as HTMLElement).style.setProperty('--color-secondary-surface', secondarySurface);\r\n }\r\n \r\n // Secondary content color - text/icon color on secondary surfaces (titles, active tabs)\r\n root.style.setProperty('--header-content-color', secondaryContent);\r\n root.style.setProperty('--color-secondary-content', secondaryContent);\r\n body.style.setProperty('--header-content-color', secondaryContent);\r\n body.style.setProperty('--color-secondary-content', secondaryContent);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--header-content-color', secondaryContent);\r\n (ionApp as HTMLElement).style.setProperty('--color-secondary-content', secondaryContent);\r\n }\r\n \r\n // Also set RGB values for use with rgba() opacity variations\r\n const rgb = this.hexToRgb(secondaryContent);\r\n if (rgb) {\r\n const rgbValue = `${rgb.r}, ${rgb.g}, ${rgb.b}`;\r\n root.style.setProperty('--header-content-color-rgb', rgbValue);\r\n root.style.setProperty('--color-secondary-content-rgb', rgbValue);\r\n body.style.setProperty('--header-content-color-rgb', rgbValue);\r\n body.style.setProperty('--color-secondary-content-rgb', rgbValue);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--header-content-color-rgb', rgbValue);\r\n (ionApp as HTMLElement).style.setProperty('--color-secondary-content-rgb', rgbValue);\r\n }\r\n }\r\n \r\n // Update theme-color meta tag for browser chrome/status bar (PWA/iOS)\r\n const metaThemeColor = document.querySelector('meta[name=\"theme-color\"]');\r\n if (metaThemeColor) {\r\n metaThemeColor.setAttribute('content', secondarySurface);\r\n }\r\n \r\n // Update native StatusBar color (Capacitor - Android only, iOS ignores this)\r\n this.updateNativeStatusBar(secondarySurface);\r\n \r\n console.log('Applied whitelabel colors:', { primarySurface, primaryContent, secondarySurface, secondaryContent });\r\n }\r\n }\r\n \r\n /**\r\n * Update the native status bar color\r\n * Note: This only works on Android. On iOS, the status bar is transparent\r\n * and shows the web content behind it (controlled by CSS variables)\r\n */\r\n private async updateNativeStatusBar(color: string): Promise<void> {\r\n try {\r\n await StatusBar.setBackgroundColor({ color });\r\n } catch (e) {\r\n // StatusBar API not available (web browser) or failed\r\n // This is expected on web and iOS, so we don't log it as an error\r\n }\r\n }\r\n}\r\n\r\n","import { Component, Input, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { WhitelabelService } from '../../services/whitelabel.service';\r\n\r\nexport type LogoVariant = 'full' | 'mark';\r\nexport type LogoSize = 'sm' | 'md' | 'lg' | 'xl';\r\n\r\n/**\r\n * DsLogoComponent\r\n * \r\n * Displays the whitelabeled logo or logomark based on current configuration.\r\n * Automatically pulls logo assets from WhitelabelService.\r\n * \r\n * @example\r\n * Full logo in header:\r\n * ```html\r\n * <ds-logo variant=\"full\" size=\"md\" />\r\n * ```\r\n * \r\n * Logomark for compact spaces:\r\n * ```html\r\n * <ds-logo variant=\"mark\" size=\"sm\" />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-logo',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: flex;\r\n justify-content: flex-start;\r\n line-height: 0;\r\n }\r\n \r\n .logo {\r\n display: block;\r\n object-fit: contain;\r\n width: auto;\r\n }\r\n `],\r\n template: `\r\n <img \r\n [src]=\"logoSrc\"\r\n [alt]=\"logoAlt\"\r\n class=\"logo\"\r\n [style.height.px]=\"effectiveHeight\"\r\n [style.width]=\"customWidth ? customWidth + 'px' : 'auto'\"\r\n />\r\n `\r\n})\r\nexport class DsLogoComponent {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n @Input() variant: LogoVariant = 'full';\r\n @Input() size: LogoSize = 'md';\r\n @Input() customHeight?: number;\r\n @Input() customWidth?: number;\r\n \r\n get logoSrc(): string {\r\n const logoUrl = this.whitelabelService.logoUrl();\r\n const logoMarkUrl = this.whitelabelService.logoMarkUrl();\r\n \r\n if (this.variant === 'full') {\r\n // Use logo, fall back to logomark if logo doesn't exist\r\n return logoUrl || logoMarkUrl;\r\n } else {\r\n // Use logomark, fall back to logo if logomark doesn't exist\r\n return logoMarkUrl || logoUrl;\r\n }\r\n }\r\n \r\n get logoAlt(): string {\r\n const alt = this.whitelabelService.logoAlt();\r\n return this.variant === 'full' ? alt : `${alt} logo`;\r\n }\r\n \r\n /** \r\n * Priority: customHeight input > whitelabel config logoHeight > default 32px\r\n */\r\n get effectiveHeight(): number {\r\n return this.customHeight ?? this.whitelabelService.logoHeight();\r\n }\r\n}\r\n\r\n","import { input, computed, Directive } from '@angular/core';\r\n\r\n/**\r\n * Content width preset values\r\n * - 'narrow' - 640px max width (reading content)\r\n * - 'standard' - 1024px max width (default)\r\n * - 'wide' - 1440px max width (dashboards)\r\n * - 'full' - 100% width (no max)\r\n */\r\nexport type ContentWidth = 'narrow' | 'standard' | 'wide' | 'full';\r\n\r\n/**\r\n * MobilePageBase\r\n * \r\n * Shared base class for mobile page components (ds-mobile-page-main, ds-mobile-page-details).\r\n * Provides consistent content width control across all page types.\r\n * \r\n * **Padding Strategy:**\r\n * - All pages use 20px horizontal padding globally\r\n * - For tappable lists, use negative margins (e.g., margin: 0 -8px) to create full-width sections\r\n * - This approach simplifies padding management and provides consistency\r\n * \r\n * @internal This is a base class and should not be used directly.\r\n */\r\n@Directive()\r\nexport abstract class MobilePageBase {\r\n /**\r\n * Maximum content width (desktop only)\r\n * \r\n * **Options:**\r\n * - `'narrow'` (640px) - For reading content, forms\r\n * - `'standard'` (1024px) - Default for most pages\r\n * - `'wide'` (1440px) - For dashboards, tables\r\n * - `'full'` - No max-width constraint\r\n * \r\n * **Note:** Only applies on desktop (>= 768px). Mobile is always full width.\r\n * \r\n * @default 'standard'\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Narrow reading layout -->\r\n * <ds-mobile-page-main title=\"Article\" contentWidth=\"narrow\">\r\n * \r\n * <!-- Wide dashboard -->\r\n * <ds-mobile-page-main title=\"Dashboard\" contentWidth=\"wide\">\r\n * ```\r\n */\r\n contentWidth = input<ContentWidth>('standard');\r\n\r\n /**\r\n * Resolved max-width value (computed)\r\n * Maps preset values to pixel values\r\n * \r\n * @internal\r\n */\r\n protected maxWidthValue = computed(() => {\r\n const w = this.contentWidth();\r\n \r\n const widthMap: Record<ContentWidth, string> = {\r\n 'narrow': '640px',\r\n 'standard': '1024px',\r\n 'wide': '1440px',\r\n 'full': '100%'\r\n };\r\n \r\n return widthMap[w];\r\n });\r\n}\r\n\r\n","import { \r\n Directive, \r\n Output, \r\n EventEmitter, \r\n HostListener, \r\n Input,\r\n OnDestroy \r\n} from '@angular/core';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\n\r\n/**\r\n * DsMobileLongPressDirective\r\n * \r\n * A reusable directive for handling long press interactions on mobile devices.\r\n * Provides haptic feedback and prevents long press when touching interactive elements.\r\n * \r\n * Features:\r\n * - Configurable duration and movement threshold\r\n * - Automatic haptic feedback (with fallback to navigator.vibrate)\r\n * - Excludes interactive elements (buttons, links, inputs)\r\n * - Handles touchmove cancellation\r\n * - Context menu support (right-click on desktop)\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Basic usage -->\r\n * <div dsMobileLongPress (longPress)=\"handleLongPress()\">\r\n * Long press me\r\n * </div>\r\n * \r\n * <!-- Custom duration and threshold -->\r\n * <div \r\n * dsMobileLongPress \r\n * [longPressDuration]=\"800\"\r\n * [moveThreshold]=\"15\"\r\n * [excludeSelectors]=\"'button, a, .no-longpress'\"\r\n * (longPress)=\"showContextMenu()\">\r\n * Custom long press\r\n * </div>\r\n * ```\r\n */\r\n@Directive({\r\n selector: '[dsMobileLongPress]',\r\n standalone: true\r\n})\r\nexport class DsMobileLongPressDirective implements OnDestroy {\r\n /**\r\n * Duration in milliseconds to trigger long press\r\n * @default 500\r\n */\r\n @Input() longPressDuration = 500;\r\n\r\n /**\r\n * Maximum movement in pixels before canceling long press\r\n * @default 10\r\n */\r\n @Input() moveThreshold = 10;\r\n\r\n /**\r\n * CSS selectors to exclude from long press detection\r\n * @default 'button, a, input, select, textarea, [role=\"button\"]'\r\n */\r\n @Input() excludeSelectors = 'button, a, input, select, textarea, [role=\"button\"]';\r\n\r\n /**\r\n * Haptic feedback style (Light, Medium, Heavy)\r\n * @default ImpactStyle.Medium\r\n */\r\n @Input() hapticStyle: ImpactStyle = ImpactStyle.Medium;\r\n\r\n /**\r\n * Enable/disable haptic feedback\r\n * @default true\r\n */\r\n @Input() enableHaptics = true;\r\n\r\n /**\r\n * Emits when long press is triggered\r\n */\r\n @Output() longPress = new EventEmitter<void>();\r\n\r\n /**\r\n * Emits when long press starts (timer begins)\r\n */\r\n @Output() longPressStart = new EventEmitter<void>();\r\n\r\n /**\r\n * Emits when long press is cancelled\r\n */\r\n @Output() longPressCancel = new EventEmitter<void>();\r\n\r\n private longPressTimer: any = null;\r\n private longPressTriggered = false;\r\n private touchStartX = 0;\r\n private touchStartY = 0;\r\n\r\n /**\r\n * Handle touch start for long press detection\r\n */\r\n @HostListener('touchstart', ['$event'])\r\n handleTouchStart(event: TouchEvent): void {\r\n // Don't start long press if touching interactive child elements\r\n // But allow if the closest match is the host element itself (where the directive is attached)\r\n const target = event.target as HTMLElement;\r\n const closestExcluded = target.closest(this.excludeSelectors);\r\n const hostElement = (event.currentTarget as HTMLElement);\r\n \r\n // Only exclude if we found an excluded element AND it's not the host itself\r\n if (closestExcluded && closestExcluded !== hostElement) {\r\n return;\r\n }\r\n\r\n this.longPressTriggered = false;\r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n\r\n // Emit start event\r\n this.longPressStart.emit();\r\n\r\n // Start long press timer\r\n this.longPressTimer = setTimeout(async () => {\r\n this.longPressTriggered = true;\r\n this.longPress.emit();\r\n\r\n // Haptic feedback for long press\r\n if (this.enableHaptics) {\r\n await this.triggerHaptics();\r\n }\r\n }, this.longPressDuration);\r\n }\r\n\r\n /**\r\n * Handle touch end to clear long press timer\r\n */\r\n @HostListener('touchend', ['$event'])\r\n handleTouchEnd(event: TouchEvent): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n \r\n if (!this.longPressTriggered) {\r\n this.longPressCancel.emit();\r\n }\r\n }\r\n\r\n // Prevent normal click if long press was triggered\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle touch move to cancel long press if moved too much\r\n */\r\n @HostListener('touchmove', ['$event'])\r\n handleTouchMove(event: TouchEvent): void {\r\n if (!this.longPressTimer) return;\r\n\r\n const touch = event.touches[0];\r\n const deltaX = Math.abs(touch.clientX - this.touchStartX);\r\n const deltaY = Math.abs(touch.clientY - this.touchStartY);\r\n\r\n // Cancel long press if moved too far\r\n if (deltaX > this.moveThreshold || deltaY > this.moveThreshold) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n this.longPressTriggered = false;\r\n this.longPressCancel.emit();\r\n }\r\n }\r\n\r\n /**\r\n * Handle context menu (right-click on desktop) to trigger long press action\r\n */\r\n @HostListener('contextmenu', ['$event'])\r\n handleContextMenu(event: Event): void {\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n\r\n /**\r\n * Trigger haptic feedback\r\n */\r\n private async triggerHaptics(): Promise<void> {\r\n try {\r\n await Haptics.impact({ style: this.hapticStyle });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n // Map haptic styles to vibration durations\r\n const vibrationMap = {\r\n [ImpactStyle.Light]: 30,\r\n [ImpactStyle.Medium]: 50,\r\n [ImpactStyle.Heavy]: 80\r\n };\r\n navigator.vibrate(vibrationMap[this.hapticStyle] || 50);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup on destroy\r\n */\r\n ngOnDestroy(): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n }\r\n}\r\n","import { Component, input, output, computed, signal, PLATFORM_ID, inject } from '@angular/core';\r\nimport { CommonModule, isPlatformBrowser } from '@angular/common';\r\nimport { DsMobileLongPressDirective } from '../shared/directives/long-press.directive';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileListItemComponent\r\n * \r\n * A versatile, reusable list item component for mobile applications.\r\n * Supports both interactive and non-interactive modes with flexible content projection.\r\n * \r\n * Features:\r\n * - Interactive mode with click and long-press support\r\n * - Pseudo-element background extends 8px beyond bounds (no negative margins needed)\r\n * - Flexible content slots (leading, main, trailing)\r\n * - Optional structured inputs for common use cases (title, subtitle)\r\n * - Accessibility features (focus states, ARIA attributes)\r\n * - Disabled and loading states\r\n * \r\n * This component serves as the foundation for specialized list item types like posts,\r\n * notifications, messages, contacts, and other list content.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple structured usage -->\r\n * <ds-mobile-list-item\r\n * title=\"Document Title\"\r\n * subtitle=\"Supporting text\"\r\n * [interactive]=\"true\"\r\n * (itemClick)=\"handleClick()\">\r\n * \r\n * <ds-icon content-leading name=\"document\" />\r\n * </ds-mobile-list-item>\r\n * \r\n * <!-- Flexible custom usage -->\r\n * <ds-mobile-list-item\r\n * [interactive]=\"true\"\r\n * (itemClick)=\"handleClick()\"\r\n * (longPress)=\"showContextMenu()\">\r\n * \r\n * <div content-leading>\r\n * <ds-avatar initials=\"JD\" />\r\n * </div>\r\n * \r\n * <div content-main>\r\n * <h3>Custom Content</h3>\r\n * <p>Full control over layout and styling</p>\r\n * </div>\r\n * \r\n * <button content-trailing (click)=\"handleAction($event)\">\r\n * Action\r\n * </button>\r\n * </ds-mobile-list-item>\r\n * \r\n * <!-- Non-interactive read-only -->\r\n * <ds-mobile-list-item\r\n * title=\"Read-only Item\"\r\n * subtitle=\"No interaction\">\r\n * <ds-icon content-leading name=\"info\" />\r\n * </ds-mobile-list-item>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-list-item',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent],\r\n hostDirectives: [\r\n {\r\n directive: DsMobileLongPressDirective,\r\n outputs: ['longPress']\r\n }\r\n ],\r\n host: {\r\n '[class.interactive]': 'interactive() && !disabled()',\r\n '[class.disabled]': 'disabled()',\r\n '[class.loading]': 'loading()',\r\n '[class.no-divider]': '!showDivider()',\r\n '[class.variant-compact]': 'variant() === \"compact\"',\r\n '[class.align-top]': 'align() === \"top\"',\r\n '[class.align-center]': 'align() === \"center\"',\r\n '[class.align-bottom]': 'align() === \"bottom\"',\r\n '[attr.role]': 'interactive() ? \"button\" : null',\r\n '[attr.tabindex]': 'interactive() && !disabled() ? \"0\" : null',\r\n '[attr.aria-disabled]': 'disabled() ? \"true\" : null',\r\n '[style.--leading-size]': 'leadingSize()',\r\n '[style.--interactive-offset]': 'interactiveOffset()',\r\n '[style.--divider-spacing]': 'dividerSpacing()',\r\n '(click)': 'handleClick($event)',\r\n '(keydown.enter)': 'handleKeyDown($event)',\r\n '(keydown.space)': 'handleKeyDown($event)',\r\n '(longPress)': 'handleLongPress()'\r\n },\r\n styles: [`\r\n :host {\r\n display: block;\r\n position: relative;\r\n padding: var(--item-padding-top, 12px) 0 var(--item-padding-bottom, 12px) 0;\r\n box-sizing: border-box;\r\n /* CSS variables defined at host level for use by children and pseudo-elements */\r\n --leading-size: 32px;\r\n --content-gap: 12px;\r\n --interactive-offset: 8px;\r\n }\r\n \r\n /* Divider line on host */\r\n :host::after {\r\n content: '';\r\n position: absolute;\r\n bottom: 0;\r\n left: calc(var(--leading-size) + var(--content-gap));\r\n right: 0;\r\n height: 1px;\r\n background: var(--border-color-default, #e5e5e5);\r\n z-index: 1;\r\n display: var(--divider-display, block);\r\n }\r\n \r\n /* Hide divider when no-divider class is present */\r\n :host(.no-divider)::after {\r\n display: none;\r\n }\r\n \r\n .list-item-inner {\r\n display: flex;\r\n flex-direction: row;\r\n align-items: flex-start;\r\n gap: var(--content-gap);\r\n position: relative;\r\n }\r\n \r\n :host(.align-center) .list-item-inner {\r\n align-items: center;\r\n }\r\n \r\n :host(.align-bottom) .list-item-inner {\r\n align-items: flex-end;\r\n }\r\n \r\n /* Pseudo-element for interactive background */\r\n :host(.interactive) .list-item-inner::before {\r\n content: '';\r\n position: absolute;\r\n top: calc(-1 * var(--interactive-offset));\r\n left: calc(-1 * var(--interactive-offset));\r\n right: calc(-1 * var(--interactive-offset));\r\n bottom: calc(-1 * var(--interactive-offset));\r\n background: var(--color-background-primary, #ffffff);\r\n border-radius: 16px;\r\n z-index: -1;\r\n pointer-events: none;\r\n }\r\n \r\n /* Interactive states */\r\n :host(.interactive) {\r\n cursor: pointer;\r\n }\r\n \r\n /* Hover state (desktop only) */\r\n @media (hover: hover) and (pointer: fine) {\r\n :host(.interactive):hover .list-item-inner::before {\r\n background: var(--color-background-neutral-primary-hover, #f5f5f5);\r\n }\r\n }\r\n \r\n /* Active state */\r\n :host(.interactive):active .list-item-inner::before {\r\n background: var(--color-background-neutral-primary-hover, #f5f5f5);\r\n }\r\n \r\n /* Focus visible for keyboard navigation */\r\n :host(.interactive):focus-visible {\r\n outline: none;\r\n }\r\n \r\n :host(.interactive):focus-visible .list-item-inner::before {\r\n outline: 2px solid var(--color-brand-primary, #5d5fef);\r\n outline-offset: 2px;\r\n }\r\n \r\n /* Disabled state */\r\n :host(.disabled) {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n }\r\n \r\n /* Loading state */\r\n :host(.loading) {\r\n pointer-events: none;\r\n }\r\n \r\n /* Variants */\r\n :host(.variant-compact) .list-item-inner {\r\n gap: 8px;\r\n }\r\n \r\n /* Content slots */\r\n .content-leading {\r\n flex-shrink: 0;\r\n width: var(--leading-size);\r\n height: var(--leading-size);\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: center;\r\n position: relative;\r\n z-index: 1;\r\n }\r\n \r\n :host(.align-center) .content-leading {\r\n align-items: center;\r\n }\r\n \r\n :host(.align-bottom) .content-leading {\r\n align-items: flex-end;\r\n }\r\n \r\n .content-main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n position: relative;\r\n z-index: 1;\r\n justify-content: flex-start;\r\n }\r\n \r\n :host(.align-center) .content-main {\r\n justify-content: center;\r\n }\r\n \r\n :host(.align-bottom) .content-main {\r\n justify-content: flex-end;\r\n }\r\n \r\n .content-trailing {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: flex-start;\r\n position: relative;\r\n z-index: 1;\r\n }\r\n \r\n /* Structured content styles */\r\n .structured-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm, 14px);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .structured-subtitle {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm, 14px);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n /* Desktop more actions button - using ds-icon-button */\r\n .desktop-more-button::ng-deep button {\r\n border-radius: 50% !important;\r\n }\r\n `],\r\n template: `\r\n <div class=\"list-item-inner\">\r\n <div class=\"content-leading\">\r\n <ng-content select=\"[content-leading]\" />\r\n </div>\r\n \r\n <div class=\"content-main\">\r\n @if (title()) {\r\n <h3 class=\"structured-title\">{{ title() }}</h3>\r\n }\r\n @if (subtitle()) {\r\n <p class=\"structured-subtitle\">{{ subtitle() }}</p>\r\n }\r\n \r\n <ng-content select=\"[content-main]\" />\r\n <ng-content />\r\n </div>\r\n \r\n <div class=\"content-trailing\">\r\n @if (interactive() && enableLongPress() && showDesktopMoreButton() && isDesktop()) {\r\n <ds-icon-button\r\n class=\"desktop-more-button\"\r\n icon=\"remixMoreFill\"\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n (clicked)=\"handleMoreButtonClick($event)\"\r\n aria-label=\"More options\">\r\n </ds-icon-button>\r\n }\r\n <ng-content select=\"[content-trailing]\" />\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileListItemComponent {\r\n private platformId = inject(PLATFORM_ID);\r\n \r\n /**\r\n * Detect if viewport is desktop size\r\n * Use viewport width for breakpoint detection (show button on tablet and above)\r\n */\r\n isDesktop = signal<boolean>(false);\r\n \r\n constructor() {\r\n if (isPlatformBrowser(this.platformId)) {\r\n // Show button on tablet breakpoint and above (768px+)\r\n const isDesktopViewport = window.innerWidth >= 768;\r\n \r\n console.log('[ListItem] Desktop detection:', {\r\n innerWidth: window.innerWidth,\r\n isDesktopViewport\r\n });\r\n \r\n this.isDesktop.set(isDesktopViewport);\r\n \r\n // Listen for window resize to update detection\r\n window.addEventListener('resize', () => {\r\n const newIsDesktop = window.innerWidth >= 768;\r\n if (newIsDesktop !== this.isDesktop()) {\r\n console.log('[ListItem] Viewport changed, updating desktop detection:', newIsDesktop);\r\n this.isDesktop.set(newIsDesktop);\r\n }\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * CSS size value for the leading content area (e.g., '32px', '40px', '48px')\r\n * Defaults to '32px' for standard list item avatars/icons\r\n */\r\n leadingSize = input<string>('32px');\r\n \r\n /**\r\n * Display variant\r\n * - undefined (default) - Standard display\r\n * - 'compact' - Compact display for nested/related items\r\n */\r\n variant = input<'compact' | undefined>(undefined);\r\n \r\n /**\r\n * Vertical alignment of leading and main content slots\r\n * - 'top' - Align to top (default)\r\n * - 'center' - Align to center\r\n * - 'bottom' - Align to bottom\r\n */\r\n align = input<'top' | 'center' | 'bottom'>('top');\r\n \r\n /**\r\n * Whether the list item is interactive (clickable and long-pressable)\r\n * When true, adds interactive background, cursor pointer, and touch handlers\r\n */\r\n interactive = input<boolean>(false);\r\n \r\n /**\r\n * Whether the list item is disabled\r\n * Disables all interactions and reduces opacity\r\n */\r\n disabled = input<boolean>(false);\r\n \r\n /**\r\n * Whether the list item is in a loading state\r\n * Disables interactions but maintains full opacity\r\n */\r\n loading = input<boolean>(false);\r\n \r\n /**\r\n * Enable long-press interaction when interactive is true\r\n * Set to false to disable long-press but keep click\r\n */\r\n enableLongPress = input<boolean>(true);\r\n \r\n /**\r\n * Show \"more actions\" button on desktop for items with long-press enabled\r\n * Only visible on desktop (hover: hover) and when enableLongPress is true\r\n * Clicking this button triggers the same handler as long-press on mobile\r\n * @default true\r\n */\r\n showDesktopMoreButton = input<boolean>(true);\r\n \r\n /**\r\n * Offset distance for the interactive background pseudo-element\r\n * Extends the background beyond the content bounds\r\n * @default '8px'\r\n */\r\n interactiveOffset = input<string>('8px');\r\n \r\n /**\r\n * Optional structured title text\r\n * Provides a simple way to add title without custom markup\r\n */\r\n title = input<string>();\r\n \r\n /**\r\n * Optional structured subtitle text\r\n * Provides a simple way to add subtitle without custom markup\r\n */\r\n subtitle = input<string>();\r\n \r\n /**\r\n * Whether to show the divider line below the list item\r\n * Automatically hidden on last-child and detail variant\r\n * @default true\r\n */\r\n showDivider = input<boolean>(true);\r\n \r\n /**\r\n * Spacing around the divider (top and bottom padding)\r\n * @default '4px'\r\n */\r\n dividerSpacing = input<string>('4px');\r\n \r\n /**\r\n * Emits when the list item is clicked (if interactive and not disabled)\r\n */\r\n itemClick = output<void>();\r\n \r\n /**\r\n * Emits when the desktop more actions button is clicked\r\n * This is separate from longPress to give more control to parent components\r\n * Typically, you can use (longPress) for both mobile and desktop actions\r\n */\r\n moreButtonClick = output<Event>();\r\n \r\n /**\r\n * Track if long press was triggered to prevent click\r\n */\r\n private longPressTriggered = false;\r\n \r\n /**\r\n * Check if leading content slot has content\r\n * Always true to maintain consistent layout\r\n */\r\n hasLeadingContent = computed(() => true);\r\n \r\n /**\r\n * Check if trailing content slot has content\r\n * Always true to maintain consistent layout\r\n */\r\n hasTrailingContent = computed(() => true);\r\n \r\n /**\r\n * Handle click events\r\n */\r\n handleClick(event: Event): void {\r\n console.log('[ListItem] Click event fired', {\r\n interactive: this.interactive(),\r\n disabled: this.disabled(),\r\n loading: this.loading(),\r\n longPressTriggered: this.longPressTriggered,\r\n target: event.target\r\n });\r\n \r\n if (!this.interactive() || this.disabled() || this.loading()) {\r\n console.log('[ListItem] Click ignored - not interactive or disabled/loading');\r\n return;\r\n }\r\n \r\n // Don't emit click if it came from an interactive child element\r\n // (but not the host element itself)\r\n const target = event.target as HTMLElement;\r\n const closestInteractive = target.closest('button, a, input, select, textarea, [role=\"button\"]');\r\n \r\n // Check if the interactive element is a child, not the host itself\r\n if (closestInteractive && closestInteractive !== event.currentTarget) {\r\n console.log('[ListItem] Click ignored - came from interactive child:', closestInteractive);\r\n return;\r\n }\r\n \r\n if (!this.longPressTriggered) {\r\n console.log('[ListItem] Emitting itemClick');\r\n this.itemClick.emit();\r\n } else {\r\n console.log('[ListItem] Click ignored - long press was triggered');\r\n }\r\n \r\n this.longPressTriggered = false;\r\n }\r\n \r\n /**\r\n * Handle keyboard events (Enter/Space)\r\n */\r\n handleKeyDown(event: KeyboardEvent): void {\r\n if (!this.interactive() || this.disabled() || this.loading()) {\r\n return;\r\n }\r\n \r\n event.preventDefault();\r\n this.itemClick.emit();\r\n }\r\n \r\n /**\r\n * Handle long press events from the directive\r\n * Set the flag to prevent the subsequent click event\r\n */\r\n handleLongPress(): void {\r\n this.longPressTriggered = true;\r\n // Reset the flag after a short delay to allow for the next interaction\r\n setTimeout(() => {\r\n this.longPressTriggered = false;\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Handle desktop more button click\r\n * Stops propagation to prevent triggering itemClick\r\n * Emits moreButtonClick for parent components to handle\r\n */\r\n handleMoreButtonClick(event: Event): void {\r\n console.log('[ListItem] Desktop more button clicked');\r\n \r\n // Stop propagation to prevent triggering itemClick\r\n event.stopPropagation();\r\n event.preventDefault();\r\n \r\n // Emit the more button click event\r\n this.moreButtonClick.emit(event);\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { DsMobileListItemComponent } from '../list-item/ds-mobile-list-item';\r\n\r\n/**\r\n * DsMobileActionListItemComponent\r\n * \r\n * Specialized list item for action sheets and menus.\r\n * Wraps ds-mobile-list-item with action-specific styling:\r\n * - Vertically centered content\r\n * - Interactive by default\r\n * - No dividers (controlled per-item)\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-action-list-item\r\n * title=\"Edit\"\r\n * [showDivider]=\"true\"\r\n * (itemClick)=\"handleEdit()\">\r\n * <ds-icon content-leading name=\"remixEditLine\" size=\"20px\" />\r\n * </ds-mobile-action-list-item>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-action-list-item',\r\n standalone: true,\r\n imports: [DsMobileListItemComponent],\r\n template: `\r\n <ds-mobile-list-item\r\n [title]=\"title()\"\r\n [interactive]=\"true\"\r\n [enableLongPress]=\"false\"\r\n [showDivider]=\"showDivider()\"\r\n [disabled]=\"disabled()\"\r\n (itemClick)=\"itemClick.emit()\">\r\n \r\n <div class=\"action-icon-wrapper\" content-leading>\r\n <ng-content select=\"[action-icon]\" />\r\n </div>\r\n </ds-mobile-list-item>\r\n `,\r\n styles: [`\r\n /* Center all content vertically for action items */\r\n :host ::ng-deep ds-mobile-list-item .list-item-inner {\r\n align-items: center;\r\n }\r\n \r\n /* Center icon within leading slot */\r\n :host ::ng-deep ds-mobile-list-item .content-leading {\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n /* Wrapper div must fill parent height and center icon */\r\n :host ::ng-deep .action-icon-wrapper {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n }\r\n \r\n /* Remove gap from content-main for single-line actions */\r\n :host ::ng-deep ds-mobile-list-item .content-main {\r\n gap: 0;\r\n justify-content: center;\r\n }\r\n `]\r\n})\r\nexport class DsMobileActionListItemComponent {\r\n /**\r\n * Action title text\r\n */\r\n title = input.required<string>();\r\n \r\n /**\r\n * Whether to show divider below item\r\n * @default false\r\n */\r\n showDivider = input<boolean>(false);\r\n \r\n /**\r\n * Whether the action is disabled\r\n * @default false\r\n */\r\n disabled = input<boolean>(false);\r\n \r\n /**\r\n * Emits when the action item is clicked\r\n */\r\n itemClick = output<void>();\r\n}\r\n\r\n","import { Component, Input, computed, signal } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileActionListItemComponent } from '../action-list-item/ds-mobile-action-list-item';\r\n\r\nexport interface ActionResult {\r\n action: string;\r\n}\r\n\r\nexport interface ActionItem {\r\n action: string;\r\n title: string;\r\n icon: string;\r\n destructive?: boolean;\r\n}\r\n\r\nexport interface ActionGroup {\r\n actions: ActionItem[];\r\n}\r\n\r\n/**\r\n * DsMobileActionsBottomSheetComponent\r\n * \r\n * Generic bottom sheet for displaying action lists.\r\n * Supports custom action groups or preset content actions (posts/comments).\r\n * Action groups are automatically separated by full-width dividers.\r\n * \r\n * @example Custom actions with auto-height (recommended to avoid cropping)\r\n * ```typescript\r\n * const sheet = await this.modalController.create({\r\n * component: DsMobileActionsBottomSheetComponent,\r\n * componentProps: {\r\n * customActionGroups: [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'Min profil', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Indstillinger', icon: 'remixSettings3Line' }\r\n * ]\r\n * },\r\n * {\r\n * actions: [\r\n * { action: 'logout', title: 'Log ud', icon: 'remixLogoutBoxLine', destructive: true }\r\n * ]\r\n * }\r\n * ]\r\n * },\r\n * breakpoints: [0, 1],\r\n * initialBreakpoint: 1,\r\n * handle: true,\r\n * cssClass: 'auto-height'\r\n * });\r\n * \r\n * const result = await sheet.onWillDismiss();\r\n * if (result.data?.action) {\r\n * // Handle the action\r\n * }\r\n * ```\r\n * \r\n * @example Preset content actions\r\n * ```typescript\r\n * const sheet = await this.modalController.create({\r\n * component: DsMobileActionsBottomSheetComponent,\r\n * componentProps: {\r\n * isOwnContent: false\r\n * },\r\n * breakpoints: [0, 1],\r\n * initialBreakpoint: 1,\r\n * handle: true,\r\n * cssClass: 'auto-height'\r\n * });\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-actions-bottom-sheet',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsMobileActionListItemComponent],\r\n template: `\r\n <div class=\"actions-sheet\">\r\n <!-- Actions List -->\r\n <div class=\"actions-list\">\r\n @for (group of actionGroups(); track $index; let isLast = $last) {\r\n <!-- Action Group -->\r\n <div class=\"action-group\">\r\n @for (actionItem of group.actions; track actionItem.action; let isLastInGroup = $last) {\r\n <ds-mobile-action-list-item\r\n [title]=\"actionItem.title\"\r\n [showDivider]=\"!isLastInGroup\"\r\n [class.destructive]=\"actionItem.destructive\"\r\n (itemClick)=\"selectAction(actionItem.action)\">\r\n <ds-icon \r\n action-icon \r\n [name]=\"actionItem.icon\" \r\n size=\"20px\" \r\n [class.destructive-icon]=\"actionItem.destructive\" />\r\n </ds-mobile-action-list-item>\r\n }\r\n </div>\r\n \r\n <!-- Full-width divider between groups -->\r\n @if (!isLast) {\r\n <div class=\"action-group-divider\"></div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n .actions-sheet {\r\n display: flex;\r\n flex-direction: column;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n padding-bottom: env(safe-area-inset-bottom, 0px);\r\n }\r\n \r\n /* Actions List */\r\n .actions-list {\r\n display: flex;\r\n flex-direction: column;\r\n padding-top: 16px; /* Only top padding for the container */\r\n }\r\n \r\n /* Action Group - padding on groups instead of list */\r\n .action-group {\r\n display: flex;\r\n flex-direction: column;\r\n padding: 0 16px; /* Horizontal padding on each group */\r\n }\r\n \r\n /* Override default background color to transparent so hover state is visible */\r\n /* Need ::ng-deep because ds-mobile-list-item uses :host styles internally */\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item {\r\n --color-background-primary: transparent;\r\n --color-background-neutral-primary-hover: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n \r\n /* Ensure the interactive background is visible */\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .list-item-inner::before {\r\n z-index: 0 !important;\r\n }\r\n \r\n /* Ensure content is above the background */\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .content-leading,\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .content-main,\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .content-trailing {\r\n position: relative;\r\n z-index: 1;\r\n }\r\n \r\n /* Hide divider on last list item using CSS variable */\r\n ds-mobile-action-list-item:last-of-type {\r\n --divider-display: none;\r\n }\r\n \r\n /* Destructive action styling */\r\n ds-mobile-action-list-item.destructive {\r\n --text-color-default-primary: var(--color-error-base, #ef4444);\r\n }\r\n \r\n .destructive-icon {\r\n color: var(--color-error-base, #ef4444);\r\n }\r\n \r\n /* Full-width divider between action groups */\r\n .action-group-divider {\r\n height: 1px;\r\n background: var(--color-border-subtle, #e5e5e5);\r\n margin: 8px 0;\r\n }\r\n `]\r\n})\r\nexport class DsMobileActionsBottomSheetComponent {\r\n /**\r\n * Custom action groups to display (overrides isOwnContent)\r\n */\r\n @Input() customActionGroups?: ActionGroup[];\r\n \r\n /**\r\n * Whether this content belongs to the current user (for preset content actions)\r\n */\r\n @Input() isOwnContent: boolean = false;\r\n \r\n /**\r\n * Computed action groups - uses custom groups if provided, otherwise falls back to preset content actions\r\n */\r\n actionGroups = computed<ActionGroup[]>(() => {\r\n // Use custom action groups if provided\r\n if (this.customActionGroups) {\r\n return this.customActionGroups;\r\n }\r\n \r\n // Otherwise fall back to preset content actions\r\n if (this.isOwnContent) {\r\n // Own content: Group 1 (Edit, Delete) + Group 2 (Like, Reply)\r\n return [\r\n {\r\n actions: [\r\n {\r\n action: 'edit',\r\n title: 'Rediger',\r\n icon: 'remixEditLine',\r\n destructive: false\r\n },\r\n {\r\n action: 'delete',\r\n title: 'Slet',\r\n icon: 'remixDeleteBinLine',\r\n destructive: true\r\n }\r\n ]\r\n },\r\n {\r\n actions: [\r\n {\r\n action: 'like',\r\n title: 'Synes om',\r\n icon: 'remixHeart3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'reply',\r\n title: 'Svar',\r\n icon: 'remixReplyLine',\r\n destructive: false\r\n }\r\n ]\r\n }\r\n ];\r\n } else {\r\n // Other users' content: Group 1 (Like, Reply)\r\n return [\r\n {\r\n actions: [\r\n {\r\n action: 'like',\r\n title: 'Synes om',\r\n icon: 'remixHeart3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'reply',\r\n title: 'Svar',\r\n icon: 'remixReplyLine',\r\n destructive: false\r\n }\r\n ]\r\n }\r\n ];\r\n }\r\n });\r\n \r\n constructor(private modalController: ModalController) {}\r\n \r\n /**\r\n * Handle action selection and dismiss with result\r\n */\r\n selectAction(action: string): void {\r\n this.modalController.dismiss(\r\n { action } as ActionResult,\r\n 'select'\r\n );\r\n }\r\n}\r\n\r\n// Legacy exports for backwards compatibility\r\nexport { DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent };\r\nexport { DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent };\r\nexport type { ActionResult as PostActionResult };\r\nexport type { ActionResult as CommentActionResult };\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { ComponentRef } from '@angular/core';\r\n\r\n/**\r\n * Configuration options for the bottom sheet modal\r\n */\r\nexport interface BottomSheetOptions {\r\n /** The component to display in the bottom sheet */\r\n component: any;\r\n /** Component props to pass to the modal content */\r\n componentProps?: { [key: string]: any };\r\n /** Breakpoints for the bottom sheet (0-1 values representing percentage of screen) */\r\n breakpoints?: number[];\r\n /** Initial breakpoint to open the sheet at */\r\n initialBreakpoint?: number;\r\n /** Show/hide the drag handle */\r\n handle?: boolean;\r\n /** Custom CSS class for styling */\r\n cssClass?: string | string[];\r\n /** Whether backdrop dismisses the modal */\r\n backdropDismiss?: boolean;\r\n /** Backdrop opacity (0-1) */\r\n backdropOpacity?: number;\r\n /** Enable backdrop blur effect */\r\n backdropBlur?: boolean;\r\n /** Keyboard close behavior */\r\n keyboardClose?: boolean;\r\n /** Auto-height mode: sheet sizes to content instead of using fixed breakpoints */\r\n autoHeight?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobileBottomSheetService\r\n * \r\n * Service for creating and managing Ionic 6 bottom sheet modals.\r\n * Based on the Ionic blog article: https://ionic.io/blog/5-examples-of-the-new-ionic-6-bottom-sheet-modal\r\n * \r\n * Features:\r\n * - Multiple breakpoints for snap-to positions\r\n * - Customizable initial height\r\n * - Optional drag handle\r\n * - Backdrop blur effect\r\n * - Custom styling support\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private bottomSheet: DsMobileBottomSheetService) {}\r\n * \r\n * async openSheet() {\r\n * const sheet = await this.bottomSheet.create({\r\n * component: PostCreateComponent,\r\n * breakpoints: [0, 0.5, 0.9],\r\n * initialBreakpoint: 0.5,\r\n * handle: true\r\n * });\r\n * \r\n * const result = await sheet.onWillDismiss();\r\n * console.log('Sheet dismissed with:', result.data);\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileBottomSheetService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Create and present a bottom sheet modal\r\n * \r\n * @param options Configuration options for the bottom sheet\r\n * @returns Promise that resolves to the modal instance\r\n */\r\n async create(options: BottomSheetOptions): Promise<HTMLIonModalElement> {\r\n const {\r\n component,\r\n componentProps = {},\r\n breakpoints = [0, 0.5, 0.9],\r\n initialBreakpoint = 0.5,\r\n handle = true,\r\n cssClass = '',\r\n backdropDismiss = true,\r\n backdropOpacity,\r\n backdropBlur = false,\r\n keyboardClose = true,\r\n autoHeight = false\r\n } = options;\r\n\r\n // Build CSS classes array\r\n const cssClasses = ['ds-bottom-sheet'];\r\n if (backdropBlur) {\r\n cssClasses.push('ds-bottom-sheet--blur');\r\n }\r\n if (autoHeight) {\r\n cssClasses.push('auto-height');\r\n }\r\n if (typeof cssClass === 'string' && cssClass) {\r\n cssClasses.push(cssClass);\r\n } else if (Array.isArray(cssClass)) {\r\n cssClasses.push(...cssClass);\r\n }\r\n\r\n const modal = await this.modalController.create({\r\n component,\r\n componentProps,\r\n breakpoints: autoHeight ? undefined : breakpoints,\r\n initialBreakpoint: autoHeight ? undefined : initialBreakpoint,\r\n handle: autoHeight ? false : handle,\r\n cssClass: cssClasses,\r\n backdropDismiss,\r\n keyboardClose,\r\n showBackdrop: true,\r\n canDismiss: backdropDismiss,\r\n // Remove animation delay for instant appearance\r\n animated: true,\r\n enterAnimation: undefined, // Use default but we'll customize via CSS\r\n leaveAnimation: undefined,\r\n ...(backdropOpacity !== undefined && { \r\n cssClass: [...cssClasses, 'ds-bottom-sheet--custom-backdrop']\r\n })\r\n });\r\n\r\n // Apply custom backdrop opacity if specified\r\n if (backdropOpacity !== undefined) {\r\n modal.style.setProperty('--backdrop-opacity', backdropOpacity.toString());\r\n }\r\n\r\n // Add ESC key listener to dismiss the modal\r\n const escKeyHandler = (event: KeyboardEvent) => {\r\n if (event.key === 'Escape') {\r\n modal.dismiss(undefined, 'escape');\r\n }\r\n };\r\n \r\n // Add listener when modal is presented\r\n modal.addEventListener('ionModalDidPresent', () => {\r\n document.addEventListener('keydown', escKeyHandler);\r\n });\r\n \r\n // Remove listener when modal is dismissed\r\n modal.addEventListener('ionModalDidDismiss', () => {\r\n document.removeEventListener('keydown', escKeyHandler);\r\n });\r\n\r\n await modal.present();\r\n \r\n // Don't wait - return immediately so component can try to focus\r\n // while still in user gesture context\r\n return modal;\r\n }\r\n\r\n /**\r\n * Dismiss all open modals\r\n */\r\n async dismiss(data?: any, role?: string): Promise<boolean> {\r\n return this.modalController.dismiss(data, role);\r\n }\r\n\r\n /**\r\n * Get the top-most modal overlay\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, signal, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ModalController, IonHeader, IonToolbar, IonTitle, IonContent, IonButtons } from '@ionic/angular/standalone';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { Camera, CameraResultType, CameraSource } from '@capacitor/camera';\r\nimport { StatusBar } from '@capacitor/status-bar';\r\nimport { DsButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobilePostCreateBottomSheetComponent\r\n * \r\n * Bottom sheet modal for creating new posts in the community feed.\r\n * This is the modal content that gets displayed in the bottom sheet.\r\n * Features Threads-inspired interface with rich text editing capabilities.\r\n * \r\n * Auto-focuses the textarea and brings up the keyboard when opened.\r\n * \r\n * Usage: Use with DsMobileBottomSheetService to present as a bottom sheet\r\n */\r\n@Component({\r\n selector: 'ds-mobile-post-create-bottom-sheet',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonContent,\r\n IonButtons,\r\n DsButtonComponent,\r\n DsIconButtonComponent\r\n ],\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n }\r\n\r\n /* ============================================\r\n HEADER\r\n ============================================ */\r\n \r\n ion-header {\r\n box-shadow: none;\r\n }\r\n\r\n ion-toolbar {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n --border-width: 0 0 1px 0;\r\n --border-color: var(--border-color-default);\r\n --padding-top: 12px;\r\n --padding-bottom: 8px;\r\n --min-height: 56px;\r\n }\r\n\r\n ion-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 22px;\r\n letter-spacing: -0.4px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n\r\n ion-button {\r\n --color: var(--color-text-secondary, #737373);\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 400;\r\n }\r\n\r\n /* Make Post button pill-shaped */\r\n ion-buttons[slot=\"end\"] ds-button {\r\n --border-radius: 100px;\r\n }\r\n \r\n ion-buttons[slot=\"end\"] ds-button::ng-deep button {\r\n border-radius: 100px;\r\n }\r\n \r\n /* Make Cancel button pill-shaped */\r\n ion-buttons[slot=\"start\"] ds-button {\r\n --border-radius: 100px;\r\n }\r\n \r\n ion-buttons[slot=\"start\"] ds-button::ng-deep button {\r\n border-radius: 100px;\r\n }\r\n\r\n /* ============================================\r\n CONTENT AREA\r\n ============================================ */\r\n \r\n ion-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n --padding-top: 0;\r\n --padding-bottom: 0;\r\n }\r\n\r\n .post-create-container {\r\n padding: 24px 16px 16px;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n }\r\n \r\n .post-composer {\r\n display: flex;\r\n gap: 12px;\r\n align-items: flex-start;\r\n }\r\n \r\n .post-composer__main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .post-composer__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n height: 32px;\r\n }\r\n \r\n .post-composer__username {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .post-composer__textarea {\r\n width: 100%;\r\n min-height: 60px;\r\n max-height: 400px;\r\n border: none;\r\n outline: none;\r\n resize: none;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n background: transparent;\r\n padding: 0;\r\n cursor: text;\r\n overflow-y: auto;\r\n /* Auto-resize as user types */\r\n field-sizing: content;\r\n }\r\n \r\n .post-composer__textarea::placeholder {\r\n color: var(--color-text-tertiary, #999999);\r\n }\r\n \r\n /* Visual focus indicator - helps users see the textarea is ready */\r\n .post-composer__textarea:focus {\r\n outline: none;\r\n }\r\n \r\n /* Subtle animation to draw attention when empty */\r\n @keyframes gentlePulse {\r\n 0%, 100% { opacity: 1; }\r\n 50% { opacity: 0.6; }\r\n }\r\n \r\n .post-composer__textarea:not(:focus):empty + .focus-hint {\r\n animation: gentlePulse 2s ease-in-out 1;\r\n }\r\n \r\n .post-composer__actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding-top: 12px;\r\n }\r\n \r\n .post-composer__actions ds-icon-button::ng-deep button {\r\n width: 44px;\r\n height: 44px;\r\n border-radius: 50%;\r\n }\r\n \r\n /* ============================================\r\n IMAGE PREVIEW\r\n ============================================ */\r\n \r\n .image-previews {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n margin-top: 12px;\r\n }\r\n \r\n .image-preview {\r\n position: relative;\r\n width: 96px;\r\n height: 96px;\r\n border-radius: 12px;\r\n overflow: visible;\r\n }\r\n \r\n .preview-image {\r\n width: 100%;\r\n height: 100%;\r\n display: block;\r\n border-radius: 12px;\r\n border: 1px solid var(--border-color-default);\r\n object-fit: cover;\r\n }\r\n \r\n .remove-image-btn {\r\n position: absolute;\r\n top: -8px;\r\n right: -8px;\r\n width: 24px;\r\n height: 24px;\r\n border-radius: 50%;\r\n background: rgba(0, 0, 0, 0.6);\r\n backdrop-filter: blur(8px);\r\n border: 2px solid white;\r\n color: white;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n padding: 0;\r\n }\r\n \r\n .remove-image-btn:hover {\r\n background: rgba(0, 0, 0, 0.8);\r\n transform: scale(1.05);\r\n }\r\n \r\n .remove-image-btn:active {\r\n transform: scale(0.95);\r\n }\r\n \r\n /* ============================================\r\n MOBILE OPTIMIZATIONS\r\n ============================================ */\r\n \r\n @media (max-width: 768px) {\r\n .post-create-container {\r\n padding: 12px 16px 24px;\r\n }\r\n\r\n .post-composer__textarea {\r\n min-height: 60px;\r\n max-height: 300px;\r\n /* Make tap target larger on mobile */\r\n padding: 8px;\r\n margin: -8px;\r\n }\r\n }\r\n `],\r\n template: `\r\n <!-- Header with cancel and post buttons -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ds-button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n (clicked)=\"handleCancel()\">\r\n Annuller\r\n </ds-button>\r\n </ion-buttons>\r\n <ion-title>{{ modalTitle() }}</ion-title>\r\n <ion-buttons slot=\"end\">\r\n <ds-button\r\n variant=\"primary\"\r\n size=\"sm\"\r\n [disabled]=\"!canPost()\"\r\n (clicked)=\"handlePost()\">\r\n {{ submitButtonLabel() }}\r\n </ds-button>\r\n </ion-buttons>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <!-- Content -->\r\n <ion-content>\r\n <div class=\"post-create-container\">\r\n <div class=\"post-composer\">\r\n <div class=\"post-composer__main\">\r\n <textarea\r\n #textareaInput\r\n class=\"post-composer__textarea\"\r\n [(ngModel)]=\"postContent\"\r\n [placeholder]=\"placeholder()\"\r\n [readonly]=\"isReadonly\"\r\n (input)=\"handleInput()\"\r\n (focus)=\"handleFocus()\"\r\n inputmode=\"text\"\r\n enterkeyhint=\"done\"\r\n rows=\"1\">\r\n </textarea>\r\n \r\n <!-- Image Previews -->\r\n @if (selectedImages().length > 0) {\r\n <div class=\"image-previews\">\r\n @for (image of selectedImages(); track image; let i = $index) {\r\n <div class=\"image-preview\">\r\n <img [src]=\"image\" alt=\"Selected image\" class=\"preview-image\" />\r\n <button \r\n class=\"remove-image-btn\" \r\n (click)=\"handleRemoveImage(i)\"\r\n type=\"button\"\r\n aria-label=\"Fjern billede\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <path d=\"M12 4L4 12M4 4L12 12\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n <div class=\"post-composer__actions\">\r\n <ds-icon-button\r\n icon=\"remixImageLine\"\r\n variant=\"secondary\"\r\n size=\"md\"\r\n (clicked)=\"handleAddImage()\"\r\n aria-label=\"Tilføj billede\">\r\n </ds-icon-button>\r\n <ds-icon-button\r\n icon=\"remixAttachmentLine\"\r\n variant=\"secondary\"\r\n size=\"md\"\r\n (clicked)=\"handleAddAttachment()\"\r\n aria-label=\"Tilføj vedhæftning\">\r\n </ds-icon-button>\r\n \r\n <!-- Hidden file input for file selection -->\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n accept=\"*/*\"\r\n multiple\r\n (change)=\"handleFileSelect($event)\"\r\n style=\"display: none;\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePostCreateBottomSheetComponent implements AfterViewInit, OnInit {\r\n @ViewChild('textareaInput') textareaInput?: ElementRef<HTMLTextAreaElement>;\r\n @ViewChild('fileInput') fileInput?: ElementRef<HTMLInputElement>;\r\n \r\n // Optional input to control auto-focus behavior\r\n autoFocus = true;\r\n \r\n // Control readonly state for keyboard trick\r\n isReadonly = true;\r\n \r\n // Edit mode properties - can be set via componentProps\r\n isEditMode = false;\r\n postId?: string;\r\n initialContent = '';\r\n \r\n postContent = '';\r\n selectedImages = signal<string[]>([]);\r\n username = signal('Lars Mikkelsen');\r\n placeholder = signal(\"Hvad er nyt?\");\r\n modalTitle = signal('Nyt opslag');\r\n submitButtonLabel = signal('Slå op');\r\n \r\n constructor(\r\n private modalController: ModalController,\r\n private elementRef: ElementRef\r\n ) {}\r\n \r\n /**\r\n * Ensure toolbar doesn't have unnecessary padding\r\n * Modal is already positioned below status bar, so no extra safe area needed\r\n */\r\n private applySafeAreaToToolbar(): void {\r\n try {\r\n const hostElement = this.elementRef?.nativeElement;\r\n if (hostElement) {\r\n const header = hostElement.querySelector('ion-header');\r\n if (header) {\r\n const toolbar = header.querySelector('ion-toolbar');\r\n if (toolbar) {\r\n const toolbarElement = toolbar as HTMLElement;\r\n // Ensure toolbar uses standard padding (no safe area since modal is already offset)\r\n toolbarElement.style.setProperty('--padding-top', '12px', 'important');\r\n toolbarElement.style.setProperty('--min-height', '56px', 'important');\r\n }\r\n }\r\n }\r\n } catch (e) {\r\n console.log('[SafeArea] Failed to apply to toolbar:', e);\r\n }\r\n }\r\n \r\n ngOnInit(): void {\r\n // Initialize edit mode if provided\r\n if (this.isEditMode && this.initialContent) {\r\n this.postContent = this.initialContent;\r\n this.modalTitle.set('Rediger opslag');\r\n this.submitButtonLabel.set('Gem');\r\n }\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Apply safe area padding immediately to prevent corruption\r\n this.applySafeAreaToToolbar();\r\n \r\n // Auto-resize textarea if there's initial content (edit mode)\r\n if (this.postContent && this.textareaInput) {\r\n setTimeout(() => {\r\n this.resizeTextarea();\r\n }, 0);\r\n }\r\n \r\n // Try to focus IMMEDIATELY - no delay\r\n // This maximizes our chance of being in user gesture context\r\n if (this.autoFocus && this.textareaInput) {\r\n const textarea = this.textareaInput.nativeElement;\r\n \r\n // Remove readonly immediately\r\n this.isReadonly = false;\r\n \r\n // Try focusing with minimal delay\r\n setTimeout(() => {\r\n textarea.focus();\r\n textarea.click();\r\n \r\n // Explicitly show keyboard\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n \r\n // iOS sometimes needs a second attempt\r\n setTimeout(() => {\r\n textarea.focus();\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n }, 100);\r\n }, 10);\r\n }\r\n }\r\n \r\n /**\r\n * Ionic lifecycle hook - called when modal enters view\r\n * At 95% height, this acts more like a page than a modal\r\n * which might allow keyboard to open\r\n */\r\n ionViewDidEnter(): void {\r\n // Resize textarea in case initial attempt didn't work\r\n if (this.postContent && this.textareaInput) {\r\n this.resizeTextarea();\r\n }\r\n \r\n // Final focus attempt when view fully enters\r\n if (this.autoFocus && this.textareaInput) {\r\n this.isReadonly = false;\r\n const textarea = this.textareaInput.nativeElement;\r\n \r\n // Try to focus as if this was a page navigation\r\n textarea.focus();\r\n textarea.click();\r\n \r\n // Explicitly show keyboard\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n \r\n // Set cursor position\r\n const length = textarea.value.length;\r\n textarea.setSelectionRange(length, length);\r\n }\r\n }\r\n \r\n handleFocus(): void {\r\n // When user focuses (or we focus programmatically), remove readonly\r\n this.isReadonly = false;\r\n // Explicitly show keyboard\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n }\r\n \r\n handleInput(): void {\r\n this.resizeTextarea();\r\n }\r\n \r\n /**\r\n * Auto-resize textarea based on content\r\n */\r\n private resizeTextarea(): void {\r\n if (this.textareaInput) {\r\n const textarea = this.textareaInput.nativeElement;\r\n // Reset height to auto to get the correct scrollHeight\r\n textarea.style.height = 'auto';\r\n // Set height based on content, respecting min/max from CSS\r\n textarea.style.height = Math.min(textarea.scrollHeight, 400) + 'px';\r\n }\r\n }\r\n \r\n canPost(): boolean {\r\n return this.postContent.trim().length > 0 || this.selectedImages().length > 0;\r\n }\r\n \r\n async handleCancel(): Promise<void> {\r\n if (this.postContent.trim().length > 0 || this.selectedImages().length > 0) {\r\n // Show confirmation\r\n const confirmed = confirm('Kassér dette opslag?');\r\n if (confirmed) {\r\n await this.modalController.dismiss(null, 'cancel');\r\n }\r\n } else {\r\n await this.modalController.dismiss(null, 'cancel');\r\n }\r\n }\r\n \r\n async handlePost(): Promise<void> {\r\n if (!this.canPost()) return;\r\n \r\n if (this.isEditMode) {\r\n console.log('Updating post:', this.postId, this.postContent);\r\n } else {\r\n console.log('Creating post:', this.postContent, 'with images:', this.selectedImages().length);\r\n }\r\n \r\n // Pass the post content, images, and edit info back to the parent\r\n await this.modalController.dismiss(\r\n { \r\n content: this.postContent,\r\n images: this.selectedImages(),\r\n timestamp: new Date(),\r\n isEdit: this.isEditMode,\r\n postId: this.postId\r\n },\r\n 'post'\r\n );\r\n }\r\n \r\n async handleAddImage(): Promise<void> {\r\n console.log('Add image button clicked');\r\n \r\n // Re-apply safe area padding before opening camera (preventive)\r\n // This ensures the value is locked in before iOS corrupts it\r\n this.applySafeAreaToToolbar();\r\n \r\n try {\r\n console.log('Requesting photo from library...');\r\n \r\n const image = await Camera.getPhoto({\r\n quality: 90,\r\n allowEditing: false,\r\n resultType: CameraResultType.Uri,\r\n source: CameraSource.Photos, // Only show photo library, not camera\r\n });\r\n\r\n console.log('Photo selected successfully:', image);\r\n \r\n // Add the image path to the array\r\n if (image.webPath) {\r\n this.selectedImages.update(images => [...images, image.webPath!]);\r\n console.log('Image added to preview:', image.webPath);\r\n }\r\n \r\n // Re-apply safe area padding immediately after returning\r\n // Since we're using fixed values, this won't cause flickering\r\n requestAnimationFrame(() => {\r\n this.applySafeAreaToToolbar();\r\n });\r\n \r\n // Restore StatusBar configuration (background task)\r\n this.restoreStatusBar();\r\n \r\n } catch (error) {\r\n console.error('Photo selection error:', error);\r\n // Only show alert for non-cancellation errors\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n const errorMessage = (error as any).message;\r\n if (!errorMessage.includes('cancel')) {\r\n alert(`Error selecting photo: ${JSON.stringify(error)}`);\r\n }\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Restore StatusBar configuration (background task)\r\n * Safe area padding is now handled preventively via applySafeAreaToToolbar()\r\n */\r\n private restoreStatusBar(): void {\r\n setTimeout(async () => {\r\n try {\r\n await StatusBar.setBackgroundColor({ color: '#221a4c' });\r\n await StatusBar.setOverlaysWebView({ overlay: false });\r\n } catch (e) {\r\n // StatusBar API not available, ignore\r\n }\r\n }, 0);\r\n }\r\n \r\n handleRemoveImage(index: number): void {\r\n console.log('Removing image at index:', index);\r\n this.selectedImages.update(images => images.filter((_, i) => i !== index));\r\n }\r\n \r\n handleAddAttachment(): void {\r\n console.log('Add attachment button clicked');\r\n // Trigger the hidden file input\r\n if (this.fileInput) {\r\n this.fileInput.nativeElement.click();\r\n }\r\n }\r\n \r\n handleFileSelect(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n const files = input.files;\r\n \r\n if (!files || files.length === 0) {\r\n console.log('No files selected');\r\n return;\r\n }\r\n \r\n console.log('Files selected:', files.length);\r\n \r\n // Process each selected file\r\n Array.from(files).forEach(file => {\r\n console.log('File:', file.name, file.type, file.size);\r\n \r\n // Create a data URL for preview (for images and other files)\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n const result = e.target?.result as string;\r\n if (result) {\r\n // Add to selectedImages array for preview\r\n this.selectedImages.update(images => [...images, result]);\r\n console.log('File added to preview:', file.name);\r\n }\r\n };\r\n reader.readAsDataURL(file);\r\n });\r\n \r\n // Reset the input so the same file can be selected again\r\n input.value = '';\r\n }\r\n}\r\n\r\n","import { Injectable, signal } from '@angular/core';\r\nimport { ActionGroup } from '../components/bottom-sheet';\r\n\r\n/**\r\n * User service for managing current user data globally\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class UserService {\r\n // User avatar configuration\r\n private _avatarInitials = signal('LM');\r\n private _avatarType = signal<'initials' | 'photo' | 'icon'>('initials');\r\n private _avatarSrc = signal('');\r\n \r\n // Profile menu items configuration\r\n private _profileMenuItems = signal<ActionGroup[] | undefined>(undefined);\r\n \r\n // Readonly computed values\r\n readonly avatarInitials = this._avatarInitials.asReadonly();\r\n readonly avatarType = this._avatarType.asReadonly();\r\n readonly avatarSrc = this._avatarSrc.asReadonly();\r\n readonly profileMenuItems = this._profileMenuItems.asReadonly();\r\n \r\n /**\r\n * Update avatar configuration\r\n */\r\n setAvatarInitials(initials: string) {\r\n this._avatarInitials.set(initials);\r\n }\r\n \r\n setAvatarType(type: 'initials' | 'photo' | 'icon') {\r\n this._avatarType.set(type);\r\n }\r\n \r\n setAvatarSrc(src: string) {\r\n this._avatarSrc.set(src);\r\n }\r\n \r\n /**\r\n * Set profile menu items globally.\r\n * This will be used by both ds-mobile-tab-bar and ds-mobile-page-main\r\n * if they don't receive profileMenuItems as an input.\r\n */\r\n setProfileMenuItems(items: ActionGroup[]) {\r\n this._profileMenuItems.set(items);\r\n }\r\n}\r\n\r\n","import { Component, Input, computed, ViewEncapsulation, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { WhitelabelService } from '../../services/whitelabel.service';\r\n\r\nexport type AvatarType = 'initials' | 'photo' | 'icon';\r\nexport type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\r\nexport type BadgePosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\r\n\r\n/**\r\n * DsAvatarWithBadgeComponent\r\n * \r\n * Displays an avatar with a logomark badge overlay.\r\n * Useful for showing user avatars with organization branding.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-avatar-with-badge\r\n * [type]=\"'initials'\"\r\n * [initials]=\"'JD'\"\r\n * [size]=\"'lg'\"\r\n * [badgePosition]=\"'bottom-right'\"\r\n * />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-avatar-with-badge',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent],\r\n encapsulation: ViewEncapsulation.Emulated,\r\n styles: [`\r\n :host {\r\n display: inline-block;\r\n position: relative;\r\n }\r\n \r\n .avatar-badge-container {\r\n position: relative;\r\n display: inline-block;\r\n }\r\n \r\n .avatar-badge {\r\n position: absolute;\r\n background: var(--color-brand-secondary, #5d5fef);\r\n border-radius: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: 2px solid var(--color-background-primary, #ffffff);\r\n }\r\n \r\n .avatar-badge img {\r\n width: 10px;\r\n height: 10px;\r\n object-fit: contain;\r\n }\r\n \r\n /* Badge positioning */\r\n .avatar-badge--bottom-right {\r\n bottom: -6px;\r\n right: -6px;\r\n }\r\n \r\n .avatar-badge--bottom-left {\r\n bottom: -6px;\r\n left: -6px;\r\n }\r\n \r\n .avatar-badge--top-right {\r\n top: -6px;\r\n right: -6px;\r\n }\r\n \r\n .avatar-badge--top-left {\r\n top: -6px;\r\n left: -6px;\r\n }\r\n \r\n /* Badge sizes based on avatar size */\r\n .avatar-badge--xs { width: 16px; height: 16px; }\r\n .avatar-badge--sm { width: 18px; height: 18px; }\r\n .avatar-badge--md { width: 20px; height: 20px; }\r\n .avatar-badge--lg { width: 24px; height: 24px; }\r\n .avatar-badge--xl { width: 28px; height: 28px; }\r\n `],\r\n template: `\r\n <div class=\"avatar-badge-container\">\r\n <ds-avatar\r\n [type]=\"type\"\r\n [size]=\"size\"\r\n [initials]=\"initials\"\r\n [src]=\"src\"\r\n [iconName]=\"iconName\"\r\n />\r\n \r\n @if (showBadge) {\r\n <div [class]=\"badgeClasses()\">\r\n <img [src]=\"whitelabelService.logoMarkUrl()\" [alt]=\"whitelabelService.logoAlt()\" />\r\n </div>\r\n }\r\n </div>\r\n `\r\n})\r\nexport class DsAvatarWithBadgeComponent {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n // Avatar props\r\n @Input() type: AvatarType = 'initials';\r\n @Input() size: AvatarSize = 'md';\r\n @Input() initials: string = '';\r\n @Input() src: string = '';\r\n @Input() iconName: string = 'remixUser3Fill';\r\n \r\n // Badge props\r\n @Input() showBadge: boolean = true;\r\n @Input() badgePosition: BadgePosition = 'bottom-right';\r\n \r\n badgeClasses = computed(() => {\r\n return `avatar-badge avatar-badge--${this.badgePosition} avatar-badge--${this.size}`;\r\n });\r\n}\r\n\r\n","import { Component, OnInit, inject, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { WhitelabelService } from '../services/whitelabel.service';\r\nimport { DsLogoComponent } from '../components/logo/ds-logo';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge/ds-avatar-with-badge';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { IonContent, ModalController } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * Whitelabel Demo Modal Component\r\n * \r\n * Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.\r\n * Opens as a full-screen modal similar to post details.\r\n */\r\n@Component({\r\n selector: 'ds-whitelabel-demo-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonContent,\r\n DsLogoComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsIconButtonComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n styles: [`\r\n /* Host fills the modal with flex layout */\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n width: 100%;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n \r\n /* Fixed header at top */\r\n .modal-header {\r\n flex-shrink: 0;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default, #e0e0e0);\r\n padding: 0 16px;\r\n }\r\n \r\n /* ion-content fills remaining space and scrolls */\r\n ion-content,\r\n .modal-content {\r\n --background: #ffffff;\r\n flex: 1;\r\n width: 100%;\r\n }\r\n \r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 56px;\r\n }\r\n \r\n .header-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 17px;\r\n font-weight: 600;\r\n color: var(--color-text-primary, #1a1a1a);\r\n flex: 1;\r\n }\r\n \r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n \r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n background: var(--color-background-neutral-secondary, #f5f5f5) !important;\r\n color: var(--color-text-primary, #1a1a1a) !important;\r\n }\r\n \r\n .demo-container {\r\n padding: 20px;\r\n max-width: 600px;\r\n margin: 0 auto;\r\n width: 100%;\r\n }\r\n \r\n .demo-section {\r\n margin-bottom: 32px;\r\n }\r\n \r\n .demo-section h2 {\r\n margin-bottom: 16px;\r\n font-size: 18px;\r\n font-weight: 600;\r\n color: #333;\r\n }\r\n \r\n /* Theme Selection */\r\n .theme-buttons {\r\n display: flex;\r\n gap: 12px;\r\n flex-wrap: wrap;\r\n }\r\n \r\n .theme-btn {\r\n padding: 8px 16px;\r\n border-radius: 8px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n border: none;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n background: #e0e0e0;\r\n color: #333;\r\n }\r\n \r\n .theme-btn:active {\r\n transform: scale(0.98);\r\n }\r\n \r\n .theme-btn.active {\r\n background: var(--color-secondary-surface);\r\n color: var(--color-secondary-content);\r\n }\r\n \r\n /* Logo Preview */\r\n .logo-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: var(--color-brand-secondary);\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .logomark-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .preview-grid {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n }\r\n \r\n .preview-tile {\r\n background: white;\r\n border-radius: 12px;\r\n }\r\n \r\n .preview-tile h3 {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #666;\r\n margin-top: 0;\r\n margin-bottom: 12px;\r\n }\r\n \r\n /* Brand Colors */\r\n .color-section {\r\n background: white;\r\n border-radius: 12px;\r\n }\r\n \r\n .color-swatches {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n margin-bottom: 24px;\r\n }\r\n \r\n .swatch {\r\n padding: 16px;\r\n border-radius: 8px;\r\n text-align: center;\r\n }\r\n \r\n .swatch-label {\r\n font-size: 12px;\r\n font-weight: 600;\r\n margin-bottom: 4px;\r\n }\r\n \r\n .swatch-value {\r\n font-size: 11px;\r\n opacity: 0.8;\r\n font-family: monospace;\r\n }\r\n \r\n .swatch--primary-surface {\r\n background: var(--color-primary-surface);\r\n color: var(--color-primary-content);\r\n }\r\n \r\n .swatch--primary-content {\r\n background: var(--color-primary-content);\r\n color: var(--color-primary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n .swatch--secondary-surface {\r\n background: var(--color-secondary-surface);\r\n color: var(--color-secondary-content);\r\n }\r\n \r\n .swatch--secondary-content {\r\n background: var(--color-secondary-content);\r\n color: var(--color-secondary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n /* Color Inputs */\r\n .color-inputs {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .color-group-label {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #333;\r\n margin-top: 8px;\r\n }\r\n \r\n .color-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n \r\n .color-row label {\r\n min-width: 70px;\r\n font-size: 13px;\r\n color: #666;\r\n }\r\n \r\n .color-row input[type=\"color\"] {\r\n width: 40px;\r\n height: 32px;\r\n border: none;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n padding: 0;\r\n }\r\n \r\n .color-row input[type=\"text\"] {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 6px;\r\n font-family: monospace;\r\n font-size: 13px;\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .demo-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n `],\r\n template: `\r\n <!-- Fixed Header -->\r\n <div class=\"modal-header\">\r\n <div class=\"header-content\">\r\n <span class=\"header-title\">Whitelabel</span>\r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (click)=\"close()\"\r\n class=\"close-button\"\r\n aria-label=\"Close\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n \r\n <!-- Scrollable Content -->\r\n <ion-content [scrollY]=\"true\" class=\"modal-content\">\r\n <div class=\"demo-container\">\r\n <!-- Theme Selection -->\r\n <div class=\"demo-section\">\r\n <h2>Theme</h2>\r\n <div class=\"theme-buttons\">\r\n <button class=\"theme-btn\" (click)=\"applyDefaultTheme()\" [class.active]=\"currentTheme === 'default'\">\r\n Propbinder\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyCejTheme()\" [class.active]=\"currentTheme === 'cej'\">\r\n CEJ\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyPkaTheme()\" [class.active]=\"currentTheme === 'pka'\">\r\n PKA\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyClaveTheme()\" [class.active]=\"currentTheme === 'clave'\">\r\n Clave\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyFreedomTheme()\" [class.active]=\"currentTheme === 'freedom'\">\r\n Freedom\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <!-- Logo & Logomark Preview -->\r\n <div class=\"demo-section\">\r\n <h2>Logo Preview</h2>\r\n <div class=\"preview-grid\">\r\n <div class=\"preview-tile\">\r\n <h3>Logo</h3>\r\n <div class=\"logo-preview\">\r\n <ds-logo variant=\"full\" />\r\n </div>\r\n </div>\r\n <div class=\"preview-tile\">\r\n <h3>Logomark</h3>\r\n <div class=\"logomark-preview\">\r\n <ds-avatar-with-badge\r\n [type]=\"'initials'\"\r\n [initials]=\"'KN'\"\r\n [size]=\"'md'\"\r\n [badgePosition]=\"'bottom-right'\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Brand Colors -->\r\n <div class=\"demo-section\">\r\n <h2>Brand Colors</h2>\r\n <div class=\"color-section\">\r\n <div class=\"color-swatches\">\r\n <div class=\"swatch swatch--primary-surface\">\r\n <div class=\"swatch-label\">Primary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--primary-content\">\r\n <div class=\"swatch-label\">Primary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primaryContent() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-surface\">\r\n <div class=\"swatch-label\">Secondary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-content\">\r\n <div class=\"swatch-label\">Secondary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondaryContent() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"color-inputs\">\r\n <div class=\"color-group-label\">Primary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n \r\n <div class=\"color-group-label\">Secondary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class WhitelabelDemoModalComponent implements OnInit {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n private modalController = inject(ModalController);\r\n \r\n // Current active theme\r\n currentTheme = 'default';\r\n \r\n // Custom color inputs\r\n customPrimarySurface = '#6B5FF5';\r\n customPrimaryContent = '#FFFFFF';\r\n customSecondarySurface = '#221a4c';\r\n customSecondaryContent = '#FFFFFF';\r\n \r\n ngOnInit() {\r\n this.updateCustomColorInputs();\r\n this.detectCurrentTheme();\r\n }\r\n \r\n /**\r\n * Detect the current active theme based on colors\r\n */\r\n private detectCurrentTheme() {\r\n const secondarySurface = this.whitelabelService.secondarySurface().toUpperCase();\r\n \r\n if (secondarySurface === '#A70923') {\r\n this.currentTheme = 'cej';\r\n } else if (secondarySurface === '#660036') {\r\n this.currentTheme = 'pka';\r\n } else if (secondarySurface === '#262424') {\r\n this.currentTheme = 'clave';\r\n } else if (secondarySurface === '#1D4A49') {\r\n this.currentTheme = 'freedom';\r\n } else {\r\n this.currentTheme = 'default';\r\n }\r\n }\r\n \r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n \r\n applyDefaultTheme() {\r\n this.currentTheme = 'default';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoAlt: 'Propbinder',\r\n logoHeight: 28,\r\n primarySurface: '#6B5FF5',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#221a4c',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Propbinder',\r\n organizationId: 'default'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCejTheme() {\r\n this.currentTheme = 'cej';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/cej-logo.png',\r\n logoMarkUrl: '/Assets/logos/cej-logo.png',\r\n logoAlt: 'CEJ',\r\n logoHeight: 36,\r\n primarySurface: '#dc092c',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#A70923',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'CEJ',\r\n organizationId: 'cej'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyPkaTheme() {\r\n this.currentTheme = 'pka';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/pka-logo.svg',\r\n logoMarkUrl: '/Assets/logos/pka-logo.svg',\r\n logoAlt: 'PKA',\r\n logoHeight: 24,\r\n primarySurface: '#CC006C',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#660036',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'PKA',\r\n organizationId: 'pka'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyClaveTheme() {\r\n this.currentTheme = 'clave';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/clave-logo.svg',\r\n logoMarkUrl: '/Assets/logos/clave-logo.svg',\r\n logoAlt: 'Clave',\r\n logoHeight: 24,\r\n primarySurface: '#868764',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#262424',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Clave',\r\n organizationId: 'clave'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyFreedomTheme() {\r\n this.currentTheme = 'freedom';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/freedom-logo.svg',\r\n logoMarkUrl: '/Assets/logos/freedom-logomark.svg',\r\n logoAlt: 'Freedom',\r\n logoHeight: 28,\r\n primarySurface: '#AACFC3',\r\n primaryContent: '#1D4A49',\r\n secondarySurface: '#1D4A49',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Freedom',\r\n organizationId: 'freedom'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCustomColors() {\r\n this.whitelabelService.updateColors({\r\n primarySurface: this.customPrimarySurface,\r\n primaryContent: this.customPrimaryContent,\r\n secondarySurface: this.customSecondarySurface,\r\n secondaryContent: this.customSecondaryContent\r\n });\r\n }\r\n \r\n private updateCustomColorInputs() {\r\n this.customPrimarySurface = this.whitelabelService.primarySurface();\r\n this.customPrimaryContent = this.whitelabelService.primaryContent();\r\n this.customSecondarySurface = this.whitelabelService.secondarySurface();\r\n this.customSecondaryContent = this.whitelabelService.secondaryContent();\r\n }\r\n}\r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { WhitelabelDemoModalComponent } from './whitelabel-demo-modal.component';\r\n\r\n/**\r\n * WhitelabelDemoModalService\r\n * \r\n * Service for displaying the whitelabel demo in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private whitelabelModal: WhitelabelDemoModalService) {}\r\n * \r\n * async openDemo() {\r\n * await this.whitelabelModal.open();\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WhitelabelDemoModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the whitelabel demo modal\r\n * \r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(): Promise<void> {\r\n try {\r\n console.log('[WhitelabelDemoModal] Opening...');\r\n \r\n const modal = await this.modalController.create({\r\n component: WhitelabelDemoModalComponent,\r\n cssClass: 'ds-whitelabel-demo-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n // Control the presenting element animation\r\n enterAnimation: undefined, // Use default\r\n leaveAnimation: undefined // Use default\r\n });\r\n\r\n console.log('[WhitelabelDemoModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[WhitelabelDemoModal] Modal presented');\r\n } catch (error) {\r\n console.error('[WhitelabelDemoModal] Error opening modal:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Close the currently open whitelabel demo modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, input, output, HostListener, ElementRef, ViewChild, AfterViewInit, computed, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { Router } from '@angular/router';\r\nimport { \r\n IonHeader, \r\n IonToolbar, \r\n IonTitle,\r\n IonContent, \r\n IonRefresher, \r\n IonRefresherContent,\r\n Platform,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsLogoComponent } from '../logo/ds-logo';\r\nimport { MobilePageBase } from '../shared/mobile-page-base';\r\nimport { DsMobileActionsBottomSheetComponent, ActionResult, ActionGroup } from '../bottom-sheet';\r\nimport { UserService } from '../../services/user.service';\r\nimport { WhitelabelDemoModalService } from '../../pages/whitelabel-demo-modal.service';\r\n\r\n/**\r\n * DsMobilePageMainComponent\r\n * \r\n * A complete mobile page layout for main/tab pages with:\r\n * - Fixed header with logomark + title + avatar\r\n * - Purple expandable header section (scrolls with content)\r\n * - White rounded content wrapper\r\n * - Pull-to-refresh support\r\n * - Auto scroll title fade-in\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple page -->\r\n * <ds-mobile-page-main\r\n * title=\"Inquiries\"\r\n * [avatarInitials]=\"'JD'\">\r\n * <div class=\"page-content\">\r\n * <!-- Your content -->\r\n * </div>\r\n * </ds-mobile-page-main>\r\n * \r\n * <!-- Page with custom header content -->\r\n * <ds-mobile-page-main\r\n * title=\"Home\"\r\n * headerTitle=\"Welcome, Lars\"\r\n * headerSubtitle=\"Your rental property at a glance.\"\r\n * [avatarInitials]=\"'L'\">\r\n * \r\n * <div header-content class=\"property-tiles\">\r\n * <!-- Custom header content like tiles -->\r\n * </div>\r\n * \r\n * <div class=\"page-content\">\r\n * <!-- Main page content -->\r\n * </div>\r\n * </ds-mobile-page-main>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-page-main',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonContent,\r\n IonRefresher,\r\n IonRefresherContent,\r\n DsAvatarComponent,\r\n DsLogoComponent\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-page-base.css',\r\n './ds-mobile-page-main.css'\r\n ],\r\n template: `\r\n <!-- Fixed header at top -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <div class=\"header-main\">\r\n <!-- Whitelabel Logomark -->\r\n <ds-logo variant=\"mark\" size=\"lg\" />\r\n \r\n <!-- Title - fades in on scroll -->\r\n <ion-title class=\"header-main__title\">{{ title() }}</ion-title>\r\n \r\n <!-- Avatar -->\r\n <div class=\"header-main__actions\">\r\n <ds-avatar\r\n [size]=\"'md'\"\r\n [type]=\"avatarType()\"\r\n [initials]=\"avatarInitials()\"\r\n [src]=\"avatarSrc()\"\r\n [iconName]=\"avatarIconName()\"\r\n (click)=\"handleAvatarClick()\"\r\n style=\"cursor: pointer;\"\r\n />\r\n </div>\r\n </div>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <!-- Content with expandable header -->\r\n <ion-content [scrollEvents]=\"true\" (ionScroll)=\"handleScroll($event)\">\r\n <!-- Condensed header for Ionic scroll effects -->\r\n @if (showCondensedHeader()) {\r\n <ion-header collapse=\"condense\">\r\n <ion-toolbar>\r\n <ion-title size=\"large\">{{ title() }}</ion-title>\r\n </ion-toolbar>\r\n </ion-header>\r\n }\r\n\r\n <!-- Pull to refresh (only on native iOS/Android) -->\r\n @if (showRefresh() && isNativePlatform()) {\r\n <ion-refresher \r\n slot=\"fixed\" \r\n (ionRefresh)=\"handleRefresh($event)\"\r\n [pullFactor]=\"0.4\" \r\n [pullMin]=\"80\" \r\n [pullMax]=\"240\"\r\n closeDuration=\"600ms\">\r\n <ion-refresher-content\r\n pullingIcon=\"remixArrowDownS\"\r\n refreshingSpinner=\"lines\">\r\n </ion-refresher-content>\r\n </ion-refresher>\r\n }\r\n\r\n <!-- Expandable header section (purple background) -->\r\n <div class=\"header-expandable\">\r\n <div class=\"header-expandable-inner\">\r\n <div class=\"header-expandable__text\">\r\n <h1 class=\"header-expandable__title\">{{ headerTitle() || title() }}</h1>\r\n @if (headerSubtitle()) {\r\n <p class=\"header-expandable__subtitle\">{{ headerSubtitle() }}</p>\r\n }\r\n </div>\r\n \r\n <!-- Slot for custom header content (e.g., property tiles) -->\r\n <ng-content select=\"[header-content]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <!-- Content wrapper -->\r\n <div class=\"content-wrapper\">\r\n <div class=\"content-inner\">\r\n <!-- Main page content -->\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePageMainComponent extends MobilePageBase implements AfterViewInit {\r\n @ViewChild(IonContent) ionContent?: IonContent;\r\n \r\n // Platform detection\r\n private platform = inject(Platform);\r\n private modalController = inject(ModalController);\r\n private router = inject(Router);\r\n private userService = inject(UserService);\r\n private whitelabelDemoModal = inject(WhitelabelDemoModalService);\r\n \r\n // Computed property to check if running on native platform\r\n isNativePlatform = computed(() => \r\n this.platform.is('ios') || \r\n this.platform.is('android') || \r\n this.platform.is('capacitor')\r\n );\r\n \r\n // Inputs - Title\r\n title = input.required<string>(); // For fixed header title\r\n headerTitle = input<string>(''); // Optional different title for expandable header\r\n headerSubtitle = input<string>('');\r\n \r\n // Inputs - Avatar\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n avatarInitials = input<string>('U');\r\n avatarSrc = input<string>('');\r\n avatarIconName = input<string>('remixUser3Line');\r\n \r\n // Inputs - Features\r\n showRefresh = input<boolean>(true);\r\n showCondensedHeader = input<boolean>(true);\r\n scrollThreshold = input<number>(160); // Pixels to scroll before title appears\r\n headerFadeDistance = input<number>(150); // Distance over which header fades out\r\n \r\n /**\r\n * Profile menu action groups to display when avatar is clicked.\r\n * If not provided, a default menu will be used (without Whitelabel Demo).\r\n * \r\n * @example\r\n * ```typescript\r\n * profileMenuItems: ActionGroup[] = [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'Min profil', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Indstillinger', icon: 'remixSettings3Line' }\r\n * ]\r\n * },\r\n * {\r\n * actions: [\r\n * { action: 'logout', title: 'Log ud', icon: 'remixLogoutBoxLine', destructive: true }\r\n * ]\r\n * }\r\n * ];\r\n * ```\r\n */\r\n profileMenuItems = input<ActionGroup[] | undefined>(undefined);\r\n \r\n // Outputs\r\n avatarClick = output<void>();\r\n \r\n /**\r\n * Emitted when a profile menu action is selected.\r\n * Parent component should handle the action logic (navigation, logout, etc.).\r\n */\r\n profileActionSelected = output<ActionResult>();\r\n \r\n refresh = output<any>();\r\n scroll = output<any>();\r\n \r\n constructor(private elementRef: ElementRef) {\r\n super();\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Initial setup if needed\r\n }\r\n \r\n /**\r\n * Handle avatar click - opens profile actions bottom sheet\r\n */\r\n async handleAvatarClick(): Promise<void> {\r\n console.log('Avatar clicked - opening profile bottom sheet');\r\n \r\n // Emit the event for any parent listeners\r\n this.avatarClick.emit();\r\n \r\n // Use input if provided, otherwise fall back to service, otherwise use default menu\r\n const menuItems = this.profileMenuItems() || this.userService.profileMenuItems() || [\r\n {\r\n actions: [\r\n {\r\n action: 'profile',\r\n title: 'Min profil',\r\n icon: 'remixUser3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'settings',\r\n title: 'Indstillinger',\r\n icon: 'remixSettings3Line',\r\n destructive: false\r\n }\r\n ]\r\n },\r\n {\r\n actions: [\r\n {\r\n action: 'logout',\r\n title: 'Log ud',\r\n icon: 'remixLogoutBoxLine',\r\n destructive: true\r\n }\r\n ]\r\n }\r\n ];\r\n \r\n // If no menu items configured, just emit and return\r\n if (!menuItems || menuItems.length === 0) {\r\n return;\r\n }\r\n \r\n const sheet = await this.modalController.create({\r\n component: DsMobileActionsBottomSheetComponent,\r\n componentProps: {\r\n customActionGroups: menuItems\r\n },\r\n // Auto-height: no breakpoints, no handle\r\n cssClass: 'ds-bottom-sheet auto-height'\r\n });\r\n \r\n await sheet.present();\r\n \r\n const result = await sheet.onWillDismiss<ActionResult>();\r\n if (result.data?.action) {\r\n // Handle whitelabel-demo action internally (works on all pages)\r\n if (result.data.action === 'whitelabel-demo') {\r\n console.log('Opening whitelabel demo...');\r\n // Small delay to ensure bottom sheet is fully dismissed\r\n setTimeout(async () => {\r\n try {\r\n await this.whitelabelDemoModal.open();\r\n } catch (error) {\r\n console.error('Failed to open whitelabel demo modal:', error);\r\n }\r\n }, 100);\r\n }\r\n \r\n // Emit the selected action to parent (for other actions)\r\n this.profileActionSelected.emit(result.data);\r\n }\r\n }\r\n \r\n /**\r\n * Handle scroll events\r\n * - Shows title in fixed header when scrolled past threshold\r\n * - Fades out expandable header content based on scroll position\r\n * - Emits scroll event for custom handling\r\n */\r\n handleScroll(event: any): void {\r\n const scrollTop = event.detail.scrollTop;\r\n const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');\r\n const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');\r\n \r\n // Show title in fixed header when scrolled past threshold\r\n if (scrollTop > this.scrollThreshold()) {\r\n header?.classList.add('header-scrolled');\r\n } else {\r\n header?.classList.remove('header-scrolled');\r\n }\r\n \r\n // Fade out header-expandable content based on scroll\r\n if (headerExpandable) {\r\n const fadeDistance = this.headerFadeDistance();\r\n const fadeProgress = Math.min(scrollTop / fadeDistance, 1);\r\n \r\n // Calculate opacity (1 to 0)\r\n const opacity = 1 - fadeProgress;\r\n \r\n // Calculate transform (0px to -20px upward)\r\n const translateY = fadeProgress * -20;\r\n \r\n // Apply styles\r\n headerExpandable.style.opacity = opacity.toString();\r\n headerExpandable.style.transform = `translateY(${translateY}px)`;\r\n }\r\n \r\n this.scroll.emit(event);\r\n }\r\n \r\n /**\r\n * Handle pull-to-refresh\r\n * Emits refresh event - parent should call event.target.complete()\r\n */\r\n async handleRefresh(event: any): Promise<void> {\r\n // Haptic feedback for pull-to-refresh\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Medium });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n \r\n this.refresh.emit(event);\r\n }\r\n}\r\n\r\n","import { Component, input, output, ElementRef } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { NavController } from '@ionic/angular/standalone';\r\nimport { IonHeader, IonToolbar, IonContent } from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { MobilePageBase } from '../shared/mobile-page-base';\r\n\r\n/**\r\n * DsMobilePageDetailsComponent\r\n * \r\n * A mobile page layout for detail/drill-down pages with:\r\n * - Back button header (mobile + desktop variants)\r\n * - White background content area\r\n * - Responsive padding\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple detail page -->\r\n * <ds-mobile-page-details\r\n * title=\"Property Details\"\r\n * (back)=\"goBack()\">\r\n * <div class=\"page-content\">\r\n * <!-- Your content -->\r\n * </div>\r\n * </ds-mobile-page-details>\r\n * \r\n * <!-- With default back route -->\r\n * <ds-mobile-page-details\r\n * title=\"Invoice Details\"\r\n * backRoute=\"/invoices\">\r\n * <div class=\"page-content\">\r\n * <!-- Your content -->\r\n * </div>\r\n * </ds-mobile-page-details>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-page-details',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonContent,\r\n DsIconComponent\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-page-base.css',\r\n './ds-mobile-page-details.css'\r\n ],\r\n template: `\r\n <!-- Mobile header - hidden on desktop -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <div class=\"header-details\">\r\n <button class=\"back-button\" (click)=\"handleBack()\" [attr.aria-label]=\"'Go back'\">\r\n <ds-icon name=\"remixArrowLeftLine\" size=\"24px\" />\r\n </button>\r\n <h1 class=\"header-title\">{{ title() }}</h1>\r\n </div>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <ion-content>\r\n <!-- Content area -->\r\n <div class=\"content-wrapper\">\r\n <div class=\"content-inner\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePageDetailsComponent extends MobilePageBase {\r\n // Inputs\r\n title = input.required<string>();\r\n backRoute = input<string>(''); // Optional default back route\r\n \r\n // Outputs\r\n back = output<void>();\r\n \r\n constructor(\r\n private navCtrl: NavController,\r\n private elementRef: ElementRef\r\n ) {\r\n super();\r\n }\r\n \r\n /**\r\n * Handle back navigation\r\n * \r\n * By default, navigates using the provided backRoute or browser back.\r\n * Parent components can listen to the (back) event to override this behavior.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Default behavior: uses backRoute or browser back -->\r\n * <ds-mobile-page-details \r\n * title=\"Details\" \r\n * backRoute=\"/home\">\r\n * </ds-mobile-page-details>\r\n * \r\n * <!-- Custom behavior: parent handles navigation -->\r\n * <ds-mobile-page-details \r\n * title=\"Details\"\r\n * (back)=\"customBackHandler()\">\r\n * </ds-mobile-page-details>\r\n * ```\r\n */\r\n handleBack(): void {\r\n // Emit event for parent to optionally handle\r\n this.back.emit();\r\n \r\n // Default behavior: navigate using backRoute or browser back\r\n if (this.backRoute()) {\r\n this.navCtrl.navigateBack(this.backRoute());\r\n } else {\r\n this.navCtrl.back();\r\n }\r\n }\r\n}\r\n\r\n","import { Component, input } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileContentComponent\r\n * \r\n * Main content container for mobile pages with flexible layout options.\r\n * Provides consistent spacing and layout patterns.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Default: stacked layout -->\r\n * <ds-mobile-content>\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * </ds-mobile-content>\r\n * \r\n * <!-- Grid layout -->\r\n * <ds-mobile-content layout=\"grid-2\">\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * </ds-mobile-content>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-content',\r\n standalone: true,\r\n imports: [CommonModule],\r\n host: {\r\n '[class.layout-stacked]': 'layout() === \"stacked\"',\r\n '[class.layout-grid-2]': 'layout() === \"grid-2\"',\r\n '[class.layout-grid-3]': 'layout() === \"grid-3\"'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 32px;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n }\r\n \r\n /* Grid layouts */\r\n :host.layout-grid-2 {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 16px;\r\n }\r\n \r\n :host.layout-grid-3 {\r\n display: grid;\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 16px;\r\n }\r\n \r\n @media (max-width: 768px) {\r\n :host.layout-grid-2,\r\n :host.layout-grid-3 {\r\n grid-template-columns: 1fr;\r\n }\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class DsMobileContentComponent {\r\n /**\r\n * Layout mode for content sections\r\n * - 'stacked' - Vertical stack with 32px gap (default)\r\n * - 'grid-2' - 2 column grid\r\n * - 'grid-3' - 3 column grid (stacks on mobile)\r\n */\r\n layout = input<'stacked' | 'grid-2' | 'grid-3'>('stacked');\r\n}\r\n\r\n/**\r\n * DsMobileContentSectionComponent\r\n * \r\n * Section within mobile content with optional header.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-content-section>\r\n * <section-header width=\"half\"></section-header>\r\n * <content-row>\r\n * <div class=\"grey-box\"></div>\r\n * </content-row>\r\n * </ds-mobile-content-section>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-content-section',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"section-header\" />\r\n <ng-content />\r\n `\r\n})\r\nexport class DsMobileContentSectionComponent {}\r\n\r\n/**\r\n * SectionHeaderComponent\r\n * \r\n * Semantic placeholder header for content sections.\r\n * Used for prototyping/placeholders.\r\n */\r\n@Component({\r\n selector: 'section-header',\r\n standalone: true,\r\n host: {\r\n '[class.w-half]': 'width() === \"half\"',\r\n '[class.w-third]': 'width() === \"third\"',\r\n '[class.w-full]': 'width() === \"full\"'\r\n },\r\n styles: [`\r\n :host {\r\n height: 20px;\r\n border-radius: 8px;\r\n background: var(--color-background-neutral-tertiary);\r\n display: block;\r\n }\r\n \r\n :host.w-half { width: 50%; }\r\n :host.w-third { width: 33%; }\r\n :host.w-full { width: 100%; }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class SectionHeaderComponent {\r\n /** Width of the header placeholder */\r\n width = input<'half' | 'third' | 'full'>('half');\r\n}\r\n\r\n/**\r\n * ContentRowComponent\r\n * \r\n * Horizontal row container for content items.\r\n */\r\n@Component({\r\n selector: 'content-row',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n gap: 12px;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class ContentRowComponent {}\r\n\r\n","import { Component, input } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileHeaderContentComponent\r\n * \r\n * Container for header content tiles - displays tiles in a responsive grid.\r\n * Used within the expandable header section of mobile pages to show\r\n * summary information like property details, statistics, etc.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-header-content header-content>\r\n * <ds-mobile-header-content-tile>\r\n * <tile-icon>\r\n * <ds-icon name=\"remixHome4Line\" />\r\n * </tile-icon>\r\n * <tile-content>\r\n * <tile-label>Area</tile-label>\r\n * <tile-value>120 m²</tile-value>\r\n * </tile-content>\r\n * </ds-mobile-header-content-tile>\r\n * </ds-mobile-header-content>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-header-content',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 12px;\r\n }\r\n \r\n @media (min-width: 768px) {\r\n :host {\r\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n }\r\n }\r\n `],\r\n template: `<ng-content select=\"ds-mobile-header-content-tile\" />`\r\n})\r\nexport class DsMobileHeaderContentComponent {}\r\n\r\n/**\r\n * DsMobileHeaderContentTileComponent\r\n * \r\n * Individual tile for displaying summary information in the header.\r\n * Styled with purple background to match the mobile header theme.\r\n * \r\n * Must contain:\r\n * - `<tile-icon>` - Icon container (optional)\r\n * - `<tile-content>` - Label and value container\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-header-content-tile>\r\n * <tile-icon>\r\n * <ds-icon name=\"remixHome4Line\" size=\"20px\" color=\"#DFE4FF\" />\r\n * </tile-icon>\r\n * <tile-content>\r\n * <tile-label>Rooms</tile-label>\r\n * <tile-value>3 rooms</tile-value>\r\n * </tile-content>\r\n * </ds-mobile-header-content-tile>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-header-content-tile',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n background: rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.05);\r\n border: 1px solid rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.1);\r\n border-radius: 12px;\r\n padding: 12px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"tile-icon\" />\r\n <ng-content select=\"tile-content\" />\r\n `\r\n})\r\nexport class DsMobileHeaderContentTileComponent {}\r\n\r\n/**\r\n * TileIconComponent\r\n * \r\n * Semantic slot for tile icon with dark purple background.\r\n * Use within `ds-mobile-header-content-tile`.\r\n */\r\n@Component({\r\n selector: 'tile-icon',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n background: var(--color-brand-secondary);\r\n border-radius: 8px;\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n color: var(--color-secondary-content, #ffffff);\r\n }\r\n \r\n /* Apply color to ds-icon inside */\r\n :host ::ng-deep ds-icon {\r\n --icon-color: var(--color-secondary-content, #ffffff);\r\n color: var(--color-secondary-content, #ffffff);\r\n }\r\n \r\n :host ::ng-deep ds-icon svg {\r\n fill: var(--color-secondary-content, #ffffff);\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class TileIconComponent {}\r\n\r\n/**\r\n * TileContentComponent\r\n * \r\n * Semantic slot for tile content containing label and value.\r\n * Use within `ds-mobile-header-content-tile`.\r\n * \r\n * Contains:\r\n * - `<tile-label>` - Small label text\r\n * - `<tile-value>` - Large value text\r\n */\r\n@Component({\r\n selector: 'tile-content',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0;\r\n }\r\n \r\n ::ng-deep tile-label {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.56px;\r\n color: rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.8);\r\n display: block;\r\n }\r\n \r\n ::ng-deep tile-value {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-lg);\r\n font-weight: 600;\r\n line-height: 26px;\r\n letter-spacing: -0.72px;\r\n color: var(--color-secondary-content, #ffffff);\r\n display: block;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"tile-label\" />\r\n <ng-content select=\"tile-value\" />\r\n `\r\n})\r\nexport class TileContentComponent {}\r\n\r\n/**\r\n * TileLabelComponent\r\n * \r\n * Label text for tile content.\r\n * Use within `tile-content` inside `ds-mobile-header-content-tile`.\r\n */\r\n@Component({\r\n selector: 'tile-label',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.56px;\r\n color: rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.8);\r\n display: block;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class TileLabelComponent {}\r\n\r\n/**\r\n * TileValueComponent\r\n * \r\n * Value text for tile content.\r\n * Use within `tile-content` inside `ds-mobile-header-content-tile`.\r\n */\r\n@Component({\r\n selector: 'tile-value',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-lg);\r\n font-weight: 600;\r\n line-height: 26px;\r\n letter-spacing: -0.72px;\r\n color: var(--color-secondary-content, #ffffff);\r\n display: block;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class TileValueComponent {}\r\n\r\n","import { Component, input, output, model, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\n\r\n/**\r\n * DsMobileCommentComponent\r\n *\r\n * Individual comment component for post discussions.\r\n * Displays user comments with avatar, content, and like action.\r\n *\r\n * @example\r\n * ```html\r\n * <ds-mobile-comment\r\n * [authorName]=\"'John Doe'\"\r\n * [authorRole]=\"'Tenant'\"\r\n * [timestamp]=\"'1h ago'\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [content]=\"'Great post!'\">\r\n * </ds-mobile-comment>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-comment',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent, DsIconButtonComponent],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n host: {\r\n '[class.clickable]': 'clickable()',\r\n '(click)': 'handleCommentClick($event)',\r\n '(touchstart)': 'handleTouchStart($event)',\r\n '(touchend)': 'handleTouchEnd($event)',\r\n '(touchmove)': 'handleTouchMove($event)',\r\n '(contextmenu)': 'handleContextMenu($event)',\r\n },\r\n styles: [\r\n `\r\n :host {\r\n display: flex;\r\n gap: 12px;\r\n padding: 8px;\r\n position: relative;\r\n border-radius: 16px;\r\n transition: all 0.2s ease;\r\n background: var(--color-background-primary, #ffffff);\r\n margin-bottom: 8px;\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n }\r\n\r\n :host:last-child {\r\n margin-bottom: 0;\r\n }\r\n\r\n :host::after {\r\n content: '';\r\n position: absolute;\r\n bottom: -4px;\r\n /* Align with comment content: padding (8px) + avatar (32px) + gap (12px) */\r\n left: 44px;\r\n /* Align with comment content right edge: padding (8px) from right */\r\n right: 8px;\r\n height: 1px;\r\n background: var(--border-color-default);\r\n }\r\n\r\n :host:last-child::after {\r\n display: none;\r\n }\r\n\r\n :host.clickable {\r\n cursor: pointer;\r\n }\r\n\r\n :host.clickable:active {\r\n background: var(--color-background-neutral-primary-hover, #f5f5f5);\r\n }\r\n\r\n .avatar-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n }\r\n\r\n .comment-content {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n\r\n .comment-header {\r\n display: flex;\r\n align-items: baseline;\r\n gap: 6px;\r\n flex-wrap: wrap;\r\n }\r\n\r\n /* Wrapper for like and more actions */\r\n .header-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n margin-left: auto;\r\n }\r\n\r\n /* Desktop more actions button - using ds-icon-button */\r\n .desktop-more-button {\r\n display: none; /* Hidden by default (mobile) */\r\n }\r\n\r\n /* Make button circular */\r\n .desktop-more-button::ng-deep button {\r\n border-radius: 50% !important;\r\n }\r\n\r\n /* Show only on desktop with hover capability */\r\n @media (hover: hover) and (pointer: fine) {\r\n .desktop-more-button {\r\n display: block;\r\n }\r\n }\r\n\r\n /* Author styles imported from mobile-common.css */\r\n\r\n .action-like {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 18px;\r\n }\r\n\r\n .like-count {\r\n opacity: 1;\r\n }\r\n\r\n .like-count.hidden {\r\n opacity: 0;\r\n }\r\n\r\n .action-like.active {\r\n color: #f91880;\r\n }\r\n\r\n .icon-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n .icon-pulse {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n opacity: 0;\r\n pointer-events: none;\r\n }\r\n\r\n .icon-pulse.animating {\r\n animation: pulse 0.4s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n\r\n @keyframes pulse {\r\n 0% {\r\n transform: translate(-50%, -50%) scale(1);\r\n opacity: 0.8;\r\n }\r\n 100% {\r\n transform: translate(-50%, -50%) scale(2.5);\r\n opacity: 0;\r\n }\r\n }\r\n\r\n .comment-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n white-space: pre-wrap;\r\n word-wrap: break-word;\r\n }\r\n\r\n .comment-text ::ng-deep .mention {\r\n color: var(--color-brand-base, #6b5ff5) !important;\r\n font-weight: 600;\r\n }\r\n\r\n .comment-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n margin-top: 4px;\r\n }\r\n\r\n .action-reply {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .action-reply:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n\r\n .action-edit {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .action-edit:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n `,\r\n ],\r\n template: `\r\n <div class=\"avatar-wrapper\">\r\n <ds-avatar [initials]=\"avatarInitials()\" [type]=\"avatarType()\" size=\"sm\" />\r\n </div>\r\n\r\n <div class=\"comment-content\">\r\n <div class=\"comment-header\">\r\n <span class=\"author-name\">{{ authorName() }}</span>\r\n <span class=\"author-meta\">{{ authorRole() }} · {{ timestamp() }}</span>\r\n\r\n <!-- Wrapper for like and more actions -->\r\n <div class=\"header-actions\">\r\n <div class=\"action-like\" [class.active]=\"isLiked()\" (click)=\"toggleLike()\">\r\n <span class=\"like-count\" [class.hidden]=\"likeCount() === 0\">{{ likeCount() }}</span>\r\n <div class=\"icon-wrapper\">\r\n <ds-icon class=\"icon-pulse\" [class.animating]=\"isPulsing()\" [name]=\"isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'\" size=\"16px\" />\r\n <ds-icon [name]=\"isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'\" size=\"16px\" />\r\n </div>\r\n </div>\r\n\r\n <!-- Desktop more button -->\r\n <ds-icon-button class=\"desktop-more-button\" icon=\"remixMoreFill\" variant=\"secondary\" size=\"sm\" (clicked)=\"handleMoreButtonClick($event)\" aria-label=\"More options\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"comment-text\" [innerHTML]=\"formattedContent()\"></div>\r\n\r\n <div class=\"comment-actions\">\r\n <div class=\"action-reply\" (click)=\"handleReply()\">Reply</div>\r\n @if (isOwnComment()) {\r\n <div class=\"action-edit\" (click)=\"handleEdit()\">Edit</div>\r\n }\r\n </div>\r\n </div>\r\n `,\r\n})\r\nexport class DsMobileCommentComponent {\r\n /**\r\n * Author's display name\r\n */\r\n authorName = input.required<string>();\r\n\r\n /**\r\n * Author's role (e.g., \"Tenant\", \"Property Manager\")\r\n */\r\n authorRole = input.required<string>();\r\n\r\n /**\r\n * Timestamp text (e.g., \"1h ago\", \"2d ago\")\r\n */\r\n timestamp = input.required<string>();\r\n\r\n /**\r\n * Comment content text\r\n */\r\n content = input.required<string>();\r\n\r\n /**\r\n * Avatar initials\r\n */\r\n avatarInitials = input<string>('');\r\n\r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n\r\n /**\r\n * Whether the comment is clickable\r\n */\r\n clickable = input<boolean>(false);\r\n\r\n /**\r\n * Whether this comment belongs to the current user\r\n */\r\n isOwnComment = input<boolean>(false);\r\n\r\n /**\r\n * Whether the comment is liked by current user\r\n */\r\n isLiked = model<boolean>(false);\r\n\r\n /**\r\n * Emits when like is toggled (after UI is opdateret)\r\n */\r\n likeToggled = output<{ active: boolean; count: number }>();\r\n\r\n /**\r\n * Number of likes\r\n */\r\n likeCount = model<number>(0);\r\n\r\n /**\r\n * Signal to control pulse animation\r\n */\r\n isPulsing = signal(false);\r\n\r\n /**\r\n * Computed property to format content with @mentions\r\n */\r\n formattedContent = computed(() => {\r\n const text = this.content();\r\n // Replace @mentions with styled spans\r\n // Matches @FirstName or @FirstName LastName (max 2 words)\r\n return text.replace(/@([A-Za-z]+(?:\\s+[A-Za-z]+)?)\\b/g, '<span class=\"mention\">@$1</span>');\r\n });\r\n\r\n /**\r\n * Emits when the comment card is clicked (if clickable)\r\n */\r\n commentClick = output<void>();\r\n\r\n /**\r\n * Emits when reply is clicked\r\n */\r\n replyClick = output<void>();\r\n\r\n /**\r\n * Emits when edit is clicked\r\n */\r\n editClick = output<void>();\r\n\r\n /**\r\n * Emits when the comment is long-pressed\r\n */\r\n longPress = output<void>();\r\n\r\n /**\r\n * Long press tracking\r\n */\r\n private longPressTimer: any = null;\r\n private longPressTriggered = false;\r\n private touchStartX = 0;\r\n private touchStartY = 0;\r\n private readonly LONG_PRESS_DURATION = 500; // ms\r\n private readonly MOVE_THRESHOLD = 10; // px\r\n\r\n handleCommentClick(event: Event): void {\r\n // Only emit if clickable and not clicking on action buttons\r\n if (this.clickable() && !(event.target as HTMLElement).closest('.comment-actions')) {\r\n this.commentClick.emit();\r\n }\r\n }\r\n\r\n async toggleLike(): Promise<void> {\r\n const newLiked = !this.isLiked();\r\n this.isLiked.set(newLiked);\r\n\r\n const newCount = newLiked ? this.likeCount() + 1 : this.likeCount() - 1;\r\n this.likeCount.set(Math.max(0, newCount));\r\n\r\n // Emit the like toggled event\r\n this.likeToggled.emit({ active: newLiked, count: Math.max(0, newCount) });\r\n\r\n // Trigger pulse animation only when liking\r\n if (newLiked) {\r\n this.isPulsing.set(true);\r\n setTimeout(() => this.isPulsing.set(false), 400);\r\n }\r\n\r\n // Haptic feedback for like/unlike\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Light });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n }\r\n\r\n handleReply(): void {\r\n this.replyClick.emit();\r\n }\r\n\r\n handleEdit(): void {\r\n this.editClick.emit();\r\n }\r\n\r\n /**\r\n * Handle touch start for long press detection\r\n */\r\n handleTouchStart(event: TouchEvent): void {\r\n this.longPressTriggered = false;\r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n\r\n // Start long press timer\r\n this.longPressTimer = setTimeout(async () => {\r\n this.longPressTriggered = true;\r\n this.longPress.emit();\r\n\r\n // Haptic feedback for long press\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Medium });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n }, this.LONG_PRESS_DURATION);\r\n }\r\n\r\n /**\r\n * Handle touch end to clear long press timer\r\n */\r\n handleTouchEnd(event: TouchEvent): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n\r\n // Prevent normal click if long press was triggered\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle touch move to cancel long press if moved too much\r\n */\r\n handleTouchMove(event: TouchEvent): void {\r\n if (!this.longPressTimer) return;\r\n\r\n const touch = event.touches[0];\r\n const deltaX = Math.abs(touch.clientX - this.touchStartX);\r\n const deltaY = Math.abs(touch.clientY - this.touchStartY);\r\n\r\n // Cancel long press if moved too far\r\n if (deltaX > this.MOVE_THRESHOLD || deltaY > this.MOVE_THRESHOLD) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle context menu (right-click on desktop) to trigger long press action\r\n */\r\n handleContextMenu(event: Event): void {\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n\r\n /**\r\n * Handle desktop more button click\r\n * Stops propagation and triggers long press action\r\n */\r\n handleMoreButtonClick(event: Event): void {\r\n console.log('[Comment] Desktop more button clicked');\r\n event.stopPropagation();\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n}\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobilePostComposerComponent\r\n * \r\n * A \"fake\" input composer for creating new posts in the community feed.\r\n * Features a user avatar, placeholder input, and post button.\r\n * Clicking opens the full post creation modal/page.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-post-composer\r\n * [avatarInitials]=\"'LM'\"\r\n * [avatarType]=\"'photo'\"\r\n * [avatarSrc]=\"'...'\"\r\n * (composerClick)=\"openPostCreator()\">\r\n * </ds-mobile-post-composer>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-post-composer',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent],\r\n host: {\r\n '(click)': 'handleClick()'\r\n },\r\n styles: [`\r\n :host {\r\n display: block;\r\n max-width: 640px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n }\r\n \r\n .composer-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n \r\n .composer-input-wrapper {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .composer-input {\r\n width: 100%;\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.1);\r\n border: none;\r\n border-radius: 24px;\r\n padding: 10px 16px;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.75);\r\n outline: none;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n pointer-events: none;\r\n user-select: none;\r\n }\r\n \r\n .composer-input::placeholder {\r\n color: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.75);\r\n opacity: 1;\r\n }\r\n \r\n /* Hover effects for desktop */\r\n @media (hover: hover) {\r\n :host:hover .composer-input {\r\n opacity: 0.8;\r\n }\r\n }\r\n `],\r\n template: `\r\n <div class=\"composer-container\">\r\n <ds-avatar \r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n [iconName]=\"avatarIconName()\"\r\n size=\"md\" />\r\n \r\n <div class=\"composer-input-wrapper\">\r\n <input \r\n type=\"text\" \r\n class=\"composer-input\" \r\n [placeholder]=\"placeholder()\"\r\n readonly\r\n tabindex=\"-1\"\r\n />\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobilePostComposerComponent {\r\n /**\r\n * Avatar initials (for initials type)\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Icon name (for icon type avatars)\r\n */\r\n avatarIconName = input<string>('remixUser3Fill');\r\n \r\n /**\r\n * Placeholder text for the input\r\n */\r\n placeholder = input<string>(\"Hvad er nyt?\");\r\n \r\n /**\r\n * Text for the post button\r\n */\r\n buttonText = input<string>('Slå op');\r\n \r\n /**\r\n * Emits when the composer is clicked\r\n */\r\n composerClick = output<void>();\r\n \r\n handleClick(): void {\r\n this.composerClick.emit();\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n input,\r\n output,\r\n signal,\r\n computed,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileMessageComposerComponent\r\n * \r\n * Reusable message composer component extracted from post-detail-modal.\r\n * Can be used for both comments and chat messages.\r\n * \r\n * Features:\r\n * - Text input with auto-resize\r\n * - Avatar display\r\n * - Send button (appears when text is entered)\r\n * - Optional mention menu support\r\n * - Optional edit/reply indicators\r\n * - Keyboard handling for mobile\r\n * - Safe area support\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-message-composer\r\n * [avatarInitials]=\"'JD'\"\r\n * [placeholder]=\"'Write a message...'\"\r\n * (messageSent)=\"handleMessage($event)\">\r\n * </ds-mobile-message-composer>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-message-composer',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n DsAvatarComponent,\r\n DsIconButtonComponent,\r\n DsIconComponent\r\n ],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n\r\n /* Composer Container */\r\n .message-composer {\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-top: 1px solid var(--border-color-default);\r\n border-bottom-left-radius: 0;\r\n border-bottom-right-radius: 0;\r\n padding: 12px 16px;\r\n /* Use dynamic viewport height safe area */\r\n padding-bottom: max(12px, env(safe-area-inset-bottom, 0px));\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n\r\n /* Edit indicator (optional) */\r\n .edit-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-brand-subtle, #f0edfe);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n \r\n .edit-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: var(--color-brand-base, #6B5FF5);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .edit-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-brand-base, #6B5FF5);\r\n }\r\n \r\n .cancel-edit {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-brand-base, #6B5FF5);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n \r\n .cancel-edit:active {\r\n background: var(--color-brand-subtle, #e0dbfe);\r\n }\r\n \r\n /* Reply indicator (optional) */\r\n .reply-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n \r\n .reply-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n color: var(--color-text-secondary, #737373);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .reply-to-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .reply-author {\r\n color: var(--color-brand-base, #6B5FF5);\r\n font-weight: 600;\r\n }\r\n \r\n .cancel-reply {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-text-secondary, #737373);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n \r\n .cancel-reply:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n \r\n @keyframes slideDown {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n \r\n .composer-content {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n width: 100%;\r\n position: relative;\r\n }\r\n \r\n .composer-content ds-avatar {\r\n position: relative;\r\n top: 6px;\r\n }\r\n \r\n .composer-input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 8px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 24px;\r\n padding: 12px 16px;\r\n padding-right: 48px; /* Extra padding for fixed send button */\r\n min-height: 44px;\r\n position: relative;\r\n }\r\n \r\n /* Mention menu (optional) */\r\n .mention-menu {\r\n position: absolute;\r\n bottom: 100%;\r\n left: 0;\r\n right: 0;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-radius: 12px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n margin-bottom: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n z-index: 10;\r\n animation: slideUp 0.2s ease-out;\r\n }\r\n \r\n @keyframes slideUp {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n \r\n .mention-menu-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 12px;\r\n border: none;\r\n background: none;\r\n width: 100%;\r\n text-align: left;\r\n cursor: pointer;\r\n transition: background 0.2s ease;\r\n border-bottom: 1px solid var(--border-color-default);\r\n }\r\n \r\n .mention-menu-item:last-child {\r\n border-bottom: none;\r\n }\r\n \r\n .mention-menu-item:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n \r\n .mention-user-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .mention-user-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .mention-user-role {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n }\r\n \r\n .composer-input {\r\n flex: 1;\r\n border: none;\r\n background: transparent;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n outline: none;\r\n resize: none;\r\n min-height: 20px;\r\n max-height: 120px;\r\n overflow-y: auto;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n \r\n .composer-input::placeholder {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n font-size: var(--font-size-sm);\r\n }\r\n \r\n /* Send button - positioned in top right corner */\r\n .send-button-fixed {\r\n position: absolute;\r\n top: 6px;\r\n right: 6px;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n animation: slideInFromRight 0.2s ease-out;\r\n }\r\n \r\n .send-button-fixed::ng-deep button {\r\n width: 32px !important;\r\n height: 32px !important;\r\n min-width: 32px !important;\r\n min-height: 32px !important;\r\n padding: 0 !important;\r\n border-radius: 50% !important;\r\n }\r\n \r\n @keyframes slideInFromRight {\r\n from {\r\n opacity: 0;\r\n transform: translateX(20px) scale(0.8);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateX(0) scale(1);\r\n }\r\n }\r\n `],\r\n template: `\r\n <div class=\"message-composer\">\r\n <!-- Edit indicator (optional) -->\r\n @if (editingMessage()) {\r\n <div class=\"edit-indicator\">\r\n <div class=\"edit-indicator-content\">\r\n <ds-icon name=\"remixEditLine\" size=\"16px\" />\r\n <span class=\"edit-text\">{{ editIndicatorText() }}</span>\r\n </div>\r\n <button class=\"cancel-edit\" (click)=\"cancelEdit()\" type=\"button\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n }\r\n \r\n <!-- Reply indicator (optional) -->\r\n @if (replyingTo() && !editingMessage()) {\r\n <div class=\"reply-indicator\">\r\n <div class=\"reply-indicator-content\">\r\n <ds-icon name=\"remixReplyLine\" size=\"16px\" />\r\n <span class=\"reply-to-text\">\r\n {{ replyIndicatorText() }} <span class=\"reply-author\">{{ replyingTo()!.authorName }}</span>\r\n </span>\r\n </div>\r\n <button class=\"cancel-reply\" (click)=\"cancelReply()\" type=\"button\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n }\r\n \r\n <div class=\"composer-content\">\r\n <ds-avatar\r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n size=\"md\"\r\n />\r\n <div class=\"composer-input-wrapper\">\r\n <!-- Mention menu (optional) -->\r\n @if (showMentionMenu() && filteredUsers().length > 0 && !editingMessage()) {\r\n <div class=\"mention-menu\">\r\n @for (user of filteredUsers(); track user.name) {\r\n <button \r\n class=\"mention-menu-item\" \r\n (click)=\"selectMention(user.name)\"\r\n type=\"button\">\r\n <ds-avatar \r\n [initials]=\"user.initials\"\r\n [type]=\"'initials'\"\r\n size=\"sm\" />\r\n <div class=\"mention-user-info\">\r\n <span class=\"mention-user-name\">{{ user.name }}</span>\r\n <span class=\"mention-user-role\">{{ user.role }}</span>\r\n </div>\r\n </button>\r\n }\r\n </div>\r\n }\r\n \r\n <textarea\r\n #messageInput\r\n class=\"composer-input\"\r\n [placeholder]=\"placeholder()\"\r\n [(ngModel)]=\"messageText\"\r\n (input)=\"handleInput($event)\"\r\n (focus)=\"showKeyboard()\"\r\n (click)=\"showKeyboard()\"\r\n rows=\"1\"\r\n ></textarea>\r\n </div>\r\n @if (messageText().trim().length > 0) {\r\n <ds-icon-button\r\n icon=\"remixCheckLine\"\r\n variant=\"primary\"\r\n size=\"sm\"\r\n (clicked)=\"sendMessage()\"\r\n [attr.aria-label]=\"sendButtonLabel()\"\r\n class=\"send-button-fixed\">\r\n </ds-icon-button>\r\n }\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileMessageComposerComponent implements AfterViewInit, OnDestroy {\r\n /**\r\n * Avatar initials\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Placeholder text for the input\r\n */\r\n placeholder = input<string>('Write a message...');\r\n \r\n /**\r\n * Send button aria label\r\n */\r\n sendButtonLabel = input<string>('Send message');\r\n \r\n /**\r\n * Edit indicator text (when editing)\r\n */\r\n editIndicatorText = input<string>('Editing message');\r\n \r\n /**\r\n * Reply indicator text prefix\r\n */\r\n replyIndicatorText = input<string>('Replying to');\r\n \r\n /**\r\n * Whether to enable mention support\r\n */\r\n enableMentions = input<boolean>(false);\r\n \r\n /**\r\n * Available users for mentions (if mentions enabled)\r\n */\r\n mentionUsers = input<Array<{ name: string; initials: string; role: string }>>([]);\r\n \r\n /**\r\n * Auto-focus input on mount\r\n */\r\n autoFocus = input<boolean>(false);\r\n \r\n /**\r\n * ViewChild for message input\r\n */\r\n @ViewChild('messageInput') messageInput?: ElementRef<HTMLTextAreaElement>;\r\n \r\n /**\r\n * Message text signal\r\n */\r\n messageText = signal('');\r\n \r\n /**\r\n * Editing message state (optional)\r\n */\r\n editingMessage = signal<{ authorName: string; originalContent: string; timestamp: string } | null>(null);\r\n \r\n /**\r\n * Replying to state (optional)\r\n */\r\n replyingTo = signal<{ authorName: string; content: string } | null>(null);\r\n \r\n /**\r\n * Mention menu state\r\n */\r\n showMentionMenu = signal(false);\r\n \r\n /**\r\n * Mention query for filtering\r\n */\r\n mentionQuery = signal('');\r\n \r\n /**\r\n * Filtered users based on mention query\r\n */\r\n filteredUsers = computed(() => {\r\n if (!this.enableMentions()) return [];\r\n \r\n const query = this.mentionQuery().toLowerCase();\r\n const users = this.mentionUsers();\r\n \r\n if (!query) return users;\r\n return users.filter(user => \r\n user.name.toLowerCase().includes(query)\r\n );\r\n });\r\n \r\n /**\r\n * Emits when a message is sent\r\n */\r\n messageSent = output<{ content: string; isReply?: boolean; replyTo?: string; isEdit?: boolean }>();\r\n \r\n /**\r\n * Emits when edit is cancelled\r\n */\r\n editCancelled = output<void>();\r\n \r\n /**\r\n * Emits when reply is cancelled\r\n */\r\n replyCancelled = output<void>();\r\n \r\n /**\r\n * Emits when mention is selected\r\n */\r\n mentionSelected = output<{ userName: string }>();\r\n \r\n ngAfterViewInit(): void {\r\n // Auto-focus input if requested\r\n if (this.autoFocus()) {\r\n setTimeout(() => {\r\n this.messageInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }, 300);\r\n }\r\n \r\n // Set up keyboard listeners\r\n this.setupKeyboardListeners();\r\n }\r\n \r\n ngOnDestroy(): void {\r\n // Clean up keyboard listeners\r\n this.cleanupKeyboardListeners();\r\n }\r\n \r\n /**\r\n * Set up keyboard event listeners\r\n */\r\n private setupKeyboardListeners(): void {\r\n Keyboard.addListener('keyboardWillShow', (info) => {\r\n document.documentElement.style.setProperty('--keyboard-height', `${info.keyboardHeight}px`);\r\n }).catch(e => console.log('Keyboard listeners not available:', e));\r\n \r\n Keyboard.addListener('keyboardWillHide', () => {\r\n document.documentElement.style.setProperty('--keyboard-height', '0px');\r\n }).catch(e => console.log('Keyboard listeners not available:', e));\r\n }\r\n \r\n /**\r\n * Clean up keyboard event listeners\r\n */\r\n private cleanupKeyboardListeners(): void {\r\n Keyboard.removeAllListeners().catch(e => console.log('Keyboard cleanup not available:', e));\r\n }\r\n \r\n /**\r\n * Show the keyboard when user interacts with input\r\n */\r\n showKeyboard(): void {\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n }\r\n \r\n /**\r\n * Handle input changes and detect @ mentions\r\n */\r\n handleInput(event: Event): void {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n const text = textarea.value;\r\n const cursorPosition = textarea.selectionStart || 0;\r\n \r\n // Update signal\r\n this.messageText.set(text);\r\n \r\n // Auto-resize textarea\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n \r\n // Handle mentions if enabled\r\n if (this.enableMentions()) {\r\n // Find the last @ before cursor\r\n const textBeforeCursor = text.substring(0, cursorPosition);\r\n const lastAtIndex = textBeforeCursor.lastIndexOf('@');\r\n \r\n if (lastAtIndex !== -1) {\r\n // Check if there's a space after @\r\n const textAfterAt = textBeforeCursor.substring(lastAtIndex + 1);\r\n const hasSpace = textAfterAt.includes(' ');\r\n \r\n if (!hasSpace) {\r\n // Show mention menu\r\n this.showMentionMenu.set(true);\r\n this.mentionQuery.set(textAfterAt);\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Select a user from mention menu\r\n */\r\n selectMention(userName: string): void {\r\n // Set as reply (similar to clicking Reply)\r\n this.replyingTo.set({ authorName: userName, content: '' });\r\n \r\n // Clear the @ from the input\r\n const currentText = this.messageText();\r\n const textWithoutMention = currentText.substring(0, currentText.lastIndexOf('@'));\r\n this.messageText.set(textWithoutMention);\r\n \r\n // Hide mention menu\r\n this.showMentionMenu.set(false);\r\n \r\n // Emit mention selected event\r\n this.mentionSelected.emit({ userName });\r\n \r\n // Focus back on input\r\n setTimeout(() => {\r\n this.messageInput?.nativeElement.focus();\r\n }, 0);\r\n }\r\n \r\n /**\r\n * Cancel edit\r\n */\r\n cancelEdit(): void {\r\n this.editingMessage.set(null);\r\n this.messageText.set('');\r\n this.editCancelled.emit();\r\n }\r\n \r\n /**\r\n * Cancel reply\r\n */\r\n cancelReply(): void {\r\n this.replyingTo.set(null);\r\n this.replyCancelled.emit();\r\n }\r\n \r\n /**\r\n * Set reply state (for external use)\r\n */\r\n setReply(authorName: string, content: string): void {\r\n this.replyingTo.set({ authorName, content });\r\n // Focus the input and show keyboard\r\n setTimeout(() => {\r\n this.messageInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Set edit state (for external use)\r\n */\r\n setEdit(authorName: string, originalContent: string, timestamp: string): void {\r\n // Clear reply state if active\r\n this.replyingTo.set(null);\r\n \r\n // Remove @mention from the content if it exists\r\n let contentToEdit = originalContent;\r\n const mentionMatch = originalContent.match(/^@([A-Za-z]+(?:\\s+[A-Za-z]+)?)\\s+/);\r\n if (mentionMatch) {\r\n contentToEdit = originalContent.substring(mentionMatch[0].length);\r\n }\r\n \r\n // Set edit state\r\n this.editingMessage.set({ authorName, originalContent, timestamp });\r\n \r\n // Populate the input with existing content\r\n this.messageText.set(contentToEdit);\r\n \r\n // Focus the input, show keyboard, and auto-resize\r\n setTimeout(() => {\r\n if (this.messageInput?.nativeElement) {\r\n const textarea = this.messageInput.nativeElement;\r\n textarea.focus();\r\n \r\n // Auto-resize textarea to fit content\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n \r\n this.showKeyboard();\r\n }\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Clear composer state\r\n */\r\n clear(): void {\r\n this.messageText.set('');\r\n this.editingMessage.set(null);\r\n this.replyingTo.set(null);\r\n this.showMentionMenu.set(false);\r\n \r\n // Reset textarea height\r\n if (this.messageInput?.nativeElement) {\r\n this.messageInput.nativeElement.style.height = 'auto';\r\n }\r\n }\r\n \r\n /**\r\n * Focus the input\r\n */\r\n focus(): void {\r\n this.messageInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }\r\n \r\n /**\r\n * Send message\r\n */\r\n sendMessage(): void {\r\n const text = this.messageText().trim();\r\n if (!text) return;\r\n \r\n const isEdit = !!this.editingMessage();\r\n const isReply = !!this.replyingTo();\r\n \r\n // Emit message sent event\r\n this.messageSent.emit({\r\n content: isReply && this.replyingTo()\r\n ? `@${this.replyingTo()!.authorName} ${text}`\r\n : text,\r\n isReply,\r\n replyTo: this.replyingTo()?.authorName,\r\n isEdit\r\n });\r\n \r\n // Clear the input and states\r\n this.clear();\r\n \r\n // Blur the input to hide the keyboard\r\n this.messageInput?.nativeElement.blur();\r\n \r\n // Hide keyboard explicitly\r\n Keyboard.hide().catch(e => console.log('Keyboard.hide() not available'));\r\n }\r\n}\r\n\r\n","import { Component, input, output, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * Chat attachment interface\r\n */\r\nexport interface ChatAttachment {\r\n id: string;\r\n type: 'image' | 'pdf' | 'file';\r\n url: string;\r\n name: string;\r\n size?: number;\r\n thumbnail?: string;\r\n}\r\n\r\n/**\r\n * DsMobileMessageBubbleComponent\r\n * \r\n * Individual message bubble component for chat conversations.\r\n * Supports left-aligned (sender) and right-aligned (user) messages with different styling.\r\n * \r\n * Features:\r\n * - Left/right alignment based on sender\r\n * - Avatar display (left for sender, right for user)\r\n * - Message content with text wrapping\r\n * - Timestamp display\r\n * - Read receipt indicator (for user's messages)\r\n * - Attachment support\r\n * - Long press support for actions\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Sender's message (left-aligned) -->\r\n * <ds-mobile-message-bubble\r\n * [isOwnMessage]=\"false\"\r\n * [senderName]=\"'Ricki Meihlen'\"\r\n * [content]=\"'We have received your case...'\"\r\n * [timestamp]=\"'12:34'\"\r\n * [avatarInitials]=\"'RM'\">\r\n * </ds-mobile-message-bubble>\r\n * \r\n * <!-- User's message (right-aligned) -->\r\n * <ds-mobile-message-bubble\r\n * [isOwnMessage]=\"true\"\r\n * [senderName]=\"'You'\"\r\n * [content]=\"'Thank you!'\"\r\n * [timestamp]=\"'12:35'\"\r\n * [readStatus]=\"true\"\r\n * [avatarInitials]=\"'JD'\">\r\n * </ds-mobile-message-bubble>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-message-bubble',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent],\r\n host: {\r\n '[class.is-own-message]': 'isOwnMessage()',\r\n '[class.has-attachments]': 'attachments() && attachments()!.length > 0',\r\n '(touchstart)': 'handleTouchStart($event)',\r\n '(touchend)': 'handleTouchEnd($event)',\r\n '(touchmove)': 'handleTouchMove($event)',\r\n '(contextmenu)': 'handleContextMenu($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n gap: 8px;\r\n margin-bottom: 12px;\r\n width: 100%;\r\n align-items: flex-end;\r\n box-sizing: border-box;\r\n }\r\n \r\n /* Left-aligned (sender's message) */\r\n :host:not(.is-own-message) {\r\n justify-content: flex-start !important;\r\n flex-direction: row !important;\r\n }\r\n \r\n /* Right-aligned (user's message) - MUST be right-aligned */\r\n :host.is-own-message {\r\n justify-content: flex-end !important;\r\n flex-direction: row-reverse !important;\r\n margin-left: auto !important;\r\n margin-right: 0 !important;\r\n }\r\n \r\n .avatar-wrapper {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: flex-end;\r\n }\r\n \r\n .message-content-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n max-width: 75%;\r\n min-width: 0;\r\n }\r\n \r\n /* Left-aligned message bubble */\r\n :host:not(.is-own-message) .message-content-wrapper {\r\n align-items: flex-start;\r\n }\r\n \r\n /* Right-aligned message bubble */\r\n :host.is-own-message .message-content-wrapper {\r\n align-items: flex-end !important;\r\n margin-left: auto !important;\r\n margin-right: 0 !important;\r\n }\r\n \r\n .message-bubble {\r\n padding: 10px 14px;\r\n padding-bottom: 6px; /* Reduced bottom padding to accommodate timestamp */\r\n border-radius: 16px;\r\n position: relative;\r\n word-wrap: break-word;\r\n white-space: pre-wrap;\r\n max-width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n \r\n /* Sender's message - white background */\r\n :host:not(.is-own-message) .message-bubble {\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border: 1px solid var(--border-color-default, #e5e5e5);\r\n }\r\n \r\n /* User's message - brand primary surface background */\r\n :host.is-own-message .message-bubble {\r\n background: var(--color-primary-surface, var(--color-brand-base, #6B5FF5));\r\n color: var(--color-primary-content, #ffffff);\r\n }\r\n \r\n .message-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n margin: 0;\r\n }\r\n \r\n :host:not(.is-own-message) .message-text {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n :host.is-own-message .message-text {\r\n color: var(--color-primary-content, #ffffff);\r\n }\r\n \r\n /* Attachments container */\r\n .attachments {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n margin-top: 8px;\r\n }\r\n \r\n :host:not(.is-own-message) .attachments {\r\n justify-content: flex-start;\r\n }\r\n \r\n :host.is-own-message .attachments {\r\n justify-content: flex-end;\r\n }\r\n \r\n .attachment-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 8px;\r\n border: 1px solid var(--border-color-default, #e5e5e5);\r\n cursor: pointer;\r\n transition: background 0.2s ease;\r\n }\r\n \r\n :host.is-own-message .attachment-item {\r\n background: rgba(255, 255, 255, 0.2);\r\n border-color: rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .attachment-item:active {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n :host.is-own-message .attachment-item:active {\r\n background: rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .attachment-icon {\r\n flex-shrink: 0;\r\n width: 24px;\r\n height: 24px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: 4px;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n \r\n :host.is-own-message .attachment-icon {\r\n background: rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .attachment-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 16px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n \r\n :host.is-own-message .attachment-name {\r\n color: var(--color-text-on-brand, #ffffff);\r\n }\r\n \r\n /* Timestamp and read receipt inside bubble */\r\n .message-footer {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n margin-top: 2px;\r\n align-self: flex-end; /* Always align to right within bubble */\r\n }\r\n \r\n :host:not(.is-own-message) .message-footer {\r\n align-self: flex-start; /* Left-align for sender's messages */\r\n }\r\n \r\n .timestamp {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 14px;\r\n }\r\n \r\n /* Timestamp color for sender's messages (white background) */\r\n :host:not(.is-own-message) .timestamp {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n \r\n /* Timestamp color for user's messages (brand primary surface background) */\r\n :host.is-own-message .timestamp {\r\n color: var(--color-primary-content, #ffffff);\r\n opacity: 0.8;\r\n }\r\n \r\n /* Long press tracking */\r\n :host {\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n `],\r\n template: `\r\n <div class=\"avatar-wrapper\">\r\n <ds-avatar\r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n size=\"sm\" />\r\n </div>\r\n \r\n <div class=\"message-content-wrapper\">\r\n <div class=\"message-bubble\">\r\n <p class=\"message-text\">{{ content() }}</p>\r\n \r\n <!-- Attachments -->\r\n @if (attachments() && attachments()!.length > 0) {\r\n <div class=\"attachments\">\r\n @for (attachment of attachments(); track attachment.id) {\r\n <div \r\n class=\"attachment-item\"\r\n (click)=\"handleAttachmentClick(attachment)\">\r\n <div class=\"attachment-icon\">\r\n @if (attachment.type === 'image') {\r\n <ds-icon name=\"remixImageLine\" size=\"16px\" />\r\n } @else if (attachment.type === 'pdf') {\r\n <ds-icon name=\"remixFilePdfLine\" size=\"16px\" />\r\n } @else {\r\n <ds-icon name=\"remixFileLine\" size=\"16px\" />\r\n }\r\n </div>\r\n <span class=\"attachment-name\">{{ attachment.name }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Timestamp inside bubble -->\r\n <div class=\"message-footer\">\r\n <span class=\"timestamp\">{{ timestamp() }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileMessageBubbleComponent {\r\n /**\r\n * Message content text\r\n */\r\n content = input.required<string>();\r\n \r\n /**\r\n * Whether this is the current user's message (right-aligned)\r\n */\r\n isOwnMessage = input<boolean>(false);\r\n \r\n /**\r\n * Sender's name (for display purposes)\r\n */\r\n senderName = input<string>('');\r\n \r\n /**\r\n * Timestamp text (e.g., \"12:34\", \"08-12-2025 13:18\")\r\n */\r\n timestamp = input.required<string>();\r\n \r\n /**\r\n * Avatar initials\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Whether to show read receipt (only for user's messages)\r\n */\r\n /**\r\n * Message attachments\r\n */\r\n attachments = input<ChatAttachment[] | undefined>(undefined);\r\n \r\n /**\r\n * Whether the message is clickable\r\n */\r\n clickable = input<boolean>(false);\r\n \r\n /**\r\n * Emits when attachment is clicked\r\n */\r\n attachmentClick = output<ChatAttachment>();\r\n \r\n /**\r\n * Emits when the message is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n /**\r\n * Long press tracking\r\n */\r\n private longPressTimer: any = null;\r\n private longPressTriggered = false;\r\n private touchStartX = 0;\r\n private touchStartY = 0;\r\n private readonly LONG_PRESS_DURATION = 500; // ms\r\n private readonly MOVE_THRESHOLD = 10; // px\r\n \r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: ChatAttachment): void {\r\n this.attachmentClick.emit(attachment);\r\n }\r\n \r\n /**\r\n * Handle touch start for long press detection\r\n */\r\n handleTouchStart(event: TouchEvent): void {\r\n if (!this.clickable()) return;\r\n \r\n this.longPressTriggered = false;\r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n \r\n // Start long press timer\r\n this.longPressTimer = setTimeout(() => {\r\n this.longPressTriggered = true;\r\n this.longPress.emit();\r\n }, this.LONG_PRESS_DURATION);\r\n }\r\n \r\n /**\r\n * Handle touch end to clear long press timer\r\n */\r\n handleTouchEnd(event: TouchEvent): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n \r\n // Prevent normal click if long press was triggered\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n \r\n /**\r\n * Handle touch move to cancel long press if moved too much\r\n */\r\n handleTouchMove(event: TouchEvent): void {\r\n if (!this.longPressTimer) return;\r\n \r\n const touch = event.touches[0];\r\n const deltaX = Math.abs(touch.clientX - this.touchStartX);\r\n const deltaY = Math.abs(touch.clientY - this.touchStartY);\r\n \r\n // Cancel long press if moved too far\r\n if (deltaX > this.MOVE_THRESHOLD || deltaY > this.MOVE_THRESHOLD) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n \r\n /**\r\n * Handle context menu (right-click on desktop) to trigger long press action\r\n */\r\n handleContextMenu(event: Event): void {\r\n if (!this.clickable()) return;\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileListItemStaticComponent\r\n * \r\n * A read-only version of the interactive list item component.\r\n * Used for displaying static information without interaction.\r\n * \r\n * This component has the same structure as the interactive list item but without:\r\n * - Padding\r\n * - Rounded corners\r\n * - Hover states\r\n * - Click interactions\r\n * - Background fill (transparent)\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-list-item-static\r\n * [leadingSize]=\"'40px'\">\r\n * \r\n * <div content-leading>\r\n * <ds-avatar initials=\"JD\" />\r\n * </div>\r\n * \r\n * <div content-main>\r\n * <h3>Main Content</h3>\r\n * <p>Supporting text goes here...</p>\r\n * </div>\r\n * \r\n * <div content-trailing>\r\n * <span>Info</span>\r\n * </div>\r\n * </ds-mobile-list-item-static>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-list-item-static',\r\n standalone: true,\r\n imports: [CommonModule],\r\n host: {\r\n '[style.--leading-size]': 'leadingSize()'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: row;\r\n align-items: flex-start;\r\n background: transparent;\r\n padding: 0;\r\n gap: 12px;\r\n position: relative;\r\n --leading-size: 32px;\r\n }\r\n \r\n :host::after {\r\n content: '';\r\n position: absolute;\r\n bottom: -10px;\r\n left: calc(var(--leading-size) + 12px);\r\n right: 0;\r\n height: 1px;\r\n background: var(--border-color-default);\r\n }\r\n \r\n :host:last-child::after {\r\n display: none;\r\n }\r\n \r\n .content-leading {\r\n flex-shrink: 0;\r\n width: var(--leading-size);\r\n min-height: var(--leading-size);\r\n height: auto;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .content-main {\r\n flex: 1;\r\n min-width: 0;\r\n min-height: var(--leading-size);\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: flex-start;\r\n gap: 8px;\r\n }\r\n \r\n .content-trailing {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: flex-start;\r\n }\r\n `],\r\n template: `\r\n @if (hasLeadingContent()) {\r\n <div class=\"content-leading\">\r\n <ng-content select=\"[content-leading]\" />\r\n </div>\r\n }\r\n \r\n <div class=\"content-main\">\r\n <ng-content select=\"[content-main]\" />\r\n <ng-content />\r\n </div>\r\n \r\n @if (hasTrailingContent()) {\r\n <div class=\"content-trailing\">\r\n <ng-content select=\"[content-trailing]\" />\r\n </div>\r\n }\r\n `\r\n})\r\nexport class DsMobileListItemStaticComponent {\r\n /**\r\n * CSS size value for the leading content area (e.g., '32px', '40px', '48px')\r\n * Defaults to '32px' for standard list item avatars\r\n */\r\n leadingSize = input<string>('32px');\r\n \r\n /**\r\n * Check if leading content slot has content\r\n */\r\n hasLeadingContent = computed(() => true); // Always render slot container for consistency\r\n \r\n /**\r\n * Check if trailing content slot has content\r\n */\r\n hasTrailingContent = computed(() => true); // Always render slot container for consistency\r\n}\r\n\r\n","import { Component, input, output, signal, model } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsMobileListItemComponent } from '../list-item';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge/ds-avatar-with-badge';\r\n\r\n/**\r\n * DsMobileInteractiveListItemPostComponent\r\n * \r\n * Specialized interactive list item for displaying social media posts.\r\n * Built on top of ds-mobile-interactive-list-item base component.\r\n * Displays user posts with avatar, content, media, and action buttons.\r\n * Follows Threads-inspired design with clean layout and interactions.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-interactive-list-item-post\r\n * [authorName]=\"'John Doe'\"\r\n * [authorRole]=\"'Tenant'\"\r\n * [timestamp]=\"'2h ago'\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [clickable]=\"true\"\r\n * (postClick)=\"openPost()\">\r\n * \r\n * <post-content>\r\n * <post-text>This is a sample post...</post-text>\r\n * </post-content>\r\n * \r\n * <post-actions>\r\n * <action-like [active]=\"true\" count=\"42\" />\r\n * <action-comment count=\"12\" />\r\n * </post-actions>\r\n * </ds-mobile-interactive-list-item-post>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-interactive-list-item-post',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarWithBadgeComponent, DsMobileListItemComponent],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n /* Hide divider on last child */\r\n :host:last-child {\r\n --divider-display: none;\r\n --item-padding-bottom: 0;\r\n }\r\n \r\n .post-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: 32px;\r\n margin-bottom: 8px;\r\n }\r\n \r\n .author-details {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 2px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .author-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .author-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-tertiary, #626B78);\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n \r\n .menu-slot {\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-list-item\r\n [leadingSize]=\"'32px'\"\r\n [variant]=\"variant()\"\r\n [interactive]=\"clickable()\"\r\n (itemClick)=\"handlePostClick()\"\r\n (longPress)=\"handleLongPress()\"\r\n (moreButtonClick)=\"handleMoreButtonClick($event)\">\r\n \r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [type]=\"avatarType()\"\r\n [initials]=\"avatarInitials()\"\r\n [src]=\"avatarSrc()\"\r\n [iconName]=\"avatarIconName()\"\r\n [size]=\"'md'\"\r\n [showBadge]=\"showBadge()\"\r\n [badgePosition]=\"'bottom-right'\"\r\n />\r\n </div>\r\n \r\n <div content-main>\r\n <div class=\"post-header\">\r\n <div class=\"author-details\">\r\n <div class=\"author-name\">{{ authorName() }}</div>\r\n <div class=\"author-meta\">{{ authorRole() }} · {{ timestamp() }}</div>\r\n </div>\r\n \r\n <div class=\"menu-slot\">\r\n <ng-content select=\"post-menu\" />\r\n </div>\r\n </div>\r\n \r\n <ng-content select=\"post-content\" />\r\n <ng-content select=\"post-actions\" />\r\n </div>\r\n </ds-mobile-list-item>\r\n `\r\n})\r\nexport class DsMobileInteractiveListItemPostComponent {\r\n /**\r\n * Author's display name\r\n */\r\n authorName = input.required<string>();\r\n \r\n /**\r\n * Author's role (e.g., \"Tenant\", \"Property Manager\")\r\n */\r\n authorRole = input.required<string>();\r\n \r\n /**\r\n * Timestamp text (e.g., \"2h ago\", \"1d ago\")\r\n */\r\n timestamp = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (for initials type)\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Icon name (for icon type avatars)\r\n */\r\n avatarIconName = input<string>('remixUser3Fill');\r\n \r\n /**\r\n * Show badge on avatar (e.g., for property managers)\r\n */\r\n showBadge = input<boolean>(false);\r\n \r\n /**\r\n * Display variant\r\n * - undefined (default) - Standard display\r\n * - 'compact' - Compact display for nested/related posts\r\n */\r\n variant = input<'compact' | undefined>(undefined);\r\n \r\n /**\r\n * Whether the post card is clickable\r\n */\r\n clickable = input<boolean>(false);\r\n \r\n /**\r\n * Emits when the post card is clicked (if clickable)\r\n */\r\n postClick = output<void>();\r\n \r\n /**\r\n * Emits when the comment button is clicked\r\n */\r\n commentClick = output<void>();\r\n \r\n /**\r\n * Emits when the post card is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n handlePostClick(): void {\r\n console.log('[InteractiveListItemPost] handlePostClick called, emitting postClick');\r\n this.postClick.emit();\r\n }\r\n \r\n handleCommentClick(): void {\r\n this.commentClick.emit();\r\n }\r\n \r\n handleLongPress(): void {\r\n this.longPress.emit();\r\n }\r\n \r\n handleMoreButtonClick(event: Event): void {\r\n // Desktop more button click - trigger the same action as long press\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n/**\r\n * PostContentComponent\r\n * \r\n * Main content section of the post.\r\n * \r\n * Contains:\r\n * - `<post-text>` - Text content\r\n * - `<post-media>` - Optional images/videos\r\n * - `<post-attachments>` - Optional file attachments\r\n */\r\n@Component({\r\n selector: 'post-content',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n margin-bottom: 8px;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"post-text\" />\r\n <ng-content select=\"post-media\" />\r\n <ng-content select=\"ds-mobile-inline-photo\" />\r\n <ng-content select=\"post-attachments\" />\r\n `\r\n})\r\nexport class PostContentComponent {}\r\n\r\n/**\r\n * PostTextComponent\r\n * \r\n * Text content of the post.\r\n */\r\n@Component({\r\n selector: 'post-text',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n display: block;\r\n white-space: pre-wrap;\r\n word-wrap: break-word;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostTextComponent {}\r\n\r\n/**\r\n * PostMediaComponent\r\n * \r\n * Media container for images/videos.\r\n */\r\n@Component({\r\n selector: 'post-media',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: block;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n }\r\n \r\n ::ng-deep img {\r\n width: 100%;\r\n height: auto;\r\n display: block;\r\n }\r\n \r\n ::ng-deep video {\r\n width: 100%;\r\n height: auto;\r\n display: block;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostMediaComponent {}\r\n\r\n/**\r\n * PostAttachmentsComponent\r\n * \r\n * Container for file attachments, links, etc.\r\n */\r\n@Component({\r\n selector: 'post-attachments',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostAttachmentsComponent {}\r\n\r\n/**\r\n * PostActionsComponent\r\n * \r\n * Action buttons container (like, comment, share).\r\n * \r\n * Contains:\r\n * - `<action-like>` - Like button with count\r\n * - `<action-comment>` - Comment button with count\r\n * - `<action-share>` - Share button\r\n */\r\n@Component({\r\n selector: 'post-actions',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n padding-top: 4px;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostActionsComponent {}\r\n\r\n/**\r\n * ActionLikeComponent\r\n * \r\n * Like action button with count display and animated heart icon.\r\n */\r\n@Component({\r\n selector: 'action-like',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n host: {\r\n '[class.active]': 'active()',\r\n '(click)': 'handleClick($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n \r\n :host.active {\r\n color: #f91880;\r\n }\r\n \r\n .icon-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .icon-pulse {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n opacity: 0;\r\n pointer-events: none;\r\n }\r\n \r\n .icon-pulse.animating {\r\n animation: pulse 0.4s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n \r\n @keyframes pulse {\r\n 0% {\r\n transform: translate(-50%, -50%) scale(1);\r\n opacity: 0.8;\r\n }\r\n 100% {\r\n transform: translate(-50%, -50%) scale(2.5);\r\n opacity: 0;\r\n }\r\n }\r\n \r\n .count {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 20px;\r\n letter-spacing: -0.28px;\r\n }\r\n `],\r\n template: `\r\n <div class=\"icon-wrapper\">\r\n <ds-icon \r\n #pulseIcon\r\n class=\"icon-pulse\"\r\n [class.animating]=\"isPulsing()\"\r\n [name]=\"active() ? 'remixHeart3Fill' : 'remixHeart3Line'\" \r\n size=\"20px\" />\r\n <ds-icon \r\n [name]=\"active() ? 'remixHeart3Fill' : 'remixHeart3Line'\" \r\n size=\"20px\" />\r\n </div>\r\n @if (count() > 0) {\r\n <span class=\"count\">{{ count() }}</span>\r\n }\r\n `\r\n})\r\nexport class ActionLikeComponent {\r\n /**\r\n * Whether the like is active (user has liked)\r\n * Using model() for two-way binding\r\n */\r\n active = model<boolean>(false);\r\n \r\n /**\r\n * Number of likes\r\n * Using model() for two-way binding\r\n */\r\n count = model<number>(0);\r\n \r\n /**\r\n * Emits when the like button is clicked\r\n */\r\n likeClick = output<{ active: boolean; count: number }>();\r\n \r\n /**\r\n * Signal to control pulse animation\r\n */\r\n isPulsing = signal(false);\r\n \r\n async handleClick(event: Event): Promise<void> {\r\n event.stopPropagation();\r\n \r\n // Toggle active state\r\n const newActive = !this.active();\r\n this.active.set(newActive);\r\n \r\n // Update count\r\n const newCount = newActive ? this.count() + 1 : this.count() - 1;\r\n this.count.set(Math.max(0, newCount));\r\n \r\n // Trigger pulse animation only when liking\r\n if (newActive) {\r\n this.isPulsing.set(true);\r\n setTimeout(() => this.isPulsing.set(false), 400);\r\n }\r\n \r\n // Haptic feedback for like/unlike\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Light });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n \r\n // Emit the event with the new state\r\n this.likeClick.emit({ active: newActive, count: newCount });\r\n }\r\n}\r\n\r\n/**\r\n * ActionCommentComponent\r\n * \r\n * Comment action button with count display.\r\n */\r\n@Component({\r\n selector: 'action-comment',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n host: {\r\n '(click)': 'handleClick($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n \r\n :host:active {\r\n transform: scale(0.95);\r\n }\r\n \r\n :host:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .count {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 20px;\r\n letter-spacing: -0.28px;\r\n }\r\n `],\r\n template: `\r\n <ds-icon name=\"remixChat3Line\" size=\"20px\" />\r\n @if (count() > 0) {\r\n <span class=\"count\">{{ count() }}</span>\r\n }\r\n `\r\n})\r\nexport class ActionCommentComponent {\r\n /**\r\n * Number of comments\r\n */\r\n count = input<number>(0);\r\n \r\n /**\r\n * Emits when the comment button is clicked\r\n */\r\n commentClick = output<void>();\r\n \r\n handleClick(event: Event): void {\r\n event.stopPropagation();\r\n this.commentClick.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * PostPdfAttachmentComponent\r\n * \r\n * PDF file attachment display for posts.\r\n * Shows PDF info card with icon, filename, and file size.\r\n * Emits click event to open PDF in viewer.\r\n */\r\n@Component({\r\n selector: 'post-pdf-attachment',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent],\r\n host: {\r\n '(click)': 'handleClick($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 10px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n }\r\n \r\n :host:hover {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n :host:active {\r\n transform: scale(0.98);\r\n }\r\n \r\n .pdf-avatar {\r\n flex-shrink: 0;\r\n }\r\n \r\n .pdf-avatar::ng-deep .avatar--icon {\r\n background-color: #ff5757 !important;\r\n }\r\n \r\n .pdf-info {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n \r\n .pdf-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .pdf-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n }\r\n \r\n .open-icon {\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"pdf-avatar\">\r\n <ds-avatar\r\n type=\"icon\"\r\n iconName=\"remixFileTextLine\"\r\n size=\"md\"\r\n />\r\n </div>\r\n \r\n <div class=\"pdf-info\">\r\n <div class=\"pdf-name\">{{ fileName() }}</div>\r\n <div class=\"pdf-meta\">PDF · {{ fileSize() }}</div>\r\n </div>\r\n \r\n <ds-icon \r\n name=\"remixArrowRightSLine\" \r\n size=\"24px\"\r\n class=\"open-icon\"\r\n />\r\n `\r\n})\r\nexport class PostPdfAttachmentComponent {\r\n /**\r\n * PDF file name\r\n */\r\n fileName = input<string>('Document.pdf');\r\n \r\n /**\r\n * File size display (e.g., \"1.2 MB\")\r\n */\r\n fileSize = input<string>('');\r\n \r\n /**\r\n * Emits when the PDF attachment is clicked\r\n */\r\n pdfClick = output<void>();\r\n \r\n handleClick(event: Event): void {\r\n event.stopPropagation();\r\n this.pdfClick.emit();\r\n }\r\n}\r\n\r\n","// Export the main component and shared post components without the indent\r\nexport {\r\n DsMobileInteractiveListItemPostComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent\r\n} from './ds-mobile-interactive-list-item-post';\r\nexport { PostPdfAttachmentComponent } from './ds-mobile-post-pdf-attachment';\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsShapeIndicatorComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsMobileListItemComponent } from '../list-item';\r\n\r\n/**\r\n * DsMobileInteractiveListItemInquiryComponent\r\n * \r\n * Specialized interactive list item for displaying inquiries/tickets.\r\n * Built on top of ds-mobile-interactive-list-item base component.\r\n * Displays inquiry title, description, status, and timestamp.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-interactive-list-item-inquiry\r\n * [title]=\"'Tumble dryer is not working'\"\r\n * [description]=\"'For the past three days, I have been experiencing...'\"\r\n * [status]=\"'open'\"\r\n * [timestamp]=\"'12 days ago'\"\r\n * [iconName]=\"'remixCalendarLine'\"\r\n * [clickable]=\"true\"\r\n * (inquiryClick)=\"openInquiry()\">\r\n * </ds-mobile-interactive-list-item-inquiry>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-interactive-list-item-inquiry',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsShapeIndicatorComponent, DsAvatarComponent, DsMobileListItemComponent],\r\n styleUrls: ['./ds-mobile-interactive-list-item-inquiry.css'],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n /* Hide divider on last child */\r\n :host:last-child {\r\n --divider-display: none;\r\n --item-padding-bottom: 0;\r\n }\r\n \r\n .inquiry-avatar {\r\n flex-shrink: 0;\r\n }\r\n \r\n /* Default/Open inquiries: brand-primary surface with brand-primary content */\r\n .inquiry-avatar:not(.closed)::ng-deep .avatar--icon {\r\n background-color: var(--color-primary-surface, #5d5fef) !important;\r\n }\r\n \r\n .inquiry-avatar:not(.closed)::ng-deep .avatar--icon ds-icon,\r\n .inquiry-avatar:not(.closed)::ng-deep .avatar--icon ds-icon::ng-deep svg {\r\n color: var(--color-primary-content, #ffffff) !important;\r\n fill: var(--color-primary-content, #ffffff) !important;\r\n }\r\n \r\n /* Closed inquiries: content tertiary surface with white icon */\r\n .inquiry-avatar.closed::ng-deep .avatar--icon {\r\n background-color: var(--text-color-default-tertiary, #737373) !important;\r\n }\r\n \r\n .inquiry-avatar.closed::ng-deep .avatar--icon ds-icon,\r\n .inquiry-avatar.closed::ng-deep .avatar--icon ds-icon::ng-deep svg {\r\n color: #ffffff !important;\r\n fill: #ffffff !important;\r\n }\r\n \r\n .inquiry-content {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .inquiry-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .inquiry-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n margin: 0;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n }\r\n \r\n .inquiry-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-top: 4px;\r\n }\r\n \r\n .inquiry-status {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n }\r\n \r\n .inquiry-status.open {\r\n color: var(--text-color-default-tertiary, #737373);\r\n }\r\n \r\n .inquiry-status.closed {\r\n color: var(--text-color-default-tertiary, #737373);\r\n }\r\n \r\n .inquiry-timestamp {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n }\r\n \r\n .inquiry-trailing {\r\n display: flex;\r\n align-items: center;\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-list-item\r\n [leadingSize]=\"'32px'\"\r\n [variant]=\"variant()\"\r\n [interactive]=\"clickable()\"\r\n (itemClick)=\"handleInquiryClick()\"\r\n (longPress)=\"handleLongPress()\"\r\n (moreButtonClick)=\"handleMoreButtonClick($event)\">\r\n \r\n <div content-leading>\r\n <div class=\"inquiry-avatar\" [class.closed]=\"status() === 'closed'\">\r\n <ds-avatar\r\n type=\"icon\"\r\n [iconName]=\"iconName()\"\r\n size=\"md\"\r\n />\r\n </div>\r\n </div>\r\n \r\n <div content-main>\r\n <div class=\"inquiry-content\">\r\n <h3 class=\"inquiry-title\">{{ title() }}</h3>\r\n \r\n @if (description()) {\r\n <p class=\"inquiry-description\">{{ description() }}</p>\r\n }\r\n \r\n <div class=\"inquiry-meta\">\r\n <div class=\"inquiry-status\" [class.open]=\"status() === 'open'\" [class.closed]=\"status() === 'closed'\">\r\n <ds-shape-indicator \r\n shape=\"circle\" \r\n [variant]=\"status() === 'open' ? 'brand' : 'grey'\">\r\n </ds-shape-indicator>\r\n <span>{{ computedStatusLabel() }}</span>\r\n </div>\r\n \r\n <div class=\"inquiry-timestamp\">\r\n <ds-icon name=\"remixTimeLine\" size=\"14px\" color=\"--color-text-secondary\" />\r\n <span>{{ timestamp() }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n @if (showChevron()) {\r\n <div content-trailing>\r\n <div class=\"inquiry-trailing\">\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n </div>\r\n }\r\n </ds-mobile-list-item>\r\n `\r\n})\r\nexport class DsMobileInteractiveListItemInquiryComponent {\r\n /**\r\n * Inquiry title\r\n */\r\n title = input.required<string>();\r\n \r\n /**\r\n * Inquiry description/preview text\r\n */\r\n description = input<string>('');\r\n \r\n /**\r\n * Inquiry status\r\n */\r\n status = input<'open' | 'closed'>('open');\r\n \r\n /**\r\n * Status label (defaults to capitalized status)\r\n */\r\n statusLabel = input<string>('');\r\n \r\n /**\r\n * Timestamp text (e.g., \"12 days ago\", \"2 months ago\")\r\n */\r\n timestamp = input.required<string>();\r\n \r\n /**\r\n * Icon name for the leading icon\r\n */\r\n iconName = input<string>('remixTodoLine');\r\n \r\n /**\r\n * Icon color\r\n */\r\n iconColor = input<string>('secondary');\r\n \r\n /**\r\n * Display variant\r\n * - undefined (default) - Standard display\r\n * - 'compact' - Compact display\r\n */\r\n variant = input<'compact' | undefined>(undefined);\r\n \r\n /**\r\n * Whether the inquiry item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Whether to show chevron icon\r\n */\r\n showChevron = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the inquiry item is clicked (if clickable)\r\n */\r\n inquiryClick = output<void>();\r\n \r\n /**\r\n * Emits when the inquiry item is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n /**\r\n * Get computed status label\r\n */\r\n computedStatusLabel(): string {\r\n if (this.statusLabel()) {\r\n return this.statusLabel();\r\n }\r\n return this.status() === 'open' ? 'Åben' : 'Lukket';\r\n }\r\n \r\n handleInquiryClick(): void {\r\n this.inquiryClick.emit();\r\n }\r\n \r\n handleLongPress(): void {\r\n this.longPress.emit();\r\n }\r\n \r\n handleMoreButtonClick(event: Event): void {\r\n // Desktop more button click - trigger the same action as long press\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsMobileListItemComponent } from '../list-item';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge';\r\n\r\n/**\r\n * DsMobileInteractiveListItemMessageComponent\r\n * \r\n * Specialized interactive list item for displaying message threads.\r\n * Built on top of ds-mobile-interactive-list-item base component.\r\n * Displays message preview with sender info - simplified version without actions.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-interactive-list-item-message\r\n * [senderName]=\"'John Doe'\"\r\n * [senderRole]=\"'Tenant'\"\r\n * [timestamp]=\"'2h ago'\"\r\n * [message]=\"'Hey, when is the maintenance scheduled?'\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [unread]=\"true\"\r\n * [clickable]=\"true\"\r\n * (messageClick)=\"openThread()\">\r\n * </ds-mobile-interactive-list-item-message>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-interactive-list-item-message',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarWithBadgeComponent, DsMobileListItemComponent],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n /* Hide divider on last child */\r\n :host:last-child {\r\n --divider-display: none;\r\n --item-padding-bottom: 0;\r\n }\r\n \r\n .message-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: 32px;\r\n margin-bottom: 8px;\r\n }\r\n \r\n .sender-details {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 2px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .sender-name-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n flex-shrink: 0;\r\n }\r\n \r\n .sender-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n flex-shrink: 0;\r\n }\r\n \r\n .sender-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-tertiary, #737373);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n flex-shrink: 1;\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n \r\n .meta-separator {\r\n color: var(--text-color-default-tertiary, #737373);\r\n opacity: 0.5;\r\n }\r\n \r\n .unread-indicator {\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n background: var(--color-brand-primary, #5d5fef);\r\n flex-shrink: 0;\r\n }\r\n \r\n .message-preview {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n margin: 0;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-list-item\r\n [leadingSize]=\"'32px'\"\r\n [interactive]=\"clickable()\"\r\n [enableLongPress]=\"false\"\r\n [showDesktopMoreButton]=\"false\"\r\n (itemClick)=\"handleMessageClick()\">\r\n \r\n <div content-leading>\r\n <ds-avatar-with-badge \r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n size=\"md\" />\r\n </div>\r\n \r\n <div content-main>\r\n <div class=\"message-header\">\r\n <div class=\"sender-details\">\r\n <div class=\"sender-name-row\">\r\n <span class=\"sender-name\">{{ senderName() }}</span>\r\n @if (unread()) {\r\n <div class=\"unread-indicator\"></div>\r\n }\r\n </div>\r\n <span class=\"sender-meta\">\r\n {{ senderRole() }}\r\n @if (timestamp()) {\r\n <span class=\"meta-separator\">·</span>\r\n <span>{{ timestamp() }}</span>\r\n }\r\n </span>\r\n </div>\r\n </div>\r\n \r\n <p class=\"message-preview\">{{ message() }}</p>\r\n </div>\r\n </ds-mobile-list-item>\r\n `\r\n})\r\nexport class DsMobileInteractiveListItemMessageComponent {\r\n /**\r\n * Sender's display name\r\n */\r\n senderName = input.required<string>();\r\n \r\n /**\r\n * Sender's role (e.g., \"Tenant\", \"Property Manager\")\r\n */\r\n senderRole = input.required<string>();\r\n \r\n /**\r\n * Timestamp for the message (e.g., \"2h ago\", \"2t siden\")\r\n */\r\n timestamp = input<string>('');\r\n \r\n /**\r\n * Message preview text\r\n */\r\n message = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (for initials type)\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Whether the message is unread\r\n */\r\n unread = input<boolean>(false);\r\n \r\n /**\r\n * Whether the message item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the message item is clicked\r\n */\r\n messageClick = output<void>();\r\n \r\n /**\r\n * Emits when the message item is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n handleMessageClick(): void {\r\n this.messageClick.emit();\r\n }\r\n \r\n handleLongPress(): void {\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileContactListItemComponent\r\n * \r\n * Specialized interactive component for displaying contacts.\r\n * Displays contact name with avatar initials and metadata (person name + phone number).\r\n * Similar styling to file attachments with rounded corners and hover states.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-contact-list-item\r\n * [name]=\"'Mortensen & Søn ApS'\"\r\n * [initials]=\"'M'\"\r\n * [contactPerson]=\"'John Mortensen'\"\r\n * [phoneNumber]=\"'+45 12 34 56 78'\"\r\n * [clickable]=\"true\"\r\n * (contactClick)=\"openContact()\">\r\n * </ds-mobile-contact-list-item>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-contact-list-item',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsAvatarComponent],\r\n host: {\r\n '[class.clickable]': 'clickable()',\r\n '(click)': 'handleContactClick()'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 10px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n transition: all 0.2s ease;\r\n }\r\n \r\n :host.clickable {\r\n cursor: pointer;\r\n }\r\n \r\n :host.clickable:hover {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n :host.clickable:active {\r\n transform: scale(0.98);\r\n }\r\n \r\n .contact-avatar {\r\n flex-shrink: 0;\r\n }\r\n\r\n .contact-content {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 2px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .contact-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .contact-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n margin: 0;\r\n }\r\n \r\n .meta-separator {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n \r\n .contact-trailing {\r\n display: flex;\r\n align-items: center;\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"contact-avatar\">\r\n <ds-avatar\r\n [initials]=\"initials()\"\r\n type=\"initials\"\r\n size=\"md\"\r\n />\r\n </div>\r\n \r\n <div class=\"contact-content\">\r\n <div class=\"contact-name\">{{ name() }}</div>\r\n \r\n @if (contactPerson() || phoneNumber()) {\r\n <div class=\"contact-meta\">\r\n @if (contactPerson()) {\r\n <span>{{ contactPerson() }}</span>\r\n }\r\n @if (contactPerson() && phoneNumber()) {\r\n <span class=\"meta-separator\">·</span>\r\n }\r\n @if (phoneNumber()) {\r\n <span>{{ phoneNumber() }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n \r\n @if (showChevron()) {\r\n <div class=\"contact-trailing\">\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n }\r\n `\r\n})\r\nexport class DsMobileContactListItemComponent {\r\n /**\r\n * Contact/company name\r\n */\r\n name = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (usually 1-2 letters)\r\n */\r\n initials = input.required<string>();\r\n \r\n /**\r\n * Contact person name (optional)\r\n */\r\n contactPerson = input<string>('');\r\n \r\n /**\r\n * Phone number (optional)\r\n */\r\n phoneNumber = input<string>('');\r\n \r\n /**\r\n * Whether the contact item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Whether to show chevron icon\r\n */\r\n showChevron = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the contact item is clicked (if clickable)\r\n */\r\n contactClick = output<void>();\r\n \r\n handleContactClick(): void {\r\n if (this.clickable()) {\r\n this.contactClick.emit();\r\n }\r\n }\r\n}\r\n\r\n","import { Component, Input, Output, EventEmitter, signal, OnInit, AfterViewInit, OnDestroy, ElementRef, computed, inject, effect } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { Router, NavigationEnd } from '@angular/router';\r\nimport { filter } from 'rxjs/operators';\r\nimport { \r\n IonTabBar, \r\n IonTabButton, \r\n IonLabel,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsLogoComponent } from '../logo/ds-logo';\r\nimport { DsMobileActionsBottomSheetComponent, ActionResult, ActionGroup } from '../bottom-sheet';\r\nimport { UserService } from '../../services/user.service';\r\n\r\nexport interface TabConfig {\r\n id: string;\r\n label: string;\r\n route: string;\r\n icon: string;\r\n iconActive: string;\r\n}\r\n\r\n/**\r\n * DsMobileTabBarComponent\r\n * \r\n * Responsive navigation tab bar that adapts from mobile to desktop:\r\n * - Mobile (< 768px): Bottom tab bar with icons + labels\r\n * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar\r\n * \r\n * Use this component INSIDE your own `ion-tabs` when Angular routing\r\n * requires `ion-tabs` to be a direct child in your component.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- In your component with child routes -->\r\n * <!-- IMPORTANT: Add class=\"ds-tabs-wrapper\" to ion-tabs for proper styling -->\r\n * <ion-tabs class=\"ds-tabs-wrapper\">\r\n * <ds-mobile-tab-bar\r\n * [tabs]=\"tabs\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [profileMenuItems]=\"profileMenuItems\"\r\n * (profileActionSelected)=\"handleProfileAction($event)\"\r\n * />\r\n * </ion-tabs>\r\n * ```\r\n * \r\n * @example With profile menu configuration\r\n * ```typescript\r\n * profileMenuItems: ActionGroup[] = [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'My Profile', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Settings', icon: 'remixSettings3Line' }\r\n * ]\r\n * },\r\n * {\r\n * actions: [\r\n * { action: 'logout', title: 'Log Out', icon: 'remixLogoutBoxLine', destructive: true }\r\n * ]\r\n * }\r\n * ];\r\n * \r\n * handleProfileAction(result: ActionResult): void {\r\n * switch (result.action) {\r\n * case 'profile': // Navigate to profile\r\n * case 'settings': // Navigate to settings\r\n * case 'logout': // Handle logout\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @note When using this component, you must add the class \"ds-tabs-wrapper\" \r\n * to your `ion-tabs` element, or manually apply these styles:\r\n * ```css\r\n * ion-tabs {\r\n * height: 100%;\r\n * background: var(--color-brand-secondary);\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-tab-bar',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonTabBar,\r\n IonTabButton,\r\n IonLabel,\r\n DsIconComponent,\r\n DsAvatarComponent,\r\n DsLogoComponent\r\n ],\r\n styleUrls: ['./ds-mobile-tab-bar.css'],\r\n template: `\r\n <ion-tab-bar \r\n [attr.slot]=\"isDesktop() ? 'top' : 'bottom'\" \r\n class=\"ds-tab-bar\"\r\n [class.ds-tab-bar--desktop]=\"isDesktop()\">\r\n \r\n <!-- Logo (desktop only, positioned via CSS) -->\r\n <div class=\"ds-tab-bar__logo\">\r\n <ds-logo variant=\"mark\" size=\"lg\" />\r\n </div>\r\n \r\n <!-- Tab buttons container -->\r\n <div class=\"ds-tab-bar__tabs\" *ngIf=\"tabs\">\r\n <ion-tab-button \r\n *ngFor=\"let tab of tabs; trackBy: trackByTabId\"\r\n [tab]=\"tab.route\"\r\n [attr.data-icon]=\"tab.icon\"\r\n [attr.data-icon-active]=\"tab.iconActive\"\r\n [attr.aria-label]=\"tab.label\"\r\n class=\"ds-tab-button ion-activatable\"\r\n [class.tab-selected]=\"isTabActive(tab.route)\">\r\n <div class=\"tab-icon-ripple\"></div>\r\n <div class=\"tab-icon-wrapper\">\r\n <ds-icon \r\n [name]=\"tab.icon\"\r\n [size]=\"isDesktop() ? '20px' : '24px'\"\r\n class=\"tab-icon-inactive\"\r\n />\r\n <ds-icon \r\n [name]=\"tab.iconActive\"\r\n [size]=\"isDesktop() ? '20px' : '24px'\"\r\n class=\"tab-icon-active\"\r\n />\r\n </div>\r\n <ion-label [attr.aria-hidden]=\"true\">{{ tab.label }}</ion-label>\r\n </ion-tab-button>\r\n </div>\r\n \r\n <!-- Avatar (desktop only, positioned via CSS) -->\r\n <div class=\"ds-tab-bar__actions\">\r\n <ds-avatar\r\n [size]=\"'md'\"\r\n [type]=\"avatarType\"\r\n [initials]=\"avatarInitials\"\r\n [src]=\"avatarSrc\"\r\n [iconName]=\"avatarIconName\"\r\n (click)=\"handleAvatarClick()\"\r\n />\r\n </div>\r\n </ion-tab-bar>\r\n `\r\n})\r\nexport class DsMobileTabBarComponent implements OnInit, AfterViewInit, OnDestroy {\r\n // Inputs\r\n @Input() tabs: TabConfig[] = [];\r\n \r\n // Avatar inputs\r\n @Input() avatarType: 'initials' | 'photo' | 'icon' = 'initials';\r\n @Input() avatarInitials: string = 'U';\r\n @Input() avatarSrc: string = '';\r\n @Input() avatarIconName: string = 'remixUser3Line';\r\n \r\n /**\r\n * Profile menu action groups to display when avatar is clicked.\r\n * If not provided, only the avatarClick event will be emitted.\r\n * \r\n * @example\r\n * ```typescript\r\n * profileMenuItems: ActionGroup[] = [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'My Profile', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Settings', icon: 'remixSettings3Line' }\r\n * ]\r\n * }\r\n * ];\r\n * ```\r\n */\r\n @Input() profileMenuItems?: ActionGroup[];\r\n \r\n // Outputs\r\n @Output() avatarClick = new EventEmitter<void>();\r\n \r\n /**\r\n * Emitted when a profile menu action is selected.\r\n * Parent component should handle the action logic (navigation, logout, etc.).\r\n */\r\n @Output() profileActionSelected = new EventEmitter<ActionResult>();\r\n \r\n // Internal state - exposed for template binding\r\n activeTab = signal<string>('');\r\n isDesktop = signal<boolean>(false);\r\n \r\n private mutationObserver?: MutationObserver;\r\n private slotEnforcementObserver?: MutationObserver;\r\n private resizeObserver?: ResizeObserver;\r\n private mediaQuery?: MediaQueryList;\r\n private routerSubscription?: any;\r\n \r\n private router?: Router | null;\r\n private modalController = inject(ModalController);\r\n private userService = inject(UserService);\r\n \r\n constructor(\r\n private elementRef: ElementRef\r\n ) {\r\n // Inject Router optionally\r\n this.router = inject(Router, { optional: true }) || undefined;\r\n \r\n // Initialize breakpoint detection EARLY (before effect)\r\n // This ensures isDesktop() is set before the effect runs\r\n this.setupBreakpointDetection();\r\n \r\n // Debug: Log initial state\r\n setTimeout(() => {\r\n console.log('[ds-mobile-tab-bar] Initial state:', {\r\n isDesktop: this.isDesktop(),\r\n windowWidth: window.innerWidth,\r\n mediaQuery: this.mediaQuery?.matches,\r\n userAgent: navigator.userAgent\r\n });\r\n }, 100);\r\n \r\n // Watch for isDesktop changes and update slot reactively\r\n // effect() must be called in constructor (injection context)\r\n effect(() => {\r\n // This effect runs whenever isDesktop() changes\r\n const _ = this.isDesktop(); // Read the signal to create dependency\r\n console.log('[ds-mobile-tab-bar] effect() triggered, isDesktop:', this.isDesktop());\r\n if (this.elementRef.nativeElement) {\r\n // Use setTimeout to ensure DOM is ready\r\n setTimeout(() => this.updateSlot(), 0);\r\n }\r\n });\r\n }\r\n \r\n ngOnInit(): void {\r\n \r\n // Listen to router events to detect active tab from URL\r\n if (this.router) {\r\n this.routerSubscription = this.router.events\r\n .pipe(filter(event => event instanceof NavigationEnd))\r\n .subscribe((event: any) => {\r\n const url = event.urlAfterRedirects || event.url;\r\n // Extract the route segment (e.g., /tab-bar-test/home -> home)\r\n const segments = url.split('/').filter((s: string) => s);\r\n const lastSegment = segments[segments.length - 1];\r\n \r\n // Find matching tab by route\r\n if (this.tabs && lastSegment) {\r\n const matchingTab = this.tabs.find(tab => tab.route === lastSegment);\r\n if (matchingTab) {\r\n this.activeTab.set(matchingTab.route);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Initial removal\r\n this.removeTitleAttributes();\r\n \r\n // Set up mutation observer to continuously remove title attributes\r\n this.setupTitleRemovalObserver();\r\n \r\n // Set up active tab detection\r\n this.setupActiveTabDetection();\r\n \r\n // Ensure slot is set correctly on initial render (with retries)\r\n this.updateSlot();\r\n \r\n // Set up slot enforcement to prevent Ionic from overriding\r\n setTimeout(() => {\r\n this.setupSlotEnforcement();\r\n // Also retry updateSlot a few times to ensure it sticks\r\n setTimeout(() => this.updateSlot(), 100);\r\n setTimeout(() => this.updateSlot(), 300);\r\n }, 0);\r\n }\r\n \r\n private updateSlot(): void {\r\n // CRITICAL: Set slot on the HOST element (ds-mobile-tab-bar) first\r\n // Ionic positions children based on the wrapper's slot, not the inner element's slot\r\n const hostElement = this.elementRef.nativeElement;\r\n const hostSlotValue = this.isDesktop() ? 'top' : 'bottom';\r\n const currentHostSlot = hostElement.getAttribute('slot');\r\n \r\n if (currentHostSlot !== hostSlotValue) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Setting HOST slot from', currentHostSlot, 'to', hostSlotValue);\r\n hostElement.setAttribute('slot', hostSlotValue);\r\n (hostElement as any).slot = hostSlotValue;\r\n }\r\n \r\n // Get the ion-tab-bar element\r\n const tabBar = this.elementRef.nativeElement.querySelector('ion-tab-bar');\r\n if (!tabBar) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: tabBar not found, retrying...');\r\n // Retry if element not found yet\r\n setTimeout(() => this.updateSlot(), 50);\r\n return;\r\n }\r\n \r\n const slotValue = this.isDesktop() ? 'top' : 'bottom';\r\n const currentSlot = tabBar.getAttribute('slot');\r\n const currentSlotProperty = (tabBar as any).slot;\r\n \r\n // Debug logging\r\n console.log('[ds-mobile-tab-bar] updateSlot:', {\r\n isDesktop: this.isDesktop(),\r\n windowWidth: window.innerWidth,\r\n slotValue,\r\n currentSlotAttribute: currentSlot,\r\n currentSlotProperty: currentSlotProperty,\r\n tabBarElement: tabBar,\r\n tabBarParent: tabBar.parentElement?.tagName,\r\n tabBarInIonTabs: tabBar.closest('ion-tabs') !== null\r\n });\r\n \r\n // Only update if different to avoid unnecessary DOM manipulation\r\n if (currentSlot !== slotValue || currentSlotProperty !== slotValue) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Setting slot from', currentSlot, 'to', slotValue);\r\n \r\n // Set both attribute and property to ensure it works\r\n tabBar.setAttribute('slot', slotValue);\r\n (tabBar as any).slot = slotValue;\r\n \r\n // Also try setting it on the parent ion-tabs\r\n const parentIonTabs = tabBar.closest('ion-tabs');\r\n if (parentIonTabs) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Found parent ion-tabs');\r\n // Force Ionic to recognize the slot change\r\n (parentIonTabs as any).forceUpdate?.();\r\n }\r\n \r\n // Force a reflow to ensure Ionic processes the change\r\n void tabBar.offsetHeight;\r\n \r\n // Verify it was set\r\n const verifySlot = tabBar.getAttribute('slot');\r\n const verifySlotProperty = (tabBar as any).slot;\r\n console.log('[ds-mobile-tab-bar] updateSlot: After update, slot attribute:', verifySlot, 'slot property:', verifySlotProperty);\r\n \r\n // Check computed styles\r\n const computedStyle = window.getComputedStyle(tabBar);\r\n const parentComputedStyle = tabBar.parentElement ? window.getComputedStyle(tabBar.parentElement) : null;\r\n const ionTabsForStyles = tabBar.closest('ion-tabs');\r\n const ionTabsComputedStyle = ionTabsForStyles ? window.getComputedStyle(ionTabsForStyles) : null;\r\n \r\n console.log('[ds-mobile-tab-bar] updateSlot: Computed styles:', {\r\n tabBar: {\r\n position: computedStyle.position,\r\n top: computedStyle.top,\r\n bottom: computedStyle.bottom,\r\n order: computedStyle.order,\r\n display: computedStyle.display,\r\n zIndex: computedStyle.zIndex,\r\n transform: computedStyle.transform\r\n },\r\n parent: parentComputedStyle ? {\r\n display: parentComputedStyle.display,\r\n flexDirection: parentComputedStyle.flexDirection,\r\n gridTemplateRows: parentComputedStyle.gridTemplateRows\r\n } : null,\r\n ionTabs: ionTabsComputedStyle ? {\r\n display: ionTabsComputedStyle.display,\r\n flexDirection: ionTabsComputedStyle.flexDirection,\r\n gridTemplateRows: ionTabsComputedStyle.gridTemplateRows,\r\n position: ionTabsComputedStyle.position\r\n } : null,\r\n tabBarRect: tabBar.getBoundingClientRect(),\r\n windowHeight: window.innerHeight\r\n });\r\n } else {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Slot already correct, no update needed');\r\n \r\n // Even if slot is correct, check computed styles to see why it's not at top\r\n const computedStyle = window.getComputedStyle(tabBar);\r\n const ionTabsForStyles = tabBar.closest('ion-tabs');\r\n const ionTabsComputedStyle = ionTabsForStyles ? window.getComputedStyle(ionTabsForStyles) : null;\r\n const tabBarRect = tabBar.getBoundingClientRect();\r\n \r\n // Log key values directly so they're always visible\r\n console.log('[ds-mobile-tab-bar] KEY VALUES:');\r\n console.log(' tabBar.position:', computedStyle.position);\r\n console.log(' tabBar.top:', computedStyle.top);\r\n console.log(' tabBar.bottom:', computedStyle.bottom);\r\n console.log(' tabBar.order:', computedStyle.order);\r\n console.log(' tabBar.display:', computedStyle.display);\r\n console.log(' tabBarRect.top:', tabBarRect.top, 'px from top');\r\n console.log(' tabBarRect.bottom:', tabBarRect.bottom, 'px from top');\r\n console.log(' window.innerHeight:', window.innerHeight);\r\n if (ionTabsComputedStyle) {\r\n console.log(' ionTabs.display:', ionTabsComputedStyle.display);\r\n console.log(' ionTabs.flexDirection:', ionTabsComputedStyle.flexDirection);\r\n console.log(' ionTabs.gridTemplateRows:', ionTabsComputedStyle.gridTemplateRows);\r\n }\r\n if (ionTabsForStyles) {\r\n const children = Array.from(ionTabsForStyles.children);\r\n console.log(' ionTabs children count:', children.length);\r\n children.forEach((child: any, index) => {\r\n console.log(` [${index}] ${child.tagName} slot=\"${child.getAttribute('slot')}\" order=\"${window.getComputedStyle(child).order}\"`);\r\n });\r\n }\r\n \r\n console.log('[ds-mobile-tab-bar] updateSlot: Computed styles (slot correct but visually wrong):', {\r\n tabBar: {\r\n position: computedStyle.position,\r\n top: computedStyle.top,\r\n bottom: computedStyle.bottom,\r\n order: computedStyle.order,\r\n display: computedStyle.display,\r\n zIndex: computedStyle.zIndex,\r\n transform: computedStyle.transform,\r\n marginTop: computedStyle.marginTop,\r\n marginBottom: computedStyle.marginBottom,\r\n width: computedStyle.width,\r\n height: computedStyle.height\r\n },\r\n ionTabs: ionTabsComputedStyle ? {\r\n display: ionTabsComputedStyle.display,\r\n flexDirection: ionTabsComputedStyle.flexDirection,\r\n gridTemplateRows: ionTabsComputedStyle.gridTemplateRows,\r\n gridTemplateColumns: ionTabsComputedStyle.gridTemplateColumns,\r\n position: ionTabsComputedStyle.position,\r\n alignItems: ionTabsComputedStyle.alignItems,\r\n justifyContent: ionTabsComputedStyle.justifyContent,\r\n height: ionTabsComputedStyle.height,\r\n minHeight: ionTabsComputedStyle.minHeight\r\n } : null,\r\n tabBarRect: {\r\n top: tabBarRect.top,\r\n bottom: tabBarRect.bottom,\r\n height: tabBarRect.height,\r\n y: tabBarRect.y,\r\n left: tabBarRect.left,\r\n right: tabBarRect.right,\r\n width: tabBarRect.width\r\n },\r\n windowHeight: window.innerHeight,\r\n distanceFromTop: tabBarRect.top,\r\n distanceFromBottom: window.innerHeight - tabBarRect.bottom,\r\n // Check if tab bar is actually in the DOM at the right position\r\n tabBarParent: tabBar.parentElement?.tagName,\r\n tabBarNextSibling: tabBar.nextElementSibling?.tagName,\r\n tabBarPreviousSibling: tabBar.previousElementSibling?.tagName,\r\n // Check all children of ion-tabs to see DOM order\r\n ionTabsChildren: ionTabsForStyles ? Array.from(ionTabsForStyles.children).map((child: any) => ({\r\n tagName: child.tagName,\r\n slot: child.getAttribute('slot'),\r\n order: window.getComputedStyle(child).order\r\n })) : null\r\n });\r\n }\r\n }\r\n \r\n private setupSlotEnforcement(): void {\r\n const hostElement = this.elementRef.nativeElement;\r\n const tabBar = this.elementRef.nativeElement.querySelector('ion-tab-bar');\r\n if (!tabBar) {\r\n console.log('[ds-mobile-tab-bar] setupSlotEnforcement: tabBar not found, retrying...');\r\n // Retry if element not found yet\r\n setTimeout(() => this.setupSlotEnforcement(), 50);\r\n return;\r\n }\r\n \r\n console.log('[ds-mobile-tab-bar] setupSlotEnforcement: Setting up MutationObserver');\r\n \r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && mutation.attributeName === 'slot') {\r\n const target = mutation.target as HTMLElement;\r\n const expectedSlot = this.isDesktop() ? 'top' : 'bottom';\r\n \r\n // Check both host element and tab bar\r\n if (target === hostElement || target === tabBar) {\r\n const currentSlot = target.getAttribute('slot');\r\n \r\n console.log('[ds-mobile-tab-bar] Slot changed by external source:', {\r\n target: target.tagName,\r\n currentSlot,\r\n expectedSlot,\r\n isDesktop: this.isDesktop()\r\n });\r\n \r\n // If Ionic or something else changed it, force it back\r\n if (currentSlot !== expectedSlot) {\r\n console.log('[ds-mobile-tab-bar] Enforcing slot back to:', expectedSlot);\r\n // Use requestAnimationFrame to avoid infinite loops\r\n requestAnimationFrame(() => {\r\n target.setAttribute('slot', expectedSlot);\r\n (target as any).slot = expectedSlot;\r\n });\r\n }\r\n }\r\n }\r\n });\r\n });\r\n \r\n // Observe both host element and tab bar for slot changes\r\n observer.observe(hostElement, {\r\n attributes: true,\r\n attributeFilter: ['slot']\r\n });\r\n \r\n observer.observe(tabBar, {\r\n attributes: true,\r\n attributeFilter: ['slot']\r\n });\r\n \r\n // Store observer for cleanup\r\n this.slotEnforcementObserver = observer;\r\n }\r\n \r\n ngOnDestroy(): void {\r\n if (this.mutationObserver) {\r\n this.mutationObserver.disconnect();\r\n }\r\n if (this.slotEnforcementObserver) {\r\n this.slotEnforcementObserver.disconnect();\r\n }\r\n if (this.mediaQuery) {\r\n this.mediaQuery.removeEventListener('change', this.handleBreakpointChange);\r\n }\r\n if (this.routerSubscription) {\r\n this.routerSubscription.unsubscribe();\r\n }\r\n }\r\n \r\n private setupBreakpointDetection(): void {\r\n // Use matchMedia for responsive breakpoint detection\r\n this.mediaQuery = window.matchMedia('(min-width: 768px)');\r\n this.isDesktop.set(this.mediaQuery.matches);\r\n \r\n this.handleBreakpointChange = this.handleBreakpointChange.bind(this);\r\n this.mediaQuery.addEventListener('change', this.handleBreakpointChange);\r\n }\r\n \r\n private handleBreakpointChange = (e: MediaQueryListEvent): void => {\r\n console.log('[ds-mobile-tab-bar] handleBreakpointChange:', {\r\n matches: e.matches,\r\n windowWidth: window.innerWidth,\r\n previousIsDesktop: this.isDesktop()\r\n });\r\n this.isDesktop.set(e.matches);\r\n // Force update the slot when breakpoint changes\r\n this.updateSlot();\r\n };\r\n \r\n private setupTitleRemovalObserver(): void {\r\n const config = { \r\n attributes: true, \r\n attributeFilter: ['title'],\r\n subtree: true,\r\n childList: true\r\n };\r\n \r\n this.mutationObserver = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && mutation.attributeName === 'title') {\r\n const target = mutation.target as HTMLElement;\r\n if (target.tagName === 'ION-TAB-BUTTON' && target.hasAttribute('title')) {\r\n target.removeAttribute('title');\r\n }\r\n }\r\n });\r\n // Also do a sweep after any changes\r\n this.removeTitleAttributes();\r\n });\r\n \r\n this.mutationObserver.observe(this.elementRef.nativeElement, config);\r\n }\r\n \r\n private removeTitleAttributes(): void {\r\n const tabButtons = this.elementRef.nativeElement.querySelectorAll('ion-tab-button');\r\n tabButtons.forEach((button: HTMLElement) => {\r\n if (button.hasAttribute('title')) {\r\n button.removeAttribute('title');\r\n }\r\n // Also remove from the native button inside shadow DOM\r\n const nativeButton = button.shadowRoot?.querySelector('button');\r\n if (nativeButton?.hasAttribute('title')) {\r\n nativeButton.removeAttribute('title');\r\n }\r\n });\r\n }\r\n \r\n private setupActiveTabDetection(): void {\r\n // Find the parent ion-tabs element\r\n const ionTabs = this.elementRef.nativeElement.closest('ion-tabs');\r\n if (!ionTabs) {\r\n console.warn('ds-mobile-tab-bar: Could not find parent ion-tabs element');\r\n return;\r\n }\r\n \r\n // Listen for tab changes using Ionic events\r\n ionTabs.addEventListener('ionTabsDidChange', (event: any) => {\r\n const tabRoute = event.detail?.tab;\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n } else {\r\n // Fallback: check DOM immediately after event\r\n setTimeout(() => this.updateActiveTabFromDOM(), 0);\r\n }\r\n });\r\n \r\n // Also listen for tab button clicks\r\n this.elementRef.nativeElement.addEventListener('click', (event: any) => {\r\n const button = event.target.closest('ion-tab-button');\r\n if (button) {\r\n setTimeout(() => this.updateActiveTabFromDOM(), 50);\r\n }\r\n });\r\n \r\n // Get initial selected tab\r\n this.updateActiveTabFromDOM();\r\n \r\n // Watch for selected attribute changes on tab buttons (more reliable)\r\n const observer = new MutationObserver(() => {\r\n this.updateActiveTabFromDOM();\r\n });\r\n \r\n observer.observe(this.elementRef.nativeElement, {\r\n attributes: true,\r\n attributeFilter: ['selected', 'tab'],\r\n subtree: true,\r\n childList: true\r\n });\r\n \r\n // Also watch the parent ion-tabs for changes\r\n observer.observe(ionTabs, {\r\n attributes: true,\r\n attributeFilter: ['selected', 'tab'],\r\n subtree: true\r\n });\r\n \r\n // Periodic check as fallback (in case events don't fire)\r\n setInterval(() => {\r\n this.updateActiveTabFromDOM();\r\n }, 100);\r\n }\r\n \r\n private updateActiveTabFromDOM(): void {\r\n // Check parent ion-tabs for selected tab (most reliable)\r\n const ionTabs = this.elementRef.nativeElement.closest('ion-tabs');\r\n if (ionTabs) {\r\n // Method 1: Check for ion-tab with selected attribute\r\n const selectedTab = ionTabs.querySelector('ion-tab[selected]');\r\n if (selectedTab) {\r\n const tabRoute = selectedTab.getAttribute('tab');\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n return;\r\n }\r\n }\r\n \r\n // Method 2: Check for ion-tab without tab-hidden class (Ionic shows active tab)\r\n const visibleTab = ionTabs.querySelector('ion-tab:not(.tab-hidden)');\r\n if (visibleTab) {\r\n const tabRoute = visibleTab.getAttribute('tab');\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n return;\r\n }\r\n }\r\n }\r\n \r\n // Method 3: Check tab buttons for selected state\r\n const tabButtons = this.elementRef.nativeElement.querySelectorAll('ion-tab-button');\r\n tabButtons.forEach((button: any) => {\r\n // Check Ionic's native selected property\r\n if (button.selected === true) {\r\n const tabRoute = button.getAttribute('tab');\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n }\r\n }\r\n });\r\n }\r\n \r\n trackByTabId(index: number, tab: TabConfig): string {\r\n return tab.id;\r\n }\r\n \r\n isTabActive(tabRoute: string): boolean {\r\n const currentActive = this.activeTab();\r\n // Match by route (primary) or by checking if the tab button is selected\r\n if (currentActive === tabRoute) {\r\n return true;\r\n }\r\n \r\n // Fallback: check if this button is actually selected in the DOM\r\n const tabButtons = this.elementRef.nativeElement.querySelectorAll('ion-tab-button');\r\n for (let i = 0; i < tabButtons.length; i++) {\r\n const button = tabButtons[i] as any;\r\n if (button.getAttribute('tab') === tabRoute && button.selected === true) {\r\n return true;\r\n }\r\n }\r\n \r\n return false;\r\n }\r\n \r\n /**\r\n * Handle avatar click - opens profile menu if configured, otherwise just emits avatarClick\r\n */\r\n async handleAvatarClick(): Promise<void> {\r\n // Emit the basic click event (for backwards compatibility)\r\n this.avatarClick.emit();\r\n \r\n // Use input if provided, otherwise fall back to service\r\n const menuItems = this.profileMenuItems || this.userService.profileMenuItems();\r\n \r\n // If no menu items configured, just emit and return\r\n if (!menuItems || menuItems.length === 0) {\r\n return;\r\n }\r\n \r\n // Open the bottom sheet with configured menu items\r\n const sheet = await this.modalController.create({\r\n component: DsMobileActionsBottomSheetComponent,\r\n componentProps: {\r\n customActionGroups: menuItems\r\n },\r\n // Auto-height: no breakpoints, no handle\r\n cssClass: 'ds-bottom-sheet auto-height'\r\n });\r\n \r\n await sheet.present();\r\n \r\n const result = await sheet.onWillDismiss<ActionResult>();\r\n if (result.data?.action) {\r\n // Emit the selected action to parent\r\n this.profileActionSelected.emit(result.data);\r\n }\r\n }\r\n}\r\n\r\n","import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { \r\n IonTabs, \r\n IonTab\r\n} from '@ionic/angular/standalone';\r\nimport { DsMobileTabBarComponent, TabConfig } from '../tab-bar';\r\n\r\n// Re-export TabConfig for backwards compatibility\r\nexport type { TabConfig } from '../tab-bar';\r\n\r\n/**\r\n * DsMobileTabsComponent\r\n * \r\n * Responsive tab navigation that adapts from mobile to desktop:\r\n * - Mobile (< 768px): Bottom tab bar with icons + labels\r\n * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar\r\n * \r\n * Wraps ion-tabs to maintain native routing functionality while\r\n * providing a responsive navigation experience with branding.\r\n * \r\n * NOTE: This component wraps `ion-tabs` internally. If your Angular\r\n * routing requires `ion-tabs` to be a direct child in your component\r\n * (e.g., when using `ion-router-outlet` in app.html), use the\r\n * `DsMobileTabBarComponent` directly inside your own `ion-tabs` instead.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-tabs\r\n * [tabs]=\"tabsConfig\"\r\n * [avatarInitials]=\"'JD'\"\r\n * (avatarClick)=\"handleAvatarClick()\"\r\n * />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-tabs',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonTabs,\r\n IonTab,\r\n DsMobileTabBarComponent\r\n ],\r\n styleUrls: ['./ds-mobile-tabs.css'],\r\n template: `\r\n <ion-tabs>\r\n <ng-container *ngIf=\"tabs && tabs.length > 0\">\r\n <ion-tab *ngFor=\"let tab of tabs; trackBy: trackByTabId\" [tab]=\"tab.id\"></ion-tab>\r\n </ng-container>\r\n \r\n <ds-mobile-tab-bar\r\n [tabs]=\"tabs\"\r\n [avatarType]=\"avatarType\"\r\n [avatarInitials]=\"avatarInitials\"\r\n [avatarSrc]=\"avatarSrc\"\r\n [avatarIconName]=\"avatarIconName\"\r\n (avatarClick)=\"handleAvatarClick()\"\r\n />\r\n </ion-tabs>\r\n `\r\n})\r\nexport class DsMobileTabsComponent implements OnInit {\r\n // Inputs\r\n @Input() tabs: TabConfig[] = [];\r\n \r\n // Avatar inputs\r\n @Input() avatarType: 'initials' | 'photo' | 'icon' = 'initials';\r\n @Input() avatarInitials: string = 'U';\r\n @Input() avatarSrc: string = '';\r\n @Input() avatarIconName: string = 'remixUser3Line';\r\n \r\n // Outputs\r\n @Output() avatarClick = new EventEmitter<void>();\r\n \r\n constructor() {}\r\n \r\n ngOnInit(): void {\r\n console.log('DsMobileTabsComponent initialized');\r\n }\r\n \r\n trackByTabId(index: number, tab: TabConfig): string {\r\n return tab.id;\r\n }\r\n \r\n handleAvatarClick(): void {\r\n this.avatarClick.emit();\r\n }\r\n}\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\nexport interface InlineTabItem {\r\n id: string;\r\n label: string;\r\n badge?: number;\r\n}\r\n\r\n/**\r\n * DsMobileInlineTabsComponent\r\n * \r\n * Pill-style inline tabs for filtering/switching views\r\n * Used in the purple header section of pages\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-inline-tabs\r\n * [tabs]=\"[\r\n * { id: 'all', label: 'All' },\r\n * { id: 'open', label: 'Open' },\r\n * { id: 'closed', label: 'Closed' }\r\n * ]\"\r\n * [activeTab]=\"'all'\"\r\n * (tabChange)=\"handleTabChange($event)\">\r\n * </ds-mobile-inline-tabs>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-inline-tabs',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n .filter-tabs {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex-wrap: wrap;\r\n height: 40px;\r\n }\r\n \r\n .filter-tab {\r\n min-width: 48px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n padding: 0px 12px;\r\n height: 32px;\r\n border-radius: 20px;\r\n background: transparent;\r\n border: none;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n color: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.6);\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n white-space: nowrap;\r\n }\r\n \r\n .filter-tab.active {\r\n background: var(--color-background-brand, #5d5fef);\r\n color: var(--color-primary-content, white);\r\n }\r\n \r\n .filter-tab:hover:not(.active) {\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.1);\r\n }\r\n \r\n .tab-badge {\r\n min-width: 24px;\r\n height: 16px;\r\n padding: 0 6px;\r\n border-radius: 10px;\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.2);\r\n color: var(--header-content-color, white);\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 600;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n line-height: 1;\r\n }\r\n \r\n .filter-tab.active .tab-badge {\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.3);\r\n color: var(--header-content-color, white);\r\n }\r\n `],\r\n template: `\r\n <div class=\"filter-tabs\">\r\n @for (tab of tabs(); track tab.id) {\r\n <button \r\n class=\"filter-tab\"\r\n [class.active]=\"activeTab() === tab.id\"\r\n (click)=\"handleTabClick(tab.id)\"\r\n [attr.aria-label]=\"tab.label\"\r\n [attr.aria-selected]=\"activeTab() === tab.id\">\r\n {{ tab.label }}\r\n @if (tab.badge && tab.badge > 0) {\r\n <span class=\"tab-badge\">{{ tab.badge }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n `\r\n})\r\nexport class DsMobileInlineTabsComponent {\r\n /**\r\n * Array of tab items to display\r\n */\r\n tabs = input.required<InlineTabItem[]>();\r\n \r\n /**\r\n * Currently active tab ID\r\n */\r\n activeTab = input.required<string>();\r\n \r\n /**\r\n * Emitted when a tab is clicked\r\n */\r\n tabChange = output<string>();\r\n \r\n handleTabClick(tabId: string): void {\r\n this.tabChange.emit(tabId);\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport type { LightboxAuthor } from './ds-mobile-lightbox.service';\r\n\r\n/**\r\n * DsMobileLightboxHeaderComponent\r\n * \r\n * Shared header component for all lightbox types (image, PDF, etc.)\r\n * Displays author information and close button with consistent styling.\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-header',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent, DsAvatarComponent],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n template: `\r\n <div class=\"lightbox-header lightbox-context\">\r\n <div class=\"header-content\">\r\n <!-- Post author info -->\r\n @if (author()) {\r\n <div class=\"post-author-info\">\r\n <ds-avatar\r\n [initials]=\"author()!.avatarInitials ?? ''\"\r\n [type]=\"author()!.avatarType ?? 'initials'\"\r\n [src]=\"author()!.avatarSrc ?? ''\"\r\n size=\"md\"\r\n />\r\n <div class=\"author-details\">\r\n <div class=\"author-name\">{{ author()!.name }}</div>\r\n <div class=\"author-meta\">\r\n @if (author()!.role) {\r\n <span>{{ author()!.role }}</span>\r\n }\r\n @if (author()!.role && author()!.timestamp) {\r\n <span class=\"separator\">·</span>\r\n }\r\n @if (author()!.timestamp) {\r\n <span>{{ author()!.timestamp }}</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Action buttons - always visible -->\r\n <div class=\"header-actions\">\r\n <ds-icon-button\r\n icon=\"remixShare2Line\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (clicked)=\"shareClick.emit()\"\r\n class=\"share-button\"\r\n [ariaLabel]=\"'Share'\">\r\n </ds-icon-button>\r\n \r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (clicked)=\"closeClick.emit()\"\r\n class=\"close-button\"\r\n [ariaLabel]=\"'Close'\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n .lightbox-header {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 1000;\r\n padding: 0 16px;\r\n background: linear-gradient(to bottom, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.4) 80%, transparent 100%);\r\n pointer-events: none;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-end;\r\n gap: 12px;\r\n pointer-events: auto;\r\n }\r\n\r\n .post-author-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n margin-right: auto;\r\n }\r\n\r\n .author-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n .author-name {\r\n color: white;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n }\r\n\r\n .author-meta {\r\n color: rgba(255, 255, 255, 0.7);\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n\r\n .author-meta .separator {\r\n color: rgba(255, 255, 255, 0.5);\r\n }\r\n\r\n .header-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex-shrink: 0;\r\n }\r\n\r\n .close-button,\r\n .share-button {\r\n pointer-events: auto;\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n\r\n .close-button::ng-deep button,\r\n .share-button::ng-deep button {\r\n color: white !important;\r\n background: rgba(255, 255, 255, 0.1) !important;\r\n border-radius: 50%;\r\n transition: background 0.2s ease;\r\n border: none;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .close-button::ng-deep button:hover,\r\n .share-button::ng-deep button:hover {\r\n background: rgba(255, 255, 255, 0.15) !important;\r\n }\r\n\r\n .close-button::ng-deep button:active,\r\n .share-button::ng-deep button:active {\r\n background: rgba(255, 255, 255, 0.15) !important;\r\n }\r\n\r\n .close-button::ng-deep svg,\r\n .share-button::ng-deep svg {\r\n color: white !important;\r\n fill: white !important;\r\n }\r\n\r\n /* Safe area support for notched devices */\r\n @supports (padding-top: env(safe-area-inset-top)) {\r\n .lightbox-header {\r\n padding-top: calc(16px + env(safe-area-inset-top));\r\n }\r\n }\r\n `]\r\n})\r\nexport class DsMobileLightboxHeaderComponent {\r\n /**\r\n * Author information to display\r\n */\r\n author = input<LightboxAuthor>();\r\n\r\n /**\r\n * Emitted when close button is clicked\r\n */\r\n closeClick = output<void>();\r\n \r\n /**\r\n * Emitted when share button is clicked\r\n */\r\n shareClick = output<void>();\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileLightboxFooterComponent\r\n * \r\n * Shared footer component for all lightbox types (image, PDF, etc.)\r\n * Displays navigation controls (for multiple images) and action buttons.\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-footer',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent],\r\n template: `\r\n <div class=\"lightbox-footer\">\r\n <!-- Navigation controls (only shown for multiple images) -->\r\n @if (showNavigation() && totalImages() > 1) {\r\n <div class=\"footer-navigation\">\r\n <button \r\n class=\"nav-button prev\"\r\n (click)=\"prevClick.emit()\"\r\n [disabled]=\"currentIndex() === 0\"\r\n aria-label=\"Previous image\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M15 18L9 12L15 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n \r\n <div class=\"counter\">\r\n {{ currentIndex() + 1 }} / {{ totalImages() }}\r\n </div>\r\n \r\n <button \r\n class=\"nav-button next\"\r\n (click)=\"nextClick.emit()\"\r\n [disabled]=\"currentIndex() === totalImages() - 1\"\r\n aria-label=\"Next image\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M9 18L15 12L9 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n }\r\n \r\n <!-- Action buttons -->\r\n @if (showActions()) {\r\n <div class=\"footer-actions\">\r\n <div class=\"action-buttons-left\">\r\n <!-- Like button -->\r\n <ds-icon-button\r\n [icon]=\"isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (click)=\"likeClick.emit()\"\r\n [attr.data-liked]=\"isLiked()\"\r\n class=\"action-button-like\"\r\n [ariaLabel]=\"'Like'\">\r\n </ds-icon-button>\r\n \r\n <!-- Comment button -->\r\n <ds-icon-button\r\n icon=\"remixChat3Line\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (click)=\"commentClick.emit()\"\r\n class=\"action-button-comment\"\r\n [ariaLabel]=\"'Comment'\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n .lightbox-footer {\r\n position: fixed;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 100;\r\n padding: 16px 20px 20px 20px;\r\n background: linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 50%, rgba(0, 0, 0, 0.4) 75%, transparent 100%);\r\n pointer-events: none;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n\r\n /* Navigation controls */\r\n .footer-navigation {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 24px;\r\n pointer-events: auto;\r\n }\r\n\r\n .nav-button {\r\n background: rgba(255, 255, 255, 0.1);\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n border-radius: 50%;\r\n color: white;\r\n width: 40px;\r\n height: 40px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n backdrop-filter: blur(10px);\r\n -webkit-backdrop-filter: blur(10px);\r\n padding: 0;\r\n }\r\n\r\n .nav-button:hover:not(:disabled) {\r\n background: rgba(255, 255, 255, 0.2);\r\n transform: scale(1.05);\r\n }\r\n\r\n .nav-button:active:not(:disabled) {\r\n transform: scale(0.95);\r\n }\r\n\r\n .nav-button:disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n }\r\n\r\n .nav-button svg {\r\n width: 24px;\r\n height: 24px;\r\n flex-shrink: 0;\r\n }\r\n\r\n .counter {\r\n background: rgba(255, 255, 255, 0.1);\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n backdrop-filter: blur(10px);\r\n -webkit-backdrop-filter: blur(10px);\r\n border-radius: 100px;\r\n padding: 8px 16px;\r\n color: white;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 1;\r\n letter-spacing: -0.3px;\r\n pointer-events: auto;\r\n user-select: none;\r\n }\r\n\r\n .footer-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n pointer-events: auto;\r\n }\r\n\r\n .action-buttons-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n }\r\n\r\n /* Style the action buttons to match the ghost/transparent look */\r\n .action-button-like::ng-deep button,\r\n .action-button-comment::ng-deep button {\r\n background: rgba(255, 255, 255, 0.1) !important;\r\n border: 1px solid rgba(255, 255, 255, 0.2) !important;\r\n color: white !important;\r\n backdrop-filter: blur(10px);\r\n -webkit-backdrop-filter: blur(10px);\r\n transition: all 0.2s ease;\r\n }\r\n\r\n .action-button-like::ng-deep button:hover,\r\n .action-button-comment::ng-deep button:hover {\r\n background: rgba(255, 255, 255, 0.2) !important;\r\n transform: scale(1.02);\r\n }\r\n\r\n .action-button-like::ng-deep button:active,\r\n .action-button-comment::ng-deep button:active {\r\n transform: scale(0.98);\r\n }\r\n\r\n /* Icon and label colors */\r\n .action-button-like::ng-deep button svg,\r\n .action-button-comment::ng-deep button svg,\r\n .action-button-like::ng-deep button .btn__icon,\r\n .action-button-comment::ng-deep button .btn__icon,\r\n .action-button-like::ng-deep button .btn__content,\r\n .action-button-comment::ng-deep button .btn__content {\r\n color: white !important;\r\n fill: white !important;\r\n }\r\n\r\n /* Make sure icons are visible */\r\n .action-button-like::ng-deep button .btn__icon svg,\r\n .action-button-comment::ng-deep button .btn__icon svg {\r\n color: white !important;\r\n fill: white !important;\r\n display: block !important;\r\n opacity: 1 !important;\r\n visibility: visible !important;\r\n width: 20px !important;\r\n height: 20px !important;\r\n }\r\n\r\n /* Ensure icon wrapper is visible */\r\n .action-button-like::ng-deep button .btn__icon,\r\n .action-button-comment::ng-deep button .btn__icon {\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n flex-shrink: 0 !important;\r\n }\r\n\r\n /* Like button active state (pink heart) */\r\n .action-button-like[data-liked=\"true\"]::ng-deep button svg {\r\n fill: #f91880 !important;\r\n color: #f91880 !important;\r\n }\r\n\r\n .action-button-like[data-liked=\"true\"]::ng-deep button {\r\n border-color: rgba(249, 24, 128, 0.3) !important;\r\n }\r\n\r\n /* All action buttons should have same circular styling */\r\n .action-button-like,\r\n .action-button-comment {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n\r\n .action-button-like::ng-deep button,\r\n .action-button-comment::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 44px !important;\r\n height: 44px !important;\r\n min-width: 44px !important;\r\n min-height: 44px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n /* Safe area support for footer */\r\n @supports (padding-bottom: env(safe-area-inset-bottom)) {\r\n .lightbox-footer {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n `]\r\n})\r\nexport class DsMobileLightboxFooterComponent {\r\n /**\r\n * Whether to show navigation controls\r\n */\r\n showNavigation = input<boolean>(false);\r\n\r\n /**\r\n * Current image index (0-based)\r\n */\r\n currentIndex = input<number>(0);\r\n\r\n /**\r\n * Total number of images\r\n */\r\n totalImages = input<number>(1);\r\n\r\n /**\r\n * Whether to show like & comment action buttons\r\n * @default false\r\n */\r\n showActions = input<boolean>(false);\r\n \r\n /**\r\n * Whether the content is liked\r\n */\r\n isLiked = input<boolean>(false);\r\n \r\n /**\r\n * Number of likes\r\n */\r\n likeCount = input<number>(0);\r\n \r\n /**\r\n * Number of comments\r\n */\r\n commentCount = input<number>(0);\r\n\r\n /**\r\n * Emitted when previous button is clicked\r\n */\r\n prevClick = output<void>();\r\n\r\n /**\r\n * Emitted when next button is clicked\r\n */\r\n nextClick = output<void>();\r\n\r\n /**\r\n * Emitted when like button is clicked\r\n */\r\n likeClick = output<void>();\r\n\r\n /**\r\n * Emitted when comment button is clicked\r\n */\r\n commentClick = output<void>();\r\n}\r\n\r\n","import {\r\n Component,\r\n signal,\r\n computed,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n OnInit,\r\n CUSTOM_ELEMENTS_SCHEMA,\r\n HostListener\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonSpinner,\r\n GestureController,\r\n Gesture\r\n} from '@ionic/angular/standalone';\r\nimport { Share } from '@capacitor/share';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';\r\nimport { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';\r\nimport type { LightboxImage, LightboxAuthor } from './ds-mobile-lightbox.service';\r\nimport Swiper from 'swiper';\r\nimport type { SwiperOptions } from 'swiper/types';\r\n\r\n/**\r\n * DsMobileLightboxImageComponent\r\n * \r\n * Full-screen image lightbox component with Swiper.js navigation and pinch-zoom.\r\n * \r\n * This component is typically not used directly - use DsMobileLightboxService instead.\r\n * \r\n * Features:\r\n * - Swiper.js for smooth image navigation\r\n * - Pinch to zoom in/out\r\n * - Double-tap to toggle zoom\r\n * - Swipe down to close (when not zoomed)\r\n * - Image counter and navigation controls\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private lightbox: DsMobileLightboxService) {}\r\n * \r\n * openImage() {\r\n * this.lightbox.openImages({\r\n * images: [{ type: 'image', src: 'image.jpg', title: 'My Image' }]\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-image',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonSpinner,\r\n DsMobileLightboxHeaderComponent,\r\n DsMobileLightboxFooterComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <div class=\"lightbox-overlay\" \r\n [class.zoomed]=\"isZoomed()\">\r\n \r\n <div class=\"lightbox-wrapper\">\r\n <!-- Header with author info and action buttons -->\r\n <ds-mobile-lightbox-header \r\n [author]=\"author\"\r\n (closeClick)=\"close()\"\r\n (shareClick)=\"onShare()\"\r\n />\r\n\r\n <!-- Swiper container -->\r\n <div class=\"swiper-container\" #swiperContainer>\r\n <div class=\"swiper-wrapper\">\r\n @for (image of images; track image.src; let i = $index) {\r\n <div class=\"swiper-slide\">\r\n <div class=\"image-zoom-container\" [attr.data-index]=\"i\">\r\n <img \r\n [src]=\"image.src\"\r\n [alt]=\"image.alt || 'Lightbox image'\"\r\n class=\"lightbox-image\"\r\n (load)=\"onImageLoad(i)\"\r\n (error)=\"onImageError(i)\">\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n \r\n <!-- Loading indicator -->\r\n @if (isLoading()) {\r\n <div class=\"loading-spinner\">\r\n <ion-spinner name=\"crescent\"></ion-spinner>\r\n </div>\r\n }\r\n\r\n <!-- Footer with navigation and actions -->\r\n <ds-mobile-lightbox-footer\r\n [showNavigation]=\"showControls && images.length > 1\"\r\n [showActions]=\"showActions\"\r\n [currentIndex]=\"currentIndex()\"\r\n [totalImages]=\"images.length\"\r\n [isLiked]=\"isLiked()\"\r\n [likeCount]=\"likeCount()\"\r\n [commentCount]=\"commentCount()\"\r\n (prevClick)=\"previousImage()\"\r\n (nextClick)=\"nextImage()\"\r\n (likeClick)=\"onLikeToggle()\"\r\n (commentClick)=\"onReply()\"\r\n />\r\n </div>\r\n </div>\r\n `,\r\n styleUrl: './ds-mobile-lightbox.css'\r\n})\r\nexport class DsMobileLightboxImageComponent implements OnInit, AfterViewInit, OnDestroy {\r\n // Inputs (passed from service as regular properties, not signals)\r\n images!: LightboxImage[];\r\n author?: LightboxAuthor;\r\n initialIndex: number = 0;\r\n enableZoom: boolean = true;\r\n showControls: boolean = true;\r\n enableSwipe: boolean = true;\r\n showInfo: boolean = true;\r\n showActions: boolean = false;\r\n animation: 'fade' | 'zoom' | 'slide' = 'fade';\r\n onCloseRequested?: () => void;\r\n\r\n // View children\r\n @ViewChild('swiperContainer', { read: ElementRef }) swiperContainer!: ElementRef<HTMLDivElement>;\r\n\r\n // State\r\n currentIndex = signal(0);\r\n scale = signal(1);\r\n isZoomed = signal(false);\r\n isLoading = signal(true);\r\n hasError = signal(false);\r\n \r\n // Action states\r\n isLiked = signal(false);\r\n likeCount = signal(0);\r\n commentCount = signal(0);\r\n\r\n // Computed\r\n currentImage = computed(() => this.images[this.currentIndex()]);\r\n\r\n // Swiper instance\r\n private swiper?: Swiper;\r\n private zoomData: Map<number, { scale: number; x: number; y: number }> = new Map();\r\n\r\n constructor(\r\n private gestureCtrl: GestureController\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n // Set initial index from the passed property\r\n if (this.initialIndex !== undefined) {\r\n this.currentIndex.set(this.initialIndex);\r\n }\r\n \r\n // Initialize action states from current image\r\n const currentImg = this.images[this.currentIndex()];\r\n if (currentImg) {\r\n this.isLiked.set(currentImg.isLiked ?? false);\r\n this.likeCount.set(currentImg.likeCount ?? 0);\r\n this.commentCount.set(currentImg.commentCount ?? 0);\r\n }\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n setTimeout(() => {\r\n this.initializeSwiper();\r\n this.initializeZoomGestures();\r\n }, 100);\r\n }\r\n\r\n ngOnDestroy(): void {\r\n // Clean up Swiper\r\n if (this.swiper) {\r\n this.swiper.destroy();\r\n this.swiper = undefined;\r\n }\r\n }\r\n /**\r\n * Initialize Swiper for image navigation\r\n */\r\n private initializeSwiper(): void {\r\n if (!this.swiperContainer) {\r\n console.error('[Lightbox] Swiper container not found');\r\n return;\r\n }\r\n\r\n const swiperOptions: SwiperOptions = {\r\n initialSlide: this.initialIndex,\r\n speed: 300,\r\n resistance: true,\r\n resistanceRatio: 0.85,\r\n slidesPerView: 1,\r\n spaceBetween: 0,\r\n touchRatio: 1,\r\n longSwipesRatio: 0.5,\r\n threshold: 10,\r\n on: {\r\n slideChange: (swiper) => {\r\n this.currentIndex.set(swiper.activeIndex);\r\n this.updateActionStates();\r\n \r\n // Check if the image is already loaded\r\n const currentSlide = swiper.slides[swiper.activeIndex];\r\n const img = currentSlide?.querySelector('img');\r\n if (img && img.complete && img.naturalHeight !== 0) {\r\n // Image is already loaded\r\n this.isLoading.set(false);\r\n }\r\n },\r\n slideChangeTransitionStart: () => {\r\n // Don't show loading spinner if image is already loaded\r\n const currentSlide = this.swiper?.slides[this.swiper.activeIndex];\r\n const img = currentSlide?.querySelector('img');\r\n if (!img || !img.complete || img.naturalHeight === 0) {\r\n this.isLoading.set(true);\r\n }\r\n }\r\n }\r\n };\r\n\r\n this.swiper = new Swiper(this.swiperContainer.nativeElement, swiperOptions);\r\n \r\n // Check if the initial image is already loaded\r\n setTimeout(() => {\r\n const currentSlide = this.swiper?.slides[this.currentIndex()];\r\n const img = currentSlide?.querySelector('img');\r\n if (img && img.complete && img.naturalHeight !== 0) {\r\n this.isLoading.set(false);\r\n }\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Initialize pinch-zoom gestures for all slides\r\n */\r\n private initializeZoomGestures(): void {\r\n if (!this.enableZoom) return;\r\n\r\n const slides = this.swiperContainer.nativeElement.querySelectorAll('.image-zoom-container');\r\n \r\n slides.forEach((slide, index) => {\r\n this.initializeZoomForSlide(slide as HTMLElement, index);\r\n });\r\n }\r\n\r\n /**\r\n * Initialize zoom gestures for a specific slide\r\n */\r\n private initializeZoomForSlide(container: HTMLElement, index: number): void {\r\n let initialDistance = 0;\r\n let initialScale = 1;\r\n let currentScale = 1;\r\n let lastTap = 0;\r\n\r\n // Double-tap to zoom\r\n container.addEventListener('click', (event: MouseEvent) => {\r\n const now = Date.now();\r\n const timeSinceLastTap = now - lastTap;\r\n\r\n if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {\r\n event.preventDefault();\r\n this.toggleZoom(container, index);\r\n }\r\n\r\n lastTap = now;\r\n });\r\n\r\n // Pinch to zoom\r\n const getTouchDistance = (touches: TouchList) => {\r\n const dx = touches[0].clientX - touches[1].clientX;\r\n const dy = touches[0].clientY - touches[1].clientY;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n };\r\n\r\n container.addEventListener('touchstart', (event: TouchEvent) => {\r\n if (event.touches.length === 2) {\r\n event.preventDefault();\r\n initialDistance = getTouchDistance(event.touches);\r\n const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };\r\n initialScale = zoomData.scale;\r\n \r\n // Disable Swiper when zooming\r\n if (this.swiper) {\r\n this.swiper.allowTouchMove = false;\r\n }\r\n }\r\n }, { passive: false });\r\n\r\n container.addEventListener('touchmove', (event: TouchEvent) => {\r\n if (event.touches.length === 2) {\r\n event.preventDefault();\r\n \r\n const currentDistance = getTouchDistance(event.touches);\r\n const pinchScale = currentDistance / initialDistance;\r\n \r\n currentScale = Math.max(1, Math.min(initialScale * pinchScale, 4));\r\n \r\n const img = container.querySelector('img');\r\n if (img) {\r\n img.style.transform = `scale(${currentScale})`;\r\n }\r\n \r\n if (currentScale > 1) {\r\n this.isZoomed.set(true);\r\n } else {\r\n this.isZoomed.set(false);\r\n }\r\n }\r\n }, { passive: false });\r\n\r\n container.addEventListener('touchend', (event: TouchEvent) => {\r\n if (event.touches.length < 2) {\r\n // Save zoom state\r\n this.zoomData.set(index, { scale: currentScale, x: 0, y: 0 });\r\n \r\n // Re-enable Swiper if not zoomed\r\n if (this.swiper && currentScale <= 1) {\r\n this.swiper.allowTouchMove = true;\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Toggle zoom on double-tap\r\n */\r\n private toggleZoom(container: HTMLElement, index: number): void {\r\n const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };\r\n const img = container.querySelector('img');\r\n \r\n if (!img) return;\r\n\r\n if (zoomData.scale > 1) {\r\n // Zoom out\r\n img.style.transform = 'scale(1)';\r\n this.zoomData.set(index, { scale: 1, x: 0, y: 0 });\r\n this.isZoomed.set(false);\r\n if (this.swiper) {\r\n this.swiper.allowTouchMove = true;\r\n }\r\n } else {\r\n // Zoom in\r\n img.style.transform = 'scale(2)';\r\n this.zoomData.set(index, { scale: 2, x: 0, y: 0 });\r\n this.isZoomed.set(true);\r\n if (this.swiper) {\r\n this.swiper.allowTouchMove = false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Update action states (like, comments) when slide changes\r\n */\r\n private updateActionStates(): void {\r\n const currentImg = this.images[this.currentIndex()];\r\n if (currentImg) {\r\n this.isLiked.set(currentImg.isLiked ?? false);\r\n this.likeCount.set(currentImg.likeCount ?? 0);\r\n this.commentCount.set(currentImg.commentCount ?? 0);\r\n }\r\n }\r\n\r\n /**\r\n * Close the lightbox\r\n */\r\n close(): void {\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Handle share button click\r\n */\r\n async onShare(): Promise<void> {\r\n console.log('[Lightbox] Share button clicked');\r\n const currentImg = this.currentImage();\r\n \r\n if (!currentImg?.src) {\r\n console.warn('[Lightbox] No image to share');\r\n return;\r\n }\r\n \r\n try {\r\n // Check if Web Share API is available (for browser)\r\n if (navigator.share) {\r\n await navigator.share({\r\n title: currentImg.title || 'Shared Image',\r\n text: currentImg.description || '',\r\n url: currentImg.src,\r\n });\r\n console.log('[Lightbox] Shared via Web Share API');\r\n } else {\r\n // Fallback to Capacitor Share API (for native apps)\r\n await Share.share({\r\n title: currentImg.title || 'Shared Image',\r\n url: currentImg.src,\r\n dialogTitle: 'Share Image',\r\n });\r\n console.log('[Lightbox] Shared via Capacitor Share API');\r\n }\r\n } catch (error: any) {\r\n // User cancellation is expected and not an error\r\n if (error?.message?.includes('cancel') || error?.code === 'USER_CANCELLED') {\r\n console.log('[Lightbox] Share cancelled by user');\r\n return;\r\n }\r\n console.error('[Lightbox] Share failed:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Handle like button toggle\r\n */\r\n onLikeToggle(): void {\r\n console.log('[Lightbox] Like button toggled');\r\n this.isLiked.update(liked => !liked);\r\n \r\n if (this.isLiked()) {\r\n this.likeCount.update(count => count + 1);\r\n } else {\r\n this.likeCount.update(count => Math.max(0, count - 1));\r\n }\r\n }\r\n\r\n /**\r\n * Handle reply/comment button click\r\n */\r\n onReply(): void {\r\n console.log('[Lightbox] Reply button clicked');\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Navigate to the next image\r\n */\r\n nextImage(): void {\r\n if (this.swiper && this.currentIndex() < this.images.length - 1) {\r\n this.swiper.slideNext();\r\n }\r\n }\r\n\r\n /**\r\n * Navigate to the previous image\r\n */\r\n previousImage(): void {\r\n if (this.swiper && this.currentIndex() > 0) {\r\n this.swiper.slidePrev();\r\n }\r\n }\r\n\r\n /**\r\n * Handle image load success\r\n */\r\n onImageLoad(index: number): void {\r\n if (index === this.currentIndex()) {\r\n this.isLoading.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * Handle image load error\r\n */\r\n onImageError(index: number): void {\r\n if (index === this.currentIndex()) {\r\n console.error(`[Lightbox] Image ${index} failed to load`);\r\n this.isLoading.set(false);\r\n this.hasError.set(true);\r\n }\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n OnInit,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonContent,\r\n IonSpinner\r\n} from '@ionic/angular/standalone';\r\nimport { Filesystem, Directory } from '@capacitor/filesystem';\r\nimport { Browser } from '@capacitor/browser';\r\nimport { Share } from '@capacitor/share';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsButtonComponent } from '@propbinder/design-system';\r\nimport { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';\r\nimport { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';\r\nimport type { LightboxPdf, LightboxAuthor } from './ds-mobile-lightbox.service';\r\n\r\n/**\r\n * DsMobileLightboxPdfComponent\r\n * \r\n * PDF viewer component that displays PDF info and allows users to open PDFs in the native device viewer.\r\n * Shows a lightbox with PDF details first, then user can choose to open in native viewer.\r\n * \r\n * This component is typically not used directly - use DsMobileLightboxService instead.\r\n * \r\n * Features:\r\n * - PDF info preview (title, size, icon)\r\n * - User-initiated native PDF viewing (iOS/Android)\r\n * - Download and cache support\r\n * - Share functionality\r\n * - Loading states\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private lightbox: DsMobileLightboxService) {}\r\n * \r\n * openPdf() {\r\n * this.lightbox.openPdf({\r\n * pdf: { type: 'pdf', src: 'document.pdf', title: 'My Document' }\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-pdf',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n IonSpinner,\r\n DsAvatarComponent,\r\n DsButtonComponent,\r\n DsMobileLightboxHeaderComponent,\r\n DsMobileLightboxFooterComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content \r\n [fullscreen]=\"true\"\r\n class=\"lightbox-content pdf-viewer\">\r\n \r\n <div class=\"lightbox-wrapper\">\r\n <!-- Header with author info and close button -->\r\n <ds-mobile-lightbox-header \r\n [author]=\"author\"\r\n (closeClick)=\"close()\"\r\n />\r\n\r\n <!-- PDF Info & Actions -->\r\n <div class=\"pdf-container\">\r\n @if (isLoading) {\r\n <div class=\"loading-state\">\r\n <ion-spinner name=\"crescent\"></ion-spinner>\r\n <p>Loading PDF...</p>\r\n </div>\r\n } @else if (hasError) {\r\n <div class=\"error-state\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M12 8V12M12 16H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n <h3>Failed to Load PDF</h3>\r\n <p>{{ errorMessage }}</p>\r\n <button class=\"retry-button\" (click)=\"openPdfInNativeViewer()\">\r\n Try Again\r\n </button>\r\n </div>\r\n } @else {\r\n <div class=\"pdf-content\">\r\n <!-- PDF Icon -->\r\n <ds-avatar\r\n type=\"icon\"\r\n iconName=\"remixFileTextLine\"\r\n size=\"xl\"\r\n />\r\n \r\n <!-- PDF Title (same as attachment fileName) -->\r\n <h2 class=\"pdf-title\">{{ getDisplayTitle() }}</h2>\r\n \r\n <!-- PDF Metadata (same format as attachment: PDF · fileSize) -->\r\n <div class=\"pdf-meta\">\r\n PDF · {{ pdf.fileSize ? formatFileSize(pdf.fileSize) : '' }}\r\n </div>\r\n \r\n <!-- Open Button -->\r\n <ds-button\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (clicked)=\"openPdfInNativeViewer()\"\r\n class=\"open-pdf-button\">\r\n Open Preview\r\n </ds-button>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Bottom actions -->\r\n <ds-mobile-lightbox-footer\r\n [isLiked]=\"false\"\r\n [likeCount]=\"0\"\r\n [commentCount]=\"0\"\r\n (likeClick)=\"onLikeToggle()\"\r\n (commentClick)=\"onReply()\"\r\n (shareClick)=\"onShare()\"\r\n />\r\n </div>\r\n </ion-content>\r\n `,\r\n styleUrl: './ds-mobile-lightbox-pdf.css'\r\n})\r\nexport class DsMobileLightboxPdfComponent implements OnInit {\r\n // Inputs (passed from service as regular properties)\r\n pdf!: LightboxPdf;\r\n author?: LightboxAuthor;\r\n onCloseRequested?: () => void;\r\n\r\n // State\r\n isLoading = false;\r\n hasError = false;\r\n errorMessage = '';\r\n cachedFilePath?: string;\r\n\r\n constructor() {}\r\n\r\n ngOnInit(): void {\r\n console.log('[PDF Lightbox] Initializing with PDF:', this.pdf);\r\n \r\n // Don't automatically open - let user click the \"Open\" button\r\n // this.openPdfInNativeViewer();\r\n }\r\n\r\n /**\r\n * Open the PDF in the native device viewer\r\n */\r\n async openPdfInNativeViewer(): Promise<void> {\r\n if (!this.pdf?.src) {\r\n console.error('[PDF Lightbox] No PDF source provided');\r\n this.hasError = true;\r\n this.errorMessage = 'No PDF file provided';\r\n return;\r\n }\r\n\r\n this.isLoading = true;\r\n this.hasError = false;\r\n this.errorMessage = '';\r\n\r\n try {\r\n console.log('[PDF Lightbox] Opening PDF:', this.pdf.src);\r\n \r\n // Check if it's already a full URL\r\n let pdfUrl: string;\r\n \r\n if (this.pdf.src.startsWith('http://') || this.pdf.src.startsWith('https://')) {\r\n // Already a full URL\r\n pdfUrl = this.pdf.src;\r\n } else {\r\n // Relative path - construct full URL\r\n // Use current origin (which includes the dev server URL in Capacitor)\r\n // Remove leading slash if present to avoid double slashes\r\n const cleanPath = this.pdf.src.startsWith('/') ? this.pdf.src.slice(1) : this.pdf.src;\r\n pdfUrl = `${window.location.origin}/${cleanPath}`;\r\n }\r\n \r\n console.log('[PDF Lightbox] Opening PDF at URL:', pdfUrl);\r\n \r\n // Use Browser to open the PDF\r\n await Browser.open({ \r\n url: pdfUrl,\r\n presentationStyle: 'fullscreen'\r\n });\r\n \r\n this.isLoading = false;\r\n \r\n // Close the modal after opening browser\r\n setTimeout(() => {\r\n this.close();\r\n }, 500);\r\n } catch (error: any) {\r\n console.error('[PDF Lightbox] Error opening PDF:', error);\r\n this.isLoading = false;\r\n this.hasError = true;\r\n this.errorMessage = error?.message || 'Failed to open PDF';\r\n }\r\n }\r\n\r\n /**\r\n * Download a remote PDF and open it\r\n */\r\n private async downloadAndOpenPdf(): Promise<void> {\r\n try {\r\n console.log('[PDF Lightbox] Downloading PDF from:', this.pdf.src);\r\n \r\n // Fetch the PDF\r\n const response = await fetch(this.pdf.src);\r\n if (!response.ok) {\r\n throw new Error(`Failed to download PDF: ${response.statusText}`);\r\n }\r\n \r\n const blob = await response.blob();\r\n const base64Data = await this.blobToBase64(blob);\r\n \r\n // Generate a filename\r\n const fileName = this.pdf.title \r\n ? `${this.pdf.title.replace(/[^a-z0-9]/gi, '_')}.pdf`\r\n : 'document.pdf';\r\n \r\n // Save to cache directory\r\n const result = await Filesystem.writeFile({\r\n path: fileName,\r\n data: base64Data,\r\n directory: Directory.Cache\r\n });\r\n \r\n console.log('[PDF Lightbox] PDF saved to cache:', result.uri);\r\n this.cachedFilePath = result.uri;\r\n \r\n // Open using Browser\r\n await Browser.open({ \r\n url: result.uri,\r\n presentationStyle: 'fullscreen'\r\n });\r\n \r\n console.log('[PDF Lightbox] PDF opened successfully');\r\n } catch (error) {\r\n console.error('[PDF Lightbox] Error downloading/opening PDF:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Open a local PDF file\r\n */\r\n private async openLocalPdf(): Promise<void> {\r\n try {\r\n // Remove leading slash if present to avoid double slashes\r\n const cleanPath = this.pdf.src.startsWith('/') ? this.pdf.src.slice(1) : this.pdf.src;\r\n const fullUrl = window.location.origin + '/' + cleanPath;\r\n \r\n await Browser.open({ \r\n url: fullUrl,\r\n presentationStyle: 'fullscreen'\r\n });\r\n \r\n console.log('[PDF Lightbox] Local PDF opened successfully');\r\n } catch (error) {\r\n console.error('[PDF Lightbox] Error opening local PDF:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Convert Blob to base64 string\r\n */\r\n private blobToBase64(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => {\r\n const base64String = reader.result as string;\r\n // Remove the data URL prefix\r\n const base64Data = base64String.split(',')[1];\r\n resolve(base64Data);\r\n };\r\n reader.onerror = reject;\r\n reader.readAsDataURL(blob);\r\n });\r\n }\r\n\r\n /**\r\n * Get display title with file extension\r\n * If title is provided, ensure it has .pdf extension\r\n * Otherwise, extract filename from src\r\n */\r\n getDisplayTitle(): string {\r\n if (this.pdf.title) {\r\n // If title doesn't end with .pdf, add it\r\n return this.pdf.title.endsWith('.pdf') ? this.pdf.title : `${this.pdf.title}.pdf`;\r\n }\r\n \r\n // Extract filename from src\r\n if (this.pdf.src) {\r\n const filename = this.pdf.src.split('/').pop() || 'PDF Document.pdf';\r\n return filename;\r\n }\r\n \r\n return 'PDF Document.pdf';\r\n }\r\n\r\n /**\r\n * Format file size for display\r\n */\r\n formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 Bytes';\r\n \r\n const k = 1024;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n \r\n return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];\r\n }\r\n\r\n /**\r\n * Share the PDF\r\n */\r\n async onShare(): Promise<void> {\r\n console.log('[PDF Lightbox] Share button clicked');\r\n \r\n if (!this.pdf?.src) return;\r\n \r\n try {\r\n await Share.share({\r\n title: this.pdf.title || 'PDF Document',\r\n text: this.pdf.description || '',\r\n url: this.pdf.src,\r\n dialogTitle: 'Share PDF'\r\n });\r\n \r\n console.log('[PDF Lightbox] PDF shared successfully');\r\n } catch (error) {\r\n console.error('[PDF Lightbox] Error sharing PDF:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Close the PDF viewer\r\n */\r\n close(): void {\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Handle like toggle\r\n */\r\n onLikeToggle(): void {\r\n console.log('[PDF Lightbox] Like toggled');\r\n // TODO: Implement like logic for PDFs if needed\r\n }\r\n\r\n /**\r\n * Handle reply/comment\r\n * Close the lightbox and signal to open post detail with comment focus\r\n */\r\n onReply(): void {\r\n console.log('[PDF Lightbox] Reply button clicked');\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n // The calling code should handle opening the post detail modal\r\n }\r\n }\r\n}\r\n\r\n","import { Injectable, ApplicationRef, ComponentRef, createComponent, EnvironmentInjector, Injector } from '@angular/core';\r\nimport { DsMobileLightboxImageComponent } from './ds-mobile-lightbox-image';\r\nimport { DsMobileLightboxPdfComponent } from './ds-mobile-lightbox-pdf';\r\n\r\n/**\r\n * Media file types supported by the lightbox\r\n */\r\nexport type LightboxMediaType = 'image' | 'pdf';\r\n\r\n/**\r\n * Base media file interface\r\n */\r\nexport interface LightboxMediaFile {\r\n /** File source URL */\r\n src: string;\r\n /** Media type - determines which viewer to use */\r\n type: LightboxMediaType;\r\n /** File title */\r\n title?: string;\r\n /** File description */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Image data for lightbox display\r\n */\r\nexport interface LightboxImage extends LightboxMediaFile {\r\n type: 'image';\r\n /** Alt text for accessibility */\r\n alt?: string;\r\n /** Thumbnail URL for faster loading (optional) */\r\n thumbnail?: string;\r\n /** Whether the image is liked */\r\n isLiked?: boolean;\r\n /** Number of likes */\r\n likeCount?: number;\r\n /** Number of comments */\r\n commentCount?: number;\r\n}\r\n\r\n/**\r\n * PDF document data for lightbox display\r\n */\r\nexport interface LightboxPdf extends LightboxMediaFile {\r\n type: 'pdf';\r\n /** File size in bytes (optional, for display) */\r\n fileSize?: number;\r\n /** Number of pages (optional, for display) */\r\n pageCount?: number;\r\n}\r\n\r\n/**\r\n * Author metadata for the lightbox\r\n */\r\nexport interface LightboxAuthor {\r\n /** Author name */\r\n name: string;\r\n /** Author role/subtitle */\r\n role?: string;\r\n /** Author avatar URL */\r\n avatarSrc?: string;\r\n /** Author avatar initials (if no photo) */\r\n avatarInitials?: string;\r\n /** Avatar type */\r\n avatarType?: 'photo' | 'initials';\r\n /** Timestamp */\r\n timestamp?: string;\r\n}\r\n\r\n/**\r\n * Configuration options for image lightbox\r\n */\r\nexport interface LightboxImageOptions {\r\n /** Array of images to display */\r\n images: LightboxImage[];\r\n /** Author information to display in header */\r\n author?: LightboxAuthor;\r\n /** Initial image index to show (0-based) */\r\n initialIndex?: number;\r\n /** Enable pinch-to-zoom and double-tap zoom */\r\n enableZoom?: boolean;\r\n /** Show navigation controls (arrows, counter) */\r\n showControls?: boolean;\r\n /** Enable swipe gestures to navigate between images */\r\n enableSwipe?: boolean;\r\n /** Show image info (title, description) */\r\n showInfo?: boolean;\r\n /** Show like & comment action buttons */\r\n showActions?: boolean;\r\n /** Animation type for opening */\r\n animation?: 'fade' | 'zoom' | 'slide';\r\n}\r\n\r\n/**\r\n * Configuration options for PDF lightbox\r\n */\r\nexport interface LightboxPdfOptions {\r\n /** PDF document to display */\r\n pdf: LightboxPdf;\r\n /** Author information to display */\r\n author?: LightboxAuthor;\r\n}\r\n\r\n/**\r\n * Generic lightbox options (for backward compatibility)\r\n */\r\nexport type LightboxOptions = LightboxImageOptions;\r\n\r\n/**\r\n * DsMobileLightboxService\r\n * \r\n * Service for displaying media files (images and PDFs) in full-screen viewers.\r\n * - Images: Full-screen modal with gestures (pinch-zoom, swipe navigation)\r\n * - PDFs: Native device PDF viewer (iOS/Android)\r\n * \r\n * Features:\r\n * - Full-screen image viewing with gestures\r\n * - Native PDF viewing\r\n * - Swipe navigation between images\r\n * - Pinch-to-zoom and double-tap zoom for images\r\n * - Mobile-optimized touch gestures\r\n * - Share functionality\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private lightbox: DsMobileLightboxService) {}\r\n * \r\n * // Open images\r\n * async openImages() {\r\n * const modal = await this.lightbox.openImages({\r\n * images: [\r\n * {\r\n * type: 'image',\r\n * src: 'https://example.com/image1.jpg',\r\n * title: 'Beautiful Sunset'\r\n * }\r\n * ]\r\n * });\r\n * \r\n * // Listen for when lightbox is dismissed\r\n * const { data } = await modal.onDidDismiss();\r\n * if (data?.action === 'comment') {\r\n * // Open post detail modal with comment focus\r\n * this.openPostDetail({ focusComment: true });\r\n * }\r\n * }\r\n * \r\n * // Open PDF\r\n * async openPdf() {\r\n * await this.lightbox.openPdf({\r\n * pdf: {\r\n * type: 'pdf',\r\n * src: 'https://example.com/document.pdf',\r\n * title: 'Document'\r\n * }\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileLightboxService {\r\n private currentLightbox: ComponentRef<any> | null = null;\r\n\r\n constructor(\r\n private appRef: ApplicationRef,\r\n private injector: EnvironmentInjector\r\n ) {}\r\n\r\n /**\r\n * Open the lightbox with images (backward compatible method)\r\n * \r\n * @param options Configuration options for the image lightbox\r\n * @returns Promise that resolves to a dismiss function\r\n */\r\n async open(options: LightboxOptions): Promise<() => void> {\r\n return this.openImages(options);\r\n }\r\n\r\n /**\r\n * Open the image lightbox with one or more images\r\n * \r\n * @param options Configuration options for the image lightbox\r\n * @returns Promise that resolves to a dismiss function\r\n */\r\n async openImages(options: LightboxImageOptions): Promise<() => void> {\r\n console.log('[Lightbox] Opening images with options:', options);\r\n \r\n // Close any existing lightbox\r\n if (this.currentLightbox) {\r\n this.close();\r\n }\r\n\r\n // Create the component\r\n const componentRef = createComponent(DsMobileLightboxImageComponent, {\r\n environmentInjector: this.injector\r\n });\r\n\r\n // Set component props\r\n componentRef.instance.images = options.images;\r\n componentRef.instance.author = options.author;\r\n componentRef.instance.initialIndex = options.initialIndex ?? 0;\r\n componentRef.instance.enableZoom = options.enableZoom !== false;\r\n componentRef.instance.showControls = options.showControls !== false;\r\n componentRef.instance.enableSwipe = options.enableSwipe !== false;\r\n componentRef.instance.showInfo = options.showInfo !== false;\r\n componentRef.instance.showActions = options.showActions ?? false;\r\n componentRef.instance.animation = options.animation ?? 'fade';\r\n \r\n // Set up close callback\r\n componentRef.instance.onCloseRequested = () => {\r\n this.close();\r\n };\r\n\r\n // Attach to application\r\n this.appRef.attachView(componentRef.hostView);\r\n \r\n // Append to body\r\n const domElem = (componentRef.hostView as any).rootNodes[0] as HTMLElement;\r\n document.body.appendChild(domElem);\r\n \r\n // Store reference\r\n this.currentLightbox = componentRef;\r\n\r\n console.log('[Lightbox] Image lightbox rendered');\r\n \r\n // Return dismiss function\r\n return () => this.close();\r\n }\r\n\r\n /**\r\n * Open the PDF lightbox (opens native PDF viewer)\r\n * \r\n * @param options Configuration options for the PDF lightbox\r\n * @returns Promise that resolves to a dismiss function\r\n */\r\n async openPdf(options: LightboxPdfOptions): Promise<() => void> {\r\n console.log('[Lightbox] Opening PDF with options:', options);\r\n \r\n // Close any existing lightbox\r\n if (this.currentLightbox) {\r\n this.close();\r\n }\r\n\r\n // Create the component\r\n const componentRef = createComponent(DsMobileLightboxPdfComponent, {\r\n environmentInjector: this.injector\r\n });\r\n\r\n // Set component props\r\n componentRef.instance.pdf = options.pdf;\r\n componentRef.instance.author = options.author;\r\n \r\n // Set up close callback\r\n componentRef.instance.onCloseRequested = () => {\r\n this.close();\r\n };\r\n\r\n // Attach to application\r\n this.appRef.attachView(componentRef.hostView);\r\n \r\n // Append to body\r\n const domElem = (componentRef.hostView as any).rootNodes[0] as HTMLElement;\r\n document.body.appendChild(domElem);\r\n \r\n // Store reference\r\n this.currentLightbox = componentRef;\r\n\r\n console.log('[Lightbox] PDF lightbox rendered');\r\n \r\n // Return dismiss function\r\n return () => this.close();\r\n }\r\n\r\n /**\r\n * Close the currently open lightbox\r\n */\r\n close(): void {\r\n if (this.currentLightbox) {\r\n const domElem = (this.currentLightbox.hostView as any).rootNodes[0] as HTMLElement;\r\n domElem.remove();\r\n this.appRef.detachView(this.currentLightbox.hostView);\r\n this.currentLightbox.destroy();\r\n this.currentLightbox = null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if a lightbox is currently open\r\n */\r\n isOpen(): boolean {\r\n return this.currentLightbox !== null;\r\n }\r\n}\r\n\r\n","// Components\r\nexport { DsMobileLightboxImageComponent } from './ds-mobile-lightbox-image';\r\nexport { DsMobileLightboxPdfComponent } from './ds-mobile-lightbox-pdf';\r\nexport { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';\r\nexport { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';\r\n\r\n// Service and Types\r\nexport { \r\n DsMobileLightboxService,\r\n type LightboxImage,\r\n type LightboxPdf,\r\n type LightboxMediaFile,\r\n type LightboxMediaType,\r\n type LightboxAuthor,\r\n type LightboxOptions,\r\n type LightboxImageOptions,\r\n type LightboxPdfOptions\r\n} from './ds-mobile-lightbox.service';\r\n\r\n// Legacy export for backward compatibility\r\nexport { DsMobileLightboxImageComponent as DsMobileLightboxComponent } from './ds-mobile-lightbox-image';\r\n\r\n","import { Component, Input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsMobileLightboxService, LightboxImage } from '../lightbox/ds-mobile-lightbox.service';\r\n\r\n/**\r\n * DsMobileInlinePhotoComponent\r\n * \r\n * Displays one or multiple photos in a grid layout optimized for social feeds.\r\n * Supports up to 5 visible images with automatic grid layouts.\r\n * \r\n * Features:\r\n * - Automatic grid layouts for 1-5 images\r\n * - Shows \"+N more\" overlay if more than 5 images\r\n * - Opens lightbox with all images (including hidden ones) when clicked\r\n * - Optimized layouts: 1 full, 2 split, 3 masonry, 4 grid, 5 grid\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-inline-photo\r\n * [images]=\"['img1.jpg', 'img2.jpg', 'img3.jpg']\"\r\n * [author]=\"authorInfo\"\r\n * />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-inline-photo',\r\n standalone: true,\r\n imports: [CommonModule],\r\n template: `\r\n <div \r\n class=\"photo-grid\" \r\n [attr.data-count]=\"visibleImages.length\"\r\n [class.has-more]=\"hiddenCount > 0\">\r\n @for (image of visibleImages; track image; let i = $index) {\r\n <div \r\n class=\"photo-item\"\r\n [class.last]=\"i === visibleImages.length - 1\"\r\n (click)=\"openLightbox(i, $event)\">\r\n <img \r\n [src]=\"image\" \r\n [alt]=\"'Photo ' + (i + 1)\"\r\n loading=\"lazy\">\r\n \r\n <!-- Show \"+N more\" overlay on last image if there are hidden images -->\r\n @if (i === visibleImages.length - 1 && hiddenCount > 0) {\r\n <div class=\"more-overlay\">\r\n <span class=\"more-text\">+{{ hiddenCount }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n\r\n .photo-grid {\r\n display: grid;\r\n gap: 4px;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n background: var(--ds-color-neutral-100);\r\n width: 100%;\r\n }\r\n\r\n .photo-item {\r\n position: relative;\r\n overflow: hidden;\r\n cursor: pointer;\r\n background: var(--ds-color-neutral-200);\r\n aspect-ratio: 1;\r\n }\r\n\r\n .photo-item img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n display: block;\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n .photo-item:active img {\r\n transform: scale(0.98);\r\n }\r\n\r\n .more-overlay {\r\n position: absolute;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.6);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n pointer-events: none;\r\n }\r\n\r\n .more-text {\r\n color: white;\r\n font-size: 32px;\r\n font-weight: 600;\r\n font-family: var(--ds-font-family-medium);\r\n }\r\n\r\n /* 1 image: full width, 4:3 ratio */\r\n .photo-grid[data-count=\"1\"] {\r\n grid-template-columns: 1fr;\r\n }\r\n \r\n .photo-grid[data-count=\"1\"] .photo-item {\r\n aspect-ratio: 4/3;\r\n }\r\n\r\n /* 2 images: side by side */\r\n .photo-grid[data-count=\"2\"] {\r\n grid-template-columns: 1fr 1fr;\r\n }\r\n\r\n /* 3 images: 1 large left, 2 stacked right */\r\n .photo-grid[data-count=\"3\"] {\r\n grid-template-columns: 2fr 1fr;\r\n grid-auto-rows: 1fr;\r\n }\r\n \r\n .photo-grid[data-count=\"3\"] .photo-item:first-child {\r\n grid-row: 1 / 3;\r\n aspect-ratio: auto;\r\n }\r\n \r\n /* Right side images remain 1:1 squares */\r\n .photo-grid[data-count=\"3\"] .photo-item:nth-child(2),\r\n .photo-grid[data-count=\"3\"] .photo-item:nth-child(3) {\r\n aspect-ratio: 1;\r\n }\r\n\r\n /* 4 images: 2x2 grid */\r\n .photo-grid[data-count=\"4\"] {\r\n grid-template-columns: 1fr 1fr;\r\n grid-template-rows: 1fr 1fr;\r\n }\r\n\r\n /* 5 images: 2 on top, 3 on bottom */\r\n .photo-grid[data-count=\"5\"] {\r\n grid-template-columns: repeat(6, 1fr);\r\n grid-template-rows: auto auto;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item {\r\n aspect-ratio: 1;\r\n width: 100%;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(1) {\r\n grid-column: 1 / 4;\r\n grid-row: 1;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(2) {\r\n grid-column: 4 / 7;\r\n grid-row: 1;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(3) {\r\n grid-column: 1 / 3;\r\n grid-row: 2;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(4) {\r\n grid-column: 3 / 5;\r\n grid-row: 2;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(5) {\r\n grid-column: 5 / 7;\r\n grid-row: 2;\r\n }\r\n\r\n /* Round bottom corners for 5-image layout */\r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(3) {\r\n border-bottom-left-radius: 8px;\r\n overflow: hidden;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(5) {\r\n border-bottom-right-radius: 8px;\r\n overflow: hidden;\r\n }\r\n `]\r\n})\r\nexport class DsMobileInlinePhotoComponent {\r\n /**\r\n * Array of image URLs to display\r\n */\r\n @Input() images: string[] = [];\r\n\r\n /**\r\n * Author information (passed to lightbox)\r\n */\r\n @Input() author?: {\r\n name: string;\r\n role?: string;\r\n avatarSrc?: string;\r\n avatarInitials?: string;\r\n avatarType?: 'photo' | 'initials';\r\n timestamp?: string;\r\n };\r\n\r\n /**\r\n * Maximum number of images to show inline (default: 5)\r\n * Remaining images shown in lightbox only\r\n */\r\n @Input() maxVisible: number = 5;\r\n\r\n /**\r\n * Event emitted when lightbox is opened\r\n */\r\n photoClick = output<{ index: number; totalImages: number }>();\r\n\r\n constructor(private lightboxService: DsMobileLightboxService) {}\r\n\r\n /**\r\n * Get the first N images to display inline\r\n */\r\n get visibleImages(): string[] {\r\n return this.images.slice(0, this.maxVisible);\r\n }\r\n\r\n /**\r\n * Calculate how many images are hidden\r\n */\r\n get hiddenCount(): number {\r\n return Math.max(0, this.images.length - this.maxVisible);\r\n }\r\n\r\n /**\r\n * Open lightbox with all images, starting at the clicked index\r\n */\r\n openLightbox(index: number, event?: Event): void {\r\n // Stop event propagation to prevent triggering parent click handlers\r\n if (event) {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n\r\n // Emit event\r\n this.photoClick.emit({\r\n index,\r\n totalImages: this.images.length\r\n });\r\n\r\n // Convert image URLs to LightboxImage format\r\n const lightboxImages: LightboxImage[] = this.images.map((src, i) => ({\r\n type: 'image',\r\n src,\r\n alt: `Photo ${i + 1}`\r\n }));\r\n\r\n // Open lightbox with all images (not just visible ones)\r\n this.lightboxService.openImages({\r\n images: lightboxImages,\r\n initialIndex: index,\r\n author: this.author,\r\n enableZoom: true,\r\n showControls: true,\r\n enableSwipe: true\r\n });\r\n }\r\n}\r\n\r\n","import { Injectable, Type } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * Configuration options for modal presentation\r\n */\r\nexport interface ModalOptions<T = any> {\r\n /** The component to display in the modal */\r\n component: Type<T>;\r\n /** Props to pass to the component */\r\n componentProps?: Record<string, any>;\r\n /** CSS class(es) to apply to the modal */\r\n cssClass?: string | string[];\r\n /** Modal presentation style */\r\n presentationStyle?: 'fullscreen' | 'card' | 'sheet';\r\n /** Enable backdrop dismiss (tap outside to close) */\r\n backdropDismiss?: boolean;\r\n /** Show backdrop */\r\n showBackdrop?: boolean;\r\n /** Enable keyboard close (ESC key) */\r\n keyboardClose?: boolean;\r\n /** Enable swipe to close */\r\n swipeToClose?: boolean;\r\n /** Initial breakpoint (0-1) for sheet presentation */\r\n initialBreakpoint?: number;\r\n /** Available breakpoints for sheet presentation */\r\n breakpoints?: number[];\r\n /** Animation type */\r\n animated?: boolean;\r\n /** Mode (ios or md) */\r\n mode?: 'ios' | 'md';\r\n /** Whether to handle navigation back button */\r\n handleNavigationBack?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobileModalService\r\n * \r\n * Generic service for displaying any component as a modal.\r\n * Built on Ionic's modal system with customizable presentation styles.\r\n * \r\n * Features:\r\n * - Open any component as a modal\r\n * - Fullscreen, card, or sheet presentation styles\r\n * - Customizable backdrop and dismissal behavior\r\n * - Native gestures and animations\r\n * - Type-safe component props\r\n * \r\n * @example\r\n * ```typescript\r\n * import { MobilePostDetailPageComponent } from './post-detail.page';\r\n * \r\n * constructor(private modal: DsMobileModalService) {}\r\n * \r\n * async openPostModal() {\r\n * await this.modal.open({\r\n * component: MobilePostDetailPageComponent,\r\n * componentProps: {\r\n * postId: '123',\r\n * authorName: 'John Doe'\r\n * },\r\n * presentationStyle: 'card',\r\n * backdropDismiss: true\r\n * });\r\n * }\r\n * ```\r\n * \r\n * @example Sheet presentation with breakpoints\r\n * ```typescript\r\n * async openSheet() {\r\n * await this.modal.open({\r\n * component: CommentsComponent,\r\n * presentationStyle: 'sheet',\r\n * initialBreakpoint: 0.5,\r\n * breakpoints: [0, 0.5, 0.75, 1],\r\n * swipeToClose: true\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open a component as a modal\r\n * \r\n * @param options Configuration options for the modal\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.open({\r\n * component: MyComponent,\r\n * componentProps: { data: 'value' },\r\n * presentationStyle: 'fullscreen'\r\n * });\r\n * ```\r\n */\r\n async open<T = any>(options: ModalOptions<T>): Promise<HTMLIonModalElement> {\r\n console.log('[Modal] Opening modal with options:', options);\r\n \r\n const {\r\n component,\r\n componentProps,\r\n cssClass,\r\n presentationStyle = 'card',\r\n backdropDismiss = true,\r\n showBackdrop = true,\r\n keyboardClose = true,\r\n swipeToClose,\r\n initialBreakpoint,\r\n breakpoints,\r\n animated = true,\r\n mode = 'ios',\r\n handleNavigationBack = true\r\n } = options;\r\n\r\n // Build modal configuration\r\n const modalConfig: any = {\r\n component,\r\n componentProps: componentProps || {},\r\n cssClass: this.buildCssClasses(cssClass, presentationStyle),\r\n mode,\r\n backdropDismiss,\r\n showBackdrop,\r\n animated,\r\n keyboardClose,\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n handle: presentationStyle === 'sheet', // Show handle for sheet presentation\r\n };\r\n\r\n // Add swipe to close for sheet presentation\r\n if (swipeToClose !== undefined) {\r\n modalConfig.canDismiss = swipeToClose;\r\n }\r\n\r\n // Add breakpoints for sheet presentation\r\n if (presentationStyle === 'sheet' && breakpoints) {\r\n modalConfig.breakpoints = breakpoints;\r\n if (initialBreakpoint !== undefined) {\r\n modalConfig.initialBreakpoint = initialBreakpoint;\r\n }\r\n }\r\n\r\n // Handle navigation back button\r\n if (handleNavigationBack) {\r\n modalConfig.canDismiss = async () => {\r\n // You can add custom logic here if needed\r\n return true;\r\n };\r\n }\r\n\r\n const modal = await this.modalController.create(modalConfig);\r\n\r\n console.log('[Modal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[Modal] Modal presented');\r\n\r\n return modal;\r\n }\r\n\r\n /**\r\n * Open a component as a fullscreen modal\r\n * \r\n * @param component Component to display\r\n * @param componentProps Props to pass to the component\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.openFullscreen(PostDetailPage, { postId: '123' });\r\n * ```\r\n */\r\n async openFullscreen<T = any>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>\r\n ): Promise<HTMLIonModalElement> {\r\n return this.open({\r\n component,\r\n componentProps,\r\n presentationStyle: 'fullscreen',\r\n backdropDismiss: false,\r\n showBackdrop: false\r\n });\r\n }\r\n\r\n /**\r\n * Open a component as a card modal\r\n * \r\n * @param component Component to display\r\n * @param componentProps Props to pass to the component\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.openCard(DetailComponent, { itemId: '456' });\r\n * ```\r\n */\r\n async openCard<T = any>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>\r\n ): Promise<HTMLIonModalElement> {\r\n return this.open({\r\n component,\r\n componentProps,\r\n presentationStyle: 'card',\r\n backdropDismiss: true,\r\n showBackdrop: true\r\n });\r\n }\r\n\r\n /**\r\n * Open a component as a bottom sheet\r\n * \r\n * @param component Component to display\r\n * @param componentProps Props to pass to the component\r\n * @param options Additional sheet options (breakpoints, etc.)\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.openSheet(\r\n * CommentsComponent,\r\n * { postId: '789' },\r\n * { initialBreakpoint: 0.5, breakpoints: [0, 0.5, 1] }\r\n * );\r\n * ```\r\n */\r\n async openSheet<T = any>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>,\r\n options?: {\r\n initialBreakpoint?: number;\r\n breakpoints?: number[];\r\n swipeToClose?: boolean;\r\n }\r\n ): Promise<HTMLIonModalElement> {\r\n return this.open({\r\n component,\r\n componentProps,\r\n presentationStyle: 'sheet',\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n swipeToClose: options?.swipeToClose ?? true,\r\n initialBreakpoint: options?.initialBreakpoint ?? 0.5,\r\n breakpoints: options?.breakpoints ?? [0, 0.5, 0.75, 1]\r\n });\r\n }\r\n\r\n /**\r\n * Close the currently open modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @param role Optional role (e.g., 'cancel', 'confirm')\r\n * @returns Promise that resolves when the modal is dismissed\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.dismiss({ saved: true }, 'confirm');\r\n * ```\r\n */\r\n async dismiss(data?: any, role?: string): Promise<boolean> {\r\n return this.modalController.dismiss(data, role);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n * \r\n * @example\r\n * ```typescript\r\n * const topModal = await this.modal.getTop();\r\n * if (topModal) {\r\n * await topModal.dismiss();\r\n * }\r\n * ```\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n\r\n /**\r\n * Get all currently open modals\r\n * \r\n * @returns Promise that resolves to an array of modal elements\r\n */\r\n async getAll(): Promise<HTMLIonModalElement[]> {\r\n const modals: HTMLIonModalElement[] = [];\r\n let modal = await this.modalController.getTop();\r\n \r\n while (modal) {\r\n modals.push(modal);\r\n // Get the next modal in the stack\r\n await modal.dismiss();\r\n modal = await this.modalController.getTop();\r\n }\r\n \r\n return modals;\r\n }\r\n\r\n /**\r\n * Build CSS classes for the modal\r\n */\r\n private buildCssClasses(\r\n customClass?: string | string[],\r\n presentationStyle?: string\r\n ): string[] {\r\n const classes: string[] = ['ds-mobile-modal'];\r\n \r\n if (presentationStyle) {\r\n classes.push(`ds-modal-${presentationStyle}`);\r\n }\r\n \r\n if (customClass) {\r\n if (Array.isArray(customClass)) {\r\n classes.push(...customClass);\r\n } else {\r\n classes.push(customClass);\r\n }\r\n }\r\n \r\n return classes;\r\n }\r\n}\r\n\r\n","/**\r\n * Mobile Modal Module\r\n * \r\n * Generic service for opening any component as a modal\r\n */\r\n\r\nexport * from './ds-mobile-modal.service';\r\n\r\n","import { Component, signal, computed, CUSTOM_ELEMENTS_SCHEMA, Input, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { IonContent, ModalController } from '@ionic/angular/standalone';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { PostContentComponent, PostTextComponent, PostMediaComponent, PostActionsComponent, ActionLikeComponent, ActionCommentComponent } from '../interactive-list-item-post';\r\nimport { DsMobileCommentComponent } from '../comment/ds-mobile-comment';\r\nimport { DsMobileLightboxService, LightboxAuthor } from '../lightbox';\r\nimport { DsMobileBottomSheetService, DsMobileCommentActionsBottomSheetComponent, CommentActionResult } from '../bottom-sheet';\r\n\r\n/**\r\n * Post data interface for the modal\r\n *\r\n * Represents a post with its content, author info, and comments.\r\n * Use this interface to map your API response data to the component.\r\n *\r\n * @example\r\n * ```typescript\r\n * const postData: PostDetailData = {\r\n * postId: '123',\r\n * authorName: 'John Doe',\r\n * authorRole: 'Tenant',\r\n * timestamp: '2h ago',\r\n * avatarInitials: 'JD',\r\n * content: 'Post content here...',\r\n * likeCount: 42,\r\n * commentCount: 12,\r\n * comments: [...]\r\n * };\r\n * ```\r\n */\r\nexport interface PostDetailData {\r\n /** Unique post identifier */\r\n postId: string;\r\n /** Post author name */\r\n authorName: string;\r\n /** Author role (e.g., 'Tenant', 'Manager') */\r\n authorRole: string;\r\n /** Post timestamp (e.g., '2h ago', 'Yesterday') */\r\n timestamp: string;\r\n /** Author avatar initials (1-2 letters) */\r\n avatarInitials?: string;\r\n /** Avatar display type */\r\n avatarType?: 'photo' | 'initials';\r\n /** Author avatar image URL */\r\n avatarSrc?: string;\r\n /** Post text content */\r\n content: string;\r\n /** Optional post image URL */\r\n imageSrc?: string;\r\n /** Image alt text */\r\n imageAlt?: string;\r\n /** Whether the current user has liked this post */\r\n isLiked?: boolean;\r\n /** Number of likes */\r\n likeCount?: number;\r\n /** Number of comments */\r\n commentCount?: number;\r\n /** Array of comments */\r\n comments?: CommentData[];\r\n /** Auto-focus comment input when modal opens */\r\n focusComment?: boolean;\r\n}\r\n\r\n/**\r\n * Comment data interface\r\n *\r\n * Represents a single comment on a post.\r\n *\r\n * @example\r\n * ```typescript\r\n * const comment: CommentData = {\r\n * authorName: 'Jane Smith',\r\n * authorRole: 'Tenant',\r\n * timestamp: '1h ago',\r\n * avatarInitials: 'JS',\r\n * content: 'Great post!',\r\n * isLiked: false,\r\n * likeCount: 5,\r\n * isOwnComment: false\r\n * };\r\n * ```\r\n */\r\nexport interface CommentData {\r\n /** Unique comment identifier */\r\n id?: string;\r\n /** Comment author name */\r\n authorName: string;\r\n /** Author role */\r\n authorRole: string;\r\n /** Comment timestamp */\r\n timestamp: string;\r\n /** Author avatar initials */\r\n avatarInitials: string;\r\n /** Comment text content */\r\n content: string;\r\n /** Whether the current user has liked this comment */\r\n isLiked?: boolean;\r\n /** Number of likes on this comment */\r\n likeCount?: number;\r\n /** Whether this comment belongs to the current user */\r\n isOwnComment?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobilePostDetailModalComponent\r\n *\r\n * Modal wrapper for displaying post details with comments.\r\n * Follows the same pattern as the lightbox modal for consistent behavior.\r\n *\r\n * Features:\r\n * - Full post content display\r\n * - Comments section\r\n * - Image lightbox integration\r\n * - Native modal controls (close, swipe down)\r\n * - Safe area support\r\n *\r\n * This component is typically not used directly - use DsMobilePostDetailModalService instead.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private postModal: DsMobilePostDetailModalService) {}\r\n *\r\n * openPost() {\r\n * this.postModal.open({\r\n * postId: '123',\r\n * authorName: 'John Doe',\r\n * content: 'Post content...'\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-post-detail-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsIconComponent,\r\n DsAvatarComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCommentComponent,\r\n ],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"post-modal-content\">\r\n <div class=\"post-modal-wrapper\">\r\n <!-- Header with post author info -->\r\n <div class=\"post-modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Post author info -->\r\n <div class=\"post-author-info\">\r\n <ds-avatar [initials]=\"post().avatarInitials || ''\" [type]=\"post().avatarType || 'initials'\" [src]=\"post().avatarSrc || ''\" size=\"md\" />\r\n <div class=\"author-details\">\r\n <div class=\"author-name\">{{ post().authorName }}</div>\r\n <div class=\"author-meta\">\r\n <span>{{ post().authorRole }}</span>\r\n <span class=\"separator\">·</span>\r\n <span>{{ post().timestamp }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Close button -->\r\n <ds-icon-button icon=\"remixCloseLine\" variant=\"secondary\" size=\"lg\" (click)=\"close()\" class=\"close-button\" aria-label=\"Luk opslag\"> </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Post content -->\r\n <div class=\"post-detail-container\">\r\n @if (loading) {\r\n <!-- Loading State -->\r\n <div class=\"post-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading post...</p>\r\n </div>\r\n } @else if (error) {\r\n <!-- Error State -->\r\n <div class=\"post-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error loading post</h3>\r\n <p class=\"error-state-description\">{{ error }}</p>\r\n </div>\r\n } @else {\r\n <!-- Post Section -->\r\n <div class=\"post-section\">\r\n <div class=\"post-content-only\">\r\n <post-text>\r\n <div [innerHTML]=\"post().content\"></div>\r\n </post-text>\r\n @if (post().imageSrc) {\r\n <post-media>\r\n <img [src]=\"post().imageSrc\" [alt]=\"post().imageAlt || 'Post image'\" class=\"clickable-image\" (click)=\"openImageLightbox()\" />\r\n </post-media>\r\n }\r\n </div>\r\n\r\n <!-- Post actions -->\r\n <div class=\"post-actions\">\r\n <action-like [active]=\"post().isLiked || false\" [count]=\"post().likeCount || 0\" />\r\n <action-comment [count]=\"post().commentCount || 0\" (commentClick)=\"focusCommentInput()\" />\r\n </div>\r\n </div>\r\n\r\n <!-- Comments Section -->\r\n <div class=\"comments-section\">\r\n @if (post().comments && post().comments!.length > 0) {\r\n <h2 class=\"comments-header\">{{ post().comments!.length }} {{ post().comments!.length === 1 ? 'reply' : 'replies' }}</h2>\r\n\r\n <div class=\"comments-list\">\r\n @for (comment of post().comments!; track comment.id || comment.authorName + comment.timestamp) {\r\n <ds-mobile-comment\r\n [authorName]=\"comment.authorName\"\r\n [authorRole]=\"comment.authorRole\"\r\n [timestamp]=\"comment.timestamp\"\r\n [avatarInitials]=\"comment.avatarInitials\"\r\n [content]=\"comment.content\"\r\n [isLiked]=\"comment.isLiked || false\"\r\n [likeCount]=\"comment.likeCount || 0\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"comment.isOwnComment || false\"\r\n (likeToggled)=\"handleCommentLikeToggle(comment, $event)\"\r\n (replyClick)=\"handleReply(comment.authorName, comment.content)\"\r\n (editClick)=\"handleEditComment(comment)\"\r\n (longPress)=\"handleCommentLongPress(comment.authorName, comment.content, comment.isOwnComment || false)\" />\r\n }\r\n </div>\r\n } @else {\r\n <!-- Empty State -->\r\n <div class=\"comments-empty-state\">\r\n <img src=\"/Assets/Empty%20state-chat.png\" alt=\"Ingen kommentarer endnu\" class=\"empty-state-image\" />\r\n <h3 class=\"empty-state-title\">Ingen svar endnu</h3>\r\n <p class=\"empty-state-description\">Vær den første til at svare på dette opslag</p>\r\n </div>\r\n }\r\n\r\n <!-- Bottom spacer for fixed composer -->\r\n <div class=\"composer-spacer\"></div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n\r\n <!-- Fixed comment composer -->\r\n @if (!loading && !error) {\r\n <div class=\"comment-composer-fixed\">\r\n <div class=\"comment-composer\">\r\n <!-- Edit indicator -->\r\n @if (editingComment()) {\r\n <div class=\"edit-indicator\">\r\n <div class=\"edit-indicator-content\">\r\n <ds-icon name=\"remixEditLine\" size=\"16px\" />\r\n <span class=\"edit-text\">Redigerer kommentar</span>\r\n </div>\r\n <button class=\"cancel-edit\" (click)=\"cancelEdit()\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n } @else if (replyingTo()) {\r\n <!-- Reply indicator -->\r\n <div class=\"reply-indicator\">\r\n <div class=\"reply-indicator-content\">\r\n <ds-icon name=\"remixReplyLine\" size=\"16px\" />\r\n <span class=\"reply-to-text\">\r\n Svarer til <span class=\"reply-author\">{{ replyingTo()!.authorName }}</span>\r\n </span>\r\n </div>\r\n <button class=\"cancel-reply\" (click)=\"cancelReply()\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"composer-content\">\r\n <ds-avatar [initials]=\"currentUserInitials()\" [type]=\"'initials'\" size=\"md\" />\r\n <div class=\"composer-input-wrapper\">\r\n <!-- Mention menu -->\r\n @if (showMentionMenu() && filteredUsers().length > 0 && !editingComment()) {\r\n <div class=\"mention-menu\">\r\n @for (user of filteredUsers(); track user.name) {\r\n <button class=\"mention-menu-item\" (click)=\"selectMention(user.name)\">\r\n <ds-avatar [initials]=\"user.initials\" [type]=\"'initials'\" size=\"sm\" />\r\n <div class=\"mention-user-info\">\r\n <span class=\"mention-user-name\">{{ user.name }}</span>\r\n <span class=\"mention-user-role\">{{ user.role }}</span>\r\n </div>\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <textarea\r\n #commentInput\r\n class=\"composer-input\"\r\n [placeholder]=\"editingComment() ? 'Rediger din kommentar...' : replyingTo() ? 'Tilføj et svar...' : 'Tilføj et svar...'\"\r\n [ngModel]=\"commentText()\"\r\n (ngModelChange)=\"commentText.set($event)\"\r\n (input)=\"handleInput($event)\"\r\n (focus)=\"showKeyboard()\"\r\n (click)=\"showKeyboard()\"\r\n rows=\"1\"></textarea>\r\n </div>\r\n @if (commentText().trim().length > 0) {\r\n <ds-icon-button icon=\"remixCheckLine\" variant=\"primary\" size=\"sm\" (clicked)=\"submitComment()\" aria-label=\"Send kommentar\" class=\"send-button-fixed\"> </ds-icon-button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n `,\r\n styles: [\r\n `\r\n :host {\r\n display: block;\r\n position: relative;\r\n height: 100%;\r\n width: 100%;\r\n }\r\n\r\n .post-modal-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .post-modal-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n min-height: 100dvh; /* Use dynamic viewport height for proper iOS safe area handling */\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .post-modal-header {\r\n position: sticky;\r\n top: 0;\r\n z-index: 10;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 16px;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 72px;\r\n /* No padding needed - StatusBar.setOverlaysWebView(false) handles all spacing */\r\n }\r\n\r\n .post-author-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .author-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n /* Author name and meta styles imported from mobile-common.css */\r\n\r\n .author-meta .separator {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n\r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n\r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .post-detail-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n padding: 16px 0 20px 0;\r\n flex: 1;\r\n }\r\n\r\n .post-section {\r\n width: 100%;\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 0 16px 0;\r\n }\r\n\r\n .post-content-only {\r\n font-size: var(--font-size-sm);\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin-bottom: 16px;\r\n padding: 0 20px;\r\n }\r\n\r\n .post-content-only post-media {\r\n margin-top: 16px;\r\n }\r\n\r\n .post-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n padding: 0 20px;\r\n }\r\n\r\n .clickable-image {\r\n cursor: pointer;\r\n transition: transform 0.2s ease, opacity 0.2s ease;\r\n border-radius: 8px;\r\n display: block;\r\n width: 100%;\r\n aspect-ratio: 16/9;\r\n object-fit: cover;\r\n }\r\n\r\n .clickable-image:active {\r\n transform: scale(0.98);\r\n opacity: 0.9;\r\n }\r\n\r\n .comments-section {\r\n display: flex;\r\n flex-direction: column;\r\n margin-left: 0;\r\n margin-right: 0;\r\n padding: 0 20px;\r\n padding-bottom: 0;\r\n }\r\n\r\n .comments-header {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0 0 16px 0;\r\n padding-left: 0;\r\n padding-right: 0;\r\n }\r\n\r\n .comments-list {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n /* Empty State */\r\n .comments-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n\r\n .empty-state-image {\r\n width: 96px;\r\n height: 96px;\r\n margin-bottom: 24px;\r\n }\r\n\r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0 0 8px 0;\r\n }\r\n\r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n\r\n .composer-spacer {\r\n /* Match full composer height + safe area:\r\n - Composer height: ~81px + safe area\r\n - Top offset is handled by margin-top on modal content, not needed here */\r\n height: calc(81px + env(safe-area-inset-bottom, 0px));\r\n }\r\n\r\n .bottom-spacer {\r\n height: 0px;\r\n }\r\n\r\n /* Fixed Comment Composer Container */\r\n .comment-composer-fixed {\r\n position: fixed;\r\n bottom: 0; /* Align with bottom of viewport - modal content has margin-top for top offset */\r\n left: 0;\r\n right: 0;\r\n z-index: 1000;\r\n pointer-events: none;\r\n /* Slide up with keyboard on native apps */\r\n transform: translateY(calc(-1 * var(--keyboard-height, 0px)));\r\n transition: transform 0.3s ease-out;\r\n /* Ensure it's within the modal viewport */\r\n max-width: 100vw;\r\n }\r\n\r\n /* Comment Composer */\r\n .comment-composer {\r\n pointer-events: auto;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-top: 1px solid var(--border-color-default);\r\n padding: 12px 16px;\r\n /* Use dynamic viewport height safe area - matches tabs fix */\r\n /* For web browsers: 12px default; for native iOS: env(safe-area-inset-bottom) */\r\n padding-bottom: max(12px, env(safe-area-inset-bottom, 0px));\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n /* White box shadow to cover content gap between keyboard and composer */\r\n box-shadow: 100px 150px 0 150px var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n /* Edit indicator */\r\n .edit-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-brand-subtle, #f0edfe);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n\r\n .edit-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: var(--color-brand-base, #6b5ff5);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .edit-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-brand-base, #6b5ff5);\r\n }\r\n\r\n .cancel-edit {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-brand-base, #6b5ff5);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .cancel-edit:active {\r\n background: var(--color-brand-subtle, #e0dbfe);\r\n }\r\n\r\n /* Reply indicator */\r\n .reply-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n\r\n .reply-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n color: var(--color-text-secondary, #737373);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .reply-to-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .reply-author {\r\n color: var(--color-brand-base, #6b5ff5);\r\n font-weight: 600;\r\n }\r\n\r\n .cancel-reply {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-text-secondary, #737373);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .cancel-reply:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n\r\n @keyframes slideDown {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .composer-content {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n width: 100%;\r\n position: relative;\r\n }\r\n\r\n .composer-content ds-avatar {\r\n position: relative;\r\n top: 6px;\r\n }\r\n\r\n .composer-input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 8px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 24px;\r\n padding: 12px 16px;\r\n padding-right: 48px; /* Extra padding for fixed send button */\r\n min-height: 44px;\r\n position: relative;\r\n }\r\n\r\n /* Mention menu */\r\n .mention-menu {\r\n position: absolute;\r\n bottom: 100%;\r\n left: 0;\r\n right: 0;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-radius: 12px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n margin-bottom: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n z-index: 10;\r\n animation: slideUp 0.2s ease-out;\r\n }\r\n\r\n @keyframes slideUp {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .mention-menu-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 12px;\r\n border: none;\r\n background: none;\r\n width: 100%;\r\n text-align: left;\r\n cursor: pointer;\r\n transition: background 0.2s ease;\r\n border-bottom: 1px solid var(--border-color-default);\r\n }\r\n\r\n .mention-menu-item:last-child {\r\n border-bottom: none;\r\n }\r\n\r\n .mention-menu-item:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n\r\n .mention-user-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .mention-user-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n\r\n .mention-user-role {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n }\r\n\r\n .composer-input {\r\n flex: 1;\r\n border: none;\r\n background: transparent;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n outline: none;\r\n resize: none;\r\n min-height: 20px;\r\n max-height: 120px;\r\n overflow-y: auto;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n\r\n .composer-input::placeholder {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n font-size: var(--font-size-sm);\r\n }\r\n\r\n /* Style the send button (ds-icon-button) - positioned in top right corner */\r\n .send-button-fixed {\r\n position: absolute;\r\n top: 6px;\r\n right: 6px;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n animation: slideInFromRight 0.2s ease-out;\r\n }\r\n\r\n .send-button-fixed::ng-deep button {\r\n width: 32px !important;\r\n height: 32px !important;\r\n min-width: 32px !important;\r\n min-height: 32px !important;\r\n padding: 0 !important;\r\n border-radius: 50% !important;\r\n }\r\n\r\n /* Keep old style for reference but won't be used */\r\n .composer-input-wrapper ds-icon-button {\r\n flex-shrink: 0;\r\n animation: slideInFromRight 0.2s ease-out;\r\n }\r\n\r\n .composer-input-wrapper ds-icon-button::ng-deep button {\r\n width: 32px !important;\r\n height: 32px !important;\r\n min-width: 32px !important;\r\n min-height: 32px !important;\r\n padding: 0 !important;\r\n border-radius: 50% !important;\r\n }\r\n\r\n /* Slide in animation from right */\r\n @keyframes slideInFromRight {\r\n from {\r\n opacity: 0;\r\n transform: translateX(20px) scale(0.8);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateX(0) scale(1);\r\n }\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .post-detail-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n\r\n /* Loading State */\r\n .post-loading-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n\r\n .loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 3px solid var(--color-background-neutral-secondary, #f0f0f0);\r\n border-top-color: var(--color-primary-base, #2563eb);\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n\r\n @keyframes spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n\r\n .loading-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin-top: 16px;\r\n }\r\n\r\n /* Error State */\r\n .post-error-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n gap: 16px;\r\n }\r\n\r\n .error-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n\r\n .error-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class DsMobilePostDetailModalComponent implements AfterViewInit, OnDestroy {\r\n // Post data passed from service\r\n @Input() postData!: PostDetailData;\r\n\r\n // Current user info for comment composer\r\n @Input() currentUserName: string = '';\r\n @Input() currentUserInitialsInput: string = '';\r\n\r\n // Callback for submitting a new comment\r\n @Input() onSubmitComment?: (payload: { postId: string; text: string }) => void;\r\n\r\n // Callback for liking/unliking a comment\r\n @Input() onToggleCommentLike?: (payload: { commentId: string; active: boolean }) => void;\r\n\r\n // Callback for editing a comment\r\n @Input() onEditComment?: (payload: { commentId: string; newText: string }) => void;\r\n\r\n // Callback for deleting a comment\r\n @Input() onDeleteComment?: (payload: { commentId: string }) => void;\r\n\r\n /**\r\n * Loading state - when true, shows loading indicator\r\n * Set this to true while fetching post data from your API\r\n */\r\n @Input() loading: boolean = false;\r\n\r\n /**\r\n * Error state - when set, shows error message\r\n * Set this to an error message string if API call fails\r\n */\r\n @Input() error?: string;\r\n\r\n // ViewChild for comment input\r\n @ViewChild('commentInput') commentInput?: ElementRef<HTMLTextAreaElement>;\r\n\r\n // Signal for reactive post data\r\n post = signal<PostDetailData>({\r\n postId: '',\r\n authorName: '',\r\n authorRole: '',\r\n timestamp: '',\r\n content: '',\r\n comments: [],\r\n });\r\n\r\n // Comment composer state\r\n commentText = signal('');\r\n currentUserInitials = signal('');\r\n replyingTo = signal<{ authorName: string; content: string } | null>(null);\r\n editingComment = signal<{ id?: string; authorName: string; originalContent: string; timestamp: string } | null>(null);\r\n\r\n // Mention menu state\r\n showMentionMenu = signal(false);\r\n mentionQuery = signal('');\r\n\r\n // Get available users to mention (post author + commenters)\r\n availableUsers = computed(() => {\r\n const post = this.post();\r\n const users: Array<{ name: string; initials: string; role: string }> = [];\r\n\r\n // Add post author\r\n users.push({\r\n name: post.authorName,\r\n initials:\r\n post.avatarInitials ||\r\n post.authorName\r\n .split(' ')\r\n .map((n) => n[0])\r\n .join(''),\r\n role: post.authorRole,\r\n });\r\n\r\n // Add unique commenters\r\n const commenterNames = new Set<string>();\r\n post.comments?.forEach((comment) => {\r\n if (!commenterNames.has(comment.authorName)) {\r\n commenterNames.add(comment.authorName);\r\n users.push({\r\n name: comment.authorName,\r\n initials: comment.avatarInitials,\r\n role: comment.authorRole,\r\n });\r\n }\r\n });\r\n\r\n return users;\r\n });\r\n\r\n // Filtered users based on mention query\r\n filteredUsers = computed(() => {\r\n const query = this.mentionQuery().toLowerCase();\r\n if (!query) return this.availableUsers();\r\n return this.availableUsers().filter((user) => user.name.toLowerCase().includes(query));\r\n });\r\n\r\n constructor(private modalController: ModalController, private lightbox: DsMobileLightboxService, private bottomSheet: DsMobileBottomSheetService) {}\r\n\r\n ngOnInit(): void {\r\n // Initialize post data from input\r\n if (this.postData) {\r\n this.post.set(this.postData);\r\n }\r\n\r\n // Set current user initials\r\n if (this.currentUserInitialsInput) {\r\n this.currentUserInitials.set(this.currentUserInitialsInput);\r\n } else if (this.currentUserName) {\r\n // fallback: derive from name\r\n const initials = this.currentUserName\r\n .trim()\r\n .split(/\\s+/)\r\n .map((p) => p[0])\r\n .join('')\r\n .substring(0, 2)\r\n .toUpperCase();\r\n this.currentUserInitials.set(initials);\r\n }\r\n\r\n // Set up keyboard listeners to update CSS variable for composer positioning\r\n this.setupKeyboardListeners();\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n // Auto-focus comment input if requested\r\n if (this.postData?.focusComment) {\r\n // Small delay to ensure modal animation is complete\r\n setTimeout(() => {\r\n this.commentInput?.nativeElement.focus();\r\n // Show keyboard on mobile\r\n this.showKeyboard();\r\n }, 300);\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n // Clean up keyboard listeners when modal is destroyed\r\n this.cleanupKeyboardListeners();\r\n }\r\n\r\n /**\r\n * Set up keyboard event listeners to adjust composer position\r\n * The CSS uses --keyboard-height variable to translate the composer up\r\n */\r\n private setupKeyboardListeners(): void {\r\n Keyboard.addListener('keyboardWillShow', (info) => {\r\n document.documentElement.style.setProperty('--keyboard-height', `${info.keyboardHeight}px`);\r\n }).catch((e) => console.log('Keyboard listeners not available:', e));\r\n\r\n Keyboard.addListener('keyboardWillHide', () => {\r\n document.documentElement.style.setProperty('--keyboard-height', '0px');\r\n }).catch((e) => console.log('Keyboard listeners not available:', e));\r\n }\r\n\r\n /**\r\n * Clean up keyboard event listeners\r\n */\r\n private cleanupKeyboardListeners(): void {\r\n Keyboard.removeAllListeners().catch((e) => console.log('Keyboard cleanup not available:', e));\r\n }\r\n\r\n /**\r\n * Show the keyboard when user interacts with input\r\n */\r\n showKeyboard(): void {\r\n Keyboard.show().catch((e) => console.log('Keyboard.show() not available'));\r\n }\r\n\r\n /**\r\n * Focus the comment input when comment icon is tapped\r\n */\r\n focusCommentInput(): void {\r\n // Focus the input\r\n this.commentInput?.nativeElement.focus();\r\n // Show keyboard on mobile\r\n this.showKeyboard();\r\n }\r\n\r\n /**\r\n * Handle input changes and detect @ mentions\r\n */\r\n handleInput(event: Event): void {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n const text = textarea.value;\r\n const cursorPosition = textarea.selectionStart || 0;\r\n\r\n // Auto-resize textarea\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n\r\n // Find the last @ before cursor\r\n const textBeforeCursor = text.substring(0, cursorPosition);\r\n const lastAtIndex = textBeforeCursor.lastIndexOf('@');\r\n\r\n if (lastAtIndex !== -1) {\r\n // Check if there's a space after @\r\n const textAfterAt = textBeforeCursor.substring(lastAtIndex + 1);\r\n const hasSpace = textAfterAt.includes(' ');\r\n\r\n if (!hasSpace) {\r\n // Show mention menu\r\n this.showMentionMenu.set(true);\r\n this.mentionQuery.set(textAfterAt);\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * Select a user from mention menu - show as reply indicator instead of inline mention\r\n */\r\n selectMention(userName: string): void {\r\n // Set as reply (similar to clicking Reply on a comment)\r\n this.replyingTo.set({ authorName: userName, content: '' });\r\n\r\n // Clear the @ from the input\r\n const currentText = this.commentText();\r\n const textWithoutMention = currentText.substring(0, currentText.lastIndexOf('@'));\r\n this.commentText.set(textWithoutMention);\r\n\r\n // Hide mention menu\r\n this.showMentionMenu.set(false);\r\n\r\n // Focus back on input\r\n setTimeout(() => {\r\n this.commentInput?.nativeElement.focus();\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Handle reply to a comment\r\n */\r\n handleReply(authorName: string, content: string): void {\r\n this.replyingTo.set({ authorName, content });\r\n // Focus the input and show keyboard\r\n setTimeout(() => {\r\n this.commentInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Cancel reply\r\n */\r\n cancelReply(): void {\r\n this.replyingTo.set(null);\r\n }\r\n\r\n /**\r\n * Cancel edit\r\n */\r\n cancelEdit(): void {\r\n this.editingComment.set(null);\r\n this.commentText.set('');\r\n }\r\n\r\n /**\r\n * Handle edit comment\r\n */\r\n handleEditComment(comment: CommentData): void {\r\n // Clear reply state if active\r\n this.replyingTo.set(null);\r\n\r\n // Remove @mention from the content if it exists\r\n let contentToEdit = comment.content;\r\n const mentionMatch = contentToEdit.match(/^@([A-Za-z]+(?:\\s+[A-Za-z]+)?)\\s+/);\r\n if (mentionMatch) {\r\n contentToEdit = contentToEdit.substring(mentionMatch[0].length);\r\n }\r\n\r\n // Set edit state\r\n this.editingComment.set({\r\n id: comment.id,\r\n authorName: comment.authorName,\r\n originalContent: comment.content,\r\n timestamp: comment.timestamp,\r\n });\r\n\r\n // Populate the input with existing content\r\n this.commentText.set(contentToEdit);\r\n\r\n // Focus the input, show keyboard, and auto-resize\r\n setTimeout(() => {\r\n if (this.commentInput?.nativeElement) {\r\n const textarea = this.commentInput.nativeElement;\r\n textarea.focus();\r\n\r\n // Auto-resize textarea to fit content\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n\r\n this.showKeyboard();\r\n }\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Handle comment like/unlike toggle\r\n * @param comment The comment being liked/unliked\r\n * @param ev Event data with active state and new count\r\n */\r\n handleCommentLikeToggle(comment: CommentData, ev: { active: boolean; count: number }): void {\r\n // Update local state immediately for responsiveness\r\n const currentPost = this.post();\r\n const updatedComments = currentPost.comments?.map((c) => (c.id === comment.id ? { ...c, isLiked: ev.active, likeCount: ev.count } : c));\r\n\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedComments,\r\n });\r\n\r\n // Call the callback if provided\r\n if (this.onToggleCommentLike) {\r\n this.onToggleCommentLike({\r\n commentId: comment.id!,\r\n active: ev.active,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n\r\n /**\r\n * Submit a comment\r\n */\r\n submitComment(): void {\r\n const text = this.commentText().trim();\r\n if (!text) return;\r\n\r\n const currentPost = this.post();\r\n const postId = currentPost.postId;\r\n\r\n // Create new comment\r\n const finalText = this.replyingTo() ? `@${this.replyingTo()!.authorName} ${text}` : text;\r\n\r\n // Check if we're editing an existing comment\r\n if (this.editingComment()) {\r\n console.log('[PostDetailModal] Updating comment:', text);\r\n\r\n const editing = this.editingComment()!;\r\n\r\n const updatedComments = currentPost.comments?.map((comment) => {\r\n if (comment.id && editing.id && comment.id === editing.id) {\r\n return {\r\n ...comment,\r\n content: text,\r\n timestamp: 'Just now (edited)',\r\n };\r\n }\r\n return comment;\r\n });\r\n\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedComments,\r\n });\r\n\r\n // Call the edit callback\r\n if (this.onEditComment && editing.id) {\r\n this.onEditComment({\r\n commentId: editing.id,\r\n newText: finalText, // or finalText if you want to include @mention\r\n });\r\n }\r\n\r\n this.editingComment.set(null);\r\n } else {\r\n console.log('[PostDetailModal] Submitting comment:', finalText);\r\n console.log('[PostDetailModal] onSubmitComment =', this.onSubmitComment);\r\n\r\n const newComment: CommentData = {\r\n authorName: this.currentUserName || 'Dig',\r\n authorRole: 'Dig',\r\n timestamp: 'Just now',\r\n avatarInitials: this.currentUserInitials(),\r\n content: finalText,\r\n isLiked: false,\r\n likeCount: 0,\r\n isOwnComment: true,\r\n };\r\n\r\n // Add comment to the list\r\n const updatedComments = [...(currentPost.comments || []), newComment];\r\n\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedComments,\r\n commentCount: updatedComments.length,\r\n });\r\n\r\n // Clear reply state\r\n this.replyingTo.set(null);\r\n }\r\n\r\n // Clear the input\r\n this.commentText.set('');\r\n this.showMentionMenu.set(false);\r\n\r\n if (this.commentInput?.nativeElement) {\r\n // Reset textarea height to initial state\r\n this.commentInput.nativeElement.style.height = 'auto';\r\n // Blur the input to hide the keyboard\r\n this.commentInput?.nativeElement.blur();\r\n }\r\n\r\n // Hide keyboard explicitly\r\n Keyboard.hide().catch(() => {});\r\n\r\n // In a real app, you would also send this to your backend\r\n // this.commentService.addComment(currentPost.postId, text);\r\n if (this.onSubmitComment) {\r\n this.onSubmitComment({ postId, text: finalText });\r\n }\r\n }\r\n\r\n /**\r\n * Open image in lightbox\r\n */\r\n openImageLightbox(): void {\r\n const postData = this.post();\r\n\r\n if (!postData.imageSrc) return;\r\n\r\n const authorMeta: LightboxAuthor = {\r\n name: postData.authorName,\r\n role: postData.authorRole,\r\n avatarInitials: postData.avatarInitials || '',\r\n avatarType: postData.avatarType || 'initials',\r\n avatarSrc: postData.avatarSrc || '',\r\n timestamp: postData.timestamp,\r\n };\r\n\r\n this.lightbox.open({\r\n images: [\r\n {\r\n type: 'image',\r\n src: postData.imageSrc,\r\n alt: postData.imageAlt || 'Post image',\r\n title: postData.imageAlt || '',\r\n description: postData.content,\r\n isLiked: postData.isLiked || false,\r\n likeCount: postData.likeCount || 0,\r\n commentCount: postData.commentCount || 0,\r\n },\r\n ],\r\n author: authorMeta,\r\n enableZoom: true,\r\n showControls: false,\r\n showInfo: true,\r\n });\r\n }\r\n\r\n /**\r\n * Handle long press on a comment to show action sheet\r\n */\r\n async handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void> {\r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobileCommentActionsBottomSheetComponent,\r\n componentProps: {\r\n isOwnContent: isOwnComment,\r\n },\r\n breakpoints: [0, 1],\r\n initialBreakpoint: 1,\r\n handle: true,\r\n backdropDismiss: true,\r\n cssClass: 'auto-height',\r\n });\r\n\r\n const result = await sheet.onWillDismiss();\r\n\r\n if (result.role === 'select' && result.data) {\r\n const action = (result.data as CommentActionResult).action;\r\n const currentPost = this.post();\r\n\r\n switch (action) {\r\n case 'like':\r\n console.log('Like comment by', authorName);\r\n let toggledCommentId: string | null = null;\r\n let newActive = false;\r\n // Update the comment like state locally\r\n const updatedComments = currentPost.comments?.map((comment) => {\r\n if (comment.authorName === authorName && comment.content === content) {\r\n newActive = !comment.isLiked;\r\n toggledCommentId = comment.id!;\r\n\r\n return {\r\n ...comment,\r\n isLiked: newActive,\r\n likeCount: newActive ? (comment.likeCount || 0) + 1 : Math.max(0, (comment.likeCount || 0) - 1),\r\n };\r\n }\r\n return comment;\r\n });\r\n\r\n this.post.set({ ...currentPost, comments: updatedComments });\r\n\r\n // Call the like callback\r\n if (toggledCommentId && this.onToggleCommentLike) {\r\n this.onToggleCommentLike({\r\n commentId: toggledCommentId,\r\n active: newActive,\r\n });\r\n }\r\n break;\r\n case 'reply':\r\n console.log('Reply to comment by', authorName);\r\n this.handleReply(authorName, content);\r\n break;\r\n case 'edit':\r\n console.log('Edit comment by', authorName);\r\n // Find the full comment data to get timestamp\r\n const commentToEdit = currentPost.comments?.find((comment) => comment.authorName === authorName && comment.content === content);\r\n if (commentToEdit) {\r\n this.handleEditComment(commentToEdit);\r\n }\r\n break;\r\n case 'delete':\r\n console.log('Delete comment by', authorName);\r\n // Show confirmation before deleting\r\n if (confirm('Are you sure you want to delete this comment?')) {\r\n const commentToDelete = currentPost.comments?.find((comment) => comment.authorName === authorName && comment.content === content);\r\n const updatedCommentsAfterDelete = currentPost.comments?.filter((comment) => !(comment.authorName === authorName && comment.content === content));\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedCommentsAfterDelete,\r\n commentCount: updatedCommentsAfterDelete?.length || 0,\r\n });\r\n\r\n // Call the delete callback\r\n if (commentToDelete?.id && this.onDeleteComment) {\r\n this.onDeleteComment({ commentId: commentToDelete.id });\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobilePostDetailModalComponent, PostDetailData } from './ds-mobile-post-detail-modal';\r\n\r\n/**\r\n * DsMobilePostDetailModalService\r\n *\r\n * Service for displaying post details in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * Follows the same pattern as DsMobileLightboxService for consistent behavior.\r\n *\r\n * Features:\r\n * - Full post content display\r\n * - Comments section\r\n * - Like/comment actions\r\n * - Image lightbox integration\r\n * - Native modal animations\r\n * - Safe area support\r\n *\r\n * @example\r\n * ```typescript\r\n * constructor(private postModal: DsMobilePostDetailModalService) {}\r\n *\r\n * async openPost() {\r\n * await this.postModal.open({\r\n * postId: '123',\r\n * authorName: 'John Doe',\r\n * authorRole: 'Tenant',\r\n * timestamp: '2h ago',\r\n * avatarInitials: 'JD',\r\n * content: 'Just moved into my new apartment!',\r\n * isLiked: false,\r\n * likeCount: 42,\r\n * commentCount: 12,\r\n * comments: [\r\n * {\r\n * authorName: 'Jane Smith',\r\n * authorRole: 'Tenant',\r\n * timestamp: '1h ago',\r\n * avatarInitials: 'JS',\r\n * content: 'Welcome to the community!'\r\n * }\r\n * ]\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class DsMobilePostDetailModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the post detail modal\r\n *\r\n * @param postData Post data to display\r\n * @param options Optional loading and error states\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(\r\n postData: PostDetailData,\r\n options?: {\r\n loading?: boolean;\r\n error?: string;\r\n onSubmitComment?: (payload: { postId: string; text: string }) => void;\r\n onToggleCommentLike?: (payload: { commentId: string; active: boolean }) => void;\r\n onEditComment?: (payload: { commentId: string; newText: string }) => void;\r\n onDeleteComment?: (payload: { commentId: string }) => void;\r\n currentUserName?: string;\r\n currentUserInitials?: string;\r\n }\r\n ): Promise<void> {\r\n console.log('[PostDetailModal] Opening with data:', postData);\r\n console.log('[PostDetailModal] options.onSubmitComment =', options?.onSubmitComment);\r\n\r\n const modal = await this.modalController.create({\r\n component: DsMobilePostDetailModalComponent,\r\n componentProps: {\r\n postData: postData,\r\n loading: options?.loading ?? false,\r\n error: options?.error,\r\n onSubmitComment: options?.onSubmitComment,\r\n onToggleCommentLike: options?.onToggleCommentLike,\r\n currentUserName: options?.currentUserName ?? '',\r\n currentUserInitialsInput: options?.currentUserInitials ?? '',\r\n },\r\n cssClass: 'ds-post-detail-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n // Control the presenting element animation\r\n enterAnimation: undefined, // Use default\r\n leaveAnimation: undefined, // Use default\r\n });\r\n\r\n console.log('[PostDetailModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[PostDetailModal] Modal presented');\r\n }\r\n\r\n /**\r\n * Close the currently open post detail modal\r\n *\r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n *\r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n","/**\r\n * Mobile Post Detail Modal Module\r\n * \r\n * Service and component for displaying posts in a modal\r\n */\r\n\r\nexport * from './ds-mobile-post-detail-modal';\r\nexport * from './ds-mobile-post-detail-modal.service';\r\n\r\n","import {\r\n Component,\r\n signal,\r\n Input,\r\n ViewChild,\r\n ElementRef,\r\n OnInit,\r\n AfterViewInit,\r\n OnDestroy,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonContent,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileMessageComposerComponent } from '../message-composer';\r\nimport { DsMobileMessageBubbleComponent, ChatAttachment } from '../message-bubble';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge';\r\n\r\n/**\r\n * Chat message data interface\r\n */\r\nexport interface ChatMessage {\r\n id: string;\r\n content: string;\r\n senderId: string;\r\n senderName: string;\r\n senderRole?: string;\r\n timestamp: string;\r\n avatarInitials?: string;\r\n avatarType?: 'initials' | 'photo' | 'icon';\r\n avatarSrc?: string;\r\n isOwnMessage: boolean;\r\n attachments?: ChatAttachment[];\r\n}\r\n\r\n/**\r\n * Chat participant interface\r\n */\r\nexport interface ChatParticipant {\r\n id: string;\r\n name: string;\r\n role?: string;\r\n avatarInitials?: string;\r\n avatarType?: 'initials' | 'photo' | 'icon';\r\n avatarSrc?: string;\r\n}\r\n\r\n/**\r\n * Chat modal data interface\r\n * \r\n * Represents the data needed to display a chat conversation.\r\n * \r\n * @example\r\n * ```typescript\r\n * const chatData: ChatModalData = {\r\n * participant: {\r\n * id: '123',\r\n * name: 'Ricki Meihlen',\r\n * role: 'Inquiry assignee',\r\n * avatarInitials: 'RM'\r\n * },\r\n * messages: [\r\n * {\r\n * id: '1',\r\n * content: 'We have received your case...',\r\n * senderId: '123',\r\n * senderName: 'Ricki Meihlen',\r\n * timestamp: '12:34',\r\n * isOwnMessage: false,\r\n * avatarInitials: 'RM'\r\n * }\r\n * ],\r\n * currentUserId: '456'\r\n * };\r\n * ```\r\n */\r\nexport interface ChatModalData {\r\n /** The other participant in the conversation */\r\n participant: ChatParticipant;\r\n /** Array of messages in the conversation */\r\n messages: ChatMessage[];\r\n /** Current user's ID */\r\n currentUserId: string;\r\n /** Current user's avatar initials */\r\n currentUserInitials?: string;\r\n /** Current user's avatar type */\r\n currentUserAvatarType?: 'initials' | 'photo' | 'icon';\r\n /** Current user's avatar source */\r\n currentUserAvatarSrc?: string;\r\n /** Auto-focus input when modal opens */\r\n autoFocus?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobileChatModalComponent\r\n * \r\n * Modal component for displaying and managing chat conversations.\r\n * Follows the same pattern as post-detail-modal for consistent behavior.\r\n * \r\n * Features:\r\n * - Header with participant info and close button\r\n * - Scrollable message thread\r\n * - Fixed message composer at bottom\r\n * - Keyboard handling\r\n * - Safe area support\r\n * \r\n * This component is typically not used directly - use DsMobileChatModalService instead.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private chatModal: DsMobileChatModalService) {}\r\n * \r\n * openChat() {\r\n * this.chatModal.open({\r\n * participant: { id: '123', name: 'Ricki Meihlen' },\r\n * messages: [...],\r\n * currentUserId: '456'\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-chat-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsIconComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsMobileMessageComposerComponent,\r\n DsMobileMessageBubbleComponent\r\n ],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"chat-modal-content\">\r\n <div class=\"chat-modal-wrapper\">\r\n <!-- Header with participant info -->\r\n <div class=\"chat-modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Participant info -->\r\n <div class=\"participant-info\">\r\n <ds-avatar-with-badge\r\n [initials]=\"participant().avatarInitials || ''\"\r\n [type]=\"participant().avatarType || 'initials'\"\r\n [src]=\"participant().avatarSrc || ''\"\r\n size=\"md\"\r\n />\r\n <div class=\"participant-details\">\r\n <div class=\"author-name\">{{ participant().name }}</div>\r\n @if (participant().role) {\r\n <div class=\"author-meta\">{{ participant().role }}</div>\r\n }\r\n </div>\r\n </div>\r\n \r\n <!-- Close button -->\r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (clicked)=\"close()\"\r\n class=\"close-button\"\r\n aria-label=\"Close chat\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Messages thread -->\r\n <div class=\"chat-messages-container\">\r\n @if (loading) {\r\n <!-- Loading State -->\r\n <div class=\"chat-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading messages...</p>\r\n </div>\r\n } @else if (error) {\r\n <!-- Error State -->\r\n <div class=\"chat-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error loading messages</h3>\r\n <p class=\"error-state-description\">{{ error }}</p>\r\n </div>\r\n } @else {\r\n <!-- Messages List -->\r\n <div class=\"messages-list\">\r\n @if (messages().length === 0) {\r\n <!-- Empty State -->\r\n <div class=\"messages-empty-state\">\r\n <h3 class=\"empty-state-title\">No messages yet</h3>\r\n <p class=\"empty-state-description\">Start the conversation by sending a message</p>\r\n </div>\r\n } @else {\r\n @for (message of messages(); track message.id) {\r\n <ds-mobile-message-bubble\r\n [content]=\"message.content\"\r\n [isOwnMessage]=\"message.isOwnMessage\"\r\n [timestamp]=\"message.timestamp\"\r\n [avatarInitials]=\"message.avatarInitials || ''\"\r\n [avatarType]=\"message.avatarType || 'initials'\"\r\n [avatarSrc]=\"message.avatarSrc || ''\"\r\n [attachments]=\"message.attachments\"\r\n [clickable]=\"true\"\r\n (attachmentClick)=\"handleAttachmentClick($event)\"\r\n (longPress)=\"handleMessageLongPress(message)\">\r\n </ds-mobile-message-bubble>\r\n }\r\n }\r\n </div>\r\n \r\n <!-- Bottom spacer for fixed composer -->\r\n <div class=\"composer-spacer\"></div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n \r\n <!-- Fixed message composer -->\r\n @if (!loading && !error) {\r\n <div class=\"message-composer-fixed\">\r\n <ds-mobile-message-composer\r\n [avatarInitials]=\"currentUserInitials()\"\r\n [avatarType]=\"currentUserAvatarType()\"\r\n [avatarSrc]=\"currentUserAvatarSrc()\"\r\n [placeholder]=\"'Write a message...'\"\r\n [autoFocus]=\"autoFocus()\"\r\n (messageSent)=\"handleMessageSent($event)\">\r\n </ds-mobile-message-composer>\r\n </div>\r\n }\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n position: relative;\r\n height: 100%;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n }\r\n\r\n .chat-modal-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .chat-modal-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n min-height: 100dvh;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n width: 100%;\r\n }\r\n\r\n .chat-modal-header {\r\n position: sticky;\r\n top: 0;\r\n z-index: 10;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 16px;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 72px;\r\n /* No padding needed - StatusBar.setOverlaysWebView(false) handles all spacing */\r\n }\r\n\r\n .participant-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .participant-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n /* Participant name and meta styles imported from mobile-common.css */\r\n\r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n \r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .chat-messages-container {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n padding: 16px 0 20px 0;\r\n flex: 1;\r\n }\r\n \r\n .messages-list {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n padding: 0 20px;\r\n align-items: stretch; /* Ensure messages take full width for proper alignment */\r\n }\r\n \r\n /* Ensure message bubbles can align properly */\r\n .messages-list ds-mobile-message-bubble {\r\n width: 100%;\r\n display: flex;\r\n }\r\n \r\n /* Empty State */\r\n .messages-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0 0 8px 0;\r\n }\r\n \r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n \r\n .composer-spacer {\r\n /* Match full composer height + safe area */\r\n height: calc(81px + env(safe-area-inset-bottom, 0px));\r\n }\r\n\r\n /* Fixed Message Composer Container */\r\n .message-composer-fixed {\r\n position: fixed;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 1000;\r\n pointer-events: none;\r\n /* Slide up with keyboard on native apps */\r\n transform: translateY(calc(-1 * var(--keyboard-height, 0px)));\r\n transition: transform 0.3s ease-out;\r\n max-width: 100vw;\r\n }\r\n\r\n .message-composer-fixed ds-mobile-message-composer {\r\n pointer-events: auto;\r\n /* White box shadow to cover content gap between keyboard and composer */\r\n box-shadow: 100px 150px 0 150px var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n /* Loading State */\r\n .chat-loading-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 3px solid var(--color-background-neutral-secondary, #f0f0f0);\r\n border-top-color: var(--color-primary-base, #2563eb);\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n \r\n @keyframes spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n \r\n .loading-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin-top: 16px;\r\n }\r\n\r\n /* Error State */\r\n .chat-error-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n gap: 16px;\r\n }\r\n \r\n .error-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n \r\n .error-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .chat-messages-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n `]\r\n})\r\nexport class DsMobileChatModalComponent implements OnInit, AfterViewInit, OnDestroy {\r\n // Chat data passed from service\r\n @Input() chatData!: ChatModalData;\r\n \r\n /**\r\n * Loading state - when true, shows loading indicator\r\n */\r\n @Input() loading: boolean = false;\r\n \r\n /**\r\n * Error state - when set, shows error message\r\n */\r\n @Input() error?: string;\r\n \r\n // Signal for reactive chat data\r\n participant = signal<ChatParticipant>({\r\n id: '',\r\n name: '',\r\n avatarInitials: ''\r\n });\r\n \r\n messages = signal<ChatMessage[]>([]);\r\n currentUserInitials = signal<string>('');\r\n currentUserAvatarType = signal<'initials' | 'photo' | 'icon'>('initials');\r\n currentUserAvatarSrc = signal<string>('');\r\n autoFocus = signal<boolean>(false);\r\n \r\n constructor(private modalController: ModalController) {}\r\n \r\n ngOnInit(): void {\r\n // Initialize chat data from input\r\n if (this.chatData) {\r\n this.participant.set(this.chatData.participant);\r\n this.messages.set(this.chatData.messages || []);\r\n this.currentUserInitials.set(this.chatData.currentUserInitials || '');\r\n this.currentUserAvatarType.set(this.chatData.currentUserAvatarType || 'initials');\r\n this.currentUserAvatarSrc.set(this.chatData.currentUserAvatarSrc || '');\r\n this.autoFocus.set(this.chatData.autoFocus || false);\r\n }\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Scroll to bottom when messages load\r\n if (this.messages().length > 0) {\r\n setTimeout(() => {\r\n this.scrollToBottom();\r\n }, 300);\r\n }\r\n }\r\n \r\n ngOnDestroy(): void {\r\n // Cleanup if needed\r\n }\r\n \r\n /**\r\n * Scroll to bottom of messages\r\n */\r\n private scrollToBottom(): void {\r\n const container = document.querySelector('.chat-messages-container');\r\n if (container) {\r\n container.scrollTop = container.scrollHeight;\r\n }\r\n }\r\n \r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n \r\n /**\r\n * Handle message sent from composer\r\n */\r\n handleMessageSent(event: { content: string; isReply?: boolean; replyTo?: string; isEdit?: boolean }): void {\r\n const newMessage: ChatMessage = {\r\n id: Date.now().toString(),\r\n content: event.content,\r\n senderId: this.chatData.currentUserId,\r\n senderName: 'You',\r\n timestamp: new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }),\r\n isOwnMessage: true,\r\n avatarInitials: this.currentUserInitials(),\r\n avatarType: this.currentUserAvatarType(),\r\n avatarSrc: this.currentUserAvatarSrc()\r\n };\r\n \r\n // Add message to list\r\n const updatedMessages = [...this.messages(), newMessage];\r\n this.messages.set(updatedMessages);\r\n \r\n // Scroll to bottom\r\n setTimeout(() => {\r\n this.scrollToBottom();\r\n }, 100);\r\n \r\n // In a real app, you would send this to your backend\r\n // this.chatService.sendMessage(this.chatData.participant.id, event.content);\r\n }\r\n \r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: ChatAttachment): void {\r\n console.log('[ChatModal] Attachment clicked:', attachment);\r\n // In a real app, you would open the attachment (image viewer, PDF viewer, etc.)\r\n }\r\n \r\n /**\r\n * Handle message long press\r\n */\r\n handleMessageLongPress(message: ChatMessage): void {\r\n console.log('[ChatModal] Message long pressed:', message);\r\n // In a real app, you would show an action sheet with options (copy, delete, etc.)\r\n }\r\n}\r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobileChatModalComponent, ChatModalData } from './ds-mobile-chat-modal';\r\n\r\n/**\r\n * DsMobileChatModalService\r\n * \r\n * Service for displaying chat conversations in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * Follows the same pattern as DsMobilePostDetailModalService for consistent behavior.\r\n * \r\n * Features:\r\n * - Full conversation display\r\n * - Message thread with bubbles\r\n * - Message composer\r\n * - Native modal animations\r\n * - Safe area support\r\n * - Keyboard handling\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private chatModal: DsMobileChatModalService) {}\r\n * \r\n * async openChat() {\r\n * await this.chatModal.open({\r\n * participant: {\r\n * id: '123',\r\n * name: 'Ricki Meihlen',\r\n * role: 'Inquiry assignee',\r\n * avatarInitials: 'RM'\r\n * },\r\n * messages: [\r\n * {\r\n * id: '1',\r\n * content: 'We have received your case...',\r\n * senderId: '123',\r\n * senderName: 'Ricki Meihlen',\r\n * timestamp: '12:34',\r\n * isOwnMessage: false,\r\n * avatarInitials: 'RM'\r\n * },\r\n * {\r\n * id: '2',\r\n * content: 'Thank you!',\r\n * senderId: '456',\r\n * senderName: 'You',\r\n * timestamp: '12:35',\r\n * isOwnMessage: true,\r\n * avatarInitials: 'JD',\r\n * readStatus: true\r\n * }\r\n * ],\r\n * currentUserId: '456',\r\n * currentUserInitials: 'JD',\r\n * autoFocus: true\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileChatModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the chat modal\r\n * \r\n * @param chatData Chat data to display\r\n * @param options Optional loading and error states\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(\r\n chatData: ChatModalData,\r\n options?: { loading?: boolean; error?: string }\r\n ): Promise<void> {\r\n console.log('[ChatModal] Opening with data:', chatData);\r\n \r\n const modal = await this.modalController.create({\r\n component: DsMobileChatModalComponent,\r\n componentProps: {\r\n chatData: chatData,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n cssClass: 'ds-chat-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n // Control the presenting element animation\r\n enterAnimation: undefined, // Use default\r\n leaveAnimation: undefined // Use default\r\n });\r\n\r\n console.log('[ChatModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[ChatModal] Modal presented');\r\n }\r\n\r\n /**\r\n * Close the currently open chat modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, Input } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileHandbookFolderMiniComponent\r\n * \r\n * A minimized folder icon component for use in headers and small spaces.\r\n * Simplified version without animations or page sheets - just folder and icon.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-handbook-folder-mini\r\n * [variant]=\"'pink'\"\r\n * [iconName]=\"'remixLightbulbLine'\">\r\n * </ds-mobile-handbook-folder-mini>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-handbook-folder-mini',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n styles: [`\r\n :host {\r\n display: inline-block;\r\n width: 32px;\r\n height: 32px;\r\n flex-shrink: 0;\r\n }\r\n \r\n .mini-folder-container {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n .mini-folder-tab {\r\n width: 50%;\r\n height: auto;\r\n display: block;\r\n }\r\n \r\n .mini-folder-back {\r\n height: 28px;\r\n border-radius: 0px 4px 4px 4px;\r\n position: relative;\r\n margin-top: -1px;\r\n }\r\n \r\n .mini-folder-front {\r\n position: absolute;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n height: 24px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 2;\r\n box-shadow: inset 0 8px 8px rgba(255, 255, 255, 0.2), \r\n inset 0 0.5px 0.5px rgba(255, 255, 255, 0.3);\r\n }\r\n `],\r\n template: `\r\n <div class=\"mini-folder-container\">\r\n <!-- Folder Tab SVG -->\r\n <svg \r\n class=\"mini-folder-tab\" \r\n width=\"101\" \r\n height=\"24\" \r\n viewBox=\"0 0 101 24\" \r\n fill=\"none\" \r\n xmlns=\"http://www.w3.org/2000/svg\">\r\n <path \r\n d=\"M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z\" \r\n [attr.fill]=\"getColorVar('strong')\"/>\r\n </svg>\r\n \r\n <!-- Folder Back -->\r\n <div class=\"mini-folder-back\" [style.background-color]=\"getColorVar('strong')\">\r\n <!-- Folder Front -->\r\n <div \r\n class=\"mini-folder-front\" \r\n [style.background-color]=\"getColorVar('base')\">\r\n <ds-icon \r\n [name]=\"iconName\" \r\n [size]=\"'14px'\"\r\n [style.color]=\"'white'\" />\r\n </div>\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileHandbookFolderMiniComponent {\r\n /**\r\n * Color variant for the folder\r\n * Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey\r\n */\r\n @Input() variant: string = 'light-purple';\r\n \r\n /**\r\n * Icon name from the design system icon library\r\n */\r\n @Input() iconName: string = 'remixFolder3Line';\r\n \r\n /**\r\n * Get the CSS variable name for the color variant\r\n */\r\n getColorVar(suffix: 'base' | 'strong'): string {\r\n const variantMap: Record<string, string> = {\r\n 'success': 'success',\r\n 'warning': 'warning',\r\n 'destructive': 'destructive',\r\n 'blue': 'blue',\r\n 'light-purple': 'light-purple',\r\n 'pink': 'pink',\r\n 'salmon-orange': 'salmon-orange',\r\n 'orange': 'orange',\r\n 'lime-green': 'lime-green',\r\n 'grey': 'grey'\r\n };\r\n \r\n const colorName = variantMap[this.variant] || 'light-purple';\r\n return `var(--color-${colorName}-${suffix})`;\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileCardInlineComponent\r\n * \r\n * A versatile, always-interactive inline card component for standalone or small-group usage.\r\n * Designed for tappable card-like elements such as file attachments, contact cards, etc.\r\n * Not intended for long scrolling lists - use ds-mobile-list-item for that purpose.\r\n * \r\n * Features:\r\n * - Always interactive/tappable (unless disabled)\r\n * - Two layout variants: default (column) and compact (row)\r\n * - Flexible content projection with leading/main/trailing slots\r\n * - Consistent styling with rounded corners and neutral background\r\n * - Built-in hover and active states\r\n * - Accessibility features (role, tabindex, aria attributes)\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Default variant (column layout) -->\r\n * <ds-mobile-card-inline\r\n * [variant]=\"'default'\"\r\n * (cardClick)=\"handleClick()\">\r\n * \r\n * <div content-leading>\r\n * <ds-avatar initials=\"JD\" />\r\n * </div>\r\n * \r\n * <div content-main>\r\n * <div class=\"title\">Document Title</div>\r\n * <div class=\"subtitle\">PDF · 1.2 MB</div>\r\n * </div>\r\n * \r\n * <ds-icon content-trailing name=\"remixArrowRightSLine\" />\r\n * </ds-mobile-card-inline>\r\n * \r\n * <!-- Compact variant (row layout) -->\r\n * <ds-mobile-card-inline\r\n * [variant]=\"'compact'\"\r\n * (cardClick)=\"handleClick()\">\r\n * \r\n * <ds-avatar content-leading size=\"sm\" />\r\n * \r\n * <div content-main>\r\n * <span class=\"name\">File.pdf</span>\r\n * <span class=\"size\">245 KB</span>\r\n * </div>\r\n * \r\n * <ds-icon content-trailing name=\"remixArrowRightSLine\" />\r\n * </ds-mobile-card-inline>\r\n * \r\n * <!-- Disabled state -->\r\n * <ds-mobile-card-inline [disabled]=\"true\">\r\n * <div content-main>Disabled card</div>\r\n * </ds-mobile-card-inline>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline',\r\n standalone: true,\r\n imports: [CommonModule],\r\n host: {\r\n '[class.disabled]': 'disabled()',\r\n '[class.variant-compact]': 'variant() === \"compact\"',\r\n '[class.variant-default]': 'variant() === \"default\"',\r\n '[attr.role]': '\"button\"',\r\n '[attr.tabindex]': 'disabled() ? null : \"0\"',\r\n '[attr.aria-disabled]': 'disabled() ? \"true\" : null',\r\n '(click)': 'handleClick($event)',\r\n '(keydown.enter)': 'handleKeyDown($event)',\r\n '(keydown.space)': 'handleKeyDown($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n box-sizing: border-box;\r\n }\r\n \r\n /* Default variant - column layout with more padding */\r\n :host(.variant-default) {\r\n gap: 12px;\r\n padding: 10px 12px;\r\n }\r\n \r\n /* Compact variant - row layout with less padding */\r\n :host(.variant-compact) {\r\n gap: 8px;\r\n padding: 10px;\r\n }\r\n \r\n /* Hover state (desktop only) */\r\n @media (hover: hover) and (pointer: fine) {\r\n :host(:hover):not(.disabled) {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n }\r\n \r\n /* Active state */\r\n :host(:active):not(.disabled) {\r\n transform: scale(0.98);\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n /* Focus visible for keyboard navigation */\r\n :host(:focus-visible):not(.disabled) {\r\n outline: 2px solid var(--color-brand-primary, #5d5fef);\r\n outline-offset: 2px;\r\n }\r\n \r\n /* Disabled state */\r\n :host(.disabled) {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n }\r\n \r\n /* Inner container */\r\n .card-inline-inner {\r\n display: flex;\r\n align-items: center;\r\n gap: inherit;\r\n width: 100%;\r\n min-width: 0;\r\n }\r\n \r\n /* Content slots */\r\n .content-leading {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .content-main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n align-items: center;\r\n }\r\n \r\n /* Compact variant - main content flows inline */\r\n :host(.variant-compact) .content-main {\r\n flex-direction: row;\r\n gap: 8px;\r\n }\r\n \r\n /* Default variant - main content flows column */\r\n :host(.variant-default) .content-main {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 2px;\r\n }\r\n \r\n .content-trailing {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n }\r\n \r\n /* ============================================\r\n Shared item styles for child components\r\n ============================================ */\r\n \r\n /* Item avatar container */\r\n ::ng-deep .item-avatar {\r\n flex-shrink: 0;\r\n }\r\n \r\n /* Item content wrapper - default stacks vertically */\r\n ::ng-deep .item-content {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 2px;\r\n }\r\n \r\n /* Compact layout - content flows inline */\r\n :host(.variant-compact) ::ng-deep .item-content {\r\n flex-direction: row;\r\n align-items: center;\r\n justify-content: flex-start;\r\n gap: 8px;\r\n }\r\n \r\n /* Item name - primary text with truncation */\r\n ::ng-deep .item-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n text-align: left;\r\n }\r\n \r\n /* Item meta - secondary text */\r\n ::ng-deep .item-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n margin: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-start;\r\n gap: 4px;\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n }\r\n \r\n /* Item trailing icon */\r\n ::ng-deep .item-trailing {\r\n display: flex;\r\n align-items: center;\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"card-inline-inner\">\r\n <div class=\"content-leading\">\r\n <ng-content select=\"[content-leading]\" />\r\n </div>\r\n \r\n <div class=\"content-main\">\r\n <ng-content select=\"[content-main]\" />\r\n <ng-content />\r\n </div>\r\n \r\n <div class=\"content-trailing\">\r\n <ng-content select=\"[content-trailing]\" />\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileCardInlineComponent {\r\n /**\r\n * Display variant\r\n * - 'default' - Column layout with standard padding (gap: 12px, padding: 10px 12px)\r\n * - 'compact' - Row layout with reduced padding (gap: 8px, padding: 10px)\r\n */\r\n variant = input<'default' | 'compact'>('default');\r\n \r\n /**\r\n * Whether the card is disabled\r\n * Disables all interactions and reduces opacity\r\n */\r\n disabled = input<boolean>(false);\r\n \r\n /**\r\n * Emits when the card is clicked (if not disabled)\r\n */\r\n cardClick = output<void>();\r\n \r\n /**\r\n * Handle click events\r\n */\r\n handleClick(event: Event): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n \r\n // Don't emit click if it came from an interactive child element\r\n const target = event.target as HTMLElement;\r\n const closestInteractive = target.closest('button, a, input, select, textarea, [role=\"button\"]');\r\n \r\n // Check if the interactive element is a child, not the host itself\r\n if (closestInteractive && closestInteractive !== event.currentTarget) {\r\n return;\r\n }\r\n \r\n this.cardClick.emit();\r\n }\r\n \r\n /**\r\n * Handle keyboard events (Enter/Space)\r\n */\r\n handleKeyDown(event: KeyboardEvent): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n \r\n event.preventDefault();\r\n this.cardClick.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileCardInlineComponent } from '../card-inline';\r\n\r\n/**\r\n * DsMobileCardInlineFileComponent\r\n * \r\n * File attachment display for various document types.\r\n * Shows file info card with icon, filename, and file size.\r\n * Supports PDF and generic document formats.\r\n * Emits click event to open file in viewer.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-card-inline-file\r\n * [fileName]=\"'Document.pdf'\"\r\n * [fileSize]=\"'1.2 MB'\"\r\n * [variant]=\"'pdf'\"\r\n * [layout]=\"'compact'\"\r\n * (fileClick)=\"openFile()\">\r\n * </ds-mobile-card-inline-file>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline-file',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent, DsMobileCardInlineComponent],\r\n styles: [`\r\n /* PDF variant - red icon background */\r\n .item-avatar.pdf ::ng-deep .avatar--icon {\r\n background-color: #ff5757 !important;\r\n }\r\n \r\n /* Doc variant - blue icon background */\r\n .item-avatar.doc ::ng-deep .avatar--icon {\r\n background-color: var(--color-blue-base, #3B82F6) !important;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-card-inline\r\n [variant]=\"layout()\"\r\n (cardClick)=\"handleClick()\">\r\n \r\n <div content-leading class=\"item-avatar\" [class.pdf]=\"variant() === 'pdf'\" [class.doc]=\"variant() === 'doc'\">\r\n <ds-avatar\r\n type=\"icon\"\r\n [iconName]=\"getIconName()\"\r\n [size]=\"layout() === 'compact' ? 'sm' : 'md'\"\r\n />\r\n </div>\r\n \r\n <div content-main class=\"item-content\">\r\n <div class=\"item-name\">{{ fileName() }}</div>\r\n @if (fileSize()) {\r\n <div class=\"item-meta\">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>\r\n } @else {\r\n <div class=\"item-meta\">{{ getFileTypeLabel() }}</div>\r\n }\r\n </div>\r\n \r\n <ds-icon \r\n content-trailing\r\n name=\"remixArrowRightSLine\" \r\n size=\"20px\"\r\n class=\"item-trailing\"\r\n />\r\n </ds-mobile-card-inline>\r\n `\r\n})\r\nexport class DsMobileCardInlineFileComponent {\r\n /**\r\n * File name\r\n */\r\n fileName = input<string>('Document');\r\n \r\n /**\r\n * File size display (e.g., \"1.2 MB\")\r\n */\r\n fileSize = input<string>('');\r\n \r\n /**\r\n * File type variant\r\n * - 'pdf' - PDF document (red icon)\r\n * - 'doc' - Generic document (blue icon)\r\n */\r\n variant = input<'pdf' | 'doc'>('doc');\r\n \r\n /**\r\n * Layout variant\r\n * - 'default' - Standard padding and column layout\r\n * - 'compact' - Reduced padding and row layout\r\n */\r\n layout = input<'default' | 'compact'>('default');\r\n \r\n /**\r\n * Emits when the file attachment is clicked\r\n */\r\n fileClick = output<void>();\r\n \r\n /**\r\n * Get the appropriate icon name based on variant\r\n */\r\n getIconName(): string {\r\n return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';\r\n }\r\n \r\n /**\r\n * Get the file type label based on variant\r\n */\r\n getFileTypeLabel(): string {\r\n return this.variant() === 'pdf' ? 'PDF' : 'DOC';\r\n }\r\n \r\n handleClick(): void {\r\n this.fileClick.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsMobileCardInlineComponent } from '../card-inline';\r\n\r\n/**\r\n * DsMobileCardInlineContactComponent\r\n * \r\n * Specialized interactive component for displaying contacts.\r\n * Displays contact name with avatar initials and metadata (person name + phone number).\r\n * Similar styling to file attachments with rounded corners and hover states.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-card-inline-contact\r\n * [name]=\"'Mortensen & Søn ApS'\"\r\n * [initials]=\"'M'\"\r\n * [contactPerson]=\"'John Mortensen'\"\r\n * [phoneNumber]=\"'+45 12 34 56 78'\"\r\n * [clickable]=\"true\"\r\n * (contactClick)=\"openContact()\">\r\n * </ds-mobile-card-inline-contact>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline-contact',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsAvatarComponent, DsMobileCardInlineComponent],\r\n styles: [`\r\n /* Component-specific styles only - shared styles come from base component */\r\n `],\r\n template: `\r\n <ds-mobile-card-inline\r\n [variant]=\"layout()\"\r\n [disabled]=\"!clickable()\"\r\n (cardClick)=\"handleContactClick()\">\r\n \r\n <div content-leading class=\"item-avatar\">\r\n <ds-avatar\r\n [initials]=\"initials()\"\r\n type=\"initials\"\r\n [size]=\"layout() === 'compact' ? 'sm' : 'md'\"\r\n />\r\n </div>\r\n \r\n <div content-main class=\"item-content\">\r\n <div class=\"item-name\">{{ name() }}</div>\r\n \r\n @if (contactPerson() || phoneNumber()) {\r\n <div class=\"item-meta\">\r\n @if (contactPerson()) {\r\n <span>{{ contactPerson() }}</span>\r\n }\r\n @if (contactPerson() && phoneNumber()) {\r\n <span>·</span>\r\n }\r\n @if (phoneNumber()) {\r\n <span>{{ phoneNumber() }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n \r\n @if (showChevron()) {\r\n <div content-trailing class=\"item-trailing\">\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n }\r\n </ds-mobile-card-inline>\r\n `\r\n})\r\nexport class DsMobileCardInlineContactComponent {\r\n /**\r\n * Contact/company name\r\n */\r\n name = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (usually 1-2 letters)\r\n */\r\n initials = input.required<string>();\r\n \r\n /**\r\n * Contact person name (optional)\r\n */\r\n contactPerson = input<string>('');\r\n \r\n /**\r\n * Phone number (optional)\r\n */\r\n phoneNumber = input<string>('');\r\n \r\n /**\r\n * Layout variant\r\n * - 'default' - Standard padding and column layout\r\n * - 'compact' - Reduced padding and row layout\r\n */\r\n layout = input<'default' | 'compact'>('default');\r\n \r\n /**\r\n * Whether the contact item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Whether to show chevron icon\r\n */\r\n showChevron = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the contact item is clicked (if clickable)\r\n */\r\n contactClick = output<void>();\r\n \r\n handleContactClick(): void {\r\n this.contactClick.emit();\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n input,\r\n AfterViewInit,\r\n OnDestroy,\r\n ElementRef,\r\n ViewChild,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport Swiper from 'swiper';\r\n\r\n/**\r\n * DsMobileSwiperComponent\r\n * \r\n * A reusable swiper/carousel component with configurable child width and spacing.\r\n * \r\n * Features:\r\n * - First slide is left-aligned\r\n * - Middle slides are centered when active\r\n * - Last slide is right-aligned\r\n * - Configurable slide width and gap\r\n * - Content projection via ng-content\r\n * \r\n * Usage:\r\n * ```html\r\n * <ds-mobile-swiper [slideWidth]=\"'75vw'\" [gap]=\"16\">\r\n * <div class=\"swiper-slide\">Slide 1</div>\r\n * <div class=\"swiper-slide\">Slide 2</div>\r\n * <div class=\"swiper-slide\">Slide 3</div>\r\n * </ds-mobile-swiper>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-swiper',\r\n standalone: true,\r\n imports: [CommonModule],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <div class=\"swiper-container\" #swiperContainer>\r\n <div class=\"swiper-wrapper\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n width: 100%;\r\n }\r\n\r\n .swiper-container {\r\n width: 100%;\r\n position: relative;\r\n overflow: hidden;\r\n border-radius: 12px;\r\n }\r\n\r\n .swiper-wrapper {\r\n display: flex;\r\n transition-property: transform;\r\n box-sizing: content-box;\r\n }\r\n\r\n :host ::ng-deep .swiper-slide {\r\n flex-shrink: 0;\r\n height: 100%;\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n `]\r\n})\r\nexport class DsMobileSwiperComponent implements AfterViewInit, OnDestroy {\r\n /**\r\n * Width of each slide (e.g., '75vw', '300px', '80%')\r\n */\r\n slideWidth = input<string>('75vw');\r\n\r\n /**\r\n * Gap between slides in pixels\r\n */\r\n gap = input<number>(16);\r\n\r\n @ViewChild('swiperContainer', { static: false }) swiperContainer!: ElementRef;\r\n\r\n private swiperInstance: Swiper | null = null;\r\n\r\n ngAfterViewInit(): void {\r\n setTimeout(() => {\r\n this.initializeSwiper();\r\n }, 100);\r\n }\r\n\r\n private initializeSwiper(): void {\r\n if (!this.swiperContainer) return;\r\n\r\n // Apply slide width to all slides\r\n const slides = this.swiperContainer.nativeElement.querySelectorAll('.swiper-slide');\r\n slides.forEach((slide: HTMLElement) => {\r\n slide.style.width = this.slideWidth();\r\n });\r\n\r\n this.swiperInstance = new Swiper(this.swiperContainer.nativeElement, {\r\n slidesPerView: 'auto',\r\n spaceBetween: this.gap(),\r\n centeredSlides: true,\r\n centeredSlidesBounds: true,\r\n speed: 300,\r\n resistance: true,\r\n resistanceRatio: 0.85,\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n if (this.swiperInstance) {\r\n this.swiperInstance.destroy();\r\n this.swiperInstance = null;\r\n }\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n signal,\r\n Input,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonContent,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsMobileHandbookFolderMiniComponent } from '../handbook-folder/ds-mobile-handbook-folder-mini';\r\nimport { DsMobileCardInlineFileComponent } from '../card-inline-file';\r\nimport { DsMobileCardInlineContactComponent } from '../card-inline-contact';\r\nimport { DsMobileSwiperComponent } from '../swiper';\r\n\r\n/**\r\n * Handbook detail data interface\r\n * \r\n * Represents a handbook category/folder with its sections/items.\r\n * Use this interface to map your API response data to the component.\r\n * \r\n * @example\r\n * ```typescript\r\n * const handbookData: HandbookDetailData = {\r\n * title: 'Access Systems',\r\n * variant: 'blue',\r\n * iconName: 'remixKey2Line',\r\n * itemCount: 5,\r\n * items: [...]\r\n * };\r\n * ```\r\n */\r\nexport interface HandbookDetailData {\r\n /** Category/folder title */\r\n title: string;\r\n /** Color variant: 'success', 'warning', 'destructive', 'blue', 'light-purple', 'pink', 'salmon-orange', 'orange', 'lime-green', 'grey' */\r\n variant: string;\r\n /** Icon name from design system (e.g., 'remixKey2Line', 'remixLightbulbLine') */\r\n iconName: string;\r\n /** Total number of items/sections in this category */\r\n itemCount: number;\r\n /** Array of handbook sections/items */\r\n items?: HandbookItem[];\r\n}\r\n\r\n/**\r\n * Handbook section/item interface\r\n * \r\n * Represents a single section within a handbook category.\r\n * Each section can have a title, description, images, contacts, and attachments.\r\n * \r\n * @example\r\n * ```typescript\r\n * const item: HandbookItem = {\r\n * title: 'Key Box Entrance',\r\n * description: 'Key box located at main entrance...',\r\n * images: ['https://api.example.com/images/keybox.jpg'],\r\n * contacts: [{ name: 'Security Co', initials: 'S', phoneNumber: '+45 12345678' }],\r\n * attachments: [{ name: 'Manual.pdf', type: 'pdf', url: 'https://...' }]\r\n * };\r\n * ```\r\n */\r\nexport interface HandbookItem {\r\n /** Section title */\r\n title: string;\r\n /** Optional section description */\r\n description?: string;\r\n /** Array of image URLs to display */\r\n images?: string[];\r\n /** Array of file attachments */\r\n attachments?: AttachmentItem[];\r\n /** Array of contact information */\r\n contacts?: ContactItem[];\r\n}\r\n\r\n/**\r\n * File attachment interface\r\n * \r\n * Represents a file attachment in a handbook section.\r\n * \r\n * @example\r\n * ```typescript\r\n * const attachment: AttachmentItem = {\r\n * name: 'Installation_Manual.pdf',\r\n * type: 'pdf',\r\n * url: 'https://api.example.com/files/manual.pdf'\r\n * };\r\n * ```\r\n */\r\nexport interface AttachmentItem {\r\n /** File name to display */\r\n name: string;\r\n /** File type: 'pdf', 'doc', etc. (used for icon display) */\r\n type?: string;\r\n /** Optional URL for downloading/opening the file */\r\n url?: string;\r\n}\r\n\r\n/**\r\n * Contact information interface\r\n * \r\n * Represents contact information in a handbook section.\r\n * \r\n * @example\r\n * ```typescript\r\n * const contact: ContactItem = {\r\n * name: 'Propbinder ApS',\r\n * initials: 'P',\r\n * contactPerson: 'John Doe',\r\n * phoneNumber: '+45 12345678',\r\n * email: 'support@propbinder.dk'\r\n * };\r\n * ```\r\n */\r\nexport interface ContactItem {\r\n /** Company or contact name */\r\n name: string;\r\n /** Initials for avatar (1-2 letters) */\r\n initials: string;\r\n /** Optional contact person name */\r\n contactPerson?: string;\r\n /** Optional phone number */\r\n phoneNumber?: string;\r\n /** Optional email address */\r\n email?: string;\r\n}\r\n\r\n/**\r\n * DsMobileHandbookDetailModalComponent\r\n * \r\n * Modal wrapper for displaying handbook folder details.\r\n * \r\n * Features:\r\n * - Folder content display\r\n * - Items list with descriptions\r\n * - Images and attachments\r\n * - Contact information\r\n * - Native modal controls (close, swipe down)\r\n * - Safe area support\r\n * \r\n * This component is typically not used directly - use DsMobileHandbookDetailModalService instead.\r\n */\r\n@Component({\r\n selector: 'ds-mobile-handbook-detail-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsMobileHandbookFolderMiniComponent,\r\n DsMobileCardInlineFileComponent,\r\n DsMobileCardInlineContactComponent,\r\n DsMobileSwiperComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"handbook-modal-content\">\r\n <div class=\"handbook-modal-wrapper\">\r\n <!-- Header -->\r\n <div class=\"handbook-modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Handbook folder info -->\r\n <div class=\"handbook-folder-info\">\r\n <ds-mobile-handbook-folder-mini\r\n [variant]=\"handbook().variant\"\r\n [iconName]=\"handbook().iconName\">\r\n </ds-mobile-handbook-folder-mini>\r\n <div class=\"folder-details\">\r\n <div class=\"folder-name\">{{ handbook().title }}</div>\r\n <div class=\"folder-meta\">\r\n <span>{{ handbook().itemCount }} emner</span>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Close button -->\r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (click)=\"close()\"\r\n class=\"close-button\"\r\n aria-label=\"Luk\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Content -->\r\n <div class=\"handbook-detail-container\">\r\n @if (loading) {\r\n <!-- Loading State -->\r\n <div class=\"handbook-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading...</p>\r\n </div>\r\n } @else if (error) {\r\n <!-- Error State -->\r\n <div class=\"handbook-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error loading content</h3>\r\n <p class=\"error-state-description\">{{ error }}</p>\r\n </div>\r\n } @else if (handbook().items && handbook().items!.length > 0) {\r\n @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {\r\n <div class=\"handbook-item\" [class.last-item]=\"isLast\">\r\n <div class=\"item-text-group\">\r\n <h2 class=\"item-title\">{{ item.title }}</h2>\r\n \r\n @if (item.description) {\r\n <p class=\"item-description\">{{ item.description }}</p>\r\n }\r\n </div>\r\n \r\n <!-- Images -->\r\n @if (item.images && item.images.length > 0) {\r\n <ds-mobile-swiper [slideWidth]=\"item.images.length === 1 ? '100%' : '85%'\" [gap]=\"16\">\r\n @for (image of item.images; track image) {\r\n <div class=\"swiper-slide\">\r\n <img \r\n [src]=\"image\" \r\n [alt]=\"item.title\"\r\n class=\"item-image\"\r\n />\r\n </div>\r\n }\r\n </ds-mobile-swiper>\r\n }\r\n \r\n <!-- Contacts -->\r\n @if (item.contacts && item.contacts.length > 0) {\r\n <div class=\"contacts-list\">\r\n @for (contact of item.contacts; track contact.name) {\r\n <ds-mobile-card-inline-contact\r\n [name]=\"contact.name\"\r\n [initials]=\"contact.initials\"\r\n [contactPerson]=\"contact.contactPerson || ''\"\r\n [phoneNumber]=\"contact.phoneNumber || ''\"\r\n [clickable]=\"true\"\r\n (contactClick)=\"handleContactClick(contact)\">\r\n </ds-mobile-card-inline-contact>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Attachments -->\r\n @if (item.attachments && item.attachments.length > 0) {\r\n <div class=\"attachments-list\">\r\n @for (attachment of item.attachments; track attachment.name) {\r\n <ds-mobile-card-inline-file\r\n [fileName]=\"attachment.name\"\r\n [variant]=\"attachment.type === 'pdf' ? 'pdf' : 'doc'\"\r\n (fileClick)=\"handleAttachmentClick(attachment)\">\r\n </ds-mobile-card-inline-file>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <!-- Empty State -->\r\n <div class=\"handbook-empty-state\">\r\n <img \r\n src=\"/Assets/Empty%20state-chat.png\" \r\n alt=\"No items yet\" \r\n class=\"empty-state-image\"\r\n />\r\n <h3 class=\"empty-state-title\">No items yet</h3>\r\n <p class=\"empty-state-description\">This folder is empty</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n `,\r\n styles: [`\r\n .handbook-modal-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .handbook-modal-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n min-height: 100dvh;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .handbook-modal-header {\r\n position: sticky;\r\n top: 0;\r\n z-index: 10;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 16px;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 72px;\r\n }\r\n\r\n .handbook-folder-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .folder-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n .folder-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .folder-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n\r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n \r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .handbook-detail-container {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n flex: 1;\r\n }\r\n \r\n .handbook-item {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 24px;\r\n padding: 24px 20px 24px 20px;\r\n border-bottom: 1px solid var(--border-color-default);\r\n }\r\n \r\n .handbook-item.last-item {\r\n border-bottom: none;\r\n }\r\n\r\n .item-text-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n\r\n .item-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 16px;\r\n font-weight: 600;\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n\r\n .item-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n\r\n .item-image {\r\n width: 100%;\r\n max-width: 100%;\r\n height: 280px;\r\n object-fit: cover;\r\n border-radius: 12px;\r\n display: block;\r\n }\r\n\r\n .contacts-list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n \r\n .attachments-list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n \r\n\r\n /* Empty State */\r\n .handbook-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-image {\r\n width: 96px;\r\n height: 96px;\r\n }\r\n \r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .handbook-detail-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n\r\n /* Loading State */\r\n .handbook-loading-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 3px solid var(--color-background-neutral-secondary, #f0f0f0);\r\n border-top-color: var(--color-primary-base, #2563eb);\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n \r\n @keyframes spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n \r\n .loading-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin-top: 16px;\r\n }\r\n\r\n /* Error State */\r\n .handbook-error-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n gap: 16px;\r\n }\r\n \r\n .error-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n \r\n .error-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n `]\r\n})\r\nexport class DsMobileHandbookDetailModalComponent {\r\n // Handbook data passed from service\r\n @Input() handbookData!: HandbookDetailData;\r\n \r\n /**\r\n * Loading state - when true, shows loading indicator\r\n */\r\n @Input() loading: boolean = false;\r\n \r\n /**\r\n * Error state - when set, shows error message\r\n */\r\n @Input() error?: string;\r\n \r\n // Signal for reactive handbook data\r\n handbook = signal<HandbookDetailData>({\r\n title: '',\r\n variant: 'light-purple',\r\n iconName: 'remixFolder3Line',\r\n itemCount: 0,\r\n items: []\r\n });\r\n\r\n constructor(\r\n private modalController: ModalController\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n // Initialize handbook data from input\r\n if (this.handbookData) {\r\n this.handbook.set(this.handbookData);\r\n }\r\n }\r\n\r\n /**\r\n * Split handbook items to enforce content structure rules:\r\n * - Never mix photos and documents (attachments) in the same section\r\n * - Never mix contact persons and attachments together in the same section\r\n * \r\n * This method splits items that violate these rules into multiple display items.\r\n * Each resulting item will have only compatible content types.\r\n */\r\n splitItemsByContentRules(item: HandbookItem): HandbookItem[] {\r\n const displayItems: HandbookItem[] = [];\r\n \r\n const hasImages = item.images && item.images.length > 0;\r\n const hasContacts = item.contacts && item.contacts.length > 0;\r\n const hasAttachments = item.attachments && item.attachments.length > 0;\r\n \r\n // Case 1: Only one type of content - keep as is\r\n const contentTypeCount = [hasImages, hasContacts, hasAttachments].filter(Boolean).length;\r\n if (contentTypeCount <= 1) {\r\n return [item];\r\n }\r\n \r\n // Case 2: Has images + contacts (allowed together) but no attachments\r\n if (hasImages && hasContacts && !hasAttachments) {\r\n return [item];\r\n }\r\n \r\n // Case 3: Violates rules - need to split\r\n \r\n // First item: Text + Images (if present)\r\n if (hasImages) {\r\n displayItems.push({\r\n title: item.title,\r\n description: item.description,\r\n images: item.images\r\n });\r\n }\r\n \r\n // Second item: Text + Contacts (if present and no images shown yet)\r\n if (hasContacts) {\r\n displayItems.push({\r\n title: item.title,\r\n description: hasImages ? undefined : item.description, // Only show description if not shown before\r\n contacts: item.contacts\r\n });\r\n }\r\n \r\n // Third item: Text + Attachments (if present)\r\n if (hasAttachments) {\r\n displayItems.push({\r\n title: item.title,\r\n description: (!hasImages && !hasContacts) ? item.description : undefined, // Only show description if not shown before\r\n attachments: item.attachments\r\n });\r\n }\r\n \r\n return displayItems;\r\n }\r\n \r\n /**\r\n * Get all display items with enforced content structure rules applied\r\n */\r\n getDisplayItems(): HandbookItem[] {\r\n const items = this.handbook().items || [];\r\n const displayItems: HandbookItem[] = [];\r\n \r\n for (const item of items) {\r\n const splitItems = this.splitItemsByContentRules(item);\r\n displayItems.push(...splitItems);\r\n }\r\n \r\n return displayItems;\r\n }\r\n\r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n \r\n /**\r\n * Handle contact click\r\n */\r\n handleContactClick(contact: ContactItem): void {\r\n console.log('Contact clicked:', contact);\r\n // Implement contact action (e.g., show contact details, call, etc.)\r\n }\r\n \r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: AttachmentItem): void {\r\n console.log('Attachment clicked:', attachment);\r\n // Implement attachment action (e.g., open file viewer, download, etc.)\r\n }\r\n}\r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobileHandbookDetailModalComponent, HandbookDetailData } from './ds-mobile-handbook-detail-modal';\r\n\r\n/**\r\n * DsMobileHandbookDetailModalService\r\n * \r\n * Service for displaying handbook folder details in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * \r\n * Features:\r\n * - Full handbook content display\r\n * - Items list with descriptions\r\n * - Images and attachments\r\n * - Contact information\r\n * - Native modal animations\r\n * - Safe area support\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private handbookModal: DsMobileHandbookDetailModalService) {}\r\n * \r\n * async openHandbook() {\r\n * await this.handbookModal.open({\r\n * title: 'Utilities',\r\n * variant: 'pink',\r\n * iconName: 'remixLightbulbLine',\r\n * itemCount: 8,\r\n * items: [\r\n * {\r\n * title: 'Hjertestarter',\r\n * description: 'Installed on the 4th floor...',\r\n * images: ['/path/to/image.jpg'],\r\n * contacts: [\r\n * { name: 'Mortensen & Søn ApS', initials: 'M' }\r\n * ]\r\n * }\r\n * ]\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileHandbookDetailModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the handbook detail modal\r\n * \r\n * @param handbookData Handbook data to display\r\n * @param options Optional loading and error states\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(\r\n handbookData: HandbookDetailData,\r\n options?: { loading?: boolean; error?: string }\r\n ): Promise<void> {\r\n console.log('[HandbookDetailModal] Opening with data:', handbookData);\r\n \r\n const modal = await this.modalController.create({\r\n component: DsMobileHandbookDetailModalComponent,\r\n componentProps: {\r\n handbookData: handbookData,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n cssClass: 'ds-handbook-detail-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n enterAnimation: undefined,\r\n leaveAnimation: undefined\r\n });\r\n\r\n console.log('[HandbookDetailModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[HandbookDetailModal] Modal presented');\r\n }\r\n\r\n /**\r\n * Close the currently open handbook detail modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, Input, signal, HostListener } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileHandbookDetailModalService, HandbookDetailData, HandbookItem } from '../handbook-detail-modal';\r\n\r\n/**\r\n * DsMobileHandbookFolderComponent\r\n * \r\n * A visually rich folder component for displaying handbook categories or sections.\r\n * Features a two-layer folder design with customizable colors, icon, item count, and label.\r\n * \r\n * Design Details:\r\n * - Folder back: 72px height with a decorative notch\r\n * - Folder front: 64px height overlaying the back\r\n * - Item count displayed in bottom-left corner\r\n * - Icon displayed in bottom-right corner\r\n * - Label text centered below the folder\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-handbook-folder\r\n * [colorBase]=\"'#d244cf'\"\r\n * [colorWeak]=\"'#f9e6f9'\"\r\n * [iconName]=\"'remixLightbulbLine'\"\r\n * [itemCount]=\"8\"\r\n * [label]=\"'Utilities'\">\r\n * </ds-mobile-handbook-folder>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-handbook-folder',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n styles: [`\r\n :host {\r\n display: inline-flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 16px;\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n padding: 16px;\r\n border-radius: 16px;\r\n background: var(--color-background-neutral-secondary, #f0f0f0);\r\n transition: background 0.2s ease;\r\n }\r\n \r\n :host:active {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n @media (hover: hover) {\r\n :host:hover {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n }\r\n \r\n .folder-container {\r\n position: relative;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n perspective: 800px;\r\n -webkit-perspective: 800px;\r\n max-width: 160px;\r\n /* Safari optimization: Ensure proper 3D rendering context */\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n }\r\n \r\n .folder-container.open .page-sheet {\r\n -webkit-transform: translateY(-8px);\r\n transform: translateY(-8px);\r\n transition-delay: 0.2s;\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(1) {\r\n -webkit-transform: scale(1) translateY(-8px) rotateX(-45deg) translateZ(0.1px);\r\n transform: scale(1) translateY(-8px) rotateX(-45deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(2) {\r\n -webkit-transform: scale(0.98) translateY(-12px) rotateX(-36deg) translateZ(0.1px);\r\n transform: scale(0.98) translateY(-12px) rotateX(-36deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(3) {\r\n -webkit-transform: scale(0.96) translateY(-16px) rotateX(-27deg) translateZ(0.1px);\r\n transform: scale(0.96) translateY(-16px) rotateX(-27deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(4) {\r\n -webkit-transform: scale(0.94) translateY(-20px) rotateX(-18deg) translateZ(0.1px);\r\n transform: scale(0.94) translateY(-20px) rotateX(-18deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(5) {\r\n -webkit-transform: scale(0.92) translateY(-24px) rotateX(-9deg) translateZ(0.1px);\r\n transform: scale(0.92) translateY(-24px) rotateX(-9deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(6) {\r\n -webkit-transform: scale(0.90) translateY(-28px) rotateX(0deg) translateZ(0.1px);\r\n transform: scale(0.90) translateY(-28px) rotateX(0.1px);\r\n }\r\n \r\n .folder-container.open .folder-front {\r\n -webkit-transform: translate3d(0, 0, 0) rotateX(-45deg);\r\n transform: translate3d(0, 0, 0) rotateX(-45deg);\r\n }\r\n \r\n .folder-tab {\r\n width: 50%;\r\n height: auto;\r\n display: block;\r\n }\r\n \r\n .folder-back {\r\n height: 128px;\r\n border-radius: 0px 12px 12px 12px;\r\n position: relative;\r\n margin-top: -1px;\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n backface-visibility: hidden;\r\n -webkit-backface-visibility: hidden;\r\n /* Safari optimization: Force GPU acceleration */\r\n -webkit-transform: translateZ(0);\r\n transform: translateZ(0);\r\n }\r\n \r\n .page-sheet {\r\n position: absolute;\r\n width: 80%;\r\n height: 120px;\r\n background: #ffffff;\r\n border-radius: 8px;\r\n box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);\r\n border: 1px solid var(--border-color-default);\r\n transition: transform 0.3s ease-out;\r\n -webkit-transition: -webkit-transform 0.3s ease-out;\r\n left: 10%;\r\n /* Safari optimization: Force hardware acceleration and proper 3D rendering */\r\n -webkit-transform: translateZ(0);\r\n transform: translateZ(0);\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n backface-visibility: hidden;\r\n -webkit-backface-visibility: hidden;\r\n /* Safari optimization: Prevent subpixel rendering issues */\r\n -webkit-font-smoothing: antialiased;\r\n /* Safari optimization: Ensure proper layer creation */\r\n will-change: transform;\r\n }\r\n \r\n .page-sheet:nth-child(1) {\r\n bottom: 2px;\r\n z-index: 6;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(1) translateZ(0.1px);\r\n transform: scale(1) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(2) {\r\n bottom: 8px;\r\n z-index: 5;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.98) translateZ(0.1px);\r\n transform: scale(0.98) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(3) {\r\n bottom: 14px;\r\n z-index: 4;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.96) translateZ(0.1px);\r\n transform: scale(0.96) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(4) {\r\n bottom: 20px;\r\n z-index: 3;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.94) translateZ(0.1px);\r\n transform: scale(0.94) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(5) {\r\n bottom: 26px;\r\n z-index: 2;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.92) translateZ(0.1px);\r\n transform: scale(0.92) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(6) {\r\n bottom: 32px;\r\n z-index: 1;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.90) translateZ(0.1px);\r\n transform: scale(0.90) translateZ(0.1px);\r\n }\r\n \r\n .folder-front {\r\n position: absolute;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n height: 116px;\r\n border-radius: 12px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 8px;\r\n z-index: 2;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n transition: transform 0.4s ease-in-out, -webkit-transform 0.4s ease-in-out;\r\n -webkit-transition: -webkit-transform 0.4s ease-in-out;\r\n will-change: transform;\r\n backface-visibility: hidden;\r\n -webkit-backface-visibility: hidden;\r\n -webkit-font-smoothing: antialiased;\r\n /* Safari optimization: Use more specific transform to avoid render glitches */\r\n -webkit-transform: rotateX(-20deg) translateZ(0.1px);\r\n transform: rotateX(-20deg) translateZ(0.1px);\r\n /* Safari optimization: Force layer creation for smoother animations */\r\n -webkit-transform: translate3d(0, 0, 0) rotateX(-20deg);\r\n transform: translate3d(0, 0, 0) rotateX(-20deg);\r\n box-shadow: inset 0 64px 48px rgba(255, 255, 255, 0.2), \r\n inset 0 2px 4px rgba(255, 255, 255, 0.3),\r\n inset 0 1px 1px rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .item-count {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n \r\n .item-count-label {\r\n letter-spacing: 0.5px;\r\n }\r\n \r\n .folder-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .folder-label-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n \r\n .folder-label {\r\n text-align: center;\r\n }\r\n\r\n .loading-indicator,\r\n .error-indicator {\r\n font-size: var(--font-size-xs);\r\n }\r\n `],\r\n template: `\r\n <div class=\"folder-container\" \r\n [class.open]=\"isOpen()\">\r\n <!-- Folder Tab SVG -->\r\n <svg \r\n class=\"folder-tab\" \r\n width=\"101\" \r\n height=\"24\" \r\n viewBox=\"0 0 101 24\" \r\n fill=\"none\" \r\n xmlns=\"http://www.w3.org/2000/svg\">\r\n <path \r\n d=\"M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z\" \r\n [attr.fill]=\"getColorVar('strong')\"/>\r\n </svg>\r\n \r\n <!-- Folder Back -->\r\n <div class=\"folder-back\" [style.background-color]=\"getColorVar('strong')\">\r\n <!-- Page Sheets -->\r\n @for (sheet of getPageSheets(); track $index) {\r\n <div class=\"page-sheet\"></div>\r\n }\r\n \r\n <!-- Folder Front -->\r\n <div \r\n class=\"folder-front\" \r\n [style.--border-color]=\"getColorVar('strong')\"\r\n [style.background-color]=\"getColorVar('base')\">\r\n <!-- Icon (Centered) -->\r\n <div class=\"folder-icon\">\r\n <ds-icon \r\n [name]=\"iconName\" \r\n [size]=\"'32px'\"\r\n [style.color]=\"'white'\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Label and Item Count -->\r\n <div class=\"folder-label-container\">\r\n <div class=\"folder-label ui-sm-semiBold\">{{ label }}</div>\r\n <div class=\"item-count ui-sm-regular\" [style.color]=\"'var(--color-text-secondary, #6b7280)'\">\r\n @if (loading) {\r\n <span class=\"loading-indicator\">Loading...</span>\r\n } @else if (error) {\r\n <span class=\"error-indicator\" [style.color]=\"'var(--color-destructive-base)'\">Error</span>\r\n } @else {\r\n <span>{{ itemCount }}</span>\r\n <span class=\"item-count-label\">emner</span>\r\n }\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileHandbookFolderComponent {\r\n /**\r\n * Color variant for the folder\r\n * Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey\r\n * Example: 'pink', 'success', 'blue'\r\n */\r\n @Input() variant: string = 'light-purple';\r\n \r\n /**\r\n * Icon name from the design system icon library\r\n * Example: 'remixLightbulbLine', 'remixFolder3Line'\r\n */\r\n @Input() iconName: string = 'remixFolder3Line';\r\n \r\n /**\r\n * Number of items in the folder\r\n * This should match the length of the items array when data is loaded\r\n */\r\n @Input() itemCount: number = 0;\r\n \r\n /**\r\n * Label text displayed below the folder (category name)\r\n */\r\n @Input() label: string = 'Folder';\r\n \r\n /**\r\n * Optional items data for the handbook folder\r\n * Pass the HandbookItem[] array from your API response here\r\n */\r\n @Input() items?: HandbookItem[];\r\n \r\n /**\r\n * Loading state - when true, shows \"Loading...\" indicator instead of item count\r\n * Set this to true while fetching data from your API\r\n */\r\n @Input() loading: boolean = false;\r\n \r\n /**\r\n * Error state - when set, shows \"Error\" indicator instead of item count\r\n * Set this to an error message string if API call fails\r\n */\r\n @Input() error?: string;\r\n \r\n /**\r\n * Track open/closed state for animation\r\n */\r\n isOpen = signal(false);\r\n \r\n /**\r\n * Get the CSS variable name for the color variant\r\n */\r\n getColorVar(suffix: 'base' | 'strong'): string {\r\n const variantMap: Record<string, string> = {\r\n 'success': 'success',\r\n 'warning': 'warning',\r\n 'destructive': 'destructive',\r\n 'blue': 'blue',\r\n 'light-purple': 'light-purple',\r\n 'pink': 'pink',\r\n 'salmon-orange': 'salmon-orange',\r\n 'orange': 'orange',\r\n 'lime-green': 'lime-green',\r\n 'grey': 'grey'\r\n };\r\n \r\n const colorName = variantMap[this.variant] || 'light-purple';\r\n return `var(--color-${colorName}-${suffix})`;\r\n }\r\n \r\n /**\r\n * Open folder animation\r\n */\r\n @HostListener('mouseenter')\r\n open(): void {\r\n this.isOpen.set(true);\r\n }\r\n \r\n /**\r\n * Close folder animation\r\n */\r\n @HostListener('mouseleave')\r\n close(): void {\r\n this.isOpen.set(false);\r\n }\r\n \r\n /**\r\n * Handle touch start - open animation\r\n */\r\n @HostListener('touchstart', ['$event'])\r\n onTouchStart(event: TouchEvent): void {\r\n this.isOpen.set(true);\r\n }\r\n \r\n /**\r\n * Handle touch end - close animation\r\n */\r\n @HostListener('touchend')\r\n onTouchEnd(): void {\r\n this.isOpen.set(false);\r\n }\r\n \r\n /**\r\n * Handle touch cancel - close animation\r\n */\r\n @HostListener('touchcancel')\r\n onTouchCancel(): void {\r\n this.isOpen.set(false);\r\n }\r\n \r\n /**\r\n * Handle click - open modal\r\n * Only opens modal if not in loading or error state\r\n */\r\n @HostListener('click')\r\n async onClick(): Promise<void> {\r\n // Don't open modal if loading or in error state\r\n if (this.loading || this.error) {\r\n return;\r\n }\r\n\r\n const handbookData: HandbookDetailData = {\r\n title: this.label,\r\n variant: this.variant,\r\n iconName: this.iconName,\r\n itemCount: this.itemCount,\r\n items: this.items\r\n };\r\n\r\n await this.handbookModal.open(handbookData, {\r\n loading: this.loading,\r\n error: this.error\r\n });\r\n }\r\n \r\n /**\r\n * Calculate the number of page sheets to display\r\n * Max 6 sheets regardless of item count\r\n */\r\n getPageSheets(): number[] {\r\n const count = Math.min(this.itemCount, 6);\r\n return Array(count).fill(0);\r\n }\r\n\r\n constructor(\r\n private handbookModal: DsMobileHandbookDetailModalService\r\n ) {}\r\n}\r\n\r\n","import { Component, input, output, signal, computed, forwardRef } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';\r\n\r\n/**\r\n * DsTextInputComponent\r\n * \r\n * Mobile-first text input field component following the design system.\r\n * Supports email, phone, text, and other input types.\r\n * \r\n * Features:\r\n * - All design system states (default, hover, focus, error, disabled)\r\n * - Validation error state with destructive border color\r\n * - Automatic error clearing when input becomes valid (configurable)\r\n * - Built-in validation based on input type or custom validator function\r\n * - Accessible with proper ARIA attributes\r\n * - ControlValueAccessor for Angular forms integration\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Basic usage -->\r\n * <ds-text-input\r\n * type=\"email\"\r\n * placeholder=\"Enter your email\"\r\n * [(ngModel)]=\"email\">\r\n * </ds-text-input>\r\n * \r\n * <!-- With validation error and auto-clear -->\r\n * <ds-text-input\r\n * type=\"email\"\r\n * placeholder=\"Enter your email\"\r\n * [hasError]=\"emailInvalid\"\r\n * errorMessage=\"Please enter a valid email\"\r\n * [autoClearError]=\"true\"\r\n * (errorCleared)=\"emailInvalid = false\"\r\n * [(ngModel)]=\"email\">\r\n * </ds-text-input>\r\n * \r\n * <!-- With custom validator -->\r\n * <ds-text-input\r\n * type=\"text\"\r\n * placeholder=\"Enter phone number\"\r\n * [validator]=\"phoneValidator\"\r\n * [hasError]=\"phoneInvalid\"\r\n * (errorCleared)=\"phoneInvalid = false\"\r\n * [(ngModel)]=\"phone\">\r\n * </ds-text-input>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-text-input',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => DsTextInputComponent),\r\n multi: true\r\n }\r\n ],\r\n styles: [`\r\n :host {\r\n display: block;\r\n width: 100%;\r\n }\r\n\r\n .text-input-wrapper {\r\n position: relative;\r\n width: 100%;\r\n }\r\n\r\n .text-input {\r\n width: 100%;\r\n height: 48px;\r\n padding: 0 16px;\r\n box-sizing: border-box;\r\n \r\n /* Typography */\r\n font-family: 'Brockmann', system-ui, -apple-system, sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--text-color-default-primary);\r\n \r\n /* Background & Border */\r\n background-color: var(--color-background-neutral-primary);\r\n border: 1px solid var(--border-color-default);\r\n border-radius: 8px;\r\n \r\n /* Transitions */\r\n transition: \r\n border-color var(--transition-duration-fast) var(--ease-smooth),\r\n background-color var(--transition-duration-fast) var(--ease-smooth),\r\n box-shadow var(--transition-duration-fast) var(--ease-smooth);\r\n \r\n /* Remove default browser styles */\r\n outline: none;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n }\r\n\r\n /* Placeholder styling */\r\n .text-input::placeholder {\r\n color: var(--text-color-default-tertiary);\r\n }\r\n\r\n /* Default state - no additional styles needed */\r\n\r\n /* Hover state */\r\n .text-input:hover:not(:disabled):not(:focus) {\r\n border-color: var(--border-color-default);\r\n background-color: var(--color-background-neutral-primary-hover);\r\n }\r\n\r\n /* Focus state */\r\n .text-input:focus {\r\n border-color: var(--color-brand-base);\r\n background-color: var(--color-background-neutral-primary);\r\n box-shadow: 0 0 0 3px var(--outline-color-default);\r\n }\r\n\r\n /* Error state */\r\n .text-input.error {\r\n border-color: var(--color-destructive-base);\r\n }\r\n\r\n .text-input.error:focus {\r\n border-color: var(--color-destructive-base);\r\n box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);\r\n }\r\n\r\n /* Disabled state */\r\n .text-input:disabled {\r\n background-color: var(--color-background-neutral-disabled);\r\n border-color: var(--border-color-default);\r\n color: var(--text-color-default-disabled);\r\n cursor: not-allowed;\r\n }\r\n\r\n .text-input:disabled::placeholder {\r\n color: var(--text-color-default-disabled);\r\n }\r\n\r\n /* Error message */\r\n .error-message {\r\n margin-top: 8px;\r\n font-family: 'Brockmann', system-ui, -apple-system, sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-destructive-base);\r\n }\r\n `],\r\n template: `\r\n <div class=\"text-input-wrapper\">\r\n <input\r\n [type]=\"type()\"\r\n [placeholder]=\"placeholder()\"\r\n [value]=\"value()\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [required]=\"required()\"\r\n [autocomplete]=\"autocomplete() || null\"\r\n [attr.inputmode]=\"inputmode() || null\"\r\n [class.error]=\"hasError()\"\r\n [attr.aria-invalid]=\"hasError()\"\r\n [attr.aria-describedby]=\"hasError() && errorMessage() ? 'error-' + inputId : null\"\r\n class=\"text-input\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onBlur()\"\r\n (focus)=\"onFocus()\"\r\n [id]=\"inputId\">\r\n \r\n @if (hasError() && errorMessage()) {\r\n <div \r\n class=\"error-message\"\r\n [id]=\"'error-' + inputId\"\r\n role=\"alert\">\r\n {{ errorMessage() }}\r\n </div>\r\n }\r\n </div>\r\n `\r\n})\r\nexport class DsTextInputComponent implements ControlValueAccessor {\r\n // Input properties\r\n type = input<'text' | 'email' | 'tel' | 'password' | 'url' | 'search'>('text');\r\n placeholder = input<string>('');\r\n disabled = input<boolean>(false);\r\n readonly = input<boolean>(false);\r\n required = input<boolean>(false);\r\n hasError = input<boolean>(false);\r\n errorMessage = input<string>('');\r\n autocomplete = input<string>('');\r\n inputmode = input<'text' | 'email' | 'tel' | 'numeric' | 'url' | 'search' | undefined>(undefined);\r\n autoClearError = input<boolean>(true);\r\n validator = input<((value: string) => boolean) | null>(null);\r\n\r\n // Output events\r\n valueChange = output<string>();\r\n blur = output<FocusEvent>();\r\n focus = output<FocusEvent>();\r\n errorCleared = output<void>();\r\n\r\n // Internal state\r\n private _value = signal<string>('');\r\n value = computed(() => this._value());\r\n \r\n // Generate unique ID for accessibility\r\n inputId = `ds-text-input-${Math.random().toString(36).substring(2, 9)}`;\r\n\r\n // ControlValueAccessor implementation\r\n private onChange = (value: string) => {};\r\n private onTouched = () => {};\r\n\r\n onInput(event: Event): void {\r\n const target = event.target as HTMLInputElement;\r\n const newValue = target.value;\r\n this._value.set(newValue);\r\n this.onChange(newValue);\r\n this.valueChange.emit(newValue);\r\n \r\n // Auto-clear error if input becomes valid\r\n if (this.autoClearError() && this.hasError()) {\r\n const isValid = this.validateInput(newValue);\r\n if (isValid) {\r\n this.errorCleared.emit();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Validates the input value based on type or custom validator\r\n */\r\n private validateInput(value: string): boolean {\r\n // Use custom validator if provided\r\n const customValidator = this.validator();\r\n if (customValidator) {\r\n return customValidator(value);\r\n }\r\n\r\n // Use built-in validation based on input type\r\n const inputType = this.type();\r\n const inputElement = document.createElement('input');\r\n inputElement.type = inputType;\r\n inputElement.value = value;\r\n \r\n // For email type, use HTML5 validation\r\n if (inputType === 'email') {\r\n return inputElement.validity.valid;\r\n }\r\n \r\n // For required fields, check if value exists\r\n if (this.required() && !value.trim()) {\r\n return false;\r\n }\r\n \r\n // Default: valid if HTML5 validation passes\r\n return inputElement.validity.valid;\r\n }\r\n\r\n onBlur(): void {\r\n this.onTouched();\r\n }\r\n\r\n onFocus(): void {\r\n // Focus event can be emitted if needed\r\n }\r\n\r\n // ControlValueAccessor methods\r\n writeValue(value: string): void {\r\n this._value.set(value || '');\r\n }\r\n\r\n registerOnChange(fn: (value: string) => void): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: () => void): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n // Angular forms will handle this via the disabled input\r\n }\r\n}\r\n\r\n","// Mobile Page Components\r\nexport * from './page-main';\r\nexport * from './page-details';\r\n\r\n// Mobile Content Components\r\nexport * from './content';\r\nexport * from './header-content';\r\n\r\n// Mobile Community Components\r\nexport * from './comment';\r\nexport * from './post-composer';\r\nexport * from './message-composer';\r\nexport * from './message-bubble';\r\n\r\n// Mobile List Components\r\nexport * from './list-item';\r\nexport * from './list-item-static';\r\nexport { \r\n DsMobileInteractiveListItemPostComponent, \r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n PostPdfAttachmentComponent \r\n} from './interactive-list-item-post';\r\nexport { DsMobileInteractiveListItemInquiryComponent } from './interactive-list-item-inquiry';\r\nexport { DsMobileInteractiveListItemMessageComponent } from './interactive-list-item-message';\r\nexport { DsMobileContactListItemComponent } from './contact-list-item';\r\n\r\n// Mobile Layout Components\r\nexport { DsMobileTabsComponent } from './tabs';\r\nexport { DsMobileTabBarComponent, type TabConfig } from './tab-bar';\r\nexport { DsMobileInlineTabsComponent, type InlineTabItem } from './inline-tabs';\r\n\r\n// Mobile Bottom Sheet Components\r\nexport * from './bottom-sheet';\r\n\r\n// Mobile Lightbox Components\r\nexport * from './lightbox';\r\n\r\n// Mobile Inline Photo Component\r\nexport * from './inline-photo';\r\n\r\n// Mobile Modal Service\r\nexport * from './modal';\r\n\r\n// Mobile Post Detail Modal\r\nexport * from './post-detail-modal';\r\n\r\n// Mobile Chat Modal\r\nexport * from './chat-modal';\r\n\r\n// Mobile Handbook Components\r\nexport * from './handbook-folder';\r\nexport * from './handbook-detail-modal';\r\n\r\n// Text Input Component\r\nexport * from './text-input';\r\n\r\n// Shared directives\r\nexport * from './shared';","import { Component, signal, computed } from '@angular/core';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { DsMobileContentComponent } from '../components/content';\r\nimport { DsMobileInteractiveListItemPostComponent } from '../components/interactive-list-item-post';\r\nimport { DsMobileCardInlineFileComponent } from '../components/card-inline-file';\r\nimport { \r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent\r\n} from '../components/interactive-list-item-post';\r\nimport { DsMobilePostComposerComponent } from '../components/post-composer';\r\nimport { DsMobileBottomSheetService } from '../components/bottom-sheet/ds-mobile-bottom-sheet.service';\r\nimport { DsMobilePostCreateBottomSheetComponent } from '../components/bottom-sheet/ds-mobile-post-create-bottom-sheet';\r\nimport { DsMobilePostActionsBottomSheetComponent, PostActionResult } from '../components/bottom-sheet';\r\nimport { DsMobileLightboxService, LightboxAuthor } from '../components/lightbox';\r\nimport { DsMobilePostDetailModalService } from '../components/post-detail-modal';\r\nimport { DsMobileInlinePhotoComponent } from '../components/inline-photo';\r\nimport { UserService } from '../services/user.service';\r\n\r\n@Component({\r\n selector: 'app-mobile-community-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageMainComponent,\r\n DsMobileContentComponent,\r\n DsMobileInteractiveListItemPostComponent,\r\n DsMobilePostComposerComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCardInlineFileComponent,\r\n DsIconComponent,\r\n DsMobileInlinePhotoComponent\r\n ],\r\n styles: [`\r\n .post-feed {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n .post-list-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n /* Remove custom dividers - now handled by ds-mobile-list-item */\r\n \r\n .pinned-posts-section {\r\n margin: -12px -12px 12px -12px;\r\n padding: 0 12px 12px 12px;\r\n box-shadow: var(--box-shadow-sm);\r\n border-radius: 16px;\r\n border: 1px solid var(--border-color-default);\r\n }\r\n \r\n .clickable-image {\r\n cursor: pointer;\r\n transition: transform 0.2s ease, opacity 0.2s ease;\r\n border-radius: 8px;\r\n display: block;\r\n width: 100%;\r\n aspect-ratio: 16/9;\r\n object-fit: cover;\r\n }\r\n \r\n .clickable-image:active {\r\n transform: scale(0.98);\r\n opacity: 0.9;\r\n }\r\n \r\n /* Empty State */\r\n .community-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-image {\r\n width: 96px;\r\n height: 96px;\r\n margin-bottom: 24px;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Fællesskab\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n (refresh)=\"handleRefresh($event)\">\r\n \r\n <!-- Post Composer in header-expandable -->\r\n <ds-mobile-post-composer\r\n header-content\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n [avatarSrc]=\"userService.avatarSrc()\"\r\n (composerClick)=\"openPostCreator()\"\r\n />\r\n \r\n <ds-mobile-content>\r\n <div class=\"post-feed\">\r\n <!-- Pinned Posts Section -->\r\n <div class=\"pinned-posts-section\">\r\n <h2 class=\"section-headline\">\r\n <ds-icon name=\"remixPushpinFill\" size=\"16px\" color=\"primary\" />\r\n Fastgjorte opslag\r\n </h2>\r\n \r\n <!-- Pinned: Maintenance Announcement -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Karen Nielsen'\"\r\n [authorRole]=\"'Ejendomsadministrator'\"\r\n [timestamp]=\"'2d siden'\"\r\n [avatarInitials]=\"'KN'\"\r\n [showBadge]=\"true\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('4')\"\r\n (commentClick)=\"openPost('4', true)\"\r\n (longPress)=\"handlePostLongPress('4', false)\">\r\n \r\n <post-content>\r\n <post-text>📢 Påmindelse: Bygningsvedligeholdelse planlagt til denne lørdag fra kl. 9 til 14. Vandet vil være midlertidigt lukket. Vær venlig at planlægge derefter!</post-text>\r\n \r\n <post-attachments>\r\n <ds-mobile-card-inline-file\r\n [fileName]=\"'Husregler.pdf'\"\r\n [fileSize]=\"'245 KB'\"\r\n [variant]=\"'pdf'\"\r\n [layout]=\"'compact'\"\r\n (fileClick)=\"openHouseRulesPdf()\">\r\n </ds-mobile-card-inline-file>\r\n </post-attachments>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"89\" />\r\n <action-comment [count]=\"67\" (commentClick)=\"openPost('4', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n </div>\r\n \r\n <!-- All Posts Section -->\r\n <h2 class=\"section-headline\">Alle opslag</h2>\r\n \r\n @if (hasAnyPosts()) {\r\n <div class=\"post-list-wrapper\">\r\n <!-- User Created Posts -->\r\n @for (post of userPosts(); track $index) {\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"post.authorName\"\r\n [authorRole]=\"post.authorRole\"\r\n [timestamp]=\"post.timestamp\"\r\n [avatarType]=\"post.avatarType\"\r\n [avatarSrc]=\"post.avatarSrc\"\r\n [avatarInitials]=\"post.avatarInitials\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openUserPost($index)\"\r\n (commentClick)=\"openUserPost($index, true)\"\r\n (longPress)=\"handlePostLongPress($index, post.authorRole === 'Dig')\">\r\n \r\n <post-content>\r\n @if (post.content) {\r\n <post-text>{{ post.content }}</post-text>\r\n }\r\n @if (post.imageSrc) {\r\n <post-media>\r\n <img \r\n [src]=\"post.imageSrc\" \r\n [alt]=\"post.imageAlt || 'Posted image'\" \r\n class=\"clickable-image\"\r\n (click)=\"openImageLightbox(post.imageSrc, post.imageAlt || 'Posted image', post.content, $event)\"\r\n />\r\n </post-media>\r\n }\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"post.likeCount\" [active]=\"post.isLiked\" />\r\n <action-comment [count]=\"post.commentCount\" (commentClick)=\"openUserPost($index, true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n }\r\n \r\n <!-- Post 1: Text only -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Anders Jensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'2t siden'\"\r\n [avatarType]=\"'photo'\"\r\n [avatarSrc]=\"'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=face'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('1')\"\r\n (commentClick)=\"openPost('1', true)\"\r\n (longPress)=\"handlePostLongPress('1', false)\">\r\n \r\n <post-content>\r\n <post-text>Lige flyttet ind i min nye lejlighed! Udlejeren var super hjælpsom gennem hele processen. Virkelig begejstret for at være en del af dette fællesskab! 🏠</post-text>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"42\" />\r\n <action-comment [count]=\"12\" (commentClick)=\"openPost('1', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 2: With multiple images (grid layout) -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Sophie Andersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'4t siden'\"\r\n [avatarInitials]=\"'SA'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('2')\"\r\n (commentClick)=\"openPost('2', true)\"\r\n (longPress)=\"handlePostLongPress('2', false)\">\r\n \r\n <post-content>\r\n <post-text>Jeg har taget nogle billeder af vores smukke ejendom i løbet af det sidste par måneder. Fra altanudsigten om morgenen til den nye trappe og fællesområderne. Elsker virkelig at bo her! 🏡✨</post-text>\r\n <ds-mobile-inline-photo\r\n [images]=\"[\r\n '/Assets/Dummy-photos/balcony-view.jpg',\r\n '/Assets/Dummy-photos/staircase.jpg',\r\n '/Assets/Dummy-photos/park.jpg',\r\n '/Assets/Dummy-photos/yard.jpg'\r\n ]\"\r\n [author]=\"{\r\n name: 'Sophie Andersen',\r\n role: 'Lejer',\r\n avatarInitials: 'SA',\r\n avatarType: 'initials',\r\n timestamp: '4t siden'\r\n }\"\r\n />\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [active]=\"true\" [count]=\"156\" />\r\n <action-comment [count]=\"34\" (commentClick)=\"openPost('2', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 3: Question -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Thomas Hansen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'1d siden'\"\r\n [avatarType]=\"'photo'\"\r\n [avatarSrc]=\"'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('3')\"\r\n (commentClick)=\"openPost('3', true)\"\r\n (longPress)=\"handlePostLongPress('3', false)\">\r\n \r\n <post-content>\r\n <post-text>Kender nogen et fælles fitnesscenter i nærheden? Leder efter anbefalinger til gode træningscentre i området. 🏋️</post-text>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"23\" />\r\n <action-comment [count]=\"45\" (commentClick)=\"openPost('3', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 3.5: Property Manager showcase with 6+ photos -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Karen Nielsen'\"\r\n [authorRole]=\"'Ejendomsadministrator'\"\r\n [timestamp]=\"'2d siden'\"\r\n [avatarInitials]=\"'KN'\"\r\n [showBadge]=\"true\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('3.5')\"\r\n (commentClick)=\"openPost('3.5', true)\"\r\n (longPress)=\"handlePostLongPress('3.5', false)\">\r\n \r\n <post-content>\r\n <post-text>Her er et kig på vores nyligt renoverede fællesområder! Vi har opgraderet postkasserne, trappeafsatsen og gårdområdet. Der er også blevet ansat en ny vicevært. Glæd dig over forbedringerne! 🏢✨</post-text>\r\n <ds-mobile-inline-photo\r\n [images]=\"[\r\n '/Assets/Dummy-photos/mailboxes.jpg',\r\n '/Assets/Dummy-photos/staircase.jpg',\r\n '/Assets/Dummy-photos/yard.jpg',\r\n '/Assets/Dummy-photos/park.jpg',\r\n '/Assets/Dummy-photos/balcony-view.jpg',\r\n '/Assets/Dummy-photos/handyman.jpg'\r\n ]\"\r\n [author]=\"{\r\n name: 'Karen Nielsen',\r\n role: 'Ejendomsadministrator',\r\n avatarInitials: 'KN',\r\n avatarType: 'initials',\r\n timestamp: '2d siden'\r\n }\"\r\n [maxVisible]=\"5\"\r\n />\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"234\" />\r\n <action-comment [count]=\"89\" (commentClick)=\"openPost('3.5', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 5: Event -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Emma Petersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'3d siden'\"\r\n [avatarType]=\"'photo'\"\r\n [avatarSrc]=\"'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('5')\"\r\n (commentClick)=\"openPost('5', true)\"\r\n (longPress)=\"handlePostLongPress('5', false)\">\r\n \r\n <post-content>\r\n <post-text>Arrangerer en fælles BBQ næste weekend! Alle er inviteret. Tag din yndlingsret med til at dele. Lad os lære hinanden bedre at kende! 🍔🌭</post-text>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [active]=\"true\" [count]=\"124\" />\r\n <action-comment [count]=\"89\" (commentClick)=\"openPost('5', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n </div>\r\n } @else {\r\n <!-- Empty State -->\r\n <div class=\"community-empty-state\">\r\n <img \r\n src=\"/Assets/Empty%20state-chat.png\" \r\n alt=\"Ingen opslag endnu\" \r\n class=\"empty-state-image\"\r\n />\r\n <h3 class=\"empty-state-title\">Ingen opslag endnu</h3>\r\n <p class=\"empty-state-description\">Vær den første til at dele noget med dit fællesskab</p>\r\n </div>\r\n }\r\n </div>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileCommunityPageComponent {\r\n // Store user-created posts\r\n userPosts = signal<any[]>([\r\n {\r\n id: 'user-post-1',\r\n authorName: 'Lars Mikkelsen',\r\n authorRole: 'Dig',\r\n timestamp: '5m siden',\r\n avatarType: 'initials' as 'photo' | 'initials' | 'icon',\r\n avatarInitials: 'LM',\r\n content: 'Dette er mit første opslag! Ser frem til at forbinde med alle i bygningen. 🏠',\r\n isLiked: false,\r\n likeCount: 3,\r\n commentCount: 1\r\n }\r\n ]);\r\n \r\n // Flag to control whether static demo posts are shown\r\n // Set to false to see the empty state\r\n showStaticPosts = signal(true);\r\n \r\n // Computed to check if there are any posts to display\r\n hasAnyPosts = computed(() => {\r\n return this.userPosts().length > 0 || this.showStaticPosts();\r\n });\r\n \r\n constructor(\r\n private router: Router,\r\n private route: ActivatedRoute,\r\n private bottomSheet: DsMobileBottomSheetService,\r\n private lightbox: DsMobileLightboxService,\r\n private postModal: DsMobilePostDetailModalService,\r\n public userService: UserService\r\n ) {}\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n \r\n /**\r\n * Open post detail modal\r\n * This provides a better UX than route navigation:\r\n * - Maintains scroll position\r\n * - Native iOS-style modal feel\r\n * - Proper close button that works\r\n */\r\n async openPost(postId: string, focusComment: boolean = false): Promise<void> {\r\n console.log('[Community] ===== openPost called =====', postId, 'Focus comment:', focusComment);\r\n \r\n // Map post ID to post data (in real app, fetch from service)\r\n const postDataMap: Record<string, any> = {\r\n '1': {\r\n postId: '1',\r\n authorName: 'Anders Jensen',\r\n authorRole: 'Lejer',\r\n timestamp: '2t siden',\r\n avatarType: 'photo' as const,\r\n avatarSrc: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=face',\r\n content: 'Lige flyttet ind i min nye lejlighed! Udlejeren var super hjælpsom gennem hele processen. Virkelig begejstret for at være en del af dette fællesskab! 🏠',\r\n isLiked: false,\r\n likeCount: 42,\r\n commentCount: 12,\r\n comments: [\r\n {\r\n authorName: 'Mette Larsen',\r\n authorRole: 'Lejer',\r\n timestamp: '1t siden',\r\n avatarInitials: 'ML',\r\n content: 'Velkommen til fællesskabet!',\r\n likeCount: 5,\r\n isOwnComment: false\r\n },\r\n {\r\n authorName: 'Lars Mikkelsen',\r\n authorRole: 'Dig',\r\n timestamp: 'Lige nu',\r\n avatarInitials: 'LM',\r\n content: 'Vxhknbh',\r\n likeCount: 0,\r\n isOwnComment: true\r\n }\r\n ]\r\n },\r\n '2': {\r\n postId: '2',\r\n authorName: 'Sophie Andersen',\r\n authorRole: 'Lejer',\r\n timestamp: '4t siden',\r\n avatarInitials: 'SA',\r\n content: 'Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️',\r\n imageSrc: '/Assets/Dummy-photos/balcony-view.jpg',\r\n imageAlt: 'Altanudsigt',\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 34,\r\n comments: [\r\n {\r\n authorName: 'Anders Jensen',\r\n authorRole: 'Lejer',\r\n timestamp: '3t siden',\r\n avatarInitials: 'AJ',\r\n content: 'Wow, den udsigt er fantastisk! Hvilken etage er du på?',\r\n likeCount: 12,\r\n isOwnComment: false\r\n },\r\n {\r\n authorName: 'Thomas Hansen',\r\n authorRole: 'Lejer',\r\n timestamp: '3t siden',\r\n avatarInitials: 'TH',\r\n content: 'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆',\r\n isLiked: true,\r\n likeCount: 8,\r\n isOwnComment: false\r\n },\r\n {\r\n authorName: 'Lars Mikkelsen',\r\n authorRole: 'Dig',\r\n timestamp: 'Lige nu',\r\n avatarInitials: 'LM',\r\n content: 'Vxhknbh',\r\n likeCount: 0,\r\n isOwnComment: true\r\n }\r\n ]\r\n },\r\n '3': {\r\n postId: '3',\r\n authorName: 'Thomas Hansen',\r\n authorRole: 'Lejer',\r\n timestamp: '1d siden',\r\n avatarType: 'photo' as const,\r\n avatarSrc: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face',\r\n content: 'Kender nogen et fælles fitnesscenter i nærheden? Leder efter anbefalinger til gode træningscentre i området. 🏋️',\r\n isLiked: false,\r\n likeCount: 23,\r\n commentCount: 45,\r\n comments: []\r\n },\r\n '4': {\r\n postId: '4',\r\n authorName: 'Karen Nielsen',\r\n authorRole: 'Ejendomsadministrator',\r\n timestamp: '2d siden',\r\n avatarInitials: 'KN',\r\n content: '📢 Påmindelse: Bygningsvedligeholdelse planlagt til denne lørdag fra kl. 9 til 14. Vandet vil være midlertidigt lukket. Vær venlig at planlægge derefter!',\r\n isLiked: false,\r\n likeCount: 89,\r\n commentCount: 67,\r\n comments: []\r\n },\r\n '5': {\r\n postId: '5',\r\n authorName: 'Emma Petersen',\r\n authorRole: 'Lejer',\r\n timestamp: '3d siden',\r\n avatarType: 'photo' as const,\r\n avatarSrc: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face',\r\n content: 'Arrangerer en fælles BBQ næste weekend! Alle er inviteret. Tag din yndlingsret med til at dele. Lad os lære hinanden bedre at kende! 🍔🌭',\r\n isLiked: true,\r\n likeCount: 124,\r\n commentCount: 89,\r\n comments: []\r\n }\r\n };\r\n\r\n const postData = postDataMap[postId];\r\n \r\n if (postData) {\r\n // Add focusComment flag to postData\r\n await this.postModal.open({ ...postData, focusComment });\r\n }\r\n }\r\n \r\n /**\r\n * Open user-created post detail modal\r\n */\r\n async openUserPost(index: number, focusComment: boolean = false): Promise<void> {\r\n const posts = this.userPosts();\r\n const post = posts[index];\r\n \r\n if (post) {\r\n console.log('[Community] Opening user post modal:', index, 'Focus comment:', focusComment);\r\n \r\n // Convert user post to modal format with empty comments array\r\n const postData = {\r\n ...post,\r\n postId: `user-${index}`,\r\n comments: [] // User posts don't have comments yet\r\n };\r\n \r\n await this.postModal.open({ ...postData, focusComment });\r\n }\r\n }\r\n \r\n async openPostCreator(): Promise<void> {\r\n // Open the post creator as a bottom sheet modal\r\n // Using 95% initial height to maximize keyboard auto-open chances\r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobilePostCreateBottomSheetComponent,\r\n componentProps: {\r\n // This helps the component know it should auto-focus\r\n autoFocus: true\r\n },\r\n breakpoints: [0, 0.95, 1],\r\n initialBreakpoint: 0.95,\r\n handle: true\r\n });\r\n \r\n // Handle the result when the sheet is dismissed\r\n const result = await sheet.onWillDismiss();\r\n if (result.role === 'post' && result.data) {\r\n console.log('New post created:', result.data);\r\n \r\n // Create a new post object\r\n const newPost = {\r\n id: `user-post-${Date.now()}`, // Generate unique ID\r\n authorName: 'Lars Mikkelsen', // Current user name\r\n authorRole: 'Dig',\r\n timestamp: 'Lige nu',\r\n avatarType: this.userService.avatarType() as 'photo' | 'initials' | 'icon',\r\n avatarSrc: this.userService.avatarSrc(),\r\n avatarInitials: this.userService.avatarInitials(),\r\n content: result.data.content,\r\n imageSrc: result.data.images && result.data.images.length > 0 ? result.data.images[0] : undefined,\r\n imageAlt: result.data.images && result.data.images.length > 0 ? 'Slået billede op' : undefined,\r\n isLiked: false,\r\n likeCount: 0,\r\n commentCount: 0\r\n };\r\n \r\n // Add to the beginning of the posts array\r\n this.userPosts.update(posts => [newPost, ...posts]);\r\n }\r\n }\r\n \r\n /**\r\n * Open an image in the lightbox viewer\r\n * Prevents the post click event from firing\r\n */\r\n async openImageLightbox(imageSrc: string, title: string, description: string, event: Event): Promise<void> {\r\n console.log('[Community] Opening lightbox for image:', imageSrc);\r\n \r\n // Prevent the post card click event from firing\r\n event.stopPropagation();\r\n \r\n const authorMeta: LightboxAuthor = {\r\n name: 'Sophie Andersen',\r\n role: 'Lejer',\r\n avatarInitials: 'SA',\r\n timestamp: '4t siden'\r\n };\r\n \r\n // Open the lightbox with the image\r\n await this.lightbox.open({\r\n images: [\r\n {\r\n type: 'image',\r\n src: imageSrc,\r\n alt: title,\r\n title: title,\r\n description: description,\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 34\r\n }\r\n ],\r\n author: authorMeta,\r\n enableZoom: true,\r\n showControls: false, // Single image, no need for controls\r\n showActions: true, // Show like & comment actions\r\n showInfo: true\r\n });\r\n }\r\n\r\n async openHouseRulesPdf(): Promise<void> {\r\n console.log('[Community] Opening House Rules PDF');\r\n \r\n // Author metadata\r\n const authorMeta: LightboxAuthor = {\r\n name: 'Karen Nielsen',\r\n role: 'Ejendomsadministrator',\r\n avatarInitials: 'KN',\r\n timestamp: '2d siden'\r\n };\r\n \r\n // Open the PDF lightbox\r\n // Use absolute path for production deployment (Vercel, etc.)\r\n await this.lightbox.openPdf({\r\n pdf: {\r\n type: 'pdf',\r\n src: '/Assets/House_Rules.pdf', // Capital A to match public/Assets folder structure\r\n title: 'House Rules',\r\n description: 'Building regulations and community guidelines',\r\n fileSize: 250880, // 245 KB in bytes\r\n pageCount: 8\r\n },\r\n author: authorMeta\r\n });\r\n }\r\n \r\n /**\r\n * Handle long press on a post to show action sheet\r\n */\r\n async handlePostLongPress(postIdOrIndex: string | number, isOwnPost: boolean): Promise<void> {\r\n console.log('[Community] Post long pressed:', postIdOrIndex, 'isOwn:', isOwnPost);\r\n \r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobilePostActionsBottomSheetComponent,\r\n componentProps: {\r\n isOwnContent: isOwnPost\r\n },\r\n breakpoints: [0, 1],\r\n initialBreakpoint: 1,\r\n handle: true,\r\n backdropDismiss: true,\r\n cssClass: 'auto-height'\r\n });\r\n \r\n const result = await sheet.onWillDismiss();\r\n \r\n if (result.role === 'select' && result.data) {\r\n const action = (result.data as PostActionResult).action;\r\n \r\n switch (action) {\r\n case 'edit':\r\n console.log('Edit post:', postIdOrIndex);\r\n // Open the post create bottom sheet in edit mode\r\n let postContent = '';\r\n let postId = '';\r\n \r\n // Get post content based on postIdOrIndex\r\n if (typeof postIdOrIndex === 'number') {\r\n const post = this.userPosts()[postIdOrIndex];\r\n if (post) {\r\n postContent = post.content || '';\r\n postId = post.id || postIdOrIndex.toString();\r\n }\r\n } else {\r\n // For static posts, we'll need to determine content\r\n // For now, use a placeholder\r\n postId = postIdOrIndex.toString();\r\n postContent = 'Edit this post...';\r\n }\r\n \r\n // Open the bottom sheet in edit mode\r\n const editSheet = await this.bottomSheet.create({\r\n component: DsMobilePostCreateBottomSheetComponent,\r\n componentProps: {\r\n autoFocus: true,\r\n isEditMode: true,\r\n postId: postId,\r\n initialContent: postContent\r\n },\r\n breakpoints: [0, 0.95, 1],\r\n initialBreakpoint: 0.95,\r\n handle: true,\r\n backdropBlur: true,\r\n backdropOpacity: 0.6\r\n });\r\n \r\n // Handle the result when the sheet is dismissed\r\n const editResult = await editSheet.onWillDismiss();\r\n if (editResult.role === 'post' && editResult.data) {\r\n console.log('Post updated:', editResult.data);\r\n \r\n // Update the post in the array\r\n if (typeof postIdOrIndex === 'number') {\r\n const currentPosts = this.userPosts();\r\n const updatedPosts = currentPosts.map((post, index) => \r\n index === postIdOrIndex \r\n ? { ...post, content: editResult.data.content, timestamp: 'Just now' }\r\n : post\r\n );\r\n this.userPosts.set(updatedPosts);\r\n }\r\n }\r\n break;\r\n case 'delete':\r\n console.log('Delete post:', postIdOrIndex);\r\n if (confirm('Er du sikker på, at du vil slette dette opslag?')) {\r\n // If it's a user post (number index), remove it from the array\r\n if (typeof postIdOrIndex === 'number') {\r\n const currentPosts = this.userPosts();\r\n const updatedPosts = currentPosts.filter((_, index) => index !== postIdOrIndex);\r\n this.userPosts.set(updatedPosts);\r\n }\r\n // Otherwise it's a static post, just show confirmation\r\n else {\r\n alert('Opslag slettet!');\r\n }\r\n }\r\n break;\r\n case 'like':\r\n console.log('Like post:', postIdOrIndex);\r\n // Toggle like - in a real app, this would call an API\r\n alert('Opslag liket!');\r\n break;\r\n case 'reply':\r\n console.log('Reply to post:', postIdOrIndex);\r\n // Open the post detail modal with comment input focused\r\n if (typeof postIdOrIndex === 'number') {\r\n await this.openUserPost(postIdOrIndex, true);\r\n } else {\r\n await this.openPost(postIdOrIndex, true);\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n","import { Component } from '@angular/core';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { \r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n} from '../components/content';\r\nimport { DsMobileHandbookFolderComponent } from '../components/handbook-folder';\r\nimport { UserService } from '../services/user.service';\r\nimport { HandbookItem } from '../components/handbook-detail-modal/ds-mobile-handbook-detail-modal';\r\n\r\n@Component({\r\n selector: 'app-mobile-handbook-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageMainComponent,\r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n DsMobileHandbookFolderComponent\r\n ],\r\n styles: [`\r\n .folders-grid {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 20px;\r\n justify-items: center;\r\n }\r\n\r\n /* 3 columns at tablet breakpoint (md: 768px) and above\r\n Content area at this breakpoint is ~864px max */\r\n @media (min-width: 768px) {\r\n .folders-grid {\r\n grid-template-columns: repeat(3, 1fr);\r\n }\r\n }\r\n \r\n ds-mobile-handbook-folder {\r\n width: 100%;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Håndbog\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n (refresh)=\"handleRefresh($event)\">\r\n \r\n <ds-mobile-content>\r\n <ds-mobile-content-section>\r\n <div class=\"folders-grid\">\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'pink'\"\r\n [iconName]=\"'remixLightbulbLine'\"\r\n [itemCount]=\"8\"\r\n [label]=\"'Forsyninger'\"\r\n [items]=\"utilitiesItems\">\r\n </ds-mobile-handbook-folder>\r\n\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'success'\"\r\n [iconName]=\"'remixKey2Line'\"\r\n [itemCount]=\"4\"\r\n [label]=\"'Sikkerhedsudstyr'\"\r\n [items]=\"sikkerhedsudstyrItems\">\r\n </ds-mobile-handbook-folder>\r\n\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'blue'\"\r\n [iconName]=\"'remixFileList3Line'\"\r\n [itemCount]=\"8\"\r\n [label]=\"'Servicekontrakter'\"\r\n [items]=\"serviceContractsItems\">\r\n </ds-mobile-handbook-folder>\r\n\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'warning'\"\r\n [iconName]=\"'remixToolsLine'\"\r\n [itemCount]=\"5\"\r\n [label]=\"'Udstyr'\"\r\n [items]=\"equipmentItems\">\r\n </ds-mobile-handbook-folder>\r\n </div>\r\n </ds-mobile-content-section>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileHandbookPageComponent {\r\n // Utilities folder data\r\n utilitiesItems: HandbookItem[] = [\r\n {\r\n title: 'El',\r\n description: 'Hovedeltavle placeret i kælderrum B-12. Nødafbryderknap er ved hovedindgangen. Alle kredsløb er mærket.',\r\n contacts: [\r\n { name: 'ElektroTek ApS', initials: 'E', contactPerson: 'Lars Nielsen', phoneNumber: '+45 23 45 67 89' }\r\n ]\r\n },\r\n {\r\n title: 'Elektrisk diagram',\r\n description: 'Komplet diagram over bygningens elektriske installation med alle kredsløb og afbrydere.',\r\n attachments: [\r\n { name: 'Elektrisk_Diagram.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Vandforsyning',\r\n description: 'Hovedvandhane er placeret i kælderens tekniske rum. Individuelle lejlighedsafspærringer er i gangpanelerne. Vandtryk overvåges automatisk.',\r\n contacts: [\r\n { name: 'VVS Hansen', initials: 'V', contactPerson: 'Peter Hansen', phoneNumber: '+45 34 56 78 90' }\r\n ]\r\n },\r\n {\r\n title: 'Varmesystem',\r\n description: 'Fjernvarmetilslutning i kælder. Termostater i hver enhed kan justeres individuelt. Systemet vedligeholdes kvartalsvis af certificerede teknikere.',\r\n contacts: [\r\n { name: 'Varme Service A/S', initials: 'V', contactPerson: 'Maria Jensen', phoneNumber: '+45 45 67 89 01' }\r\n ]\r\n },\r\n {\r\n title: 'Varmeanlæg dokumentation',\r\n description: 'Teknisk dokumentation og vedligeholdelseshistorik for bygningens varmesystem.',\r\n attachments: [\r\n { name: 'Varmeplan.pdf', type: 'pdf' },\r\n { name: 'Vedligeholdelseslog.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Internet & TV',\r\n description: 'Fiberforbindelse i bygningen. Distributionspanel er i stueetageteknisk rum. Hver lejlighed har ethernet-stik i stue og soveværelser.',\r\n contacts: [\r\n { name: 'TeleCom Solutions', initials: 'T', contactPerson: 'Anders Petersen', phoneNumber: '+45 56 78 90 12' }\r\n ]\r\n },\r\n {\r\n title: 'Netværksopsætning guide',\r\n attachments: [\r\n { name: 'Netværksopsætning.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Affaldshåndtering',\r\n description: 'Affaldssorteringsstation placeret i gården. Afhentninger: Dagrenovation (man/tor), Genbrug (ons), Organisk (tir/fre). Storskrald kræver booking.',\r\n attachments: [\r\n { name: 'Affaldsretningslinjer.pdf', type: 'pdf' }\r\n ]\r\n }\r\n ];\r\n\r\n // Safety Equipment folder data\r\n sikkerhedsudstyrItems: HandbookItem[] = [\r\n {\r\n title: 'Fælles områder og sikkerhed',\r\n description: 'Trappeopgange med nødbelysning og brandsikre døre. Postkasser placeret i indgangspartiet. Hold altid flugtveje fri.',\r\n images: [\r\n '/Assets/Dummy-photos/staircase.jpg',\r\n '/Assets/Dummy-photos/mailboxes.jpg'\r\n ]\r\n },\r\n {\r\n title: 'Hjertestarter (AED)',\r\n description: 'Automatisk hjertestarter placeret i stueetagen ved hovedindgangen. Tilgængelig 24/7. Ingen særlig uddannelse kræves - enheden guider dig gennem processen.',\r\n contacts: [\r\n { name: 'MediTech Service', initials: 'M', contactPerson: 'John Mortensen', phoneNumber: '+45 12 34 56 78' }\r\n ]\r\n },\r\n {\r\n title: 'Brandslukningsudstyr',\r\n description: 'Brandslukkere placeret på hver etage. Eftersyn udføres årligt. Brandalarm aktiveres automatisk ved røg.',\r\n attachments: [\r\n { name: 'Brandplan.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Alarmsystem',\r\n description: 'Adgangskontrol med kodesystem ved alle indgange. Kode ændres kvartalsvis. Ved indbrud kontakt straks politiet og ejendomsadministrationen.',\r\n contacts: [\r\n { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 98 76 54 32' }\r\n ]\r\n }\r\n ];\r\n\r\n // Service Contracts folder data\r\n serviceContractsItems: HandbookItem[] = [\r\n {\r\n title: 'Rengøringsservice',\r\n description: 'Ugentlig rengøring af fællesarealer inklusiv indgangshal, trapper og elevatorer. Hovedrengøring kvartalsvis. Service leveres mandag-fredag, 6:00-9:00.',\r\n contacts: [\r\n { name: 'CleanCo Denmark', initials: 'C', contactPerson: 'Anne Kristensen', phoneNumber: '+45 89 01 23 45' }\r\n ]\r\n },\r\n {\r\n title: 'Rengøringskontrakt',\r\n attachments: [\r\n { name: 'Rengøringskontrakt_2024.pdf', type: 'pdf' },\r\n { name: 'Rengøringsplan.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Udendørs arealer',\r\n description: 'Fælles grønne områder med bede, siddepladser og terrasse. Beboere må frit benytte området. Respektér planterne og hold området pænt.',\r\n images: [\r\n '/Assets/Dummy-photos/park.jpg',\r\n '/Assets/Dummy-photos/yard.jpg'\r\n ]\r\n },\r\n {\r\n title: 'Havevedligeholdelse',\r\n description: 'Professionel havepleje inklusiv plæneklipning, hækklipning og blomsterbedvedligeholdelse. Vintersnefjerning inkluderet.',\r\n contacts: [\r\n { name: 'Green Gardens ApS', initials: 'G', contactPerson: 'Michael Olsen', phoneNumber: '+45 90 12 34 56' }\r\n ]\r\n },\r\n {\r\n title: 'Haveserviceaftale',\r\n attachments: [\r\n { name: 'Haveserviceaftale.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Vinduespolering',\r\n description: 'Professionel vinduespoleringsservice for alle udvendige vinduer to gange årligt - forår og efterår.',\r\n contacts: [\r\n { name: 'Crystal Clear Windows', initials: 'C', contactPerson: 'Lene Schmidt', phoneNumber: '+45 01 23 45 67' }\r\n ]\r\n },\r\n {\r\n title: 'Sikkerhedsservice',\r\n description: '24/7 overvågningsservice med alarmrespons. Direkte forbindelse til politi og brandvæsen.',\r\n contacts: [\r\n { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 12 34 56 78' }\r\n ]\r\n },\r\n {\r\n title: 'Sikkerhedskontrakt og procedurer',\r\n attachments: [\r\n { name: 'Sikkerhedskontrakt.pdf', type: 'pdf' },\r\n { name: 'Nødprocedurer.pdf', type: 'pdf' }\r\n ]\r\n }\r\n ];\r\n\r\n // Equipment folder data\r\n equipmentItems: HandbookItem[] = [\r\n {\r\n title: 'Balkon udsigt',\r\n description: 'Eksempel på udsigt fra øverste etagers balkoner. Flere lejligheder har privat altan med fantastisk udsyn.',\r\n images: [\r\n '/Assets/Dummy-photos/balcony-view.jpg'\r\n ]\r\n },\r\n {\r\n title: 'Vaskerum',\r\n description: 'Fælles vaskerum med 4 vaskemaskiner og 4 tørretumblere. Bookingsystem tilgængeligt via beboerportal. Maskiner accepterer betalingskort. Åbningstider: 7:00-22:00.',\r\n contacts: [\r\n { name: 'WashTech Service', initials: 'W', contactPerson: 'Kirsten Berg', phoneNumber: '+45 34 56 78 90' }\r\n ]\r\n },\r\n {\r\n title: 'Vaskeri instruktioner',\r\n attachments: [\r\n { name: 'Vaskeinstruktioner.pdf', type: 'pdf' },\r\n { name: 'Bookingguide.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Vedligeholdelse og reparationer',\r\n description: 'Ved behov for reparationer eller vedligeholdelse i din lejlighed, kontakt vores hausmeister. Akutte problemer håndteres samme dag.',\r\n images: [\r\n '/Assets/Dummy-photos/handyman.jpg'\r\n ],\r\n contacts: [\r\n { name: 'Hausmeister Service', initials: 'H', contactPerson: 'Erik Sørensen', phoneNumber: '+45 56 78 90 12' }\r\n ]\r\n },\r\n {\r\n title: 'Værktøjsudlån',\r\n description: 'Basis håndværktøj tilgængeligt til beboerbrug. Kvittér for værktøj ved receptionen. Returnér inden for 48 timer.',\r\n attachments: [\r\n { name: 'Værktøjsliste.pdf', type: 'pdf' },\r\n { name: 'Udlånspolitik.pdf', type: 'pdf' }\r\n ]\r\n }\r\n ];\r\n \r\n constructor(public userService: UserService) {}\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n}\r\n\r\n","import { Component } from '@angular/core';\r\nimport { NavController } from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { \r\n DsMobileHeaderContentComponent,\r\n DsMobileHeaderContentTileComponent,\r\n TileIconComponent,\r\n TileContentComponent,\r\n TileLabelComponent,\r\n TileValueComponent\r\n} from '../components/header-content';\r\nimport { \r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n SectionHeaderComponent,\r\n ContentRowComponent\r\n} from '../components/content';\r\nimport { UserService } from '../services/user.service';\r\n\r\n@Component({\r\n selector: 'app-home-page',\r\n standalone: true,\r\n imports: [\r\n DsIconComponent,\r\n DsMobilePageMainComponent,\r\n DsMobileHeaderContentComponent,\r\n DsMobileHeaderContentTileComponent,\r\n TileIconComponent,\r\n TileContentComponent,\r\n TileLabelComponent,\r\n TileValueComponent,\r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n SectionHeaderComponent,\r\n ContentRowComponent\r\n ],\r\n styles: [`\r\n /* Placeholder grey boxes for content */\r\n .grey-box {\r\n height: 120px;\r\n border-radius: 12px;\r\n background: var(--color-background-neutral-tertiary);\r\n flex: 1;\r\n }\r\n\r\n .grey-box.clickable {\r\n background: var(--color-background-brand);\r\n cursor: pointer;\r\n transition: transform var(--transition-duration-fast) var(--ease-smooth);\r\n }\r\n\r\n .grey-box.clickable:active {\r\n transform: scale(0.98);\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Hjem\"\r\n headerTitle=\"Velkommen, Lars\"\r\n headerSubtitle=\"Din lejebolig på et øjeblik.\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n (refresh)=\"handleRefresh($event)\">\r\n \r\n <!-- Property info tiles in header -->\r\n <ds-mobile-header-content header-content>\r\n <ds-mobile-header-content-tile>\r\n <tile-icon>\r\n <ds-icon name=\"remixHome4Line\" size=\"20px\" />\r\n </tile-icon>\r\n <tile-content>\r\n <tile-label>Areal</tile-label>\r\n <tile-value>120 m²</tile-value>\r\n </tile-content>\r\n </ds-mobile-header-content-tile>\r\n\r\n <ds-mobile-header-content-tile>\r\n <tile-icon>\r\n <ds-icon name=\"remixCollageLine\" size=\"20px\" />\r\n </tile-icon>\r\n <tile-content>\r\n <tile-label>Værelser</tile-label>\r\n <tile-value>3 værelser</tile-value>\r\n </tile-content>\r\n </ds-mobile-header-content-tile>\r\n </ds-mobile-header-content>\r\n \r\n <!-- Main page content -->\r\n <ds-mobile-content>\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <!-- Purple box - clickable with brand background -->\r\n <content-row>\r\n <div class=\"grey-box clickable\" (click)=\"navigateToDetail()\"></div>\r\n </content-row>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"half\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"half\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"half\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileHomePageComponent {\r\n constructor(\r\n private navCtrl: NavController,\r\n public userService: UserService\r\n ) {\r\n console.log('MobileHomePageComponent constructor');\r\n }\r\n\r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n\r\n navigateToDetail(): void {\r\n // Navigation removed - home/detail page was deleted\r\n console.log('Navigate to detail (page removed)');\r\n }\r\n}\r\n\r\n","import { Animation } from '@ionic/angular';\r\nimport { createAnimation } from '@ionic/core';\r\n\r\n/**\r\n * Custom page transition - iOS-style push/pop\r\n * \r\n * FORWARD (navigating TO detail):\r\n * - Entering page (detail): slides in from RIGHT, z-index 10 (on top)\r\n * - Leaving page (list): slides LEFT slightly, z-index 9 (underneath)\r\n * \r\n * REVERSE (swipe back FROM detail):\r\n * - Entering page (list): slides in from LEFT, z-index 9 (underneath)\r\n * - Leaving page (detail): slides out to RIGHT, z-index 10 (on top)\r\n */\r\nexport const customPageTransition = (_: HTMLElement, opts: any): Animation => {\r\n const DURATION = 400;\r\n const isBackDirection = opts.direction === 'back';\r\n \r\n const rootTransition = createAnimation()\r\n .duration(opts.duration || DURATION)\r\n .easing('cubic-bezier(0.32,0.72,0,1)');\r\n\r\n // Entering page animation\r\n const enteringPage = createAnimation()\r\n .addElement(opts.enteringEl)\r\n .beforeRemoveClass('ion-page-invisible')\r\n .beforeStyles({\r\n 'z-index': isBackDirection ? '9' : '10',\r\n 'opacity': '1'\r\n })\r\n .fromTo('transform', \r\n isBackDirection ? 'translateX(-20%)' : 'translateX(100%)', \r\n 'translateX(0)'\r\n );\r\n\r\n // Leaving page animation\r\n const leavingPage = createAnimation()\r\n .addElement(opts.leavingEl)\r\n .beforeStyles({\r\n 'z-index': isBackDirection ? '10' : '9'\r\n })\r\n .fromTo('transform', \r\n 'translateX(0)', \r\n isBackDirection ? 'translateX(100%)' : 'translateX(-20%)'\r\n );\r\n\r\n rootTransition.addAnimation([enteringPage, leavingPage]);\r\n \r\n return rootTransition;\r\n};\r\n\r\n/**\r\n * Custom back transition - iOS style where page slides out to reveal page underneath\r\n * The entering page (inquiries) slides in from the LEFT underneath\r\n * The leaving page (detail) slides out to the RIGHT on top\r\n */\r\nexport const customBackTransition = (_: HTMLElement, opts: any): Animation => {\r\n const DURATION = 400;\r\n \r\n const rootTransition = createAnimation()\r\n .duration(opts.duration || DURATION)\r\n .easing('cubic-bezier(0.32,0.72,0,1)');\r\n\r\n // Entering page: underneath, sliding in from LEFT (-20% to 0)\r\n const enteringPage = createAnimation()\r\n .addElement(opts.enteringEl)\r\n .beforeRemoveClass('ion-page-invisible')\r\n .beforeStyles({\r\n 'z-index': '9',\r\n 'opacity': '1'\r\n })\r\n .fromTo('transform', 'translateX(-20%)', 'translateX(0)');\r\n\r\n // Leaving page: on top, sliding out to the RIGHT (0 to 100%)\r\n const leavingPage = createAnimation()\r\n .addElement(opts.leavingEl)\r\n .beforeStyles({\r\n 'z-index': '10',\r\n })\r\n .fromTo('transform', 'translateX(0)', 'translateX(100%)');\r\n\r\n rootTransition.addAnimation([enteringPage, leavingPage]);\r\n \r\n return rootTransition;\r\n};\r\n\r\n","import { Component, signal, computed, effect } from '@angular/core';\r\nimport { NavController } from '@ionic/angular/standalone';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { DsMobileContentComponent } from '../components/content';\r\nimport { DsMobileInteractiveListItemInquiryComponent } from '../components/interactive-list-item-inquiry';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { UserService } from '../services/user.service';\r\nimport { customPageTransition } from '../animations/page-transitions';\r\nimport { DsMobileInlineTabsComponent, type InlineTabItem } from '../components/inline-tabs';\r\n\r\ninterface Inquiry {\r\n id: string;\r\n title: string;\r\n description: string;\r\n status: 'open' | 'closed';\r\n timestamp: string;\r\n category: 'maintenance' | 'plumbing' | 'electrical' | 'heating' | 'security' | 'appliance' | 'other';\r\n}\r\n\r\n@Component({\r\n selector: 'app-mobile-inquiries-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageMainComponent,\r\n DsMobileContentComponent,\r\n DsMobileInteractiveListItemInquiryComponent,\r\n DsIconComponent,\r\n DsMobileInlineTabsComponent\r\n ],\r\n host: {\r\n class: 'ion-page'\r\n },\r\n styles: [`\r\n .inquiries-container {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n .inquiry-list-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n margin-top: -8px;\r\n }\r\n \r\n /* Remove custom dividers - now handled by ds-mobile-list-item */\r\n \r\n .empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n color: var(--color-text-primary);\r\n margin: 16px 0 8px 0;\r\n }\r\n \r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n color: var(--color-text-secondary);\r\n margin: 0;\r\n }\r\n \r\n\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Henvendelser\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\">\r\n \r\n <!-- Filter tabs in header -->\r\n <div header-content>\r\n <ds-mobile-inline-tabs\r\n [tabs]=\"tabItems\"\r\n [activeTab]=\"filterStatus()\"\r\n (tabChange)=\"setFilter($any($event))\">\r\n </ds-mobile-inline-tabs>\r\n </div>\r\n \r\n <ds-mobile-content>\r\n <div class=\"inquiries-container\">\r\n @if (filteredInquiries().length > 0) {\r\n <div class=\"inquiry-list-wrapper\">\r\n @for (inquiry of filteredInquiries(); track inquiry.id; let idx = $index) {\r\n <ds-mobile-interactive-list-item-inquiry\r\n [title]=\"inquiry.title\"\r\n [description]=\"inquiry.description\"\r\n [status]=\"inquiry.status\"\r\n [timestamp]=\"inquiry.timestamp\"\r\n [iconName]=\"getInquiryIcon(inquiry.category)\"\r\n [clickable]=\"true\"\r\n [showChevron]=\"false\"\r\n (inquiryClick)=\"openInquiryDetail(inquiry.id)\"\r\n (longPress)=\"showInquiryActions(inquiry.id)\">\r\n </ds-mobile-interactive-list-item-inquiry>\r\n\r\n }\r\n </div>\r\n } @else {\r\n <!-- Empty state -->\r\n <div class=\"empty-state\">\r\n <ds-icon name=\"remixInboxLine\" size=\"48px\" color=\"tertiary\" />\r\n <h3 class=\"empty-state-title\">Ingen henvendelser endnu</h3>\r\n <p class=\"empty-state-description\">\r\n @if (filterStatus() === 'open') {\r\n Du har ingen åbne henvendelser\r\n } @else if (filterStatus() === 'closed') {\r\n Du har ingen lukkede henvendelser\r\n } @else {\r\n Du har ikke oprettet nogen henvendelser endnu\r\n }\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileInquiriesPageComponent {\r\n constructor(\r\n public userService: UserService,\r\n private navCtrl: NavController\r\n ) {}\r\n \r\n filterStatus = signal<'all' | 'open' | 'closed'>('all');\r\n \r\n tabItems: InlineTabItem[] = [\r\n { id: 'all', label: 'Alle' },\r\n { id: 'open', label: 'Åben' },\r\n { id: 'closed', label: 'Lukket' }\r\n ];\r\n \r\n inquiries = signal<Inquiry[]>([\r\n {\r\n id: '1',\r\n title: 'Tørretumbler virker ikke',\r\n description: 'I de sidste tre dage har jeg oplevet vedvarende problemer med tørretumbleren. Den starter, men stopper efter få minutter.',\r\n status: 'open',\r\n timestamp: '12 dage siden',\r\n category: 'appliance'\r\n },\r\n {\r\n id: '2',\r\n title: 'Problem med vandtryk',\r\n description: 'Lavt vandtryk i badeværelseshåndvasken. Det er blevet gradvist værre i løbet af den sidste uge.',\r\n status: 'open',\r\n timestamp: '5 dage siden',\r\n category: 'plumbing'\r\n },\r\n {\r\n id: '3',\r\n title: 'Varme virker ikke ordentligt',\r\n description: 'Varmesystemet holder ikke den indstillede temperatur. Lejligheden er meget koldere, end den burde være.',\r\n status: 'closed',\r\n timestamp: '2 måneder siden',\r\n category: 'heating'\r\n }\r\n ]);\r\n \r\n // Computed signals that automatically update when dependencies change\r\n filteredInquiries = computed(() => {\r\n const all = this.inquiries();\r\n const status = this.filterStatus();\r\n \r\n if (status === 'all') {\r\n return all;\r\n } else if (status === 'open') {\r\n return all.filter(i => i.status === 'open');\r\n } else {\r\n return all.filter(i => i.status === 'closed');\r\n }\r\n });\r\n \r\n openInquiries = computed(() => {\r\n return this.inquiries().filter(i => i.status === 'open');\r\n });\r\n \r\n closedInquiries = computed(() => {\r\n return this.inquiries().filter(i => i.status === 'closed');\r\n });\r\n \r\n setFilter(status: 'all' | 'open' | 'closed'): void {\r\n this.filterStatus.set(status);\r\n }\r\n \r\n getInquiryIcon(category: string): string {\r\n return 'remixTodoLine';\r\n }\r\n \r\n openInquiryDetail(inquiryId: string): void {\r\n console.log('Opening inquiry:', inquiryId);\r\n // Navigate to inquiry detail page with custom transition (absolute path outside tabs for animations)\r\n this.navCtrl.navigateForward([`/inquiry-detail/${inquiryId}`], {\r\n animation: customPageTransition\r\n });\r\n }\r\n \r\n showInquiryActions(inquiryId: string): void {\r\n console.log('Showing actions for inquiry:', inquiryId);\r\n // Show bottom sheet with actions (edit, delete, etc.)\r\n }\r\n}\r\n\r\n","import { Component, signal, computed, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { NavController, Platform } from '@ionic/angular/standalone';\r\nimport { \r\n IonHeader, \r\n IonToolbar, \r\n IonTitle,\r\n IonContent, \r\n IonRefresher, \r\n IonRefresherContent \r\n} from '@ionic/angular/standalone';\r\nimport { DsIconComponent, DsBadgeComponent } from '@propbinder/design-system';\r\nimport { DsMobileInlineTabsComponent, type InlineTabItem } from '../components/inline-tabs';\r\nimport { DsMobileInteractiveListItemMessageComponent } from '../components/interactive-list-item-message';\r\nimport { DsMobileListItemComponent } from '../components/list-item/ds-mobile-list-item';\r\nimport { DsMobileLightboxService, type LightboxImage } from '../components/lightbox';\r\nimport { DsMobileChatModalService, type ChatModalData, type ChatMessage } from '../components/chat-modal';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge';\r\nimport { UserService } from '../services/user.service';\r\nimport { MobilePageBase } from '../components/shared/mobile-page-base';\r\nimport { customBackTransition } from '../animations/page-transitions';\r\n\r\ninterface ActivityItem {\r\n id: string;\r\n type: 'assignment' | 'status_change' | 'creation';\r\n actor?: string;\r\n actorInitials?: string;\r\n title: string;\r\n description?: string;\r\n timestamp: string;\r\n date: string;\r\n iconName: string;\r\n iconBgColor?: string;\r\n}\r\n\r\ninterface MessageThread {\r\n id: string;\r\n senderName: string;\r\n senderAvatar: string;\r\n senderInitials: string;\r\n message: string;\r\n role: string;\r\n timestamp: string;\r\n unread: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'app-mobile-inquiry-detail-page',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonContent,\r\n IonRefresher,\r\n IonRefresherContent,\r\n DsIconComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsMobileInlineTabsComponent,\r\n DsMobileInteractiveListItemMessageComponent,\r\n DsMobileListItemComponent,\r\n DsBadgeComponent\r\n ],\r\n host: {\r\n class: 'ion-page'\r\n },\r\n styleUrls: [\r\n '../components/shared/mobile-page-base.css',\r\n './inquiry-detail.example.css'\r\n ],\r\n template: `\r\n <!-- Fixed header at top -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <div class=\"header-details\">\r\n <!-- Back Button -->\r\n <button class=\"back-button\" (click)=\"goBack()\" [attr.aria-label]=\"'Go back'\">\r\n <ds-icon name=\"remixArrowLeftSLine\" size=\"24px\" color=\"white\" />\r\n </button>\r\n \r\n <!-- Title - fades in on scroll -->\r\n <ion-title class=\"header-title\">{{ inquiryTitle }}</ion-title>\r\n </div>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <!-- Content with expandable header -->\r\n <ion-content [scrollEvents]=\"true\" (ionScroll)=\"handleScroll($event)\">\r\n <!-- Pull to refresh (only on native iOS/Android) -->\r\n @if (isNativePlatform()) {\r\n <ion-refresher \r\n slot=\"fixed\" \r\n (ionRefresh)=\"handleRefresh($event)\"\r\n [pullFactor]=\"0.4\" \r\n [pullMin]=\"80\" \r\n [pullMax]=\"240\"\r\n closeDuration=\"600ms\">\r\n <ion-refresher-content\r\n pullingIcon=\"remixArrowDownS\"\r\n refreshingSpinner=\"lines\">\r\n </ion-refresher-content>\r\n </ion-refresher>\r\n }\r\n\r\n <!-- Expandable header section (purple background) -->\r\n <div class=\"header-expandable\">\r\n <div class=\"header-expandable-inner\">\r\n <div class=\"header-expandable__text\">\r\n <h1 class=\"header-expandable__title\">{{ inquiryTitle }}</h1>\r\n </div>\r\n \r\n <!-- Tabs in header -->\r\n <ds-mobile-inline-tabs\r\n [tabs]=\"tabItems\"\r\n [activeTab]=\"activeTab()\"\r\n (tabChange)=\"setActiveTab($event)\">\r\n </ds-mobile-inline-tabs>\r\n </div>\r\n </div>\r\n\r\n <!-- Content wrapper -->\r\n <div class=\"content-wrapper\">\r\n <div class=\"content-inner\">\r\n <!-- Activity Tab Content -->\r\n @if (activeTab() === 'activity') {\r\n <div class=\"activity-list\">\r\n @for (activity of activities; track activity.id) {\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"false\">\r\n @if (activity.actor) {\r\n <!-- Avatar with badge for actor activities -->\r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [type]=\"'initials'\"\r\n [initials]=\"activity.actorInitials || ''\"\r\n size=\"md\" />\r\n </div>\r\n } @else {\r\n <!-- Icon wrapper for non-actor activities -->\r\n <div content-leading class=\"activity-icon-wrapper\">\r\n <ds-icon \r\n [name]=\"activity.iconName\"\r\n size=\"18px\"\r\n color=\"secondary\" />\r\n </div>\r\n }\r\n \r\n <div content-main class=\"activity-content\">\r\n <p class=\"activity-title\">\r\n @if (activity.actor) {\r\n <span class=\"actor-name\">{{ activity.actor }}</span>\r\n <span class=\"activity-text\"> {{ activity.title }}</span>\r\n } @else {\r\n <span class=\"actor-name\">{{ activity.title }}</span>\r\n }\r\n </p>\r\n @if (activity.description) {\r\n <p class=\"activity-description\">{{ activity.description }}</p>\r\n }\r\n <div class=\"activity-timestamp\">\r\n <ds-icon name=\"remixCalendarLine\" size=\"12px\" color=\"--color-text-tertiary\" />\r\n <span>{{ activity.date }}</span>\r\n </div>\r\n </div>\r\n </ds-mobile-list-item>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Messages Tab Content -->\r\n @if (activeTab() === 'messages') {\r\n <div class=\"messages-list\">\r\n @for (message of messageThreads; track message.id) {\r\n <ds-mobile-interactive-list-item-message\r\n [senderName]=\"message.senderName\"\r\n [senderRole]=\"message.role\"\r\n [timestamp]=\"message.timestamp\"\r\n [message]=\"message.message\"\r\n [avatarInitials]=\"message.senderInitials\"\r\n [unread]=\"message.unread\"\r\n (messageClick)=\"openMessage(message.id)\">\r\n </ds-mobile-interactive-list-item-message>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Details Tab Content -->\r\n @if (activeTab() === 'details') {\r\n <div class=\"details-list\">\r\n <!-- Assignee -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [size]=\"'sm'\"\r\n [type]=\"'initials'\"\r\n [initials]=\"'R'\" />\r\n </div>\r\n <div content-main>\r\n <div class=\"detail-label\">Sagsbehandler</div>\r\n <div class=\"detail-value\">Ricki Meihlen</div>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Technician -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [size]=\"'sm'\"\r\n [type]=\"'initials'\"\r\n [initials]=\"'M'\" />\r\n </div>\r\n <div content-main>\r\n <div class=\"detail-label\">Tekniker</div>\r\n <div class=\"detail-value\">Martin Smith</div>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Title -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\" [align]=\"'center'\">\r\n <ds-icon content-leading name=\"remixTextBlock\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"detail-value\">{{ inquiryTitle }}</div>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Description -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <ds-icon content-leading name=\"remixAlignLeft\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"detail-value description-text\">\r\n I de sidste tre dage har vi oplevet vedvarende problemer med tørretumbleren i vores lejlighed. På trods af at vi følger betjeningsvejledningen, fejler maskinen konsekvent i at fuldføre sine tørrecyklusser.\r\n </div>\r\n <ds-badge content=\"Husholdningsapparater\" size=\"sm\"/>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Photos -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <ds-icon content-leading name=\"remixCameraLine\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"photo-grid\">\r\n <button class=\"photo-add\">\r\n <ds-icon name=\"remixAddLine\" size=\"20px\" color=\"tertiary\" />\r\n </button>\r\n <!-- Photos -->\r\n @for (photo of photos; track photo.src; let i = $index) {\r\n <img \r\n class=\"photo-item\" \r\n [src]=\"photo.src\" \r\n [alt]=\"photo.alt\"\r\n (click)=\"openPhotoLightbox(i)\"\r\n style=\"cursor: pointer;\" />\r\n }\r\n </div>\r\n </div>\r\n </ds-mobile-list-item>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class MobileInquiryDetailPageComponent extends MobilePageBase implements AfterViewInit {\r\n @ViewChild(IonContent) ionContent?: IonContent;\r\n \r\n // Platform detection\r\n private platform = inject(Platform);\r\n \r\n // Computed property to check if running on native platform\r\n isNativePlatform = computed(() => \r\n this.platform.is('ios') || \r\n this.platform.is('android') || \r\n this.platform.is('capacitor')\r\n );\r\n \r\n inquiryTitle = 'Tørretumbler virker ikke';\r\n activeTab = signal<string>('activity');\r\n \r\n tabItems: InlineTabItem[] = [\r\n { id: 'activity', label: 'Aktivitet' },\r\n { id: 'messages', label: 'Beskeder', badge: 0 },\r\n { id: 'details', label: 'Detaljer' }\r\n ];\r\n \r\n activities: ActivityItem[] = [\r\n {\r\n id: '1',\r\n type: 'assignment',\r\n actor: 'Martin Smith',\r\n actorInitials: 'MS',\r\n title: 'er blevet tildelt som din dedikerede tekniker.',\r\n timestamp: '2 dage siden',\r\n date: '28. feb 2025',\r\n iconName: 'remixUserAddLine'\r\n },\r\n {\r\n id: '2',\r\n type: 'assignment',\r\n actor: 'Ricki Meihlen',\r\n actorInitials: 'RM',\r\n title: 'er blevet tildelt til at håndtere din henvendelse.',\r\n timestamp: '8 dage siden',\r\n date: '22. feb 2025',\r\n iconName: 'remixUserLine'\r\n },\r\n {\r\n id: '3',\r\n type: 'creation',\r\n title: 'Henvendelse oprettet',\r\n timestamp: '8 dage siden',\r\n date: '22. feb 2025',\r\n iconName: 'remixAddCircleLine'\r\n }\r\n ];\r\n \r\n messageThreads: MessageThread[] = [\r\n {\r\n id: '1',\r\n senderName: 'Ove Hindborg',\r\n senderAvatar: '',\r\n senderInitials: 'OH',\r\n message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',\r\n role: 'Sagsbehandler',\r\n timestamp: '2t siden',\r\n unread: true\r\n },\r\n {\r\n id: '2',\r\n senderName: 'Martin Smith',\r\n senderAvatar: '',\r\n senderInitials: 'MS',\r\n message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',\r\n role: 'Tekniker',\r\n timestamp: '4t siden',\r\n unread: true\r\n }\r\n ];\r\n \r\n unreadMessagesCount = computed(() => {\r\n const count = this.messageThreads.filter(m => m.unread).length;\r\n // Update badge in tab items\r\n const messagesTab = this.tabItems.find(t => t.id === 'messages');\r\n if (messagesTab) {\r\n messagesTab.badge = count;\r\n }\r\n return count;\r\n });\r\n \r\n // Photos for lightbox\r\n photos: LightboxImage[] = [\r\n { type: 'image', src: '/Assets/Dummy-photos/handyman.jpg', alt: 'Handyman', title: 'Handyman' },\r\n { type: 'image', src: '/Assets/Dummy-photos/balcony-view.jpg', alt: 'Balcony view', title: 'Balcony view' },\r\n { type: 'image', src: '/Assets/Dummy-photos/staircase.jpg', alt: 'Staircase', title: 'Staircase' },\r\n { type: 'image', src: '/Assets/Dummy-photos/yard.jpg', alt: 'Yard', title: 'Yard' },\r\n { type: 'image', src: '/Assets/Dummy-photos/mailboxes.jpg', alt: 'Mailboxes', title: 'Mailboxes' }\r\n ];\r\n \r\n constructor(\r\n public userService: UserService,\r\n private navCtrl: NavController,\r\n private elementRef: ElementRef,\r\n private lightbox: DsMobileLightboxService,\r\n private chatModal: DsMobileChatModalService\r\n ) {\r\n super();\r\n // Trigger initial badge update\r\n this.unreadMessagesCount();\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Initial setup if needed\r\n }\r\n \r\n setActiveTab(tabId: string): void {\r\n this.activeTab.set(tabId);\r\n }\r\n \r\n goBack(): void {\r\n this.navCtrl.back({ animation: customBackTransition });\r\n }\r\n \r\n handleScroll(event: any): void {\r\n const scrollTop = event.detail.scrollTop;\r\n const threshold = 160;\r\n const fadeDistance = 200;\r\n const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');\r\n const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');\r\n \r\n // Show title in fixed header when scrolled past threshold\r\n if (scrollTop > threshold) {\r\n header?.classList.add('header-scrolled');\r\n } else {\r\n header?.classList.remove('header-scrolled');\r\n }\r\n \r\n // Fade out header-expandable content based on scroll\r\n if (headerExpandable) {\r\n const fadeProgress = Math.min(scrollTop / fadeDistance, 1);\r\n \r\n // Calculate opacity (1 to 0)\r\n const opacity = 1 - fadeProgress;\r\n \r\n // Calculate transform (0px to -20px upward)\r\n const translateY = fadeProgress * -20;\r\n \r\n // Apply styles\r\n headerExpandable.style.opacity = opacity.toString();\r\n headerExpandable.style.transform = `translateY(${translateY}px)`;\r\n }\r\n }\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n \r\n async openMessage(messageId: string): Promise<void> {\r\n console.log('Opening message:', messageId);\r\n \r\n // Find the message thread\r\n const messageThread = this.messageThreads.find(m => m.id === messageId);\r\n if (!messageThread) {\r\n console.error('Message thread not found:', messageId);\r\n return;\r\n }\r\n \r\n // Prepare chat modal data\r\n // In a real app, you would fetch the actual messages from your API\r\n const chatData: ChatModalData = {\r\n participant: {\r\n id: messageId,\r\n name: messageThread.senderName,\r\n role: messageThread.role,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials'\r\n },\r\n messages: [\r\n // Example messages - in real app, fetch from API\r\n {\r\n id: '1',\r\n content: messageThread.message,\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: messageThread.timestamp,\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n // Add more messages as needed\r\n {\r\n id: '2',\r\n content: 'Thank you for the update!',\r\n senderId: 'current-user',\r\n senderName: 'You',\r\n timestamp: '1t siden',\r\n isOwnMessage: true,\r\n avatarInitials: this.userService.avatarInitials(),\r\n avatarType: 'initials',\r\n }\r\n ],\r\n currentUserId: 'current-user',\r\n currentUserInitials: this.userService.avatarInitials(),\r\n currentUserAvatarType: 'initials',\r\n autoFocus: false\r\n };\r\n \r\n // Open the chat modal\r\n await this.chatModal.open(chatData);\r\n }\r\n \r\n async openPhotoLightbox(index: number): Promise<void> {\r\n await this.lightbox.openImages({\r\n images: this.photos,\r\n initialIndex: index,\r\n showControls: true,\r\n enableSwipe: true,\r\n enableZoom: true,\r\n showInfo: false\r\n });\r\n }\r\n}\r\n\r\n","import { Component, OnInit, inject } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { IonTabs } from '@ionic/angular/standalone';\r\nimport { UserService } from '../services/user.service';\r\nimport { DsMobileTabBarComponent, TabConfig } from '../components/tab-bar';\r\nimport { ActionResult, ActionGroup } from '../components/bottom-sheet';\r\nimport { WhitelabelDemoModalService } from './whitelabel-demo-modal.service';\r\n\r\n/**\r\n * MobileTabsExampleComponent\r\n * \r\n * Example page using the TenantApp pattern:\r\n * - Uses ion-tabs as wrapper (required for Angular routing)\r\n * - Uses ds-mobile-tab-bar inside (not ds-mobile-tabs)\r\n * \r\n * This matches the pattern used in TenantApp for consistency.\r\n */\r\n@Component({\r\n selector: 'app-mobile-tabs-example',\r\n standalone: true,\r\n imports: [CommonModule, IonTabs, DsMobileTabBarComponent],\r\n styles: [`\r\n :host {\r\n display: block;\r\n height: 100vh;\r\n width: 100vw;\r\n position: relative;\r\n }\r\n `],\r\n template: `\r\n <ion-tabs class=\"ds-tabs-wrapper\">\r\n <!-- Tab bar with slot=\"top\" on desktop, slot=\"bottom\" on mobile -->\r\n <!-- Ionic automatically creates ion-tab elements from child routes -->\r\n <ds-mobile-tab-bar\r\n [tabs]=\"tabs\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n [profileMenuItems]=\"profileMenuItems\"\r\n (profileActionSelected)=\"handleProfileAction($event)\">\r\n </ds-mobile-tab-bar>\r\n </ion-tabs>\r\n `\r\n})\r\nexport class MobileTabsExampleComponent implements OnInit {\r\n private whitelabelDemoModal = inject(WhitelabelDemoModalService);\r\n \r\n constructor(\r\n public userService: UserService,\r\n private router: Router\r\n ) {\r\n console.log('MobileTabsExampleComponent constructor');\r\n }\r\n \r\n ngOnInit() {\r\n console.log('MobileTabsExampleComponent ngOnInit');\r\n // Configure user avatar globally - this is now the single source of truth\r\n this.userService.setAvatarInitials('LM');\r\n this.userService.setAvatarType('initials');\r\n \r\n // Set profile menu items globally - this will be used by both tab bar and page-main components\r\n this.userService.setProfileMenuItems(this.profileMenuItems);\r\n }\r\n \r\n tabs: TabConfig[] = [\r\n {\r\n id: 'home',\r\n label: 'Hjem',\r\n route: 'home',\r\n icon: 'remixHomeSmile2Line',\r\n iconActive: 'remixHomeSmile2Fill'\r\n },\r\n {\r\n id: 'inquiries',\r\n label: 'Henvendelser',\r\n route: 'inquiries',\r\n icon: 'remixFileList3Line',\r\n iconActive: 'remixFileList3Fill'\r\n },\r\n {\r\n id: 'announcements',\r\n label: 'Fællesskab',\r\n route: 'announcements',\r\n icon: 'remixCommunityLine',\r\n iconActive: 'remixCommunityFill'\r\n },\r\n {\r\n id: 'handbook',\r\n label: 'Håndbog',\r\n route: 'handbook',\r\n icon: 'remixBook2Line',\r\n iconActive: 'remixBook2Fill'\r\n }\r\n ];\r\n \r\n /**\r\n * Profile menu items configuration.\r\n * Define once here - this is set globally in UserService in ngOnInit(),\r\n * so it will be used by both ds-mobile-tab-bar and ds-mobile-page-main components\r\n * throughout the entire application.\r\n */\r\n profileMenuItems: ActionGroup[] = [\r\n {\r\n actions: [\r\n {\r\n action: 'profile',\r\n title: 'Min profil',\r\n icon: 'remixUser3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'settings',\r\n title: 'Indstillinger',\r\n icon: 'remixSettings3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'whitelabel-demo',\r\n title: 'Whitelabel Demo',\r\n icon: 'remixPaletteLine',\r\n destructive: false\r\n }\r\n ]\r\n },\r\n {\r\n actions: [\r\n {\r\n action: 'logout',\r\n title: 'Log ud',\r\n icon: 'remixLogoutBoxLine',\r\n destructive: true\r\n }\r\n ]\r\n }\r\n ];\r\n \r\n /**\r\n * Handle profile menu action selection.\r\n * The tab bar component handles the UI (opening/closing menu),\r\n * this method handles the business logic.\r\n */\r\n handleProfileAction(result: ActionResult): void {\r\n console.log('Profile action selected:', result.action);\r\n \r\n switch (result.action) {\r\n case 'logout':\r\n console.log('Logging out...');\r\n // TODO: Implement logout logic\r\n break;\r\n case 'profile':\r\n console.log('Opening profile...');\r\n // TODO: Navigate to profile page\r\n break;\r\n case 'settings':\r\n console.log('Opening settings...');\r\n // TODO: Navigate to settings page\r\n break;\r\n case 'whitelabel-demo':\r\n console.log('Opening whitelabel demo...');\r\n // Small delay to ensure bottom sheet is fully dismissed\r\n setTimeout(async () => {\r\n try {\r\n await this.whitelabelDemoModal.open();\r\n } catch (error) {\r\n console.error('Failed to open whitelabel demo modal:', error);\r\n }\r\n }, 100);\r\n break;\r\n }\r\n }\r\n}\r\n","import { Component, signal, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n DsAvatarComponent,\r\n DsIconComponent,\r\n DsButtonComponent\r\n} from '@propbinder/design-system';\r\nimport { DsMobilePageDetailsComponent } from '../components/page-details';\r\nimport { UserService } from '../services/user.service';\r\n\r\n/**\r\n * PostCreatePageComponent\r\n * \r\n * Full-screen detail page for creating new posts in the community feed.\r\n * Features Threads-inspired interface with rich text editing capabilities.\r\n */\r\n@Component({\r\n selector: 'app-post-create-page',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n DsAvatarComponent,\r\n DsIconComponent,\r\n DsButtonComponent,\r\n DsMobilePageDetailsComponent\r\n ],\r\n styles: [`\r\n .post-create-container {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n max-width: 640px;\r\n }\r\n \r\n /* ============================================\r\n CONTENT AREA\r\n ============================================ */\r\n \r\n .content {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n }\r\n \r\n .post-composer {\r\n display: flex;\r\n gap: 12px;\r\n margin-bottom: 24px;\r\n align-items: flex-start;\r\n }\r\n \r\n .post-composer__avatar {\r\n flex-shrink: 0;\r\n padding-top: 2px;\r\n }\r\n \r\n .post-composer__main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .post-composer__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n height: 32px;\r\n }\r\n \r\n .post-composer__username {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 15px;\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .post-composer__textarea {\r\n width: 100%;\r\n min-height: 120px;\r\n border: none;\r\n outline: none;\r\n resize: none;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 15px;\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n background: transparent;\r\n padding: 0;\r\n }\r\n \r\n .post-composer__textarea::placeholder {\r\n color: var(--color-text-tertiary, #999999);\r\n }\r\n \r\n .post-composer__actions {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 16px;\r\n }\r\n \r\n .post-composer__action-btns {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n }\r\n \r\n .post-composer__action-btn {\r\n background: none;\r\n border: none;\r\n padding: 0;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-text-secondary, #737373);\r\n transition: color 0.2s ease;\r\n }\r\n \r\n .post-composer__action-btn:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n /* Thread connector line */\r\n .thread-line {\r\n position: absolute;\r\n left: 35px;\r\n top: 60px;\r\n bottom: 0;\r\n width: 2px;\r\n background: var(--border-color-default);\r\n }\r\n \r\n /* ============================================\r\n MOBILE OPTIMIZATIONS\r\n ============================================ */\r\n \r\n @media (max-width: 768px) {\r\n .content {\r\n padding: 12px 16px;\r\n }\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-details\r\n [title]=\"pageTitle()\"\r\n [backRoute]=\"'/mobile-tabs-example/announcements'\"\r\n (back)=\"handleCancel()\">\r\n \r\n <div class=\"post-create-container\">\r\n <div class=\"post-composer\">\r\n <div class=\"post-composer__avatar\">\r\n <ds-avatar \r\n [initials]=\"userService.avatarInitials()\"\r\n [type]=\"userService.avatarType()\"\r\n [src]=\"userService.avatarSrc()\"\r\n size=\"md\" />\r\n </div>\r\n \r\n <div class=\"post-composer__main\">\r\n <div class=\"post-composer__header\">\r\n <span class=\"post-composer__username\">{{ username() }}</span>\r\n </div>\r\n \r\n <textarea\r\n #textareaInput\r\n class=\"post-composer__textarea\"\r\n [(ngModel)]=\"postContent\"\r\n [placeholder]=\"placeholder()\"\r\n (input)=\"handleInput()\">\r\n </textarea>\r\n \r\n <div class=\"post-composer__actions\">\r\n <div class=\"post-composer__action-btns\">\r\n <button class=\"post-composer__action-btn\" (click)=\"handleAddImage()\">\r\n <ds-icon name=\"remixImageLine\" size=\"22px\" />\r\n </button>\r\n <button class=\"post-composer__action-btn\" (click)=\"handleAddEmoji()\">\r\n <ds-icon name=\"remixEmotionLine\" size=\"22px\" />\r\n </button>\r\n </div>\r\n \r\n <ds-button\r\n variant=\"primary\"\r\n size=\"md\"\r\n [disabled]=\"!canPost()\"\r\n (clicked)=\"handlePost()\">\r\n {{ submitButtonLabel() }}\r\n </ds-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ds-mobile-page-details>\r\n `\r\n})\r\nexport class PostCreatePageComponent implements AfterViewInit, OnInit {\r\n @ViewChild('textareaInput') textareaInput?: ElementRef<HTMLTextAreaElement>;\r\n \r\n postContent = '';\r\n username = signal('Lars Mikkelsen');\r\n placeholder = signal(\"What's new?\");\r\n \r\n // Edit mode state\r\n isEditMode = signal(false);\r\n postId = signal<string | null>(null);\r\n pageTitle = signal('New post');\r\n submitButtonLabel = signal('Post');\r\n \r\n constructor(\r\n private router: Router,\r\n private route: ActivatedRoute,\r\n public userService: UserService\r\n ) {}\r\n \r\n ngOnInit(): void {\r\n // Check for edit mode via query parameters\r\n this.route.queryParams.subscribe(params => {\r\n const editMode = params['edit'] === 'true';\r\n const postId = params['id'];\r\n const content = params['content'];\r\n \r\n if (editMode && postId) {\r\n this.isEditMode.set(true);\r\n this.postId.set(postId);\r\n this.pageTitle.set('Edit post');\r\n this.submitButtonLabel.set('Save');\r\n \r\n // Prefill content if provided\r\n if (content) {\r\n this.postContent = decodeURIComponent(content);\r\n }\r\n } else {\r\n // Reset to create mode\r\n this.isEditMode.set(false);\r\n this.postId.set(null);\r\n this.pageTitle.set('New post');\r\n this.submitButtonLabel.set('Post');\r\n this.postContent = '';\r\n }\r\n });\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Focus the textarea after view initialization to trigger keyboard on mobile\r\n setTimeout(() => {\r\n this.textareaInput?.nativeElement.focus();\r\n }, 300);\r\n }\r\n \r\n handleInput(): void {\r\n // Handle text input changes\r\n }\r\n \r\n canPost(): boolean {\r\n return this.postContent.trim().length > 0;\r\n }\r\n \r\n handleCancel(): void {\r\n if (this.postContent.trim().length > 0) {\r\n // Show confirmation dialog\r\n const confirmed = confirm('Discard this post?');\r\n if (confirmed) {\r\n this.router.navigate(['/mobile-tabs-example/community']);\r\n }\r\n } else {\r\n this.router.navigate(['/mobile-tabs-example/community']);\r\n }\r\n }\r\n \r\n handlePost(): void {\r\n if (!this.canPost()) return;\r\n \r\n if (this.isEditMode()) {\r\n console.log('Updating post:', this.postId(), this.postContent);\r\n // TODO: Implement post update logic\r\n // this.postService.updatePost(this.postId(), this.postContent).subscribe(() => {\r\n // this.router.navigate(['/mobile-tabs-example/community']);\r\n // });\r\n } else {\r\n console.log('Creating post:', this.postContent);\r\n // TODO: Implement post creation logic\r\n // this.postService.createPost(this.postContent).subscribe(() => {\r\n // this.router.navigate(['/mobile-tabs-example/community']);\r\n // });\r\n }\r\n \r\n // For now, just navigate back\r\n this.router.navigate(['/mobile-tabs-example/community']);\r\n }\r\n \r\n handleAddImage(): void {\r\n console.log('Add image');\r\n // TODO: Open image picker\r\n }\r\n \r\n handleAddEmoji(): void {\r\n console.log('Add emoji');\r\n // TODO: Open emoji picker\r\n }\r\n}\r\n\r\n","import { Component } from '@angular/core';\r\nimport { DsMobilePageDetailsComponent } from '../components/page-details';\r\nimport { \r\n DsMobileInteractiveListItemPostComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent\r\n} from '../components/interactive-list-item-post';\r\nimport { DsMobileCommentComponent } from '../components/comment';\r\nimport { DsMobileLightboxService, LightboxAuthor } from '../components/lightbox';\r\nimport { DsMobileBottomSheetService } from '../components/bottom-sheet/ds-mobile-bottom-sheet.service';\r\nimport { DsMobileCommentActionsBottomSheetComponent, CommentActionResult } from '../components/bottom-sheet';\r\n\r\n@Component({\r\n selector: 'app-mobile-post-detail-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageDetailsComponent,\r\n DsMobileInteractiveListItemPostComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCommentComponent\r\n ],\r\n styles: [`\r\n .post-detail-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n max-width: 640px;\r\n }\r\n \r\n .post-section {\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding-bottom: 16px;\r\n }\r\n \r\n .clickable-image {\r\n cursor: pointer;\r\n transition: transform 0.2s ease, opacity 0.2s ease;\r\n border-radius: 8px;\r\n display: block;\r\n width: 100%;\r\n aspect-ratio: 16/9;\r\n object-fit: cover;\r\n }\r\n \r\n .clickable-image:active {\r\n transform: scale(0.98);\r\n opacity: 0.9;\r\n }\r\n \r\n .comments-section {\r\n display: flex;\r\n flex-direction: column;\r\n /* Negative margin to pull comments out by 8px on each side */\r\n /* Page has 20px padding, this makes comments effectively 12px from edge */\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n }\r\n \r\n .comments-header {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 18px;\r\n font-weight: 600;\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin-bottom: 16px;\r\n /* Add padding to keep header at 20px from edge (8px to offset negative margin) */\r\n padding-left: 8px;\r\n padding-right: 8px;\r\n }\r\n \r\n .comments-list {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-details title=\"Opslag\">\r\n <div class=\"post-detail-container\">\r\n <!-- Post Section -->\r\n <div class=\"post-section\">\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Sophie Andersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'4t siden'\"\r\n [avatarInitials]=\"'SA'\"\r\n [clickable]=\"false\">\r\n \r\n <post-content>\r\n <post-text>Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️</post-text>\r\n <post-media>\r\n <img \r\n src=\"/Assets/Dummy-photos/balcony-view.jpg\" \r\n alt=\"Altanudsigt\" \r\n class=\"clickable-image\"\r\n (click)=\"openImageLightbox('/Assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')\"\r\n />\r\n </post-media>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [active]=\"true\" [count]=\"156\" />\r\n <action-comment [count]=\"34\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n </div>\r\n \r\n <!-- Comments Section -->\r\n <div class=\"comments-section\">\r\n <h2 class=\"comments-header\">{{ repliesCount }} svar</h2>\r\n \r\n <div class=\"comments-list\">\r\n <ds-mobile-comment\r\n [authorName]=\"'Anders Jensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'3t siden'\"\r\n [avatarInitials]=\"'AJ'\"\r\n [content]=\"'Wow, den udsigt er fantastisk! Hvilken etage er du på?'\"\r\n [likeCount]=\"12\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Anders Jensen', 'Wow, den udsigt er fantastisk! Hvilken etage er du på?', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Thomas Hansen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'3t siden'\"\r\n [avatarInitials]=\"'TH'\"\r\n [content]=\"'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆'\"\r\n [isLiked]=\"true\"\r\n [likeCount]=\"8\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"true\"\r\n (longPress)=\"handleCommentLongPress('Thomas Hansen', 'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆', true)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Emma Petersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'2t siden'\"\r\n [avatarInitials]=\"'EP'\"\r\n [content]=\"'Dette er præcis derfor jeg elsker at bo her. Godt billede!'\"\r\n [likeCount]=\"15\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Emma Petersen', 'Dette er præcis derfor jeg elsker at bo her. Godt billede!', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Nikolaj Sørensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'2t siden'\"\r\n [avatarInitials]=\"'NS'\"\r\n [content]=\"'Solnedgangene fra den vinkel må være utrolige'\"\r\n [likeCount]=\"6\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Nikolaj Sørensen', 'Solnedgangene fra den vinkel må være utrolige', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Mette Larsen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'1t siden'\"\r\n [avatarInitials]=\"'ML'\"\r\n [content]=\"'Giver mig lyst til at få min morgenkaffe på altanen også! ☕'\"\r\n [likeCount]=\"9\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Mette Larsen', 'Giver mig lyst til at få min morgenkaffe på altanen også! ☕', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Frederik Nielsen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'1t siden'\"\r\n [avatarInitials]=\"'FN'\"\r\n [content]=\"'Heldig! Min altan vender den anden vej, men stadig pæn'\"\r\n [likeCount]=\"4\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Frederik Nielsen', 'Heldig! Min altan vender den anden vej, men stadig pæn', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Caroline Jensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'45m siden'\"\r\n [avatarInitials]=\"'CJ'\"\r\n [content]=\"'Denne bygning har den bedste udsigt i byen, uden tvivl'\"\r\n [likeCount]=\"11\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Caroline Jensen', 'Denne bygning har den bedste udsigt i byen, uden tvivl', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Anna Hansen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'30m siden'\"\r\n [avatarInitials]=\"'AH'\"\r\n [content]=\"'Jeg skal se din altan en dag! 😍'\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Anna Hansen', 'Jeg skal se din altan en dag! 😍', false)\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ds-mobile-page-details>\r\n `\r\n})\r\nexport class MobilePostDetailPageComponent {\r\n repliesCount = 6;\r\n \r\n constructor(\r\n private lightbox: DsMobileLightboxService,\r\n private bottomSheet: DsMobileBottomSheetService\r\n ) {}\r\n \r\n /**\r\n * Open an image in the lightbox viewer\r\n */\r\n openImageLightbox(imageSrc: string, title: string, description: string): void {\r\n const authorMeta: LightboxAuthor = {\r\n name: 'Sophie Andersen',\r\n role: 'Lejer',\r\n avatarInitials: 'SA',\r\n timestamp: '4t siden'\r\n };\r\n \r\n this.lightbox.open({\r\n showActions: true, // Show like & comment actions\r\n images: [\r\n {\r\n type: 'image',\r\n src: imageSrc,\r\n alt: title,\r\n title: title,\r\n description: description,\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 34\r\n }\r\n ],\r\n author: authorMeta,\r\n enableZoom: true,\r\n showControls: false, // Single image, no need for controls\r\n showInfo: true\r\n });\r\n }\r\n \r\n /**\r\n * Handle long press on a comment to show action sheet\r\n */\r\n async handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void> {\r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobileCommentActionsBottomSheetComponent,\r\n componentProps: {\r\n isOwnContent: isOwnComment\r\n },\r\n breakpoints: [0, 1],\r\n initialBreakpoint: 1,\r\n handle: true,\r\n backdropDismiss: true,\r\n cssClass: 'auto-height'\r\n });\r\n \r\n const result = await sheet.onWillDismiss();\r\n \r\n if (result.role === 'select' && result.data) {\r\n const action = (result.data as CommentActionResult).action;\r\n \r\n switch (action) {\r\n case 'like':\r\n console.log('Like comment by', authorName);\r\n // Implement like logic\r\n break;\r\n case 'reply':\r\n console.log('Reply to comment by', authorName);\r\n // Implement reply logic\r\n break;\r\n case 'edit':\r\n console.log('Edit comment by', authorName);\r\n // Implement edit logic\r\n break;\r\n case 'delete':\r\n console.log('Delete comment by', authorName);\r\n // Implement delete logic (with confirmation)\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n","import { Component, OnInit, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { WhitelabelService } from '../services/whitelabel.service';\r\nimport { DsLogoComponent } from '../components/logo/ds-logo';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge/ds-avatar-with-badge';\r\nimport { IonContent, IonHeader, IonToolbar, IonTitle, IonButton } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * Whitelabel Demo Page\r\n * \r\n * Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.\r\n */\r\n@Component({\r\n selector: 'app-whitelabel-demo',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonContent,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonButton,\r\n DsLogoComponent,\r\n DsAvatarWithBadgeComponent\r\n ],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n ion-toolbar {\r\n --background: var(--color-brand-secondary);\r\n --color: var(--color-secondary-content);\r\n }\r\n \r\n ion-content {\r\n --background: #f5f5f5;\r\n }\r\n \r\n .demo-container {\r\n padding: 20px;\r\n max-width: 600px;\r\n margin: 0 auto;\r\n }\r\n \r\n .demo-section {\r\n margin-bottom: 32px;\r\n }\r\n \r\n .demo-section h2 {\r\n margin-bottom: 16px;\r\n font-size: 18px;\r\n font-weight: 600;\r\n color: #333;\r\n }\r\n \r\n /* Theme Selection */\r\n .theme-buttons {\r\n display: flex;\r\n gap: 12px;\r\n flex-wrap: wrap;\r\n }\r\n \r\n .theme-buttons ion-button {\r\n --background: #e0e0e0;\r\n --color: #333;\r\n --ripple-color: transparent;\r\n --background-activated: #e0e0e0;\r\n --background-focused: #e0e0e0;\r\n --background-hover: #d0d0d0;\r\n }\r\n \r\n .theme-buttons ion-button.active {\r\n --background: var(--color-secondary-surface);\r\n --color: var(--color-secondary-content);\r\n --background-activated: var(--color-secondary-surface);\r\n --background-focused: var(--color-secondary-surface);\r\n --background-hover: var(--color-secondary-surface);\r\n }\r\n \r\n .theme-buttons ion-button::part(native)::after {\r\n display: none;\r\n }\r\n \r\n /* Logo Preview */\r\n .logo-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: var(--color-brand-secondary);\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .logomark-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .preview-grid {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n }\r\n \r\n .preview-tile {\r\n background: white;\r\n border-radius: 12px;\r\n padding: 16px;\r\n }\r\n \r\n .preview-tile h3 {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #666;\r\n margin-bottom: 12px;\r\n }\r\n \r\n /* Brand Colors */\r\n .color-section {\r\n background: white;\r\n border-radius: 12px;\r\n padding: 20px;\r\n }\r\n \r\n .color-swatches {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n margin-bottom: 24px;\r\n }\r\n \r\n .swatch {\r\n padding: 16px;\r\n border-radius: 8px;\r\n text-align: center;\r\n }\r\n \r\n .swatch-label {\r\n font-size: 12px;\r\n font-weight: 600;\r\n margin-bottom: 4px;\r\n }\r\n \r\n .swatch-value {\r\n font-size: 11px;\r\n opacity: 0.8;\r\n font-family: monospace;\r\n }\r\n \r\n .swatch--primary-surface {\r\n background: var(--color-primary-surface);\r\n color: var(--color-primary-content);\r\n }\r\n \r\n .swatch--primary-content {\r\n background: var(--color-primary-content);\r\n color: var(--color-primary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n .swatch--secondary-surface {\r\n background: var(--color-secondary-surface);\r\n color: var(--color-secondary-content);\r\n }\r\n \r\n .swatch--secondary-content {\r\n background: var(--color-secondary-content);\r\n color: var(--color-secondary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n /* Color Inputs */\r\n .color-inputs {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .color-group-label {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #333;\r\n margin-top: 8px;\r\n }\r\n \r\n .color-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n \r\n .color-row label {\r\n min-width: 70px;\r\n font-size: 13px;\r\n color: #666;\r\n }\r\n \r\n .color-row input[type=\"color\"] {\r\n width: 40px;\r\n height: 32px;\r\n border: none;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n padding: 0;\r\n }\r\n \r\n .color-row input[type=\"text\"] {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 6px;\r\n font-family: monospace;\r\n font-size: 13px;\r\n }\r\n `],\r\n template: `\r\n <ion-header>\r\n <ion-toolbar>\r\n <ion-title>Whitelabel</ion-title>\r\n </ion-toolbar>\r\n </ion-header>\r\n \r\n <ion-content>\r\n <div class=\"demo-container\">\r\n <!-- Theme Selection -->\r\n <div class=\"demo-section\">\r\n <h2>Theme</h2>\r\n <div class=\"theme-buttons\">\r\n <ion-button (click)=\"applyDefaultTheme()\" size=\"small\" [class.active]=\"currentTheme === 'default'\">\r\n Propbinder\r\n </ion-button>\r\n <ion-button (click)=\"applyCejTheme()\" size=\"small\" [class.active]=\"currentTheme === 'cej'\">\r\n CEJ\r\n </ion-button>\r\n <ion-button (click)=\"applyPkaTheme()\" size=\"small\" [class.active]=\"currentTheme === 'pka'\">\r\n PKA\r\n </ion-button>\r\n <ion-button (click)=\"applyClaveTheme()\" size=\"small\" [class.active]=\"currentTheme === 'clave'\">\r\n Clave\r\n </ion-button>\r\n <ion-button (click)=\"applyFreedomTheme()\" size=\"small\" [class.active]=\"currentTheme === 'freedom'\">\r\n Freedom\r\n </ion-button>\r\n </div>\r\n </div>\r\n \r\n <!-- Logo & Logomark Preview -->\r\n <div class=\"demo-section\">\r\n <h2>Logo Preview</h2>\r\n <div class=\"preview-grid\">\r\n <div class=\"preview-tile\">\r\n <h3>Logo</h3>\r\n <div class=\"logo-preview\">\r\n <ds-logo variant=\"full\" />\r\n </div>\r\n </div>\r\n <div class=\"preview-tile\">\r\n <h3>Logomark</h3>\r\n <div class=\"logomark-preview\">\r\n <ds-avatar-with-badge\r\n [type]=\"'initials'\"\r\n [initials]=\"'KN'\"\r\n [size]=\"'md'\"\r\n [badgePosition]=\"'bottom-right'\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Brand Colors -->\r\n <div class=\"demo-section\">\r\n <h2>Brand Colors</h2>\r\n <div class=\"color-section\">\r\n <div class=\"color-swatches\">\r\n <div class=\"swatch swatch--primary-surface\">\r\n <div class=\"swatch-label\">Primary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--primary-content\">\r\n <div class=\"swatch-label\">Primary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primaryContent() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-surface\">\r\n <div class=\"swatch-label\">Secondary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-content\">\r\n <div class=\"swatch-label\">Secondary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondaryContent() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"color-inputs\">\r\n <div class=\"color-group-label\">Primary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n \r\n <div class=\"color-group-label\">Secondary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class WhitelabelDemoPage implements OnInit {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n // Current active theme\r\n currentTheme = 'default';\r\n \r\n // Custom color inputs\r\n customPrimarySurface = '#6B5FF5';\r\n customPrimaryContent = '#FFFFFF';\r\n customSecondarySurface = '#221a4c';\r\n customSecondaryContent = '#FFFFFF';\r\n \r\n ngOnInit() {\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyDefaultTheme() {\r\n this.currentTheme = 'default';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoAlt: 'Propbinder',\r\n logoHeight: 28,\r\n primarySurface: '#6B5FF5',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#221a4c',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Propbinder',\r\n organizationId: 'default'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCejTheme() {\r\n this.currentTheme = 'cej';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/cej-logo.png',\r\n logoMarkUrl: '/Assets/logos/cej-logo.png',\r\n logoAlt: 'CEJ',\r\n logoHeight: 36,\r\n primarySurface: '#dc092c',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#A70923',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'CEJ',\r\n organizationId: 'cej'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyPkaTheme() {\r\n this.currentTheme = 'pka';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/pka-logo.svg',\r\n logoMarkUrl: '/Assets/logos/pka-logo.svg',\r\n logoAlt: 'PKA',\r\n logoHeight: 24,\r\n primarySurface: '#CC006C',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#660036',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'PKA',\r\n organizationId: 'pka'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyClaveTheme() {\r\n this.currentTheme = 'clave';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/clave-logo.svg',\r\n logoMarkUrl: '/Assets/logos/clave-logo.svg',\r\n logoAlt: 'Clave',\r\n logoHeight: 24,\r\n primarySurface: '#868764',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#262424',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Clave',\r\n organizationId: 'clave'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyFreedomTheme() {\r\n this.currentTheme = 'freedom';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/freedom-logo.svg',\r\n logoMarkUrl: '/Assets/logos/freedom-logomark.svg',\r\n logoAlt: 'Freedom',\r\n logoHeight: 28,\r\n primarySurface: '#AACFC3',\r\n primaryContent: '#1D4A49',\r\n secondarySurface: '#1D4A49',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Freedom',\r\n organizationId: 'freedom'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCustomColors() {\r\n this.whitelabelService.updateColors({\r\n primarySurface: this.customPrimarySurface,\r\n primaryContent: this.customPrimaryContent,\r\n secondarySurface: this.customSecondarySurface,\r\n secondaryContent: this.customSecondaryContent\r\n });\r\n }\r\n \r\n private updateCustomColorInputs() {\r\n this.customPrimarySurface = this.whitelabelService.primarySurface();\r\n this.customPrimaryContent = this.whitelabelService.primaryContent();\r\n this.customSecondarySurface = this.whitelabelService.secondarySurface();\r\n this.customSecondaryContent = this.whitelabelService.secondaryContent();\r\n }\r\n}\r\n","/* Auto-generated. Do not edit. */\nexport * from './components';\nexport * from './pages';\nexport * from './animations/page-transitions';\nexport * from './services/user.service';\nexport * from './services/whitelabel.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.DsMobileLongPressDirective","i2","i1","i1.DsMobileLightboxService","DsMobileCommentActionsBottomSheetComponent","i2.DsMobileLightboxService","i3.DsMobileBottomSheetService","i4","i1.DsMobileHandbookDetailModalService","DsMobilePostActionsBottomSheetComponent","i2.DsMobileBottomSheetService","i3.DsMobileLightboxService","i4.DsMobilePostDetailModalService","i5.UserService","i1.UserService","i2.UserService","i4.DsMobileChatModalService","i3"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"propbinder-mobile-design.mjs","sources":["../../../projects/mobile-design-lib/src/services/whitelabel.service.ts","../../../projects/mobile-design-lib/src/components/logo/ds-logo.ts","../../../projects/mobile-design-lib/src/components/shared/mobile-page-base.ts","../../../projects/mobile-design-lib/src/components/shared/directives/long-press.directive.ts","../../../projects/mobile-design-lib/src/components/list-item/ds-mobile-list-item.ts","../../../projects/mobile-design-lib/src/components/action-list-item/ds-mobile-action-list-item.ts","../../../projects/mobile-design-lib/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts","../../../projects/mobile-design-lib/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts","../../../projects/mobile-design-lib/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts","../../../projects/mobile-design-lib/src/services/user.service.ts","../../../projects/mobile-design-lib/src/components/avatar-with-badge/ds-avatar-with-badge.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo-modal.component.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo-modal.service.ts","../../../projects/mobile-design-lib/src/components/page-main/ds-mobile-page-main.ts","../../../projects/mobile-design-lib/src/components/page-details/ds-mobile-page-details.ts","../../../projects/mobile-design-lib/src/components/content/ds-mobile-content.ts","../../../projects/mobile-design-lib/src/components/header-content/ds-mobile-header-content.ts","../../../projects/mobile-design-lib/src/components/comment/ds-mobile-comment.ts","../../../projects/mobile-design-lib/src/components/post-composer/ds-mobile-post-composer.ts","../../../projects/mobile-design-lib/src/components/message-composer/ds-mobile-message-composer.ts","../../../projects/mobile-design-lib/src/components/message-bubble/ds-mobile-message-bubble.ts","../../../projects/mobile-design-lib/src/components/list-item-static/ds-mobile-list-item-static.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-post/index.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts","../../../projects/mobile-design-lib/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts","../../../projects/mobile-design-lib/src/components/contact-list-item/ds-mobile-contact-list-item.ts","../../../projects/mobile-design-lib/src/components/tab-bar/ds-mobile-tab-bar.ts","../../../projects/mobile-design-lib/src/components/tabs/ds-mobile-tabs.ts","../../../projects/mobile-design-lib/src/components/inline-tabs/ds-mobile-inline-tabs.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-header.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-footer.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-image.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox-pdf.ts","../../../projects/mobile-design-lib/src/components/lightbox/ds-mobile-lightbox.service.ts","../../../projects/mobile-design-lib/src/components/lightbox/index.ts","../../../projects/mobile-design-lib/src/components/inline-photo/ds-mobile-inline-photo.ts","../../../projects/mobile-design-lib/src/components/modal/ds-mobile-modal.service.ts","../../../projects/mobile-design-lib/src/components/modal/index.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/index.ts","../../../projects/mobile-design-lib/src/components/chat-modal/ds-mobile-chat-modal.ts","../../../projects/mobile-design-lib/src/components/chat-modal/ds-mobile-chat-modal.service.ts","../../../projects/mobile-design-lib/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts","../../../projects/mobile-design-lib/src/components/card-inline/ds-mobile-card-inline.ts","../../../projects/mobile-design-lib/src/components/card-inline-file/ds-mobile-card-inline-file.ts","../../../projects/mobile-design-lib/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts","../../../projects/mobile-design-lib/src/components/swiper/ds-mobile-swiper.ts","../../../projects/mobile-design-lib/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts","../../../projects/mobile-design-lib/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts","../../../projects/mobile-design-lib/src/components/handbook-folder/ds-mobile-handbook-folder.ts","../../../projects/mobile-design-lib/src/components/text-input/ds-text-input.ts","../../../projects/mobile-design-lib/src/components/index.ts","../../../projects/mobile-design-lib/src/pages/community.page.ts","../../../projects/mobile-design-lib/src/pages/handbook.page.ts","../../../projects/mobile-design-lib/src/pages/home.page.ts","../../../projects/mobile-design-lib/src/animations/page-transitions.ts","../../../projects/mobile-design-lib/src/pages/inquiries.example.ts","../../../projects/mobile-design-lib/src/pages/inquiry-detail.example.ts","../../../projects/mobile-design-lib/src/pages/mobile-tabs-example.component.ts","../../../projects/mobile-design-lib/src/pages/post-create.page.ts","../../../projects/mobile-design-lib/src/pages/post-detail.page.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo.page.ts","../../../projects/mobile-design-lib/src/public-api.ts","../../../projects/mobile-design-lib/src/propbinder-mobile-design.ts"],"sourcesContent":["import { Injectable, signal, effect, computed } from '@angular/core';\r\nimport { StatusBar } from '@capacitor/status-bar';\r\n\r\nexport interface WhitelabelConfig {\r\n // Logo assets\r\n logoUrl: string; // Full logo for header (typically horizontal)\r\n logoMarkUrl: string; // Compact logo mark for avatars/badges\r\n logoAlt: string; // Alt text for accessibility\r\n \r\n // Logo dimensions (optional, for optimization)\r\n logoWidth?: number;\r\n logoHeight?: number;\r\n logoMarkWidth?: number;\r\n logoMarkHeight?: number;\r\n \r\n // Brand colors - these will update CSS custom properties\r\n primarySurface: string; // Background for primary elements (buttons, active states)\r\n primaryContent: string; // Text/icon color on primary surfaces\r\n secondarySurface: string; // Background for secondary elements (headers)\r\n secondaryContent: string; // Text/icon color on secondary surfaces (titles, active tabs)\r\n \r\n // Organization info\r\n organizationName: string;\r\n organizationId: string;\r\n}\r\n\r\nconst DEFAULT_CONFIG: WhitelabelConfig = {\r\n logoUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoAlt: 'Propbinder',\r\n logoHeight: 28, // Default logo height in pixels\r\n primarySurface: '#6B5FF5', // Propbinder brand purple - buttons, active states\r\n primaryContent: '#FFFFFF', // White text on primary surfaces\r\n secondarySurface: '#221a4c', // Propbinder dark purple - headers\r\n secondaryContent: '#FFFFFF', // White text on secondary surfaces (titles, active tabs)\r\n organizationName: 'Propbinder',\r\n organizationId: 'default'\r\n};\r\n\r\n/**\r\n * WhitelabelService\r\n * \r\n * Manages whitelabel configuration including logos and brand colors.\r\n * Automatically updates CSS custom properties when colors change.\r\n * \r\n * @example\r\n * Initialize with custom config:\r\n * ```typescript\r\n * whitelabelService.initialize({\r\n * logoUrl: '/Assets/logos/acme-logo.svg',\r\n * logoMarkUrl: '/Assets/logos/acme-mark.svg',\r\n * primaryColor: '#2563eb',\r\n * secondaryColor: '#3b82f6',\r\n * organizationName: 'Acme Corp'\r\n * });\r\n * ```\r\n * \r\n * Load from API:\r\n * ```typescript\r\n * await whitelabelService.loadFromApi('acme-corp');\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WhitelabelService {\r\n private _config = signal<WhitelabelConfig>(DEFAULT_CONFIG);\r\n \r\n // Readonly computed signals for accessing config values\r\n readonly logoUrl = computed(() => this._config().logoUrl);\r\n readonly logoMarkUrl = computed(() => this._config().logoMarkUrl);\r\n readonly logoAlt = computed(() => this._config().logoAlt);\r\n readonly logoHeight = computed(() => this._config().logoHeight ?? 32);\r\n readonly primarySurface = computed(() => this._config().primarySurface);\r\n readonly primaryContent = computed(() => this._config().primaryContent);\r\n readonly secondarySurface = computed(() => this._config().secondarySurface);\r\n readonly secondaryContent = computed(() => this._config().secondaryContent);\r\n readonly organizationName = computed(() => this._config().organizationName);\r\n readonly organizationId = computed(() => this._config().organizationId);\r\n \r\n // Full config accessor\r\n readonly config = this._config.asReadonly();\r\n \r\n constructor() {\r\n // Apply default colors on initialization\r\n this.applyColors(DEFAULT_CONFIG);\r\n \r\n // Watch for config changes and update CSS custom properties\r\n effect(() => {\r\n const config = this._config();\r\n this.applyColors(config);\r\n });\r\n }\r\n \r\n /**\r\n * Initialize whitelabel configuration\r\n * Call this early in app initialization (app.config.ts or app.component.ts)\r\n */\r\n initialize(config: Partial<WhitelabelConfig>) {\r\n this._config.update(current => ({\r\n ...current,\r\n ...config\r\n }));\r\n }\r\n \r\n /**\r\n * Load whitelabel config from API\r\n * Typically called on app startup based on subdomain, user tenant, etc.\r\n * \r\n * @param organizationId - The organization identifier (subdomain, tenant ID, etc.)\r\n */\r\n async loadFromApi(organizationId?: string): Promise<void> {\r\n try {\r\n // Example API call structure\r\n // const response = await fetch(`/api/whitelabel/${organizationId || 'default'}`);\r\n // const config = await response.json();\r\n // this.initialize(config);\r\n \r\n console.log('Loading whitelabel config from API for:', organizationId);\r\n \r\n // Example: Different configs for different organizations\r\n if (organizationId === 'demo-client') {\r\n this.initialize({\r\n logoUrl: '/Assets/logos/demo-logo.svg',\r\n logoMarkUrl: '/Assets/logos/demo-mark.svg',\r\n logoAlt: 'Demo Client',\r\n primarySurface: '#2563eb', // Blue\r\n primaryContent: '#FFFFFF', // White text on blue\r\n secondarySurface: '#3b82f6', // Lighter blue\r\n secondaryContent: '#FFFFFF', // White text on header\r\n organizationName: 'Demo Client',\r\n organizationId: 'demo-client'\r\n });\r\n }\r\n // Add more organization-specific configs as needed\r\n \r\n } catch (error) {\r\n console.error('Failed to load whitelabel config:', error);\r\n // Fallback to defaults already set\r\n }\r\n }\r\n \r\n /**\r\n * Update config dynamically (e.g., when user switches organizations)\r\n */\r\n updateConfig(updates: Partial<WhitelabelConfig>) {\r\n this.initialize(updates);\r\n }\r\n \r\n /**\r\n * Update only the brand colors\r\n */\r\n updateColors(colors: {\r\n primarySurface?: string;\r\n primaryContent?: string;\r\n secondarySurface?: string;\r\n secondaryContent?: string;\r\n }) {\r\n this._config.update(current => ({\r\n ...current,\r\n ...colors\r\n }));\r\n }\r\n \r\n /**\r\n * Reset to default configuration\r\n */\r\n resetToDefault() {\r\n this._config.set(DEFAULT_CONFIG);\r\n }\r\n \r\n /**\r\n * Convert hex color to RGB values\r\n */\r\n private hexToRgb(hex: string): { r: number; g: number; b: number } | null {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n return result ? {\r\n r: parseInt(result[1], 16),\r\n g: parseInt(result[2], 16),\r\n b: parseInt(result[3], 16)\r\n } : null;\r\n }\r\n \r\n /**\r\n * Apply colors to CSS custom properties and native StatusBar\r\n * This updates the actual CSS variables used throughout the app\r\n * and the native status bar color on mobile devices\r\n */\r\n private applyColors(config: WhitelabelConfig) {\r\n if (typeof document !== 'undefined') {\r\n const { primarySurface, primaryContent, secondarySurface, secondaryContent } = config;\r\n const root = document.documentElement;\r\n const body = document.body;\r\n const ionApp = document.querySelector('ion-app');\r\n \r\n // Primary surface color - used for buttons, selected states, accents background\r\n root.style.setProperty('--color-background-brand', primarySurface);\r\n root.style.setProperty('--color-brand-base', primarySurface);\r\n root.style.setProperty('--color-primary-surface', primarySurface);\r\n body.style.setProperty('--color-background-brand', primarySurface);\r\n body.style.setProperty('--color-brand-base', primarySurface);\r\n body.style.setProperty('--color-primary-surface', primarySurface);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--color-background-brand', primarySurface);\r\n (ionApp as HTMLElement).style.setProperty('--color-brand-base', primarySurface);\r\n (ionApp as HTMLElement).style.setProperty('--color-primary-surface', primarySurface);\r\n }\r\n \r\n // Primary content color - text/icon color on primary surfaces\r\n root.style.setProperty('--color-primary-content', primaryContent);\r\n body.style.setProperty('--color-primary-content', primaryContent);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--color-primary-content', primaryContent);\r\n }\r\n \r\n // Update tab button selected color directly\r\n // CSS variable inheritance doesn't always work dynamically with Ionic components\r\n document.querySelectorAll('ion-tab-button').forEach(tabButton => {\r\n (tabButton as HTMLElement).style.setProperty('--color-selected', primarySurface);\r\n });\r\n \r\n // Secondary surface color - used for headers, status bar background\r\n root.style.setProperty('--color-brand-secondary', secondarySurface);\r\n root.style.setProperty('--color-secondary-surface', secondarySurface);\r\n body.style.setProperty('--color-brand-secondary', secondarySurface);\r\n body.style.setProperty('--color-secondary-surface', secondarySurface);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--color-brand-secondary', secondarySurface);\r\n (ionApp as HTMLElement).style.setProperty('--color-secondary-surface', secondarySurface);\r\n }\r\n \r\n // Secondary content color - text/icon color on secondary surfaces (titles, active tabs)\r\n root.style.setProperty('--header-content-color', secondaryContent);\r\n root.style.setProperty('--color-secondary-content', secondaryContent);\r\n body.style.setProperty('--header-content-color', secondaryContent);\r\n body.style.setProperty('--color-secondary-content', secondaryContent);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--header-content-color', secondaryContent);\r\n (ionApp as HTMLElement).style.setProperty('--color-secondary-content', secondaryContent);\r\n }\r\n \r\n // Also set RGB values for use with rgba() opacity variations\r\n const rgb = this.hexToRgb(secondaryContent);\r\n if (rgb) {\r\n const rgbValue = `${rgb.r}, ${rgb.g}, ${rgb.b}`;\r\n root.style.setProperty('--header-content-color-rgb', rgbValue);\r\n root.style.setProperty('--color-secondary-content-rgb', rgbValue);\r\n body.style.setProperty('--header-content-color-rgb', rgbValue);\r\n body.style.setProperty('--color-secondary-content-rgb', rgbValue);\r\n if (ionApp) {\r\n (ionApp as HTMLElement).style.setProperty('--header-content-color-rgb', rgbValue);\r\n (ionApp as HTMLElement).style.setProperty('--color-secondary-content-rgb', rgbValue);\r\n }\r\n }\r\n \r\n // Update theme-color meta tag for browser chrome/status bar (PWA/iOS)\r\n const metaThemeColor = document.querySelector('meta[name=\"theme-color\"]');\r\n if (metaThemeColor) {\r\n metaThemeColor.setAttribute('content', secondarySurface);\r\n }\r\n \r\n // Update native StatusBar color (Capacitor - Android only, iOS ignores this)\r\n this.updateNativeStatusBar(secondarySurface);\r\n \r\n console.log('Applied whitelabel colors:', { primarySurface, primaryContent, secondarySurface, secondaryContent });\r\n }\r\n }\r\n \r\n /**\r\n * Update the native status bar color\r\n * Note: This only works on Android. On iOS, the status bar is transparent\r\n * and shows the web content behind it (controlled by CSS variables)\r\n */\r\n private async updateNativeStatusBar(color: string): Promise<void> {\r\n try {\r\n await StatusBar.setBackgroundColor({ color });\r\n } catch (e) {\r\n // StatusBar API not available (web browser) or failed\r\n // This is expected on web and iOS, so we don't log it as an error\r\n }\r\n }\r\n}\r\n\r\n","import { Component, Input, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { WhitelabelService } from '../../services/whitelabel.service';\r\n\r\nexport type LogoVariant = 'full' | 'mark';\r\nexport type LogoSize = 'sm' | 'md' | 'lg' | 'xl';\r\n\r\n/**\r\n * DsLogoComponent\r\n * \r\n * Displays the whitelabeled logo or logomark based on current configuration.\r\n * Automatically pulls logo assets from WhitelabelService.\r\n * \r\n * @example\r\n * Full logo in header:\r\n * ```html\r\n * <ds-logo variant=\"full\" size=\"md\" />\r\n * ```\r\n * \r\n * Logomark for compact spaces:\r\n * ```html\r\n * <ds-logo variant=\"mark\" size=\"sm\" />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-logo',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: flex;\r\n justify-content: flex-start;\r\n line-height: 0;\r\n }\r\n \r\n .logo {\r\n display: block;\r\n object-fit: contain;\r\n width: auto;\r\n }\r\n `],\r\n template: `\r\n <img \r\n [src]=\"logoSrc\"\r\n [alt]=\"logoAlt\"\r\n class=\"logo\"\r\n [style.height.px]=\"effectiveHeight\"\r\n [style.width]=\"customWidth ? customWidth + 'px' : 'auto'\"\r\n />\r\n `\r\n})\r\nexport class DsLogoComponent {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n @Input() variant: LogoVariant = 'full';\r\n @Input() size: LogoSize = 'md';\r\n @Input() customHeight?: number;\r\n @Input() customWidth?: number;\r\n \r\n get logoSrc(): string {\r\n const logoUrl = this.whitelabelService.logoUrl();\r\n const logoMarkUrl = this.whitelabelService.logoMarkUrl();\r\n \r\n if (this.variant === 'full') {\r\n // Use logo, fall back to logomark if logo doesn't exist\r\n return logoUrl || logoMarkUrl;\r\n } else {\r\n // Use logomark, fall back to logo if logomark doesn't exist\r\n return logoMarkUrl || logoUrl;\r\n }\r\n }\r\n \r\n get logoAlt(): string {\r\n const alt = this.whitelabelService.logoAlt();\r\n return this.variant === 'full' ? alt : `${alt} logo`;\r\n }\r\n \r\n /** \r\n * Priority: customHeight input > whitelabel config logoHeight > default 32px\r\n */\r\n get effectiveHeight(): number {\r\n return this.customHeight ?? this.whitelabelService.logoHeight();\r\n }\r\n}\r\n\r\n","import { input, computed, Directive } from '@angular/core';\r\n\r\n/**\r\n * Content width preset values\r\n * - 'narrow' - 640px max width (reading content)\r\n * - 'standard' - 1024px max width (default)\r\n * - 'wide' - 1440px max width (dashboards)\r\n * - 'full' - 100% width (no max)\r\n */\r\nexport type ContentWidth = 'narrow' | 'standard' | 'wide' | 'full';\r\n\r\n/**\r\n * MobilePageBase\r\n * \r\n * Shared base class for mobile page components (ds-mobile-page-main, ds-mobile-page-details).\r\n * Provides consistent content width control across all page types.\r\n * \r\n * **Padding Strategy:**\r\n * - All pages use 20px horizontal padding globally\r\n * - For tappable lists, use negative margins (e.g., margin: 0 -8px) to create full-width sections\r\n * - This approach simplifies padding management and provides consistency\r\n * \r\n * @internal This is a base class and should not be used directly.\r\n */\r\n@Directive()\r\nexport abstract class MobilePageBase {\r\n /**\r\n * Maximum content width (desktop only)\r\n * \r\n * **Options:**\r\n * - `'narrow'` (640px) - For reading content, forms\r\n * - `'standard'` (1024px) - Default for most pages\r\n * - `'wide'` (1440px) - For dashboards, tables\r\n * - `'full'` - No max-width constraint\r\n * \r\n * **Note:** Only applies on desktop (>= 768px). Mobile is always full width.\r\n * \r\n * @default 'standard'\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Narrow reading layout -->\r\n * <ds-mobile-page-main title=\"Article\" contentWidth=\"narrow\">\r\n * \r\n * <!-- Wide dashboard -->\r\n * <ds-mobile-page-main title=\"Dashboard\" contentWidth=\"wide\">\r\n * ```\r\n */\r\n contentWidth = input<ContentWidth>('standard');\r\n\r\n /**\r\n * Resolved max-width value (computed)\r\n * Maps preset values to pixel values\r\n * \r\n * @internal\r\n */\r\n protected maxWidthValue = computed(() => {\r\n const w = this.contentWidth();\r\n \r\n const widthMap: Record<ContentWidth, string> = {\r\n 'narrow': '640px',\r\n 'standard': '1024px',\r\n 'wide': '1440px',\r\n 'full': '100%'\r\n };\r\n \r\n return widthMap[w];\r\n });\r\n}\r\n\r\n","import { \r\n Directive, \r\n Output, \r\n EventEmitter, \r\n HostListener, \r\n Input,\r\n OnDestroy \r\n} from '@angular/core';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\n\r\n/**\r\n * DsMobileLongPressDirective\r\n * \r\n * A reusable directive for handling long press interactions on mobile devices.\r\n * Provides haptic feedback and prevents long press when touching interactive elements.\r\n * \r\n * Features:\r\n * - Configurable duration and movement threshold\r\n * - Automatic haptic feedback (with fallback to navigator.vibrate)\r\n * - Excludes interactive elements (buttons, links, inputs)\r\n * - Handles touchmove cancellation\r\n * - Context menu support (right-click on desktop)\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Basic usage -->\r\n * <div dsMobileLongPress (longPress)=\"handleLongPress()\">\r\n * Long press me\r\n * </div>\r\n * \r\n * <!-- Custom duration and threshold -->\r\n * <div \r\n * dsMobileLongPress \r\n * [longPressDuration]=\"800\"\r\n * [moveThreshold]=\"15\"\r\n * [excludeSelectors]=\"'button, a, .no-longpress'\"\r\n * (longPress)=\"showContextMenu()\">\r\n * Custom long press\r\n * </div>\r\n * ```\r\n */\r\n@Directive({\r\n selector: '[dsMobileLongPress]',\r\n standalone: true\r\n})\r\nexport class DsMobileLongPressDirective implements OnDestroy {\r\n /**\r\n * Duration in milliseconds to trigger long press\r\n * @default 500\r\n */\r\n @Input() longPressDuration = 500;\r\n\r\n /**\r\n * Maximum movement in pixels before canceling long press\r\n * @default 10\r\n */\r\n @Input() moveThreshold = 10;\r\n\r\n /**\r\n * CSS selectors to exclude from long press detection\r\n * @default 'button, a, input, select, textarea, [role=\"button\"]'\r\n */\r\n @Input() excludeSelectors = 'button, a, input, select, textarea, [role=\"button\"]';\r\n\r\n /**\r\n * Haptic feedback style (Light, Medium, Heavy)\r\n * @default ImpactStyle.Medium\r\n */\r\n @Input() hapticStyle: ImpactStyle = ImpactStyle.Medium;\r\n\r\n /**\r\n * Enable/disable haptic feedback\r\n * @default true\r\n */\r\n @Input() enableHaptics = true;\r\n\r\n /**\r\n * Emits when long press is triggered\r\n */\r\n @Output() longPress = new EventEmitter<void>();\r\n\r\n /**\r\n * Emits when long press starts (timer begins)\r\n */\r\n @Output() longPressStart = new EventEmitter<void>();\r\n\r\n /**\r\n * Emits when long press is cancelled\r\n */\r\n @Output() longPressCancel = new EventEmitter<void>();\r\n\r\n private longPressTimer: any = null;\r\n private longPressTriggered = false;\r\n private touchStartX = 0;\r\n private touchStartY = 0;\r\n\r\n /**\r\n * Handle touch start for long press detection\r\n */\r\n @HostListener('touchstart', ['$event'])\r\n handleTouchStart(event: TouchEvent): void {\r\n // Don't start long press if touching interactive child elements\r\n // But allow if the closest match is the host element itself (where the directive is attached)\r\n const target = event.target as HTMLElement;\r\n const closestExcluded = target.closest(this.excludeSelectors);\r\n const hostElement = (event.currentTarget as HTMLElement);\r\n \r\n // Only exclude if we found an excluded element AND it's not the host itself\r\n if (closestExcluded && closestExcluded !== hostElement) {\r\n return;\r\n }\r\n\r\n this.longPressTriggered = false;\r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n\r\n // Emit start event\r\n this.longPressStart.emit();\r\n\r\n // Start long press timer\r\n this.longPressTimer = setTimeout(async () => {\r\n this.longPressTriggered = true;\r\n this.longPress.emit();\r\n\r\n // Haptic feedback for long press\r\n if (this.enableHaptics) {\r\n await this.triggerHaptics();\r\n }\r\n }, this.longPressDuration);\r\n }\r\n\r\n /**\r\n * Handle touch end to clear long press timer\r\n */\r\n @HostListener('touchend', ['$event'])\r\n handleTouchEnd(event: TouchEvent): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n \r\n if (!this.longPressTriggered) {\r\n this.longPressCancel.emit();\r\n }\r\n }\r\n\r\n // Prevent normal click if long press was triggered\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle touch move to cancel long press if moved too much\r\n */\r\n @HostListener('touchmove', ['$event'])\r\n handleTouchMove(event: TouchEvent): void {\r\n if (!this.longPressTimer) return;\r\n\r\n const touch = event.touches[0];\r\n const deltaX = Math.abs(touch.clientX - this.touchStartX);\r\n const deltaY = Math.abs(touch.clientY - this.touchStartY);\r\n\r\n // Cancel long press if moved too far\r\n if (deltaX > this.moveThreshold || deltaY > this.moveThreshold) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n this.longPressTriggered = false;\r\n this.longPressCancel.emit();\r\n }\r\n }\r\n\r\n /**\r\n * Handle context menu (right-click on desktop) to trigger long press action\r\n */\r\n @HostListener('contextmenu', ['$event'])\r\n handleContextMenu(event: Event): void {\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n\r\n /**\r\n * Trigger haptic feedback\r\n */\r\n private async triggerHaptics(): Promise<void> {\r\n try {\r\n await Haptics.impact({ style: this.hapticStyle });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n // Map haptic styles to vibration durations\r\n const vibrationMap = {\r\n [ImpactStyle.Light]: 30,\r\n [ImpactStyle.Medium]: 50,\r\n [ImpactStyle.Heavy]: 80\r\n };\r\n navigator.vibrate(vibrationMap[this.hapticStyle] || 50);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup on destroy\r\n */\r\n ngOnDestroy(): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n }\r\n}\r\n","import { Component, input, output, computed, signal, PLATFORM_ID, inject } from '@angular/core';\r\nimport { CommonModule, isPlatformBrowser } from '@angular/common';\r\nimport { DsMobileLongPressDirective } from '../shared/directives/long-press.directive';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileListItemComponent\r\n * \r\n * A versatile, reusable list item component for mobile applications.\r\n * Supports both interactive and non-interactive modes with flexible content projection.\r\n * \r\n * Features:\r\n * - Interactive mode with click and long-press support\r\n * - Pseudo-element background extends 8px beyond bounds (no negative margins needed)\r\n * - Flexible content slots (leading, main, trailing)\r\n * - Optional structured inputs for common use cases (title, subtitle)\r\n * - Accessibility features (focus states, ARIA attributes)\r\n * - Disabled and loading states\r\n * \r\n * This component serves as the foundation for specialized list item types like posts,\r\n * notifications, messages, contacts, and other list content.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple structured usage -->\r\n * <ds-mobile-list-item\r\n * title=\"Document Title\"\r\n * subtitle=\"Supporting text\"\r\n * [interactive]=\"true\"\r\n * (itemClick)=\"handleClick()\">\r\n * \r\n * <ds-icon content-leading name=\"document\" />\r\n * </ds-mobile-list-item>\r\n * \r\n * <!-- Flexible custom usage -->\r\n * <ds-mobile-list-item\r\n * [interactive]=\"true\"\r\n * (itemClick)=\"handleClick()\"\r\n * (longPress)=\"showContextMenu()\">\r\n * \r\n * <div content-leading>\r\n * <ds-avatar initials=\"JD\" />\r\n * </div>\r\n * \r\n * <div content-main>\r\n * <h3>Custom Content</h3>\r\n * <p>Full control over layout and styling</p>\r\n * </div>\r\n * \r\n * <button content-trailing (click)=\"handleAction($event)\">\r\n * Action\r\n * </button>\r\n * </ds-mobile-list-item>\r\n * \r\n * <!-- Non-interactive read-only -->\r\n * <ds-mobile-list-item\r\n * title=\"Read-only Item\"\r\n * subtitle=\"No interaction\">\r\n * <ds-icon content-leading name=\"info\" />\r\n * </ds-mobile-list-item>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-list-item',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent],\r\n hostDirectives: [\r\n {\r\n directive: DsMobileLongPressDirective,\r\n outputs: ['longPress']\r\n }\r\n ],\r\n host: {\r\n '[class.interactive]': 'interactive() && !disabled()',\r\n '[class.disabled]': 'disabled()',\r\n '[class.loading]': 'loading()',\r\n '[class.no-divider]': '!showDivider()',\r\n '[class.variant-compact]': 'variant() === \"compact\"',\r\n '[class.align-top]': 'align() === \"top\"',\r\n '[class.align-center]': 'align() === \"center\"',\r\n '[class.align-bottom]': 'align() === \"bottom\"',\r\n '[attr.role]': 'interactive() ? \"button\" : null',\r\n '[attr.tabindex]': 'interactive() && !disabled() ? \"0\" : null',\r\n '[attr.aria-disabled]': 'disabled() ? \"true\" : null',\r\n '[style.--leading-size]': 'leadingSize()',\r\n '[style.--interactive-offset]': 'interactiveOffset()',\r\n '[style.--divider-spacing]': 'dividerSpacing()',\r\n '(click)': 'handleClick($event)',\r\n '(keydown.enter)': 'handleKeyDown($event)',\r\n '(keydown.space)': 'handleKeyDown($event)',\r\n '(longPress)': 'handleLongPress()'\r\n },\r\n styles: [`\r\n :host {\r\n display: block;\r\n position: relative;\r\n padding: var(--item-padding-top, 12px) 0 var(--item-padding-bottom, 12px) 0;\r\n box-sizing: border-box;\r\n /* CSS variables defined at host level for use by children and pseudo-elements */\r\n --leading-size: 32px;\r\n --content-gap: 12px;\r\n --interactive-offset: 8px;\r\n }\r\n \r\n /* Divider line on host */\r\n :host::after {\r\n content: '';\r\n position: absolute;\r\n bottom: 0;\r\n left: calc(var(--leading-size) + var(--content-gap));\r\n right: 0;\r\n height: 1px;\r\n background: var(--border-color-default, #e5e5e5);\r\n z-index: 1;\r\n display: var(--divider-display, block);\r\n }\r\n \r\n /* Hide divider when no-divider class is present */\r\n :host(.no-divider)::after {\r\n display: none;\r\n }\r\n \r\n .list-item-inner {\r\n display: flex;\r\n flex-direction: row;\r\n align-items: flex-start;\r\n gap: var(--content-gap);\r\n position: relative;\r\n }\r\n \r\n :host(.align-center) .list-item-inner {\r\n align-items: center;\r\n }\r\n \r\n :host(.align-bottom) .list-item-inner {\r\n align-items: flex-end;\r\n }\r\n \r\n /* Pseudo-element for interactive background */\r\n :host(.interactive) .list-item-inner::before {\r\n content: '';\r\n position: absolute;\r\n top: calc(-1 * var(--interactive-offset));\r\n left: calc(-1 * var(--interactive-offset));\r\n right: calc(-1 * var(--interactive-offset));\r\n bottom: calc(-1 * var(--interactive-offset));\r\n background: var(--color-background-primary, #ffffff);\r\n border-radius: 16px;\r\n z-index: -1;\r\n pointer-events: none;\r\n }\r\n \r\n /* Interactive states */\r\n :host(.interactive) {\r\n cursor: pointer;\r\n }\r\n \r\n /* Hover state (desktop only) */\r\n @media (hover: hover) and (pointer: fine) {\r\n :host(.interactive):hover .list-item-inner::before {\r\n background: var(--color-background-neutral-primary-hover, #f5f5f5);\r\n }\r\n }\r\n \r\n /* Active state */\r\n :host(.interactive):active .list-item-inner::before {\r\n background: var(--color-background-neutral-primary-hover, #f5f5f5);\r\n }\r\n \r\n /* Focus visible for keyboard navigation */\r\n :host(.interactive):focus-visible {\r\n outline: none;\r\n }\r\n \r\n :host(.interactive):focus-visible .list-item-inner::before {\r\n outline: 2px solid var(--color-brand-primary, #5d5fef);\r\n outline-offset: 2px;\r\n }\r\n \r\n /* Disabled state */\r\n :host(.disabled) {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n }\r\n \r\n /* Loading state */\r\n :host(.loading) {\r\n pointer-events: none;\r\n }\r\n \r\n /* Variants */\r\n :host(.variant-compact) .list-item-inner {\r\n gap: 8px;\r\n }\r\n \r\n /* Content slots */\r\n .content-leading {\r\n flex-shrink: 0;\r\n width: var(--leading-size);\r\n height: var(--leading-size);\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: center;\r\n position: relative;\r\n z-index: 1;\r\n }\r\n \r\n :host(.align-center) .content-leading {\r\n align-items: center;\r\n }\r\n \r\n :host(.align-bottom) .content-leading {\r\n align-items: flex-end;\r\n }\r\n \r\n .content-main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n position: relative;\r\n z-index: 1;\r\n justify-content: flex-start;\r\n }\r\n \r\n :host(.align-center) .content-main {\r\n justify-content: center;\r\n }\r\n \r\n :host(.align-bottom) .content-main {\r\n justify-content: flex-end;\r\n }\r\n \r\n .content-trailing {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: flex-start;\r\n position: relative;\r\n z-index: 1;\r\n }\r\n \r\n /* Structured content styles */\r\n .structured-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm, 14px);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .structured-subtitle {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm, 14px);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n /* Desktop more actions button - using ds-icon-button */\r\n .desktop-more-button::ng-deep button {\r\n border-radius: 50% !important;\r\n }\r\n `],\r\n template: `\r\n <div class=\"list-item-inner\">\r\n <div class=\"content-leading\">\r\n <ng-content select=\"[content-leading]\" />\r\n </div>\r\n \r\n <div class=\"content-main\">\r\n @if (title()) {\r\n <h3 class=\"structured-title\">{{ title() }}</h3>\r\n }\r\n @if (subtitle()) {\r\n <p class=\"structured-subtitle\">{{ subtitle() }}</p>\r\n }\r\n \r\n <ng-content select=\"[content-main]\" />\r\n <ng-content />\r\n </div>\r\n \r\n <div class=\"content-trailing\">\r\n @if (interactive() && enableLongPress() && showDesktopMoreButton() && isDesktop()) {\r\n <ds-icon-button\r\n class=\"desktop-more-button\"\r\n icon=\"remixMoreFill\"\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n (clicked)=\"handleMoreButtonClick($event)\"\r\n aria-label=\"More options\">\r\n </ds-icon-button>\r\n }\r\n <ng-content select=\"[content-trailing]\" />\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileListItemComponent {\r\n private platformId = inject(PLATFORM_ID);\r\n \r\n /**\r\n * Detect if viewport is desktop size\r\n * Use viewport width for breakpoint detection (show button on tablet and above)\r\n */\r\n isDesktop = signal<boolean>(false);\r\n \r\n constructor() {\r\n if (isPlatformBrowser(this.platformId)) {\r\n // Show button on tablet breakpoint and above (768px+)\r\n const isDesktopViewport = window.innerWidth >= 768;\r\n \r\n console.log('[ListItem] Desktop detection:', {\r\n innerWidth: window.innerWidth,\r\n isDesktopViewport\r\n });\r\n \r\n this.isDesktop.set(isDesktopViewport);\r\n \r\n // Listen for window resize to update detection\r\n window.addEventListener('resize', () => {\r\n const newIsDesktop = window.innerWidth >= 768;\r\n if (newIsDesktop !== this.isDesktop()) {\r\n console.log('[ListItem] Viewport changed, updating desktop detection:', newIsDesktop);\r\n this.isDesktop.set(newIsDesktop);\r\n }\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * CSS size value for the leading content area (e.g., '32px', '40px', '48px')\r\n * Defaults to '32px' for standard list item avatars/icons\r\n */\r\n leadingSize = input<string>('32px');\r\n \r\n /**\r\n * Display variant\r\n * - undefined (default) - Standard display\r\n * - 'compact' - Compact display for nested/related items\r\n */\r\n variant = input<'compact' | undefined>(undefined);\r\n \r\n /**\r\n * Vertical alignment of leading and main content slots\r\n * - 'top' - Align to top (default)\r\n * - 'center' - Align to center\r\n * - 'bottom' - Align to bottom\r\n */\r\n align = input<'top' | 'center' | 'bottom'>('top');\r\n \r\n /**\r\n * Whether the list item is interactive (clickable and long-pressable)\r\n * When true, adds interactive background, cursor pointer, and touch handlers\r\n */\r\n interactive = input<boolean>(false);\r\n \r\n /**\r\n * Whether the list item is disabled\r\n * Disables all interactions and reduces opacity\r\n */\r\n disabled = input<boolean>(false);\r\n \r\n /**\r\n * Whether the list item is in a loading state\r\n * Disables interactions but maintains full opacity\r\n */\r\n loading = input<boolean>(false);\r\n \r\n /**\r\n * Enable long-press interaction when interactive is true\r\n * Set to false to disable long-press but keep click\r\n */\r\n enableLongPress = input<boolean>(true);\r\n \r\n /**\r\n * Show \"more actions\" button on desktop for items with long-press enabled\r\n * Only visible on desktop (hover: hover) and when enableLongPress is true\r\n * Clicking this button triggers the same handler as long-press on mobile\r\n * @default true\r\n */\r\n showDesktopMoreButton = input<boolean>(true);\r\n \r\n /**\r\n * Offset distance for the interactive background pseudo-element\r\n * Extends the background beyond the content bounds\r\n * @default '8px'\r\n */\r\n interactiveOffset = input<string>('8px');\r\n \r\n /**\r\n * Optional structured title text\r\n * Provides a simple way to add title without custom markup\r\n */\r\n title = input<string>();\r\n \r\n /**\r\n * Optional structured subtitle text\r\n * Provides a simple way to add subtitle without custom markup\r\n */\r\n subtitle = input<string>();\r\n \r\n /**\r\n * Whether to show the divider line below the list item\r\n * Automatically hidden on last-child and detail variant\r\n * @default true\r\n */\r\n showDivider = input<boolean>(true);\r\n \r\n /**\r\n * Spacing around the divider (top and bottom padding)\r\n * @default '4px'\r\n */\r\n dividerSpacing = input<string>('4px');\r\n \r\n /**\r\n * Emits when the list item is clicked (if interactive and not disabled)\r\n */\r\n itemClick = output<void>();\r\n \r\n /**\r\n * Emits when the desktop more actions button is clicked\r\n * This is separate from longPress to give more control to parent components\r\n * Typically, you can use (longPress) for both mobile and desktop actions\r\n */\r\n moreButtonClick = output<Event>();\r\n \r\n /**\r\n * Track if long press was triggered to prevent click\r\n */\r\n private longPressTriggered = false;\r\n \r\n /**\r\n * Check if leading content slot has content\r\n * Always true to maintain consistent layout\r\n */\r\n hasLeadingContent = computed(() => true);\r\n \r\n /**\r\n * Check if trailing content slot has content\r\n * Always true to maintain consistent layout\r\n */\r\n hasTrailingContent = computed(() => true);\r\n \r\n /**\r\n * Handle click events\r\n */\r\n handleClick(event: Event): void {\r\n console.log('[ListItem] Click event fired', {\r\n interactive: this.interactive(),\r\n disabled: this.disabled(),\r\n loading: this.loading(),\r\n longPressTriggered: this.longPressTriggered,\r\n target: event.target\r\n });\r\n \r\n if (!this.interactive() || this.disabled() || this.loading()) {\r\n console.log('[ListItem] Click ignored - not interactive or disabled/loading');\r\n return;\r\n }\r\n \r\n // Don't emit click if it came from an interactive child element\r\n // (but not the host element itself)\r\n const target = event.target as HTMLElement;\r\n const closestInteractive = target.closest('button, a, input, select, textarea, [role=\"button\"]');\r\n \r\n // Check if the interactive element is a child, not the host itself\r\n if (closestInteractive && closestInteractive !== event.currentTarget) {\r\n console.log('[ListItem] Click ignored - came from interactive child:', closestInteractive);\r\n return;\r\n }\r\n \r\n if (!this.longPressTriggered) {\r\n console.log('[ListItem] Emitting itemClick');\r\n this.itemClick.emit();\r\n } else {\r\n console.log('[ListItem] Click ignored - long press was triggered');\r\n }\r\n \r\n this.longPressTriggered = false;\r\n }\r\n \r\n /**\r\n * Handle keyboard events (Enter/Space)\r\n */\r\n handleKeyDown(event: KeyboardEvent): void {\r\n if (!this.interactive() || this.disabled() || this.loading()) {\r\n return;\r\n }\r\n \r\n event.preventDefault();\r\n this.itemClick.emit();\r\n }\r\n \r\n /**\r\n * Handle long press events from the directive\r\n * Set the flag to prevent the subsequent click event\r\n */\r\n handleLongPress(): void {\r\n this.longPressTriggered = true;\r\n // Reset the flag after a short delay to allow for the next interaction\r\n setTimeout(() => {\r\n this.longPressTriggered = false;\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Handle desktop more button click\r\n * Stops propagation to prevent triggering itemClick\r\n * Emits moreButtonClick for parent components to handle\r\n */\r\n handleMoreButtonClick(event: Event): void {\r\n console.log('[ListItem] Desktop more button clicked');\r\n \r\n // Stop propagation to prevent triggering itemClick\r\n event.stopPropagation();\r\n event.preventDefault();\r\n \r\n // Emit the more button click event\r\n this.moreButtonClick.emit(event);\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { DsMobileListItemComponent } from '../list-item/ds-mobile-list-item';\r\n\r\n/**\r\n * DsMobileActionListItemComponent\r\n * \r\n * Specialized list item for action sheets and menus.\r\n * Wraps ds-mobile-list-item with action-specific styling:\r\n * - Vertically centered content\r\n * - Interactive by default\r\n * - No dividers (controlled per-item)\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-action-list-item\r\n * title=\"Edit\"\r\n * [showDivider]=\"true\"\r\n * (itemClick)=\"handleEdit()\">\r\n * <ds-icon content-leading name=\"remixEditLine\" size=\"20px\" />\r\n * </ds-mobile-action-list-item>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-action-list-item',\r\n standalone: true,\r\n imports: [DsMobileListItemComponent],\r\n template: `\r\n <ds-mobile-list-item\r\n [title]=\"title()\"\r\n [interactive]=\"true\"\r\n [enableLongPress]=\"false\"\r\n [showDivider]=\"showDivider()\"\r\n [disabled]=\"disabled()\"\r\n (itemClick)=\"itemClick.emit()\">\r\n \r\n <div class=\"action-icon-wrapper\" content-leading>\r\n <ng-content select=\"[action-icon]\" />\r\n </div>\r\n </ds-mobile-list-item>\r\n `,\r\n styles: [`\r\n /* Center all content vertically for action items */\r\n :host ::ng-deep ds-mobile-list-item .list-item-inner {\r\n align-items: center;\r\n }\r\n \r\n /* Center icon within leading slot */\r\n :host ::ng-deep ds-mobile-list-item .content-leading {\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n /* Wrapper div must fill parent height and center icon */\r\n :host ::ng-deep .action-icon-wrapper {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n }\r\n \r\n /* Remove gap from content-main for single-line actions */\r\n :host ::ng-deep ds-mobile-list-item .content-main {\r\n gap: 0;\r\n justify-content: center;\r\n }\r\n `]\r\n})\r\nexport class DsMobileActionListItemComponent {\r\n /**\r\n * Action title text\r\n */\r\n title = input.required<string>();\r\n \r\n /**\r\n * Whether to show divider below item\r\n * @default false\r\n */\r\n showDivider = input<boolean>(false);\r\n \r\n /**\r\n * Whether the action is disabled\r\n * @default false\r\n */\r\n disabled = input<boolean>(false);\r\n \r\n /**\r\n * Emits when the action item is clicked\r\n */\r\n itemClick = output<void>();\r\n}\r\n\r\n","import { Component, Input, computed, signal } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileActionListItemComponent } from '../action-list-item/ds-mobile-action-list-item';\r\n\r\nexport interface ActionResult {\r\n action: string;\r\n}\r\n\r\nexport interface ActionItem {\r\n action: string;\r\n title: string;\r\n icon: string;\r\n destructive?: boolean;\r\n}\r\n\r\nexport interface ActionGroup {\r\n actions: ActionItem[];\r\n}\r\n\r\n/**\r\n * DsMobileActionsBottomSheetComponent\r\n * \r\n * Generic bottom sheet for displaying action lists.\r\n * Supports custom action groups or preset content actions (posts/comments).\r\n * Action groups are automatically separated by full-width dividers.\r\n * \r\n * @example Custom actions with auto-height (recommended to avoid cropping)\r\n * ```typescript\r\n * const sheet = await this.modalController.create({\r\n * component: DsMobileActionsBottomSheetComponent,\r\n * componentProps: {\r\n * customActionGroups: [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'Min profil', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Indstillinger', icon: 'remixSettings3Line' }\r\n * ]\r\n * },\r\n * {\r\n * actions: [\r\n * { action: 'logout', title: 'Log ud', icon: 'remixLogoutBoxLine', destructive: true }\r\n * ]\r\n * }\r\n * ]\r\n * },\r\n * breakpoints: [0, 1],\r\n * initialBreakpoint: 1,\r\n * handle: true,\r\n * cssClass: 'auto-height'\r\n * });\r\n * \r\n * const result = await sheet.onWillDismiss();\r\n * if (result.data?.action) {\r\n * // Handle the action\r\n * }\r\n * ```\r\n * \r\n * @example Preset content actions\r\n * ```typescript\r\n * const sheet = await this.modalController.create({\r\n * component: DsMobileActionsBottomSheetComponent,\r\n * componentProps: {\r\n * isOwnContent: false\r\n * },\r\n * breakpoints: [0, 1],\r\n * initialBreakpoint: 1,\r\n * handle: true,\r\n * cssClass: 'auto-height'\r\n * });\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-actions-bottom-sheet',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsMobileActionListItemComponent],\r\n template: `\r\n <div class=\"actions-sheet\">\r\n <!-- Actions List -->\r\n <div class=\"actions-list\">\r\n @for (group of actionGroups(); track $index; let isLast = $last) {\r\n <!-- Action Group -->\r\n <div class=\"action-group\">\r\n @for (actionItem of group.actions; track actionItem.action; let isLastInGroup = $last) {\r\n <ds-mobile-action-list-item\r\n [title]=\"actionItem.title\"\r\n [showDivider]=\"!isLastInGroup\"\r\n [class.destructive]=\"actionItem.destructive\"\r\n (itemClick)=\"selectAction(actionItem.action)\">\r\n <ds-icon \r\n action-icon \r\n [name]=\"actionItem.icon\" \r\n size=\"20px\" \r\n [class.destructive-icon]=\"actionItem.destructive\" />\r\n </ds-mobile-action-list-item>\r\n }\r\n </div>\r\n \r\n <!-- Full-width divider between groups -->\r\n @if (!isLast) {\r\n <div class=\"action-group-divider\"></div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n .actions-sheet {\r\n display: flex;\r\n flex-direction: column;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n padding-bottom: env(safe-area-inset-bottom, 0px);\r\n }\r\n \r\n /* Actions List */\r\n .actions-list {\r\n display: flex;\r\n flex-direction: column;\r\n padding-top: 16px; /* Only top padding for the container */\r\n }\r\n \r\n /* Action Group - padding on groups instead of list */\r\n .action-group {\r\n display: flex;\r\n flex-direction: column;\r\n padding: 0 16px; /* Horizontal padding on each group */\r\n }\r\n \r\n /* Override default background color to transparent so hover state is visible */\r\n /* Need ::ng-deep because ds-mobile-list-item uses :host styles internally */\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item {\r\n --color-background-primary: transparent;\r\n --color-background-neutral-primary-hover: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n \r\n /* Ensure the interactive background is visible */\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .list-item-inner::before {\r\n z-index: 0 !important;\r\n }\r\n \r\n /* Ensure content is above the background */\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .content-leading,\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .content-main,\r\n ::ng-deep ds-mobile-action-list-item ds-mobile-list-item .content-trailing {\r\n position: relative;\r\n z-index: 1;\r\n }\r\n \r\n /* Hide divider on last list item using CSS variable */\r\n ds-mobile-action-list-item:last-of-type {\r\n --divider-display: none;\r\n }\r\n \r\n /* Destructive action styling */\r\n ds-mobile-action-list-item.destructive {\r\n --text-color-default-primary: var(--color-error-base, #ef4444);\r\n }\r\n \r\n .destructive-icon {\r\n color: var(--color-error-base, #ef4444);\r\n }\r\n \r\n /* Full-width divider between action groups */\r\n .action-group-divider {\r\n height: 1px;\r\n background: var(--color-border-subtle, #e5e5e5);\r\n margin: 8px 0;\r\n }\r\n `]\r\n})\r\nexport class DsMobileActionsBottomSheetComponent {\r\n /**\r\n * Custom action groups to display (overrides isOwnContent)\r\n */\r\n @Input() customActionGroups?: ActionGroup[];\r\n \r\n /**\r\n * Whether this content belongs to the current user (for preset content actions)\r\n */\r\n @Input() isOwnContent: boolean = false;\r\n \r\n /**\r\n * Computed action groups - uses custom groups if provided, otherwise falls back to preset content actions\r\n */\r\n actionGroups = computed<ActionGroup[]>(() => {\r\n // Use custom action groups if provided\r\n if (this.customActionGroups) {\r\n return this.customActionGroups;\r\n }\r\n \r\n // Otherwise fall back to preset content actions\r\n if (this.isOwnContent) {\r\n // Own content: Group 1 (Edit, Delete) + Group 2 (Like, Reply)\r\n return [\r\n {\r\n actions: [\r\n {\r\n action: 'edit',\r\n title: 'Rediger',\r\n icon: 'remixEditLine',\r\n destructive: false\r\n },\r\n {\r\n action: 'delete',\r\n title: 'Slet',\r\n icon: 'remixDeleteBinLine',\r\n destructive: true\r\n }\r\n ]\r\n },\r\n {\r\n actions: [\r\n {\r\n action: 'like',\r\n title: 'Synes om',\r\n icon: 'remixHeart3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'reply',\r\n title: 'Svar',\r\n icon: 'remixReplyLine',\r\n destructive: false\r\n }\r\n ]\r\n }\r\n ];\r\n } else {\r\n // Other users' content: Group 1 (Like, Reply)\r\n return [\r\n {\r\n actions: [\r\n {\r\n action: 'like',\r\n title: 'Synes om',\r\n icon: 'remixHeart3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'reply',\r\n title: 'Svar',\r\n icon: 'remixReplyLine',\r\n destructive: false\r\n }\r\n ]\r\n }\r\n ];\r\n }\r\n });\r\n \r\n constructor(private modalController: ModalController) {}\r\n \r\n /**\r\n * Handle action selection and dismiss with result\r\n */\r\n selectAction(action: string): void {\r\n this.modalController.dismiss(\r\n { action } as ActionResult,\r\n 'select'\r\n );\r\n }\r\n}\r\n\r\n// Legacy exports for backwards compatibility\r\nexport { DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent };\r\nexport { DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent };\r\nexport type { ActionResult as PostActionResult };\r\nexport type { ActionResult as CommentActionResult };\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { ComponentRef } from '@angular/core';\r\n\r\n/**\r\n * Configuration options for the bottom sheet modal\r\n */\r\nexport interface BottomSheetOptions {\r\n /** The component to display in the bottom sheet */\r\n component: any;\r\n /** Component props to pass to the modal content */\r\n componentProps?: { [key: string]: any };\r\n /** Breakpoints for the bottom sheet (0-1 values representing percentage of screen) */\r\n breakpoints?: number[];\r\n /** Initial breakpoint to open the sheet at */\r\n initialBreakpoint?: number;\r\n /** Show/hide the drag handle */\r\n handle?: boolean;\r\n /** Custom CSS class for styling */\r\n cssClass?: string | string[];\r\n /** Whether backdrop dismisses the modal */\r\n backdropDismiss?: boolean;\r\n /** Backdrop opacity (0-1) */\r\n backdropOpacity?: number;\r\n /** Enable backdrop blur effect */\r\n backdropBlur?: boolean;\r\n /** Keyboard close behavior */\r\n keyboardClose?: boolean;\r\n /** Auto-height mode: sheet sizes to content instead of using fixed breakpoints */\r\n autoHeight?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobileBottomSheetService\r\n * \r\n * Service for creating and managing Ionic 6 bottom sheet modals.\r\n * Based on the Ionic blog article: https://ionic.io/blog/5-examples-of-the-new-ionic-6-bottom-sheet-modal\r\n * \r\n * Features:\r\n * - Multiple breakpoints for snap-to positions\r\n * - Customizable initial height\r\n * - Optional drag handle\r\n * - Backdrop blur effect\r\n * - Custom styling support\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private bottomSheet: DsMobileBottomSheetService) {}\r\n * \r\n * async openSheet() {\r\n * const sheet = await this.bottomSheet.create({\r\n * component: PostCreateComponent,\r\n * breakpoints: [0, 0.5, 0.9],\r\n * initialBreakpoint: 0.5,\r\n * handle: true\r\n * });\r\n * \r\n * const result = await sheet.onWillDismiss();\r\n * console.log('Sheet dismissed with:', result.data);\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileBottomSheetService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Create and present a bottom sheet modal\r\n * \r\n * @param options Configuration options for the bottom sheet\r\n * @returns Promise that resolves to the modal instance\r\n */\r\n async create(options: BottomSheetOptions): Promise<HTMLIonModalElement> {\r\n const {\r\n component,\r\n componentProps = {},\r\n breakpoints = [0, 0.5, 0.9],\r\n initialBreakpoint = 0.5,\r\n handle = true,\r\n cssClass = '',\r\n backdropDismiss = true,\r\n backdropOpacity,\r\n backdropBlur = false,\r\n keyboardClose = true,\r\n autoHeight = false\r\n } = options;\r\n\r\n // Build CSS classes array\r\n const cssClasses = ['ds-bottom-sheet'];\r\n if (backdropBlur) {\r\n cssClasses.push('ds-bottom-sheet--blur');\r\n }\r\n if (autoHeight) {\r\n cssClasses.push('auto-height');\r\n }\r\n if (typeof cssClass === 'string' && cssClass) {\r\n cssClasses.push(cssClass);\r\n } else if (Array.isArray(cssClass)) {\r\n cssClasses.push(...cssClass);\r\n }\r\n\r\n const modal = await this.modalController.create({\r\n component,\r\n componentProps,\r\n breakpoints: autoHeight ? undefined : breakpoints,\r\n initialBreakpoint: autoHeight ? undefined : initialBreakpoint,\r\n handle: autoHeight ? false : handle,\r\n cssClass: cssClasses,\r\n backdropDismiss,\r\n keyboardClose,\r\n showBackdrop: true,\r\n canDismiss: backdropDismiss,\r\n // Remove animation delay for instant appearance\r\n animated: true,\r\n enterAnimation: undefined, // Use default but we'll customize via CSS\r\n leaveAnimation: undefined,\r\n ...(backdropOpacity !== undefined && { \r\n cssClass: [...cssClasses, 'ds-bottom-sheet--custom-backdrop']\r\n })\r\n });\r\n\r\n // Apply custom backdrop opacity if specified\r\n if (backdropOpacity !== undefined) {\r\n modal.style.setProperty('--backdrop-opacity', backdropOpacity.toString());\r\n }\r\n\r\n // Add ESC key listener to dismiss the modal\r\n const escKeyHandler = (event: KeyboardEvent) => {\r\n if (event.key === 'Escape') {\r\n modal.dismiss(undefined, 'escape');\r\n }\r\n };\r\n \r\n // Add listener when modal is presented\r\n modal.addEventListener('ionModalDidPresent', () => {\r\n document.addEventListener('keydown', escKeyHandler);\r\n });\r\n \r\n // Remove listener when modal is dismissed\r\n modal.addEventListener('ionModalDidDismiss', () => {\r\n document.removeEventListener('keydown', escKeyHandler);\r\n });\r\n\r\n await modal.present();\r\n \r\n // Don't wait - return immediately so component can try to focus\r\n // while still in user gesture context\r\n return modal;\r\n }\r\n\r\n /**\r\n * Dismiss all open modals\r\n */\r\n async dismiss(data?: any, role?: string): Promise<boolean> {\r\n return this.modalController.dismiss(data, role);\r\n }\r\n\r\n /**\r\n * Get the top-most modal overlay\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, signal, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ModalController, IonHeader, IonToolbar, IonTitle, IonContent, IonButtons } from '@ionic/angular/standalone';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { Camera, CameraResultType, CameraSource } from '@capacitor/camera';\r\nimport { StatusBar } from '@capacitor/status-bar';\r\nimport { DsButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobilePostCreateBottomSheetComponent\r\n * \r\n * Bottom sheet modal for creating new posts in the community feed.\r\n * This is the modal content that gets displayed in the bottom sheet.\r\n * Features Threads-inspired interface with rich text editing capabilities.\r\n * \r\n * Auto-focuses the textarea and brings up the keyboard when opened.\r\n * \r\n * Usage: Use with DsMobileBottomSheetService to present as a bottom sheet\r\n */\r\n@Component({\r\n selector: 'ds-mobile-post-create-bottom-sheet',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonContent,\r\n IonButtons,\r\n DsButtonComponent,\r\n DsIconButtonComponent\r\n ],\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n }\r\n\r\n /* ============================================\r\n HEADER\r\n ============================================ */\r\n \r\n ion-header {\r\n box-shadow: none;\r\n }\r\n\r\n ion-toolbar {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n --border-width: 0 0 1px 0;\r\n --border-color: var(--border-color-default);\r\n --padding-top: 12px;\r\n --padding-bottom: 8px;\r\n --min-height: 56px;\r\n }\r\n\r\n ion-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 22px;\r\n letter-spacing: -0.4px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n\r\n ion-button {\r\n --color: var(--color-text-secondary, #737373);\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 400;\r\n }\r\n\r\n /* Make Post button pill-shaped */\r\n ion-buttons[slot=\"end\"] ds-button {\r\n --border-radius: 100px;\r\n }\r\n \r\n ion-buttons[slot=\"end\"] ds-button::ng-deep button {\r\n border-radius: 100px;\r\n }\r\n \r\n /* Make Cancel button pill-shaped */\r\n ion-buttons[slot=\"start\"] ds-button {\r\n --border-radius: 100px;\r\n }\r\n \r\n ion-buttons[slot=\"start\"] ds-button::ng-deep button {\r\n border-radius: 100px;\r\n }\r\n\r\n /* ============================================\r\n CONTENT AREA\r\n ============================================ */\r\n \r\n ion-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n --padding-top: 0;\r\n --padding-bottom: 0;\r\n }\r\n\r\n .post-create-container {\r\n padding: 24px 16px 16px;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n }\r\n \r\n .post-composer {\r\n display: flex;\r\n gap: 12px;\r\n align-items: flex-start;\r\n }\r\n \r\n .post-composer__main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .post-composer__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n height: 32px;\r\n }\r\n \r\n .post-composer__username {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .post-composer__textarea {\r\n width: 100%;\r\n min-height: 60px;\r\n max-height: 400px;\r\n border: none;\r\n outline: none;\r\n resize: none;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n background: transparent;\r\n padding: 0;\r\n cursor: text;\r\n overflow-y: auto;\r\n /* Auto-resize as user types */\r\n field-sizing: content;\r\n }\r\n \r\n .post-composer__textarea::placeholder {\r\n color: var(--color-text-tertiary, #999999);\r\n }\r\n \r\n /* Visual focus indicator - helps users see the textarea is ready */\r\n .post-composer__textarea:focus {\r\n outline: none;\r\n }\r\n \r\n /* Subtle animation to draw attention when empty */\r\n @keyframes gentlePulse {\r\n 0%, 100% { opacity: 1; }\r\n 50% { opacity: 0.6; }\r\n }\r\n \r\n .post-composer__textarea:not(:focus):empty + .focus-hint {\r\n animation: gentlePulse 2s ease-in-out 1;\r\n }\r\n \r\n .post-composer__actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding-top: 12px;\r\n }\r\n \r\n .post-composer__actions ds-icon-button::ng-deep button {\r\n width: 44px;\r\n height: 44px;\r\n border-radius: 50%;\r\n }\r\n \r\n /* ============================================\r\n IMAGE PREVIEW\r\n ============================================ */\r\n \r\n .image-previews {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n margin-top: 12px;\r\n }\r\n \r\n .image-preview {\r\n position: relative;\r\n width: 96px;\r\n height: 96px;\r\n border-radius: 12px;\r\n overflow: visible;\r\n }\r\n \r\n .preview-image {\r\n width: 100%;\r\n height: 100%;\r\n display: block;\r\n border-radius: 12px;\r\n border: 1px solid var(--border-color-default);\r\n object-fit: cover;\r\n }\r\n \r\n .remove-image-btn {\r\n position: absolute;\r\n top: -8px;\r\n right: -8px;\r\n width: 24px;\r\n height: 24px;\r\n border-radius: 50%;\r\n background: rgba(0, 0, 0, 0.6);\r\n backdrop-filter: blur(8px);\r\n border: 2px solid white;\r\n color: white;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n padding: 0;\r\n }\r\n \r\n .remove-image-btn:hover {\r\n background: rgba(0, 0, 0, 0.8);\r\n transform: scale(1.05);\r\n }\r\n \r\n .remove-image-btn:active {\r\n transform: scale(0.95);\r\n }\r\n \r\n /* ============================================\r\n MOBILE OPTIMIZATIONS\r\n ============================================ */\r\n \r\n @media (max-width: 768px) {\r\n .post-create-container {\r\n padding: 12px 16px 24px;\r\n }\r\n\r\n .post-composer__textarea {\r\n min-height: 60px;\r\n max-height: 300px;\r\n /* Make tap target larger on mobile */\r\n padding: 8px;\r\n margin: -8px;\r\n }\r\n }\r\n `],\r\n template: `\r\n <!-- Header with cancel and post buttons -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ds-button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n (clicked)=\"handleCancel()\">\r\n Annuller\r\n </ds-button>\r\n </ion-buttons>\r\n <ion-title>{{ modalTitle() }}</ion-title>\r\n <ion-buttons slot=\"end\">\r\n <ds-button\r\n variant=\"primary\"\r\n size=\"sm\"\r\n [disabled]=\"!canPost()\"\r\n (clicked)=\"handlePost()\">\r\n {{ submitButtonLabel() }}\r\n </ds-button>\r\n </ion-buttons>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <!-- Content -->\r\n <ion-content>\r\n <div class=\"post-create-container\">\r\n <div class=\"post-composer\">\r\n <div class=\"post-composer__main\">\r\n <textarea\r\n #textareaInput\r\n class=\"post-composer__textarea\"\r\n [(ngModel)]=\"postContent\"\r\n [placeholder]=\"placeholder()\"\r\n [readonly]=\"isReadonly\"\r\n (input)=\"handleInput()\"\r\n (focus)=\"handleFocus()\"\r\n inputmode=\"text\"\r\n enterkeyhint=\"done\"\r\n rows=\"1\">\r\n </textarea>\r\n \r\n <!-- Image Previews -->\r\n @if (selectedImages().length > 0) {\r\n <div class=\"image-previews\">\r\n @for (image of selectedImages(); track image; let i = $index) {\r\n <div class=\"image-preview\">\r\n <img [src]=\"image\" alt=\"Selected image\" class=\"preview-image\" />\r\n <button \r\n class=\"remove-image-btn\" \r\n (click)=\"handleRemoveImage(i)\"\r\n type=\"button\"\r\n aria-label=\"Fjern billede\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <path d=\"M12 4L4 12M4 4L12 12\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n <div class=\"post-composer__actions\">\r\n <ds-icon-button\r\n icon=\"remixImageLine\"\r\n variant=\"secondary\"\r\n size=\"md\"\r\n (clicked)=\"handleAddImage()\"\r\n aria-label=\"Tilføj billede\">\r\n </ds-icon-button>\r\n <ds-icon-button\r\n icon=\"remixAttachmentLine\"\r\n variant=\"secondary\"\r\n size=\"md\"\r\n (clicked)=\"handleAddAttachment()\"\r\n aria-label=\"Tilføj vedhæftning\">\r\n </ds-icon-button>\r\n \r\n <!-- Hidden file input for file selection -->\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n accept=\"*/*\"\r\n multiple\r\n (change)=\"handleFileSelect($event)\"\r\n style=\"display: none;\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePostCreateBottomSheetComponent implements AfterViewInit, OnInit {\r\n @ViewChild('textareaInput') textareaInput?: ElementRef<HTMLTextAreaElement>;\r\n @ViewChild('fileInput') fileInput?: ElementRef<HTMLInputElement>;\r\n \r\n // Optional input to control auto-focus behavior\r\n autoFocus = true;\r\n \r\n // Control readonly state for keyboard trick\r\n isReadonly = true;\r\n \r\n // Edit mode properties - can be set via componentProps\r\n isEditMode = false;\r\n postId?: string;\r\n initialContent = '';\r\n \r\n postContent = '';\r\n selectedImages = signal<string[]>([]);\r\n username = signal('Lars Mikkelsen');\r\n placeholder = signal(\"Hvad er nyt?\");\r\n modalTitle = signal('Nyt opslag');\r\n submitButtonLabel = signal('Slå op');\r\n \r\n constructor(\r\n private modalController: ModalController,\r\n private elementRef: ElementRef\r\n ) {}\r\n \r\n /**\r\n * Ensure toolbar doesn't have unnecessary padding\r\n * Modal is already positioned below status bar, so no extra safe area needed\r\n */\r\n private applySafeAreaToToolbar(): void {\r\n try {\r\n const hostElement = this.elementRef?.nativeElement;\r\n if (hostElement) {\r\n const header = hostElement.querySelector('ion-header');\r\n if (header) {\r\n const toolbar = header.querySelector('ion-toolbar');\r\n if (toolbar) {\r\n const toolbarElement = toolbar as HTMLElement;\r\n // Ensure toolbar uses standard padding (no safe area since modal is already offset)\r\n toolbarElement.style.setProperty('--padding-top', '12px', 'important');\r\n toolbarElement.style.setProperty('--min-height', '56px', 'important');\r\n }\r\n }\r\n }\r\n } catch (e) {\r\n console.log('[SafeArea] Failed to apply to toolbar:', e);\r\n }\r\n }\r\n \r\n ngOnInit(): void {\r\n // Initialize edit mode if provided\r\n if (this.isEditMode && this.initialContent) {\r\n this.postContent = this.initialContent;\r\n this.modalTitle.set('Rediger opslag');\r\n this.submitButtonLabel.set('Gem');\r\n }\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Apply safe area padding immediately to prevent corruption\r\n this.applySafeAreaToToolbar();\r\n \r\n // Auto-resize textarea if there's initial content (edit mode)\r\n if (this.postContent && this.textareaInput) {\r\n setTimeout(() => {\r\n this.resizeTextarea();\r\n }, 0);\r\n }\r\n \r\n // Try to focus IMMEDIATELY - no delay\r\n // This maximizes our chance of being in user gesture context\r\n if (this.autoFocus && this.textareaInput) {\r\n const textarea = this.textareaInput.nativeElement;\r\n \r\n // Remove readonly immediately\r\n this.isReadonly = false;\r\n \r\n // Try focusing with minimal delay\r\n setTimeout(() => {\r\n textarea.focus();\r\n textarea.click();\r\n \r\n // Explicitly show keyboard\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n \r\n // iOS sometimes needs a second attempt\r\n setTimeout(() => {\r\n textarea.focus();\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n }, 100);\r\n }, 10);\r\n }\r\n }\r\n \r\n /**\r\n * Ionic lifecycle hook - called when modal enters view\r\n * At 95% height, this acts more like a page than a modal\r\n * which might allow keyboard to open\r\n */\r\n ionViewDidEnter(): void {\r\n // Resize textarea in case initial attempt didn't work\r\n if (this.postContent && this.textareaInput) {\r\n this.resizeTextarea();\r\n }\r\n \r\n // Final focus attempt when view fully enters\r\n if (this.autoFocus && this.textareaInput) {\r\n this.isReadonly = false;\r\n const textarea = this.textareaInput.nativeElement;\r\n \r\n // Try to focus as if this was a page navigation\r\n textarea.focus();\r\n textarea.click();\r\n \r\n // Explicitly show keyboard\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n \r\n // Set cursor position\r\n const length = textarea.value.length;\r\n textarea.setSelectionRange(length, length);\r\n }\r\n }\r\n \r\n handleFocus(): void {\r\n // When user focuses (or we focus programmatically), remove readonly\r\n this.isReadonly = false;\r\n // Explicitly show keyboard\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n }\r\n \r\n handleInput(): void {\r\n this.resizeTextarea();\r\n }\r\n \r\n /**\r\n * Auto-resize textarea based on content\r\n */\r\n private resizeTextarea(): void {\r\n if (this.textareaInput) {\r\n const textarea = this.textareaInput.nativeElement;\r\n // Reset height to auto to get the correct scrollHeight\r\n textarea.style.height = 'auto';\r\n // Set height based on content, respecting min/max from CSS\r\n textarea.style.height = Math.min(textarea.scrollHeight, 400) + 'px';\r\n }\r\n }\r\n \r\n canPost(): boolean {\r\n return this.postContent.trim().length > 0 || this.selectedImages().length > 0;\r\n }\r\n \r\n async handleCancel(): Promise<void> {\r\n if (this.postContent.trim().length > 0 || this.selectedImages().length > 0) {\r\n // Show confirmation\r\n const confirmed = confirm('Kassér dette opslag?');\r\n if (confirmed) {\r\n await this.modalController.dismiss(null, 'cancel');\r\n }\r\n } else {\r\n await this.modalController.dismiss(null, 'cancel');\r\n }\r\n }\r\n \r\n async handlePost(): Promise<void> {\r\n if (!this.canPost()) return;\r\n \r\n if (this.isEditMode) {\r\n console.log('Updating post:', this.postId, this.postContent);\r\n } else {\r\n console.log('Creating post:', this.postContent, 'with images:', this.selectedImages().length);\r\n }\r\n \r\n // Pass the post content, images, and edit info back to the parent\r\n await this.modalController.dismiss(\r\n { \r\n content: this.postContent,\r\n images: this.selectedImages(),\r\n timestamp: new Date(),\r\n isEdit: this.isEditMode,\r\n postId: this.postId\r\n },\r\n 'post'\r\n );\r\n }\r\n \r\n async handleAddImage(): Promise<void> {\r\n console.log('Add image button clicked');\r\n \r\n // Re-apply safe area padding before opening camera (preventive)\r\n // This ensures the value is locked in before iOS corrupts it\r\n this.applySafeAreaToToolbar();\r\n \r\n try {\r\n console.log('Requesting photo from library...');\r\n \r\n const image = await Camera.getPhoto({\r\n quality: 90,\r\n allowEditing: false,\r\n resultType: CameraResultType.Uri,\r\n source: CameraSource.Photos, // Only show photo library, not camera\r\n });\r\n\r\n console.log('Photo selected successfully:', image);\r\n \r\n // Add the image path to the array\r\n if (image.webPath) {\r\n this.selectedImages.update(images => [...images, image.webPath!]);\r\n console.log('Image added to preview:', image.webPath);\r\n }\r\n \r\n // Re-apply safe area padding immediately after returning\r\n // Since we're using fixed values, this won't cause flickering\r\n requestAnimationFrame(() => {\r\n this.applySafeAreaToToolbar();\r\n });\r\n \r\n // Restore StatusBar configuration (background task)\r\n this.restoreStatusBar();\r\n \r\n } catch (error) {\r\n console.error('Photo selection error:', error);\r\n // Only show alert for non-cancellation errors\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n const errorMessage = (error as any).message;\r\n if (!errorMessage.includes('cancel')) {\r\n alert(`Error selecting photo: ${JSON.stringify(error)}`);\r\n }\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Restore StatusBar configuration (background task)\r\n * Safe area padding is now handled preventively via applySafeAreaToToolbar()\r\n */\r\n private restoreStatusBar(): void {\r\n setTimeout(async () => {\r\n try {\r\n await StatusBar.setBackgroundColor({ color: '#221a4c' });\r\n await StatusBar.setOverlaysWebView({ overlay: false });\r\n } catch (e) {\r\n // StatusBar API not available, ignore\r\n }\r\n }, 0);\r\n }\r\n \r\n handleRemoveImage(index: number): void {\r\n console.log('Removing image at index:', index);\r\n this.selectedImages.update(images => images.filter((_, i) => i !== index));\r\n }\r\n \r\n handleAddAttachment(): void {\r\n console.log('Add attachment button clicked');\r\n // Trigger the hidden file input\r\n if (this.fileInput) {\r\n this.fileInput.nativeElement.click();\r\n }\r\n }\r\n \r\n handleFileSelect(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n const files = input.files;\r\n \r\n if (!files || files.length === 0) {\r\n console.log('No files selected');\r\n return;\r\n }\r\n \r\n console.log('Files selected:', files.length);\r\n \r\n // Process each selected file\r\n Array.from(files).forEach(file => {\r\n console.log('File:', file.name, file.type, file.size);\r\n \r\n // Create a data URL for preview (for images and other files)\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n const result = e.target?.result as string;\r\n if (result) {\r\n // Add to selectedImages array for preview\r\n this.selectedImages.update(images => [...images, result]);\r\n console.log('File added to preview:', file.name);\r\n }\r\n };\r\n reader.readAsDataURL(file);\r\n });\r\n \r\n // Reset the input so the same file can be selected again\r\n input.value = '';\r\n }\r\n}\r\n\r\n","import { Injectable, signal } from '@angular/core';\r\nimport { ActionGroup } from '../components/bottom-sheet';\r\n\r\n/**\r\n * User service for managing current user data globally\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class UserService {\r\n // User avatar configuration\r\n private _avatarInitials = signal('LM');\r\n private _avatarType = signal<'initials' | 'photo' | 'icon'>('initials');\r\n private _avatarSrc = signal('');\r\n \r\n // Profile menu items configuration\r\n private _profileMenuItems = signal<ActionGroup[] | undefined>(undefined);\r\n \r\n // Readonly computed values\r\n readonly avatarInitials = this._avatarInitials.asReadonly();\r\n readonly avatarType = this._avatarType.asReadonly();\r\n readonly avatarSrc = this._avatarSrc.asReadonly();\r\n readonly profileMenuItems = this._profileMenuItems.asReadonly();\r\n \r\n /**\r\n * Update avatar configuration\r\n */\r\n setAvatarInitials(initials: string) {\r\n this._avatarInitials.set(initials);\r\n }\r\n \r\n setAvatarType(type: 'initials' | 'photo' | 'icon') {\r\n this._avatarType.set(type);\r\n }\r\n \r\n setAvatarSrc(src: string) {\r\n this._avatarSrc.set(src);\r\n }\r\n \r\n /**\r\n * Set profile menu items globally.\r\n * This will be used by both ds-mobile-tab-bar and ds-mobile-page-main\r\n * if they don't receive profileMenuItems as an input.\r\n */\r\n setProfileMenuItems(items: ActionGroup[]) {\r\n this._profileMenuItems.set(items);\r\n }\r\n}\r\n\r\n","import { Component, Input, computed, ViewEncapsulation, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { WhitelabelService } from '../../services/whitelabel.service';\r\n\r\nexport type AvatarType = 'initials' | 'photo' | 'icon';\r\nexport type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\r\nexport type BadgePosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\r\n\r\n/**\r\n * DsAvatarWithBadgeComponent\r\n * \r\n * Displays an avatar with a logomark badge overlay.\r\n * Useful for showing user avatars with organization branding.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-avatar-with-badge\r\n * [type]=\"'initials'\"\r\n * [initials]=\"'JD'\"\r\n * [size]=\"'lg'\"\r\n * [badgePosition]=\"'bottom-right'\"\r\n * />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-avatar-with-badge',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent],\r\n encapsulation: ViewEncapsulation.Emulated,\r\n styles: [`\r\n :host {\r\n display: inline-block;\r\n position: relative;\r\n }\r\n \r\n .avatar-badge-container {\r\n position: relative;\r\n display: inline-block;\r\n }\r\n \r\n .avatar-badge {\r\n position: absolute;\r\n background: var(--color-brand-secondary, #5d5fef);\r\n border-radius: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: 2px solid var(--color-background-primary, #ffffff);\r\n }\r\n \r\n .avatar-badge img {\r\n width: 10px;\r\n height: 10px;\r\n object-fit: contain;\r\n }\r\n \r\n /* Badge positioning */\r\n .avatar-badge--bottom-right {\r\n bottom: -6px;\r\n right: -6px;\r\n }\r\n \r\n .avatar-badge--bottom-left {\r\n bottom: -6px;\r\n left: -6px;\r\n }\r\n \r\n .avatar-badge--top-right {\r\n top: -6px;\r\n right: -6px;\r\n }\r\n \r\n .avatar-badge--top-left {\r\n top: -6px;\r\n left: -6px;\r\n }\r\n \r\n /* Badge sizes based on avatar size */\r\n .avatar-badge--xs { width: 16px; height: 16px; }\r\n .avatar-badge--sm { width: 18px; height: 18px; }\r\n .avatar-badge--md { width: 20px; height: 20px; }\r\n .avatar-badge--lg { width: 24px; height: 24px; }\r\n .avatar-badge--xl { width: 28px; height: 28px; }\r\n `],\r\n template: `\r\n <div class=\"avatar-badge-container\">\r\n <ds-avatar\r\n [type]=\"type\"\r\n [size]=\"size\"\r\n [initials]=\"initials\"\r\n [src]=\"src\"\r\n [iconName]=\"iconName\"\r\n />\r\n \r\n @if (showBadge) {\r\n <div [class]=\"badgeClasses()\">\r\n <img [src]=\"whitelabelService.logoMarkUrl()\" [alt]=\"whitelabelService.logoAlt()\" />\r\n </div>\r\n }\r\n </div>\r\n `\r\n})\r\nexport class DsAvatarWithBadgeComponent {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n // Avatar props\r\n @Input() type: AvatarType = 'initials';\r\n @Input() size: AvatarSize = 'md';\r\n @Input() initials: string = '';\r\n @Input() src: string = '';\r\n @Input() iconName: string = 'remixUser3Fill';\r\n \r\n // Badge props\r\n @Input() showBadge: boolean = true;\r\n @Input() badgePosition: BadgePosition = 'bottom-right';\r\n \r\n badgeClasses = computed(() => {\r\n return `avatar-badge avatar-badge--${this.badgePosition} avatar-badge--${this.size}`;\r\n });\r\n}\r\n\r\n","import { Component, OnInit, inject, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { WhitelabelService } from '../services/whitelabel.service';\r\nimport { DsLogoComponent } from '../components/logo/ds-logo';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge/ds-avatar-with-badge';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { IonContent, ModalController } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * Whitelabel Demo Modal Component\r\n * \r\n * Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.\r\n * Opens as a full-screen modal similar to post details.\r\n */\r\n@Component({\r\n selector: 'ds-whitelabel-demo-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonContent,\r\n DsLogoComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsIconButtonComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n styles: [`\r\n /* Host fills the modal with flex layout */\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n width: 100%;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n \r\n /* Fixed header at top */\r\n .modal-header {\r\n flex-shrink: 0;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default, #e0e0e0);\r\n padding: 0 16px;\r\n }\r\n \r\n /* ion-content fills remaining space and scrolls */\r\n ion-content,\r\n .modal-content {\r\n --background: #ffffff;\r\n flex: 1;\r\n width: 100%;\r\n }\r\n \r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 56px;\r\n }\r\n \r\n .header-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 17px;\r\n font-weight: 600;\r\n color: var(--color-text-primary, #1a1a1a);\r\n flex: 1;\r\n }\r\n \r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n \r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n background: var(--color-background-neutral-secondary, #f5f5f5) !important;\r\n color: var(--color-text-primary, #1a1a1a) !important;\r\n }\r\n \r\n .demo-container {\r\n padding: 20px;\r\n max-width: 600px;\r\n margin: 0 auto;\r\n width: 100%;\r\n }\r\n \r\n .demo-section {\r\n margin-bottom: 32px;\r\n }\r\n \r\n .demo-section h2 {\r\n margin-bottom: 16px;\r\n font-size: 18px;\r\n font-weight: 600;\r\n color: #333;\r\n }\r\n \r\n /* Theme Selection */\r\n .theme-buttons {\r\n display: flex;\r\n gap: 12px;\r\n flex-wrap: wrap;\r\n }\r\n \r\n .theme-btn {\r\n padding: 8px 16px;\r\n border-radius: 8px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n border: none;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n background: #e0e0e0;\r\n color: #333;\r\n }\r\n \r\n .theme-btn:active {\r\n transform: scale(0.98);\r\n }\r\n \r\n .theme-btn.active {\r\n background: var(--color-secondary-surface);\r\n color: var(--color-secondary-content);\r\n }\r\n \r\n /* Logo Preview */\r\n .logo-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: var(--color-brand-secondary);\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .logomark-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .preview-grid {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n }\r\n \r\n .preview-tile {\r\n background: white;\r\n border-radius: 12px;\r\n }\r\n \r\n .preview-tile h3 {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #666;\r\n margin-top: 0;\r\n margin-bottom: 12px;\r\n }\r\n \r\n /* Brand Colors */\r\n .color-section {\r\n background: white;\r\n border-radius: 12px;\r\n }\r\n \r\n .color-swatches {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n margin-bottom: 24px;\r\n }\r\n \r\n .swatch {\r\n padding: 16px;\r\n border-radius: 8px;\r\n text-align: center;\r\n }\r\n \r\n .swatch-label {\r\n font-size: 12px;\r\n font-weight: 600;\r\n margin-bottom: 4px;\r\n }\r\n \r\n .swatch-value {\r\n font-size: 11px;\r\n opacity: 0.8;\r\n font-family: monospace;\r\n }\r\n \r\n .swatch--primary-surface {\r\n background: var(--color-primary-surface);\r\n color: var(--color-primary-content);\r\n }\r\n \r\n .swatch--primary-content {\r\n background: var(--color-primary-content);\r\n color: var(--color-primary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n .swatch--secondary-surface {\r\n background: var(--color-secondary-surface);\r\n color: var(--color-secondary-content);\r\n }\r\n \r\n .swatch--secondary-content {\r\n background: var(--color-secondary-content);\r\n color: var(--color-secondary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n /* Color Inputs */\r\n .color-inputs {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .color-group-label {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #333;\r\n margin-top: 8px;\r\n }\r\n \r\n .color-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n \r\n .color-row label {\r\n min-width: 70px;\r\n font-size: 13px;\r\n color: #666;\r\n }\r\n \r\n .color-row input[type=\"color\"] {\r\n width: 40px;\r\n height: 32px;\r\n border: none;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n padding: 0;\r\n }\r\n \r\n .color-row input[type=\"text\"] {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 6px;\r\n font-family: monospace;\r\n font-size: 13px;\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .demo-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n `],\r\n template: `\r\n <!-- Fixed Header -->\r\n <div class=\"modal-header\">\r\n <div class=\"header-content\">\r\n <span class=\"header-title\">Whitelabel</span>\r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (click)=\"close()\"\r\n class=\"close-button\"\r\n aria-label=\"Close\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n \r\n <!-- Scrollable Content -->\r\n <ion-content [scrollY]=\"true\" class=\"modal-content\">\r\n <div class=\"demo-container\">\r\n <!-- Theme Selection -->\r\n <div class=\"demo-section\">\r\n <h2>Theme</h2>\r\n <div class=\"theme-buttons\">\r\n <button class=\"theme-btn\" (click)=\"applyDefaultTheme()\" [class.active]=\"currentTheme === 'default'\">\r\n Propbinder\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyCejTheme()\" [class.active]=\"currentTheme === 'cej'\">\r\n CEJ\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyPkaTheme()\" [class.active]=\"currentTheme === 'pka'\">\r\n PKA\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyClaveTheme()\" [class.active]=\"currentTheme === 'clave'\">\r\n Clave\r\n </button>\r\n <button class=\"theme-btn\" (click)=\"applyFreedomTheme()\" [class.active]=\"currentTheme === 'freedom'\">\r\n Freedom\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <!-- Logo & Logomark Preview -->\r\n <div class=\"demo-section\">\r\n <h2>Logo Preview</h2>\r\n <div class=\"preview-grid\">\r\n <div class=\"preview-tile\">\r\n <h3>Logo</h3>\r\n <div class=\"logo-preview\">\r\n <ds-logo variant=\"full\" />\r\n </div>\r\n </div>\r\n <div class=\"preview-tile\">\r\n <h3>Logomark</h3>\r\n <div class=\"logomark-preview\">\r\n <ds-avatar-with-badge\r\n [type]=\"'initials'\"\r\n [initials]=\"'KN'\"\r\n [size]=\"'md'\"\r\n [badgePosition]=\"'bottom-right'\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Brand Colors -->\r\n <div class=\"demo-section\">\r\n <h2>Brand Colors</h2>\r\n <div class=\"color-section\">\r\n <div class=\"color-swatches\">\r\n <div class=\"swatch swatch--primary-surface\">\r\n <div class=\"swatch-label\">Primary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--primary-content\">\r\n <div class=\"swatch-label\">Primary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primaryContent() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-surface\">\r\n <div class=\"swatch-label\">Secondary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-content\">\r\n <div class=\"swatch-label\">Secondary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondaryContent() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"color-inputs\">\r\n <div class=\"color-group-label\">Primary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n \r\n <div class=\"color-group-label\">Secondary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class WhitelabelDemoModalComponent implements OnInit {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n private modalController = inject(ModalController);\r\n \r\n // Current active theme\r\n currentTheme = 'default';\r\n \r\n // Custom color inputs\r\n customPrimarySurface = '#6B5FF5';\r\n customPrimaryContent = '#FFFFFF';\r\n customSecondarySurface = '#221a4c';\r\n customSecondaryContent = '#FFFFFF';\r\n \r\n ngOnInit() {\r\n this.updateCustomColorInputs();\r\n this.detectCurrentTheme();\r\n }\r\n \r\n /**\r\n * Detect the current active theme based on colors\r\n */\r\n private detectCurrentTheme() {\r\n const secondarySurface = this.whitelabelService.secondarySurface().toUpperCase();\r\n \r\n if (secondarySurface === '#A70923') {\r\n this.currentTheme = 'cej';\r\n } else if (secondarySurface === '#660036') {\r\n this.currentTheme = 'pka';\r\n } else if (secondarySurface === '#262424') {\r\n this.currentTheme = 'clave';\r\n } else if (secondarySurface === '#1D4A49') {\r\n this.currentTheme = 'freedom';\r\n } else {\r\n this.currentTheme = 'default';\r\n }\r\n }\r\n \r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n \r\n applyDefaultTheme() {\r\n this.currentTheme = 'default';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoAlt: 'Propbinder',\r\n logoHeight: 28,\r\n primarySurface: '#6B5FF5',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#221a4c',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Propbinder',\r\n organizationId: 'default'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCejTheme() {\r\n this.currentTheme = 'cej';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/cej-logo.png',\r\n logoMarkUrl: '/Assets/logos/cej-logo.png',\r\n logoAlt: 'CEJ',\r\n logoHeight: 36,\r\n primarySurface: '#dc092c',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#A70923',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'CEJ',\r\n organizationId: 'cej'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyPkaTheme() {\r\n this.currentTheme = 'pka';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/pka-logo.svg',\r\n logoMarkUrl: '/Assets/logos/pka-logo.svg',\r\n logoAlt: 'PKA',\r\n logoHeight: 24,\r\n primarySurface: '#CC006C',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#660036',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'PKA',\r\n organizationId: 'pka'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyClaveTheme() {\r\n this.currentTheme = 'clave';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/clave-logo.svg',\r\n logoMarkUrl: '/Assets/logos/clave-logo.svg',\r\n logoAlt: 'Clave',\r\n logoHeight: 24,\r\n primarySurface: '#868764',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#262424',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Clave',\r\n organizationId: 'clave'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyFreedomTheme() {\r\n this.currentTheme = 'freedom';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/freedom-logo.svg',\r\n logoMarkUrl: '/Assets/logos/freedom-logomark.svg',\r\n logoAlt: 'Freedom',\r\n logoHeight: 28,\r\n primarySurface: '#AACFC3',\r\n primaryContent: '#1D4A49',\r\n secondarySurface: '#1D4A49',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Freedom',\r\n organizationId: 'freedom'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCustomColors() {\r\n this.whitelabelService.updateColors({\r\n primarySurface: this.customPrimarySurface,\r\n primaryContent: this.customPrimaryContent,\r\n secondarySurface: this.customSecondarySurface,\r\n secondaryContent: this.customSecondaryContent\r\n });\r\n }\r\n \r\n private updateCustomColorInputs() {\r\n this.customPrimarySurface = this.whitelabelService.primarySurface();\r\n this.customPrimaryContent = this.whitelabelService.primaryContent();\r\n this.customSecondarySurface = this.whitelabelService.secondarySurface();\r\n this.customSecondaryContent = this.whitelabelService.secondaryContent();\r\n }\r\n}\r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { WhitelabelDemoModalComponent } from './whitelabel-demo-modal.component';\r\n\r\n/**\r\n * WhitelabelDemoModalService\r\n * \r\n * Service for displaying the whitelabel demo in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private whitelabelModal: WhitelabelDemoModalService) {}\r\n * \r\n * async openDemo() {\r\n * await this.whitelabelModal.open();\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WhitelabelDemoModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the whitelabel demo modal\r\n * \r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(): Promise<void> {\r\n try {\r\n console.log('[WhitelabelDemoModal] Opening...');\r\n \r\n const modal = await this.modalController.create({\r\n component: WhitelabelDemoModalComponent,\r\n cssClass: 'ds-whitelabel-demo-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n // Control the presenting element animation\r\n enterAnimation: undefined, // Use default\r\n leaveAnimation: undefined // Use default\r\n });\r\n\r\n console.log('[WhitelabelDemoModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[WhitelabelDemoModal] Modal presented');\r\n } catch (error) {\r\n console.error('[WhitelabelDemoModal] Error opening modal:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Close the currently open whitelabel demo modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, input, output, HostListener, ElementRef, ViewChild, AfterViewInit, computed, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { Router } from '@angular/router';\r\nimport { \r\n IonHeader, \r\n IonToolbar, \r\n IonTitle,\r\n IonContent, \r\n IonRefresher, \r\n IonRefresherContent,\r\n Platform,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsLogoComponent } from '../logo/ds-logo';\r\nimport { MobilePageBase } from '../shared/mobile-page-base';\r\nimport { DsMobileActionsBottomSheetComponent, ActionResult, ActionGroup } from '../bottom-sheet';\r\nimport { UserService } from '../../services/user.service';\r\nimport { WhitelabelDemoModalService } from '../../pages/whitelabel-demo-modal.service';\r\n\r\n/**\r\n * DsMobilePageMainComponent\r\n * \r\n * A complete mobile page layout for main/tab pages with:\r\n * - Fixed header with logomark + title + avatar\r\n * - Purple expandable header section (scrolls with content)\r\n * - White rounded content wrapper\r\n * - Pull-to-refresh support\r\n * - Auto scroll title fade-in\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple page -->\r\n * <ds-mobile-page-main\r\n * title=\"Inquiries\"\r\n * [avatarInitials]=\"'JD'\">\r\n * <div class=\"page-content\">\r\n * <!-- Your content -->\r\n * </div>\r\n * </ds-mobile-page-main>\r\n * \r\n * <!-- Page with custom header content -->\r\n * <ds-mobile-page-main\r\n * title=\"Home\"\r\n * headerTitle=\"Welcome, Lars\"\r\n * headerSubtitle=\"Your rental property at a glance.\"\r\n * [avatarInitials]=\"'L'\">\r\n * \r\n * <div header-content class=\"property-tiles\">\r\n * <!-- Custom header content like tiles -->\r\n * </div>\r\n * \r\n * <div class=\"page-content\">\r\n * <!-- Main page content -->\r\n * </div>\r\n * </ds-mobile-page-main>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-page-main',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonContent,\r\n IonRefresher,\r\n IonRefresherContent,\r\n DsAvatarComponent,\r\n DsLogoComponent\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-page-base.css',\r\n './ds-mobile-page-main.css'\r\n ],\r\n template: `\r\n <!-- Fixed header at top -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <div class=\"header-main\">\r\n <!-- Whitelabel Logomark -->\r\n <ds-logo variant=\"mark\" size=\"lg\" />\r\n \r\n <!-- Title - fades in on scroll -->\r\n <ion-title class=\"header-main__title\">{{ title() }}</ion-title>\r\n \r\n <!-- Avatar -->\r\n <div class=\"header-main__actions\">\r\n <ds-avatar\r\n [size]=\"'md'\"\r\n [type]=\"avatarType()\"\r\n [initials]=\"avatarInitials()\"\r\n [src]=\"avatarSrc()\"\r\n [iconName]=\"avatarIconName()\"\r\n (click)=\"handleAvatarClick()\"\r\n style=\"cursor: pointer;\"\r\n />\r\n </div>\r\n </div>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <!-- Content with expandable header -->\r\n <ion-content [scrollEvents]=\"true\" (ionScroll)=\"handleScroll($event)\">\r\n <!-- Condensed header for Ionic scroll effects -->\r\n @if (showCondensedHeader()) {\r\n <ion-header collapse=\"condense\">\r\n <ion-toolbar>\r\n <ion-title size=\"large\">{{ title() }}</ion-title>\r\n </ion-toolbar>\r\n </ion-header>\r\n }\r\n\r\n <!-- Pull to refresh (only on native iOS/Android) -->\r\n @if (showRefresh() && isNativePlatform()) {\r\n <ion-refresher \r\n slot=\"fixed\" \r\n (ionRefresh)=\"handleRefresh($event)\"\r\n [pullFactor]=\"0.4\" \r\n [pullMin]=\"80\" \r\n [pullMax]=\"240\"\r\n closeDuration=\"600ms\">\r\n <ion-refresher-content\r\n pullingIcon=\"remixArrowDownS\"\r\n refreshingSpinner=\"lines\">\r\n </ion-refresher-content>\r\n </ion-refresher>\r\n }\r\n\r\n <!-- Expandable header section (purple background) -->\r\n <div class=\"header-expandable\">\r\n <div class=\"header-expandable-inner\">\r\n <div class=\"header-expandable__text\">\r\n <h1 class=\"header-expandable__title\">{{ headerTitle() || title() }}</h1>\r\n @if (headerSubtitle()) {\r\n <p class=\"header-expandable__subtitle\">{{ headerSubtitle() }}</p>\r\n }\r\n </div>\r\n \r\n <!-- Slot for custom header content (e.g., property tiles) -->\r\n <ng-content select=\"[header-content]\"></ng-content>\r\n </div>\r\n </div>\r\n\r\n <!-- Content wrapper -->\r\n <div class=\"content-wrapper\">\r\n <div class=\"content-inner\">\r\n <!-- Main page content -->\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePageMainComponent extends MobilePageBase implements AfterViewInit {\r\n @ViewChild(IonContent) ionContent?: IonContent;\r\n \r\n // Platform detection\r\n private platform = inject(Platform);\r\n private modalController = inject(ModalController);\r\n private router = inject(Router);\r\n private userService = inject(UserService);\r\n private whitelabelDemoModal = inject(WhitelabelDemoModalService);\r\n \r\n // Computed property to check if running on native platform\r\n isNativePlatform = computed(() => \r\n this.platform.is('ios') || \r\n this.platform.is('android') || \r\n this.platform.is('capacitor')\r\n );\r\n \r\n // Inputs - Title\r\n title = input.required<string>(); // For fixed header title\r\n headerTitle = input<string>(''); // Optional different title for expandable header\r\n headerSubtitle = input<string>('');\r\n \r\n // Inputs - Avatar\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n avatarInitials = input<string>('U');\r\n avatarSrc = input<string>('');\r\n avatarIconName = input<string>('remixUser3Line');\r\n \r\n // Inputs - Features\r\n showRefresh = input<boolean>(true);\r\n showCondensedHeader = input<boolean>(true);\r\n scrollThreshold = input<number>(160); // Pixels to scroll before title appears\r\n headerFadeDistance = input<number>(150); // Distance over which header fades out\r\n \r\n /**\r\n * Profile menu action groups to display when avatar is clicked.\r\n * If not provided, a default menu will be used (without Whitelabel Demo).\r\n * \r\n * @example\r\n * ```typescript\r\n * profileMenuItems: ActionGroup[] = [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'Min profil', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Indstillinger', icon: 'remixSettings3Line' }\r\n * ]\r\n * },\r\n * {\r\n * actions: [\r\n * { action: 'logout', title: 'Log ud', icon: 'remixLogoutBoxLine', destructive: true }\r\n * ]\r\n * }\r\n * ];\r\n * ```\r\n */\r\n profileMenuItems = input<ActionGroup[] | undefined>(undefined);\r\n \r\n // Outputs\r\n avatarClick = output<void>();\r\n \r\n /**\r\n * Emitted when a profile menu action is selected.\r\n * Parent component should handle the action logic (navigation, logout, etc.).\r\n */\r\n profileActionSelected = output<ActionResult>();\r\n \r\n refresh = output<any>();\r\n scroll = output<any>();\r\n \r\n constructor(private elementRef: ElementRef) {\r\n super();\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Initial setup if needed\r\n }\r\n \r\n /**\r\n * Handle avatar click - opens profile actions bottom sheet\r\n */\r\n async handleAvatarClick(): Promise<void> {\r\n console.log('Avatar clicked - opening profile bottom sheet');\r\n \r\n // Emit the event for any parent listeners\r\n this.avatarClick.emit();\r\n \r\n // Use input if provided, otherwise fall back to service, otherwise use default menu\r\n const menuItems = this.profileMenuItems() || this.userService.profileMenuItems() || [\r\n {\r\n actions: [\r\n {\r\n action: 'profile',\r\n title: 'Min profil',\r\n icon: 'remixUser3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'settings',\r\n title: 'Indstillinger',\r\n icon: 'remixSettings3Line',\r\n destructive: false\r\n }\r\n ]\r\n },\r\n {\r\n actions: [\r\n {\r\n action: 'logout',\r\n title: 'Log ud',\r\n icon: 'remixLogoutBoxLine',\r\n destructive: true\r\n }\r\n ]\r\n }\r\n ];\r\n \r\n // If no menu items configured, just emit and return\r\n if (!menuItems || menuItems.length === 0) {\r\n return;\r\n }\r\n \r\n const sheet = await this.modalController.create({\r\n component: DsMobileActionsBottomSheetComponent,\r\n componentProps: {\r\n customActionGroups: menuItems\r\n },\r\n // Auto-height: no breakpoints, no handle\r\n cssClass: 'ds-bottom-sheet auto-height'\r\n });\r\n \r\n await sheet.present();\r\n \r\n const result = await sheet.onWillDismiss<ActionResult>();\r\n if (result.data?.action) {\r\n // Handle whitelabel-demo action internally (works on all pages)\r\n if (result.data.action === 'whitelabel-demo') {\r\n console.log('Opening whitelabel demo...');\r\n // Small delay to ensure bottom sheet is fully dismissed\r\n setTimeout(async () => {\r\n try {\r\n await this.whitelabelDemoModal.open();\r\n } catch (error) {\r\n console.error('Failed to open whitelabel demo modal:', error);\r\n }\r\n }, 100);\r\n }\r\n \r\n // Emit the selected action to parent (for other actions)\r\n this.profileActionSelected.emit(result.data);\r\n }\r\n }\r\n \r\n /**\r\n * Handle scroll events\r\n * - Shows title in fixed header when scrolled past threshold\r\n * - Fades out expandable header content based on scroll position\r\n * - Emits scroll event for custom handling\r\n */\r\n handleScroll(event: any): void {\r\n const scrollTop = event.detail.scrollTop;\r\n const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');\r\n const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');\r\n \r\n // Show title in fixed header when scrolled past threshold\r\n if (scrollTop > this.scrollThreshold()) {\r\n header?.classList.add('header-scrolled');\r\n } else {\r\n header?.classList.remove('header-scrolled');\r\n }\r\n \r\n // Fade out header-expandable content based on scroll\r\n if (headerExpandable) {\r\n const fadeDistance = this.headerFadeDistance();\r\n const fadeProgress = Math.min(scrollTop / fadeDistance, 1);\r\n \r\n // Calculate opacity (1 to 0)\r\n const opacity = 1 - fadeProgress;\r\n \r\n // Calculate transform (0px to -20px upward)\r\n const translateY = fadeProgress * -20;\r\n \r\n // Apply styles\r\n headerExpandable.style.opacity = opacity.toString();\r\n headerExpandable.style.transform = `translateY(${translateY}px)`;\r\n }\r\n \r\n this.scroll.emit(event);\r\n }\r\n \r\n /**\r\n * Handle pull-to-refresh\r\n * Emits refresh event - parent should call event.target.complete()\r\n */\r\n async handleRefresh(event: any): Promise<void> {\r\n // Haptic feedback for pull-to-refresh\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Medium });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n \r\n this.refresh.emit(event);\r\n }\r\n}\r\n\r\n","import { Component, input, output, ElementRef } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { NavController } from '@ionic/angular/standalone';\r\nimport { IonHeader, IonToolbar, IonContent } from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { MobilePageBase } from '../shared/mobile-page-base';\r\n\r\n/**\r\n * DsMobilePageDetailsComponent\r\n * \r\n * A mobile page layout for detail/drill-down pages with:\r\n * - Back button header (mobile + desktop variants)\r\n * - White background content area\r\n * - Responsive padding\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple detail page -->\r\n * <ds-mobile-page-details\r\n * title=\"Property Details\"\r\n * (back)=\"goBack()\">\r\n * <div class=\"page-content\">\r\n * <!-- Your content -->\r\n * </div>\r\n * </ds-mobile-page-details>\r\n * \r\n * <!-- With default back route -->\r\n * <ds-mobile-page-details\r\n * title=\"Invoice Details\"\r\n * backRoute=\"/invoices\">\r\n * <div class=\"page-content\">\r\n * <!-- Your content -->\r\n * </div>\r\n * </ds-mobile-page-details>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-page-details',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonContent,\r\n DsIconComponent\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-page-base.css',\r\n './ds-mobile-page-details.css'\r\n ],\r\n template: `\r\n <!-- Mobile header - hidden on desktop -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <div class=\"header-details\">\r\n <button class=\"back-button\" (click)=\"handleBack()\" [attr.aria-label]=\"'Go back'\">\r\n <ds-icon name=\"remixArrowLeftLine\" size=\"24px\" />\r\n </button>\r\n <h1 class=\"header-title\">{{ title() }}</h1>\r\n </div>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <ion-content>\r\n <!-- Content area -->\r\n <div class=\"content-wrapper\">\r\n <div class=\"content-inner\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePageDetailsComponent extends MobilePageBase {\r\n // Inputs\r\n title = input.required<string>();\r\n backRoute = input<string>(''); // Optional default back route\r\n \r\n // Outputs\r\n back = output<void>();\r\n \r\n constructor(\r\n private navCtrl: NavController,\r\n private elementRef: ElementRef\r\n ) {\r\n super();\r\n }\r\n \r\n /**\r\n * Handle back navigation\r\n * \r\n * By default, navigates using the provided backRoute or browser back.\r\n * Parent components can listen to the (back) event to override this behavior.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Default behavior: uses backRoute or browser back -->\r\n * <ds-mobile-page-details \r\n * title=\"Details\" \r\n * backRoute=\"/home\">\r\n * </ds-mobile-page-details>\r\n * \r\n * <!-- Custom behavior: parent handles navigation -->\r\n * <ds-mobile-page-details \r\n * title=\"Details\"\r\n * (back)=\"customBackHandler()\">\r\n * </ds-mobile-page-details>\r\n * ```\r\n */\r\n handleBack(): void {\r\n // Emit event for parent to optionally handle\r\n this.back.emit();\r\n \r\n // Default behavior: navigate using backRoute or browser back\r\n if (this.backRoute()) {\r\n this.navCtrl.navigateBack(this.backRoute());\r\n } else {\r\n this.navCtrl.back();\r\n }\r\n }\r\n}\r\n\r\n","import { Component, input } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileContentComponent\r\n * \r\n * Main content container for mobile pages with flexible layout options.\r\n * Provides consistent spacing and layout patterns.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Default: stacked layout -->\r\n * <ds-mobile-content>\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * </ds-mobile-content>\r\n * \r\n * <!-- Grid layout -->\r\n * <ds-mobile-content layout=\"grid-2\">\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * <ds-mobile-content-section>...</ds-mobile-content-section>\r\n * </ds-mobile-content>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-content',\r\n standalone: true,\r\n imports: [CommonModule],\r\n host: {\r\n '[class.layout-stacked]': 'layout() === \"stacked\"',\r\n '[class.layout-grid-2]': 'layout() === \"grid-2\"',\r\n '[class.layout-grid-3]': 'layout() === \"grid-3\"'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 32px;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n }\r\n \r\n /* Grid layouts */\r\n :host.layout-grid-2 {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 16px;\r\n }\r\n \r\n :host.layout-grid-3 {\r\n display: grid;\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 16px;\r\n }\r\n \r\n @media (max-width: 768px) {\r\n :host.layout-grid-2,\r\n :host.layout-grid-3 {\r\n grid-template-columns: 1fr;\r\n }\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class DsMobileContentComponent {\r\n /**\r\n * Layout mode for content sections\r\n * - 'stacked' - Vertical stack with 32px gap (default)\r\n * - 'grid-2' - 2 column grid\r\n * - 'grid-3' - 3 column grid (stacks on mobile)\r\n */\r\n layout = input<'stacked' | 'grid-2' | 'grid-3'>('stacked');\r\n}\r\n\r\n/**\r\n * DsMobileContentSectionComponent\r\n * \r\n * Section within mobile content with optional header.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-content-section>\r\n * <section-header width=\"half\"></section-header>\r\n * <content-row>\r\n * <div class=\"grey-box\"></div>\r\n * </content-row>\r\n * </ds-mobile-content-section>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-content-section',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"section-header\" />\r\n <ng-content />\r\n `\r\n})\r\nexport class DsMobileContentSectionComponent {}\r\n\r\n/**\r\n * SectionHeaderComponent\r\n * \r\n * Semantic placeholder header for content sections.\r\n * Used for prototyping/placeholders.\r\n */\r\n@Component({\r\n selector: 'section-header',\r\n standalone: true,\r\n host: {\r\n '[class.w-half]': 'width() === \"half\"',\r\n '[class.w-third]': 'width() === \"third\"',\r\n '[class.w-full]': 'width() === \"full\"'\r\n },\r\n styles: [`\r\n :host {\r\n height: 20px;\r\n border-radius: 8px;\r\n background: var(--color-background-neutral-tertiary);\r\n display: block;\r\n }\r\n \r\n :host.w-half { width: 50%; }\r\n :host.w-third { width: 33%; }\r\n :host.w-full { width: 100%; }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class SectionHeaderComponent {\r\n /** Width of the header placeholder */\r\n width = input<'half' | 'third' | 'full'>('half');\r\n}\r\n\r\n/**\r\n * ContentRowComponent\r\n * \r\n * Horizontal row container for content items.\r\n */\r\n@Component({\r\n selector: 'content-row',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n gap: 12px;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class ContentRowComponent {}\r\n\r\n","import { Component, input } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileHeaderContentComponent\r\n * \r\n * Container for header content tiles - displays tiles in a responsive grid.\r\n * Used within the expandable header section of mobile pages to show\r\n * summary information like property details, statistics, etc.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-header-content header-content>\r\n * <ds-mobile-header-content-tile>\r\n * <tile-icon>\r\n * <ds-icon name=\"remixHome4Line\" />\r\n * </tile-icon>\r\n * <tile-content>\r\n * <tile-label>Area</tile-label>\r\n * <tile-value>120 m²</tile-value>\r\n * </tile-content>\r\n * </ds-mobile-header-content-tile>\r\n * </ds-mobile-header-content>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-header-content',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 12px;\r\n }\r\n \r\n @media (min-width: 768px) {\r\n :host {\r\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n }\r\n }\r\n `],\r\n template: `<ng-content select=\"ds-mobile-header-content-tile\" />`\r\n})\r\nexport class DsMobileHeaderContentComponent {}\r\n\r\n/**\r\n * DsMobileHeaderContentTileComponent\r\n * \r\n * Individual tile for displaying summary information in the header.\r\n * Styled with purple background to match the mobile header theme.\r\n * \r\n * Must contain:\r\n * - `<tile-icon>` - Icon container (optional)\r\n * - `<tile-content>` - Label and value container\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-header-content-tile>\r\n * <tile-icon>\r\n * <ds-icon name=\"remixHome4Line\" size=\"20px\" color=\"#DFE4FF\" />\r\n * </tile-icon>\r\n * <tile-content>\r\n * <tile-label>Rooms</tile-label>\r\n * <tile-value>3 rooms</tile-value>\r\n * </tile-content>\r\n * </ds-mobile-header-content-tile>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-header-content-tile',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n background: rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.05);\r\n border: 1px solid rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.1);\r\n border-radius: 12px;\r\n padding: 12px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"tile-icon\" />\r\n <ng-content select=\"tile-content\" />\r\n `\r\n})\r\nexport class DsMobileHeaderContentTileComponent {}\r\n\r\n/**\r\n * TileIconComponent\r\n * \r\n * Semantic slot for tile icon with dark purple background.\r\n * Use within `ds-mobile-header-content-tile`.\r\n */\r\n@Component({\r\n selector: 'tile-icon',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n background: var(--color-brand-secondary);\r\n border-radius: 8px;\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n color: var(--color-secondary-content, #ffffff);\r\n }\r\n \r\n /* Apply color to ds-icon inside */\r\n :host ::ng-deep ds-icon {\r\n --icon-color: var(--color-secondary-content, #ffffff);\r\n color: var(--color-secondary-content, #ffffff);\r\n }\r\n \r\n :host ::ng-deep ds-icon svg {\r\n fill: var(--color-secondary-content, #ffffff);\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class TileIconComponent {}\r\n\r\n/**\r\n * TileContentComponent\r\n * \r\n * Semantic slot for tile content containing label and value.\r\n * Use within `ds-mobile-header-content-tile`.\r\n * \r\n * Contains:\r\n * - `<tile-label>` - Small label text\r\n * - `<tile-value>` - Large value text\r\n */\r\n@Component({\r\n selector: 'tile-content',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0;\r\n }\r\n \r\n ::ng-deep tile-label {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.56px;\r\n color: rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.8);\r\n display: block;\r\n }\r\n \r\n ::ng-deep tile-value {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-lg);\r\n font-weight: 600;\r\n line-height: 26px;\r\n letter-spacing: -0.72px;\r\n color: var(--color-secondary-content, #ffffff);\r\n display: block;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"tile-label\" />\r\n <ng-content select=\"tile-value\" />\r\n `\r\n})\r\nexport class TileContentComponent {}\r\n\r\n/**\r\n * TileLabelComponent\r\n * \r\n * Label text for tile content.\r\n * Use within `tile-content` inside `ds-mobile-header-content-tile`.\r\n */\r\n@Component({\r\n selector: 'tile-label',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.56px;\r\n color: rgba(var(--color-secondary-content-rgb, 255, 255, 255), 0.8);\r\n display: block;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class TileLabelComponent {}\r\n\r\n/**\r\n * TileValueComponent\r\n * \r\n * Value text for tile content.\r\n * Use within `tile-content` inside `ds-mobile-header-content-tile`.\r\n */\r\n@Component({\r\n selector: 'tile-value',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-lg);\r\n font-weight: 600;\r\n line-height: 26px;\r\n letter-spacing: -0.72px;\r\n color: var(--color-secondary-content, #ffffff);\r\n display: block;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class TileValueComponent {}\r\n\r\n","import { Component, input, output, model, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\n\r\n/**\r\n * DsMobileCommentComponent\r\n *\r\n * Individual comment component for post discussions.\r\n * Displays user comments with avatar, content, and like action.\r\n *\r\n * @example\r\n * ```html\r\n * <ds-mobile-comment\r\n * [authorName]=\"'John Doe'\"\r\n * [authorRole]=\"'Tenant'\"\r\n * [timestamp]=\"'1h ago'\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [content]=\"'Great post!'\">\r\n * </ds-mobile-comment>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-comment',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent, DsIconButtonComponent],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n host: {\r\n '[class.clickable]': 'clickable()',\r\n '(click)': 'handleCommentClick($event)',\r\n '(touchstart)': 'handleTouchStart($event)',\r\n '(touchend)': 'handleTouchEnd($event)',\r\n '(touchmove)': 'handleTouchMove($event)',\r\n '(contextmenu)': 'handleContextMenu($event)',\r\n },\r\n styles: [\r\n `\r\n :host {\r\n display: flex;\r\n gap: 12px;\r\n padding: 8px;\r\n position: relative;\r\n border-radius: 16px;\r\n transition: all 0.2s ease;\r\n background: var(--color-background-primary, #ffffff);\r\n margin-bottom: 8px;\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n }\r\n\r\n :host:last-child {\r\n margin-bottom: 0;\r\n }\r\n\r\n :host::after {\r\n content: '';\r\n position: absolute;\r\n bottom: -4px;\r\n /* Align with comment content: padding (8px) + avatar (32px) + gap (12px) */\r\n left: 44px;\r\n /* Align with comment content right edge: padding (8px) from right */\r\n right: 8px;\r\n height: 1px;\r\n background: var(--border-color-default);\r\n }\r\n\r\n :host:last-child::after {\r\n display: none;\r\n }\r\n\r\n :host.clickable {\r\n cursor: pointer;\r\n }\r\n\r\n :host.clickable:active {\r\n background: var(--color-background-neutral-primary-hover, #f5f5f5);\r\n }\r\n\r\n .avatar-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n }\r\n\r\n .comment-content {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n\r\n .comment-header {\r\n display: flex;\r\n align-items: baseline;\r\n gap: 6px;\r\n flex-wrap: wrap;\r\n }\r\n\r\n /* Wrapper for like and more actions */\r\n .header-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n margin-left: auto;\r\n }\r\n\r\n /* Desktop more actions button - using ds-icon-button */\r\n .desktop-more-button {\r\n display: none; /* Hidden by default (mobile) */\r\n }\r\n\r\n /* Make button circular */\r\n .desktop-more-button::ng-deep button {\r\n border-radius: 50% !important;\r\n }\r\n\r\n /* Show only on desktop with hover capability */\r\n @media (hover: hover) and (pointer: fine) {\r\n .desktop-more-button {\r\n display: block;\r\n }\r\n }\r\n\r\n /* Author styles imported from mobile-common.css */\r\n\r\n .action-like {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 18px;\r\n }\r\n\r\n .like-count {\r\n opacity: 1;\r\n }\r\n\r\n .like-count.hidden {\r\n opacity: 0;\r\n }\r\n\r\n .action-like.active {\r\n color: #f91880;\r\n }\r\n\r\n .icon-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n .icon-pulse {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n opacity: 0;\r\n pointer-events: none;\r\n }\r\n\r\n .icon-pulse.animating {\r\n animation: pulse 0.4s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n\r\n @keyframes pulse {\r\n 0% {\r\n transform: translate(-50%, -50%) scale(1);\r\n opacity: 0.8;\r\n }\r\n 100% {\r\n transform: translate(-50%, -50%) scale(2.5);\r\n opacity: 0;\r\n }\r\n }\r\n\r\n .comment-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n white-space: pre-wrap;\r\n word-wrap: break-word;\r\n }\r\n\r\n .comment-text ::ng-deep .mention {\r\n color: var(--color-brand-base, #6b5ff5) !important;\r\n font-weight: 600;\r\n }\r\n\r\n .comment-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n margin-top: 4px;\r\n }\r\n\r\n .action-reply {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .action-reply:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n\r\n .action-edit {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .action-edit:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n `,\r\n ],\r\n template: `\r\n <div class=\"avatar-wrapper\">\r\n <ds-avatar [initials]=\"avatarInitials()\" [type]=\"avatarType()\" size=\"sm\" />\r\n </div>\r\n\r\n <div class=\"comment-content\">\r\n <div class=\"comment-header\">\r\n <span class=\"author-name\">{{ authorName() }}</span>\r\n <span class=\"author-meta\">{{ authorRole() }} · {{ timestamp() }}</span>\r\n\r\n <!-- Wrapper for like and more actions -->\r\n <div class=\"header-actions\">\r\n <div class=\"action-like\" [class.active]=\"isLiked()\" (click)=\"toggleLike()\">\r\n <span class=\"like-count\" [class.hidden]=\"likeCount() === 0\">{{ likeCount() }}</span>\r\n <div class=\"icon-wrapper\">\r\n <ds-icon class=\"icon-pulse\" [class.animating]=\"isPulsing()\" [name]=\"isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'\" size=\"16px\" />\r\n <ds-icon [name]=\"isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'\" size=\"16px\" />\r\n </div>\r\n </div>\r\n\r\n <!-- Desktop more button -->\r\n <ds-icon-button class=\"desktop-more-button\" icon=\"remixMoreFill\" variant=\"secondary\" size=\"sm\" (clicked)=\"handleMoreButtonClick($event)\" aria-label=\"More options\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"comment-text\" [innerHTML]=\"formattedContent()\"></div>\r\n\r\n <div class=\"comment-actions\">\r\n <div class=\"action-reply\" (click)=\"handleReply()\">Reply</div>\r\n @if (isOwnComment()) {\r\n <div class=\"action-edit\" (click)=\"handleEdit()\">Edit</div>\r\n }\r\n </div>\r\n </div>\r\n `,\r\n})\r\nexport class DsMobileCommentComponent {\r\n /**\r\n * Author's display name\r\n */\r\n authorName = input.required<string>();\r\n\r\n /**\r\n * Author's role (e.g., \"Tenant\", \"Property Manager\")\r\n */\r\n authorRole = input.required<string>();\r\n\r\n /**\r\n * Timestamp text (e.g., \"1h ago\", \"2d ago\")\r\n */\r\n timestamp = input.required<string>();\r\n\r\n /**\r\n * Comment content text\r\n */\r\n content = input.required<string>();\r\n\r\n /**\r\n * Avatar initials\r\n */\r\n avatarInitials = input<string>('');\r\n\r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n\r\n /**\r\n * Whether the comment is clickable\r\n */\r\n clickable = input<boolean>(false);\r\n\r\n /**\r\n * Whether this comment belongs to the current user\r\n */\r\n isOwnComment = input<boolean>(false);\r\n\r\n /**\r\n * Whether the comment is liked by current user\r\n */\r\n isLiked = model<boolean>(false);\r\n\r\n /**\r\n * Emits when like is toggled (after UI is opdateret)\r\n */\r\n likeToggled = output<{ active: boolean; count: number }>();\r\n\r\n /**\r\n * Number of likes\r\n */\r\n likeCount = model<number>(0);\r\n\r\n /**\r\n * Signal to control pulse animation\r\n */\r\n isPulsing = signal(false);\r\n\r\n /**\r\n * Computed property to format content with @mentions\r\n */\r\n formattedContent = computed(() => {\r\n const text = this.content();\r\n // Replace @mentions with styled spans\r\n // Matches @FirstName or @FirstName LastName (max 2 words)\r\n return text.replace(/@([A-Za-z]+(?:\\s+[A-Za-z]+)?)\\b/g, '<span class=\"mention\">@$1</span>');\r\n });\r\n\r\n /**\r\n * Emits when the comment card is clicked (if clickable)\r\n */\r\n commentClick = output<void>();\r\n\r\n /**\r\n * Emits when reply is clicked\r\n */\r\n replyClick = output<void>();\r\n\r\n /**\r\n * Emits when edit is clicked\r\n */\r\n editClick = output<void>();\r\n\r\n /**\r\n * Emits when the comment is long-pressed\r\n */\r\n longPress = output<void>();\r\n\r\n /**\r\n * Long press tracking\r\n */\r\n private longPressTimer: any = null;\r\n private longPressTriggered = false;\r\n private touchStartX = 0;\r\n private touchStartY = 0;\r\n private readonly LONG_PRESS_DURATION = 500; // ms\r\n private readonly MOVE_THRESHOLD = 10; // px\r\n\r\n handleCommentClick(event: Event): void {\r\n // Only emit if clickable and not clicking on action buttons\r\n if (this.clickable() && !(event.target as HTMLElement).closest('.comment-actions')) {\r\n this.commentClick.emit();\r\n }\r\n }\r\n\r\n async toggleLike(): Promise<void> {\r\n const newLiked = !this.isLiked();\r\n this.isLiked.set(newLiked);\r\n\r\n const newCount = newLiked ? this.likeCount() + 1 : this.likeCount() - 1;\r\n this.likeCount.set(Math.max(0, newCount));\r\n\r\n // Emit the like toggled event\r\n this.likeToggled.emit({ active: newLiked, count: Math.max(0, newCount) });\r\n\r\n // Trigger pulse animation only when liking\r\n if (newLiked) {\r\n this.isPulsing.set(true);\r\n setTimeout(() => this.isPulsing.set(false), 400);\r\n }\r\n\r\n // Haptic feedback for like/unlike\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Light });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n }\r\n\r\n handleReply(): void {\r\n this.replyClick.emit();\r\n }\r\n\r\n handleEdit(): void {\r\n this.editClick.emit();\r\n }\r\n\r\n /**\r\n * Handle touch start for long press detection\r\n */\r\n handleTouchStart(event: TouchEvent): void {\r\n this.longPressTriggered = false;\r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n\r\n // Start long press timer\r\n this.longPressTimer = setTimeout(async () => {\r\n this.longPressTriggered = true;\r\n this.longPress.emit();\r\n\r\n // Haptic feedback for long press\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Medium });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n }, this.LONG_PRESS_DURATION);\r\n }\r\n\r\n /**\r\n * Handle touch end to clear long press timer\r\n */\r\n handleTouchEnd(event: TouchEvent): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n\r\n // Prevent normal click if long press was triggered\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle touch move to cancel long press if moved too much\r\n */\r\n handleTouchMove(event: TouchEvent): void {\r\n if (!this.longPressTimer) return;\r\n\r\n const touch = event.touches[0];\r\n const deltaX = Math.abs(touch.clientX - this.touchStartX);\r\n const deltaY = Math.abs(touch.clientY - this.touchStartY);\r\n\r\n // Cancel long press if moved too far\r\n if (deltaX > this.MOVE_THRESHOLD || deltaY > this.MOVE_THRESHOLD) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle context menu (right-click on desktop) to trigger long press action\r\n */\r\n handleContextMenu(event: Event): void {\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n\r\n /**\r\n * Handle desktop more button click\r\n * Stops propagation and triggers long press action\r\n */\r\n handleMoreButtonClick(event: Event): void {\r\n console.log('[Comment] Desktop more button clicked');\r\n event.stopPropagation();\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n}\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobilePostComposerComponent\r\n * \r\n * A \"fake\" input composer for creating new posts in the community feed.\r\n * Features a user avatar, placeholder input, and post button.\r\n * Clicking opens the full post creation modal/page.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-post-composer\r\n * [avatarInitials]=\"'LM'\"\r\n * [avatarType]=\"'photo'\"\r\n * [avatarSrc]=\"'...'\"\r\n * (composerClick)=\"openPostCreator()\">\r\n * </ds-mobile-post-composer>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-post-composer',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent],\r\n host: {\r\n '(click)': 'handleClick()'\r\n },\r\n styles: [`\r\n :host {\r\n display: block;\r\n max-width: 640px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n }\r\n \r\n .composer-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n \r\n .composer-input-wrapper {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .composer-input {\r\n width: 100%;\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.1);\r\n border: none;\r\n border-radius: 24px;\r\n padding: 10px 16px;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.75);\r\n outline: none;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n pointer-events: none;\r\n user-select: none;\r\n }\r\n \r\n .composer-input::placeholder {\r\n color: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.75);\r\n opacity: 1;\r\n }\r\n \r\n /* Hover effects for desktop */\r\n @media (hover: hover) {\r\n :host:hover .composer-input {\r\n opacity: 0.8;\r\n }\r\n }\r\n `],\r\n template: `\r\n <div class=\"composer-container\">\r\n <ds-avatar \r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n [iconName]=\"avatarIconName()\"\r\n size=\"md\" />\r\n \r\n <div class=\"composer-input-wrapper\">\r\n <input \r\n type=\"text\" \r\n class=\"composer-input\" \r\n [placeholder]=\"placeholder()\"\r\n readonly\r\n tabindex=\"-1\"\r\n />\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobilePostComposerComponent {\r\n /**\r\n * Avatar initials (for initials type)\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Icon name (for icon type avatars)\r\n */\r\n avatarIconName = input<string>('remixUser3Fill');\r\n \r\n /**\r\n * Placeholder text for the input\r\n */\r\n placeholder = input<string>(\"Hvad er nyt?\");\r\n \r\n /**\r\n * Text for the post button\r\n */\r\n buttonText = input<string>('Slå op');\r\n \r\n /**\r\n * Emits when the composer is clicked\r\n */\r\n composerClick = output<void>();\r\n \r\n handleClick(): void {\r\n this.composerClick.emit();\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n input,\r\n output,\r\n signal,\r\n computed,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileMessageComposerComponent\r\n * \r\n * Reusable message composer component extracted from post-detail-modal.\r\n * Can be used for both comments and chat messages.\r\n * \r\n * Features:\r\n * - Text input with auto-resize\r\n * - Avatar display\r\n * - Send button (appears when text is entered)\r\n * - Optional mention menu support\r\n * - Optional edit/reply indicators\r\n * - Keyboard handling for mobile\r\n * - Safe area support\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-message-composer\r\n * [avatarInitials]=\"'JD'\"\r\n * [placeholder]=\"'Write a message...'\"\r\n * (messageSent)=\"handleMessage($event)\">\r\n * </ds-mobile-message-composer>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-message-composer',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n DsAvatarComponent,\r\n DsIconButtonComponent,\r\n DsIconComponent\r\n ],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n\r\n /* Composer Container */\r\n .message-composer {\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-top: 1px solid var(--border-color-default);\r\n border-bottom-left-radius: 0;\r\n border-bottom-right-radius: 0;\r\n padding: 12px 16px;\r\n /* Use dynamic viewport height safe area */\r\n padding-bottom: max(12px, env(safe-area-inset-bottom, 0px));\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n\r\n /* Edit indicator (optional) */\r\n .edit-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-brand-subtle, #f0edfe);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n \r\n .edit-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: var(--color-brand-base, #6B5FF5);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .edit-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-brand-base, #6B5FF5);\r\n }\r\n \r\n .cancel-edit {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-brand-base, #6B5FF5);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n \r\n .cancel-edit:active {\r\n background: var(--color-brand-subtle, #e0dbfe);\r\n }\r\n \r\n /* Reply indicator (optional) */\r\n .reply-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n \r\n .reply-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n color: var(--color-text-secondary, #737373);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .reply-to-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .reply-author {\r\n color: var(--color-brand-base, #6B5FF5);\r\n font-weight: 600;\r\n }\r\n \r\n .cancel-reply {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-text-secondary, #737373);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n \r\n .cancel-reply:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n \r\n @keyframes slideDown {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n \r\n .composer-content {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n width: 100%;\r\n position: relative;\r\n }\r\n \r\n .composer-content ds-avatar {\r\n position: relative;\r\n top: 6px;\r\n }\r\n \r\n .composer-input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 8px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 24px;\r\n padding: 12px 16px;\r\n padding-right: 48px; /* Extra padding for fixed send button */\r\n min-height: 44px;\r\n position: relative;\r\n }\r\n \r\n /* Mention menu (optional) */\r\n .mention-menu {\r\n position: absolute;\r\n bottom: 100%;\r\n left: 0;\r\n right: 0;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-radius: 12px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n margin-bottom: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n z-index: 10;\r\n animation: slideUp 0.2s ease-out;\r\n }\r\n \r\n @keyframes slideUp {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n \r\n .mention-menu-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 12px;\r\n border: none;\r\n background: none;\r\n width: 100%;\r\n text-align: left;\r\n cursor: pointer;\r\n transition: background 0.2s ease;\r\n border-bottom: 1px solid var(--border-color-default);\r\n }\r\n \r\n .mention-menu-item:last-child {\r\n border-bottom: none;\r\n }\r\n \r\n .mention-menu-item:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n \r\n .mention-user-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .mention-user-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .mention-user-role {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n }\r\n \r\n .composer-input {\r\n flex: 1;\r\n border: none;\r\n background: transparent;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n outline: none;\r\n resize: none;\r\n min-height: 20px;\r\n max-height: 120px;\r\n overflow-y: auto;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n \r\n .composer-input::placeholder {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n font-size: var(--font-size-sm);\r\n }\r\n \r\n /* Send button - positioned in top right corner */\r\n .send-button-fixed {\r\n position: absolute;\r\n top: 6px;\r\n right: 6px;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n animation: slideInFromRight 0.2s ease-out;\r\n }\r\n \r\n .send-button-fixed::ng-deep button {\r\n width: 32px !important;\r\n height: 32px !important;\r\n min-width: 32px !important;\r\n min-height: 32px !important;\r\n padding: 0 !important;\r\n border-radius: 50% !important;\r\n }\r\n \r\n @keyframes slideInFromRight {\r\n from {\r\n opacity: 0;\r\n transform: translateX(20px) scale(0.8);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateX(0) scale(1);\r\n }\r\n }\r\n `],\r\n template: `\r\n <div class=\"message-composer\">\r\n <!-- Edit indicator (optional) -->\r\n @if (editingMessage()) {\r\n <div class=\"edit-indicator\">\r\n <div class=\"edit-indicator-content\">\r\n <ds-icon name=\"remixEditLine\" size=\"16px\" />\r\n <span class=\"edit-text\">{{ editIndicatorText() }}</span>\r\n </div>\r\n <button class=\"cancel-edit\" (click)=\"cancelEdit()\" type=\"button\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n }\r\n \r\n <!-- Reply indicator (optional) -->\r\n @if (replyingTo() && !editingMessage()) {\r\n <div class=\"reply-indicator\">\r\n <div class=\"reply-indicator-content\">\r\n <ds-icon name=\"remixReplyLine\" size=\"16px\" />\r\n <span class=\"reply-to-text\">\r\n {{ replyIndicatorText() }} <span class=\"reply-author\">{{ replyingTo()!.authorName }}</span>\r\n </span>\r\n </div>\r\n <button class=\"cancel-reply\" (click)=\"cancelReply()\" type=\"button\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n }\r\n \r\n <div class=\"composer-content\">\r\n <ds-avatar\r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n size=\"md\"\r\n />\r\n <div class=\"composer-input-wrapper\">\r\n <!-- Mention menu (optional) -->\r\n @if (showMentionMenu() && filteredUsers().length > 0 && !editingMessage()) {\r\n <div class=\"mention-menu\">\r\n @for (user of filteredUsers(); track user.name) {\r\n <button \r\n class=\"mention-menu-item\" \r\n (click)=\"selectMention(user.name)\"\r\n type=\"button\">\r\n <ds-avatar \r\n [initials]=\"user.initials\"\r\n [type]=\"'initials'\"\r\n size=\"sm\" />\r\n <div class=\"mention-user-info\">\r\n <span class=\"mention-user-name\">{{ user.name }}</span>\r\n <span class=\"mention-user-role\">{{ user.role }}</span>\r\n </div>\r\n </button>\r\n }\r\n </div>\r\n }\r\n \r\n <textarea\r\n #messageInput\r\n class=\"composer-input\"\r\n [placeholder]=\"placeholder()\"\r\n [(ngModel)]=\"messageText\"\r\n (input)=\"handleInput($event)\"\r\n (focus)=\"showKeyboard()\"\r\n (click)=\"showKeyboard()\"\r\n rows=\"1\"\r\n ></textarea>\r\n </div>\r\n @if (messageText().trim().length > 0) {\r\n <ds-icon-button\r\n icon=\"remixCheckLine\"\r\n variant=\"primary\"\r\n size=\"sm\"\r\n (clicked)=\"sendMessage()\"\r\n [attr.aria-label]=\"sendButtonLabel()\"\r\n class=\"send-button-fixed\">\r\n </ds-icon-button>\r\n }\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileMessageComposerComponent implements AfterViewInit, OnDestroy {\r\n /**\r\n * Avatar initials\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Placeholder text for the input\r\n */\r\n placeholder = input<string>('Write a message...');\r\n \r\n /**\r\n * Send button aria label\r\n */\r\n sendButtonLabel = input<string>('Send message');\r\n \r\n /**\r\n * Edit indicator text (when editing)\r\n */\r\n editIndicatorText = input<string>('Editing message');\r\n \r\n /**\r\n * Reply indicator text prefix\r\n */\r\n replyIndicatorText = input<string>('Replying to');\r\n \r\n /**\r\n * Whether to enable mention support\r\n */\r\n enableMentions = input<boolean>(false);\r\n \r\n /**\r\n * Available users for mentions (if mentions enabled)\r\n */\r\n mentionUsers = input<Array<{ name: string; initials: string; role: string }>>([]);\r\n \r\n /**\r\n * Auto-focus input on mount\r\n */\r\n autoFocus = input<boolean>(false);\r\n \r\n /**\r\n * ViewChild for message input\r\n */\r\n @ViewChild('messageInput') messageInput?: ElementRef<HTMLTextAreaElement>;\r\n \r\n /**\r\n * Message text signal\r\n */\r\n messageText = signal('');\r\n \r\n /**\r\n * Editing message state (optional)\r\n */\r\n editingMessage = signal<{ authorName: string; originalContent: string; timestamp: string } | null>(null);\r\n \r\n /**\r\n * Replying to state (optional)\r\n */\r\n replyingTo = signal<{ authorName: string; content: string } | null>(null);\r\n \r\n /**\r\n * Mention menu state\r\n */\r\n showMentionMenu = signal(false);\r\n \r\n /**\r\n * Mention query for filtering\r\n */\r\n mentionQuery = signal('');\r\n \r\n /**\r\n * Filtered users based on mention query\r\n */\r\n filteredUsers = computed(() => {\r\n if (!this.enableMentions()) return [];\r\n \r\n const query = this.mentionQuery().toLowerCase();\r\n const users = this.mentionUsers();\r\n \r\n if (!query) return users;\r\n return users.filter(user => \r\n user.name.toLowerCase().includes(query)\r\n );\r\n });\r\n \r\n /**\r\n * Emits when a message is sent\r\n */\r\n messageSent = output<{ content: string; isReply?: boolean; replyTo?: string; isEdit?: boolean }>();\r\n \r\n /**\r\n * Emits when edit is cancelled\r\n */\r\n editCancelled = output<void>();\r\n \r\n /**\r\n * Emits when reply is cancelled\r\n */\r\n replyCancelled = output<void>();\r\n \r\n /**\r\n * Emits when mention is selected\r\n */\r\n mentionSelected = output<{ userName: string }>();\r\n \r\n ngAfterViewInit(): void {\r\n // Auto-focus input if requested\r\n if (this.autoFocus()) {\r\n setTimeout(() => {\r\n this.messageInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }, 300);\r\n }\r\n \r\n // Set up keyboard listeners\r\n this.setupKeyboardListeners();\r\n }\r\n \r\n ngOnDestroy(): void {\r\n // Clean up keyboard listeners\r\n this.cleanupKeyboardListeners();\r\n }\r\n \r\n /**\r\n * Set up keyboard event listeners\r\n */\r\n private setupKeyboardListeners(): void {\r\n Keyboard.addListener('keyboardWillShow', (info) => {\r\n document.documentElement.style.setProperty('--keyboard-height', `${info.keyboardHeight}px`);\r\n }).catch(e => console.log('Keyboard listeners not available:', e));\r\n \r\n Keyboard.addListener('keyboardWillHide', () => {\r\n document.documentElement.style.setProperty('--keyboard-height', '0px');\r\n }).catch(e => console.log('Keyboard listeners not available:', e));\r\n }\r\n \r\n /**\r\n * Clean up keyboard event listeners\r\n */\r\n private cleanupKeyboardListeners(): void {\r\n Keyboard.removeAllListeners().catch(e => console.log('Keyboard cleanup not available:', e));\r\n }\r\n \r\n /**\r\n * Show the keyboard when user interacts with input\r\n */\r\n showKeyboard(): void {\r\n Keyboard.show().catch(e => console.log('Keyboard.show() not available'));\r\n }\r\n \r\n /**\r\n * Handle input changes and detect @ mentions\r\n */\r\n handleInput(event: Event): void {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n const text = textarea.value;\r\n const cursorPosition = textarea.selectionStart || 0;\r\n \r\n // Update signal\r\n this.messageText.set(text);\r\n \r\n // Auto-resize textarea\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n \r\n // Handle mentions if enabled\r\n if (this.enableMentions()) {\r\n // Find the last @ before cursor\r\n const textBeforeCursor = text.substring(0, cursorPosition);\r\n const lastAtIndex = textBeforeCursor.lastIndexOf('@');\r\n \r\n if (lastAtIndex !== -1) {\r\n // Check if there's a space after @\r\n const textAfterAt = textBeforeCursor.substring(lastAtIndex + 1);\r\n const hasSpace = textAfterAt.includes(' ');\r\n \r\n if (!hasSpace) {\r\n // Show mention menu\r\n this.showMentionMenu.set(true);\r\n this.mentionQuery.set(textAfterAt);\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Select a user from mention menu\r\n */\r\n selectMention(userName: string): void {\r\n // Set as reply (similar to clicking Reply)\r\n this.replyingTo.set({ authorName: userName, content: '' });\r\n \r\n // Clear the @ from the input\r\n const currentText = this.messageText();\r\n const textWithoutMention = currentText.substring(0, currentText.lastIndexOf('@'));\r\n this.messageText.set(textWithoutMention);\r\n \r\n // Hide mention menu\r\n this.showMentionMenu.set(false);\r\n \r\n // Emit mention selected event\r\n this.mentionSelected.emit({ userName });\r\n \r\n // Focus back on input\r\n setTimeout(() => {\r\n this.messageInput?.nativeElement.focus();\r\n }, 0);\r\n }\r\n \r\n /**\r\n * Cancel edit\r\n */\r\n cancelEdit(): void {\r\n this.editingMessage.set(null);\r\n this.messageText.set('');\r\n this.editCancelled.emit();\r\n }\r\n \r\n /**\r\n * Cancel reply\r\n */\r\n cancelReply(): void {\r\n this.replyingTo.set(null);\r\n this.replyCancelled.emit();\r\n }\r\n \r\n /**\r\n * Set reply state (for external use)\r\n */\r\n setReply(authorName: string, content: string): void {\r\n this.replyingTo.set({ authorName, content });\r\n // Focus the input and show keyboard\r\n setTimeout(() => {\r\n this.messageInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Set edit state (for external use)\r\n */\r\n setEdit(authorName: string, originalContent: string, timestamp: string): void {\r\n // Clear reply state if active\r\n this.replyingTo.set(null);\r\n \r\n // Remove @mention from the content if it exists\r\n let contentToEdit = originalContent;\r\n const mentionMatch = originalContent.match(/^@([A-Za-z]+(?:\\s+[A-Za-z]+)?)\\s+/);\r\n if (mentionMatch) {\r\n contentToEdit = originalContent.substring(mentionMatch[0].length);\r\n }\r\n \r\n // Set edit state\r\n this.editingMessage.set({ authorName, originalContent, timestamp });\r\n \r\n // Populate the input with existing content\r\n this.messageText.set(contentToEdit);\r\n \r\n // Focus the input, show keyboard, and auto-resize\r\n setTimeout(() => {\r\n if (this.messageInput?.nativeElement) {\r\n const textarea = this.messageInput.nativeElement;\r\n textarea.focus();\r\n \r\n // Auto-resize textarea to fit content\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n \r\n this.showKeyboard();\r\n }\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Clear composer state\r\n */\r\n clear(): void {\r\n this.messageText.set('');\r\n this.editingMessage.set(null);\r\n this.replyingTo.set(null);\r\n this.showMentionMenu.set(false);\r\n \r\n // Reset textarea height\r\n if (this.messageInput?.nativeElement) {\r\n this.messageInput.nativeElement.style.height = 'auto';\r\n }\r\n }\r\n \r\n /**\r\n * Focus the input\r\n */\r\n focus(): void {\r\n this.messageInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }\r\n \r\n /**\r\n * Send message\r\n */\r\n sendMessage(): void {\r\n const text = this.messageText().trim();\r\n if (!text) return;\r\n \r\n const isEdit = !!this.editingMessage();\r\n const isReply = !!this.replyingTo();\r\n \r\n // Emit message sent event\r\n this.messageSent.emit({\r\n content: isReply && this.replyingTo()\r\n ? `@${this.replyingTo()!.authorName} ${text}`\r\n : text,\r\n isReply,\r\n replyTo: this.replyingTo()?.authorName,\r\n isEdit\r\n });\r\n \r\n // Clear the input and states\r\n this.clear();\r\n \r\n // Blur the input to hide the keyboard\r\n this.messageInput?.nativeElement.blur();\r\n \r\n // Hide keyboard explicitly\r\n Keyboard.hide().catch(e => console.log('Keyboard.hide() not available'));\r\n }\r\n}\r\n\r\n","import { Component, input, output, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * Chat attachment interface\r\n */\r\nexport interface ChatAttachment {\r\n id: string;\r\n type: 'image' | 'pdf' | 'file';\r\n url: string;\r\n name: string;\r\n size?: number;\r\n thumbnail?: string;\r\n}\r\n\r\n/**\r\n * DsMobileMessageBubbleComponent\r\n * \r\n * Individual message bubble component for chat conversations.\r\n * Supports left-aligned (sender) and right-aligned (user) messages with different styling.\r\n * \r\n * Features:\r\n * - Left/right alignment based on sender\r\n * - Avatar display (left for sender, right for user)\r\n * - Message content with text wrapping\r\n * - Timestamp display\r\n * - Read receipt indicator (for user's messages)\r\n * - Attachment support\r\n * - Long press support for actions\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Sender's message (left-aligned) -->\r\n * <ds-mobile-message-bubble\r\n * [isOwnMessage]=\"false\"\r\n * [senderName]=\"'Ricki Meihlen'\"\r\n * [content]=\"'We have received your case...'\"\r\n * [timestamp]=\"'12:34'\"\r\n * [avatarInitials]=\"'RM'\">\r\n * </ds-mobile-message-bubble>\r\n * \r\n * <!-- User's message (right-aligned) -->\r\n * <ds-mobile-message-bubble\r\n * [isOwnMessage]=\"true\"\r\n * [senderName]=\"'You'\"\r\n * [content]=\"'Thank you!'\"\r\n * [timestamp]=\"'12:35'\"\r\n * [readStatus]=\"true\"\r\n * [avatarInitials]=\"'JD'\">\r\n * </ds-mobile-message-bubble>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-message-bubble',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent],\r\n host: {\r\n '[class.is-own-message]': 'isOwnMessage()',\r\n '[class.has-attachments]': 'attachments() && attachments()!.length > 0',\r\n '(touchstart)': 'handleTouchStart($event)',\r\n '(touchend)': 'handleTouchEnd($event)',\r\n '(touchmove)': 'handleTouchMove($event)',\r\n '(contextmenu)': 'handleContextMenu($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n gap: 8px;\r\n margin-bottom: 12px;\r\n width: 100%;\r\n align-items: flex-end;\r\n box-sizing: border-box;\r\n }\r\n \r\n /* Left-aligned (sender's message) */\r\n :host:not(.is-own-message) {\r\n justify-content: flex-start !important;\r\n flex-direction: row !important;\r\n }\r\n \r\n /* Right-aligned (user's message) - MUST be right-aligned */\r\n :host.is-own-message {\r\n justify-content: flex-end !important;\r\n flex-direction: row-reverse !important;\r\n margin-left: auto !important;\r\n margin-right: 0 !important;\r\n }\r\n \r\n .avatar-wrapper {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: flex-end;\r\n }\r\n \r\n .message-content-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n max-width: 75%;\r\n min-width: 0;\r\n }\r\n \r\n /* Left-aligned message bubble */\r\n :host:not(.is-own-message) .message-content-wrapper {\r\n align-items: flex-start;\r\n }\r\n \r\n /* Right-aligned message bubble */\r\n :host.is-own-message .message-content-wrapper {\r\n align-items: flex-end !important;\r\n margin-left: auto !important;\r\n margin-right: 0 !important;\r\n }\r\n \r\n .message-bubble {\r\n padding: 10px 14px;\r\n padding-bottom: 6px; /* Reduced bottom padding to accommodate timestamp */\r\n border-radius: 16px;\r\n position: relative;\r\n word-wrap: break-word;\r\n white-space: pre-wrap;\r\n max-width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n \r\n /* Sender's message - white background */\r\n :host:not(.is-own-message) .message-bubble {\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border: 1px solid var(--border-color-default, #e5e5e5);\r\n }\r\n \r\n /* User's message - brand primary surface background */\r\n :host.is-own-message .message-bubble {\r\n background: var(--color-primary-surface, var(--color-brand-base, #6B5FF5));\r\n color: var(--color-primary-content, #ffffff);\r\n }\r\n \r\n .message-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n margin: 0;\r\n }\r\n \r\n :host:not(.is-own-message) .message-text {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n :host.is-own-message .message-text {\r\n color: var(--color-primary-content, #ffffff);\r\n }\r\n \r\n /* Attachments container */\r\n .attachments {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n margin-top: 8px;\r\n }\r\n \r\n :host:not(.is-own-message) .attachments {\r\n justify-content: flex-start;\r\n }\r\n \r\n :host.is-own-message .attachments {\r\n justify-content: flex-end;\r\n }\r\n \r\n .attachment-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 8px;\r\n border: 1px solid var(--border-color-default, #e5e5e5);\r\n cursor: pointer;\r\n transition: background 0.2s ease;\r\n }\r\n \r\n :host.is-own-message .attachment-item {\r\n background: rgba(255, 255, 255, 0.2);\r\n border-color: rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .attachment-item:active {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n :host.is-own-message .attachment-item:active {\r\n background: rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .attachment-icon {\r\n flex-shrink: 0;\r\n width: 24px;\r\n height: 24px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: 4px;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n \r\n :host.is-own-message .attachment-icon {\r\n background: rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .attachment-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 16px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n \r\n :host.is-own-message .attachment-name {\r\n color: var(--color-text-on-brand, #ffffff);\r\n }\r\n \r\n /* Timestamp and read receipt inside bubble */\r\n .message-footer {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n margin-top: 2px;\r\n align-self: flex-end; /* Always align to right within bubble */\r\n }\r\n \r\n :host:not(.is-own-message) .message-footer {\r\n align-self: flex-start; /* Left-align for sender's messages */\r\n }\r\n \r\n .timestamp {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 14px;\r\n }\r\n \r\n /* Timestamp color for sender's messages (white background) */\r\n :host:not(.is-own-message) .timestamp {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n \r\n /* Timestamp color for user's messages (brand primary surface background) */\r\n :host.is-own-message .timestamp {\r\n color: var(--color-primary-content, #ffffff);\r\n opacity: 0.8;\r\n }\r\n \r\n /* Long press tracking */\r\n :host {\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n `],\r\n template: `\r\n <div class=\"avatar-wrapper\">\r\n <ds-avatar\r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n size=\"sm\" />\r\n </div>\r\n \r\n <div class=\"message-content-wrapper\">\r\n <div class=\"message-bubble\">\r\n <p class=\"message-text\">{{ content() }}</p>\r\n \r\n <!-- Attachments -->\r\n @if (attachments() && attachments()!.length > 0) {\r\n <div class=\"attachments\">\r\n @for (attachment of attachments(); track attachment.id) {\r\n <div \r\n class=\"attachment-item\"\r\n (click)=\"handleAttachmentClick(attachment)\">\r\n <div class=\"attachment-icon\">\r\n @if (attachment.type === 'image') {\r\n <ds-icon name=\"remixImageLine\" size=\"16px\" />\r\n } @else if (attachment.type === 'pdf') {\r\n <ds-icon name=\"remixFilePdfLine\" size=\"16px\" />\r\n } @else {\r\n <ds-icon name=\"remixFileLine\" size=\"16px\" />\r\n }\r\n </div>\r\n <span class=\"attachment-name\">{{ attachment.name }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Timestamp inside bubble -->\r\n <div class=\"message-footer\">\r\n <span class=\"timestamp\">{{ timestamp() }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileMessageBubbleComponent {\r\n /**\r\n * Message content text\r\n */\r\n content = input.required<string>();\r\n \r\n /**\r\n * Whether this is the current user's message (right-aligned)\r\n */\r\n isOwnMessage = input<boolean>(false);\r\n \r\n /**\r\n * Sender's name (for display purposes)\r\n */\r\n senderName = input<string>('');\r\n \r\n /**\r\n * Timestamp text (e.g., \"12:34\", \"08-12-2025 13:18\")\r\n */\r\n timestamp = input.required<string>();\r\n \r\n /**\r\n * Avatar initials\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Whether to show read receipt (only for user's messages)\r\n */\r\n /**\r\n * Message attachments\r\n */\r\n attachments = input<ChatAttachment[] | undefined>(undefined);\r\n \r\n /**\r\n * Whether the message is clickable\r\n */\r\n clickable = input<boolean>(false);\r\n \r\n /**\r\n * Emits when attachment is clicked\r\n */\r\n attachmentClick = output<ChatAttachment>();\r\n \r\n /**\r\n * Emits when the message is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n /**\r\n * Long press tracking\r\n */\r\n private longPressTimer: any = null;\r\n private longPressTriggered = false;\r\n private touchStartX = 0;\r\n private touchStartY = 0;\r\n private readonly LONG_PRESS_DURATION = 500; // ms\r\n private readonly MOVE_THRESHOLD = 10; // px\r\n \r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: ChatAttachment): void {\r\n this.attachmentClick.emit(attachment);\r\n }\r\n \r\n /**\r\n * Handle touch start for long press detection\r\n */\r\n handleTouchStart(event: TouchEvent): void {\r\n if (!this.clickable()) return;\r\n \r\n this.longPressTriggered = false;\r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n \r\n // Start long press timer\r\n this.longPressTimer = setTimeout(() => {\r\n this.longPressTriggered = true;\r\n this.longPress.emit();\r\n }, this.LONG_PRESS_DURATION);\r\n }\r\n \r\n /**\r\n * Handle touch end to clear long press timer\r\n */\r\n handleTouchEnd(event: TouchEvent): void {\r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n \r\n // Prevent normal click if long press was triggered\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n \r\n /**\r\n * Handle touch move to cancel long press if moved too much\r\n */\r\n handleTouchMove(event: TouchEvent): void {\r\n if (!this.longPressTimer) return;\r\n \r\n const touch = event.touches[0];\r\n const deltaX = Math.abs(touch.clientX - this.touchStartX);\r\n const deltaY = Math.abs(touch.clientY - this.touchStartY);\r\n \r\n // Cancel long press if moved too far\r\n if (deltaX > this.MOVE_THRESHOLD || deltaY > this.MOVE_THRESHOLD) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n this.longPressTriggered = false;\r\n }\r\n }\r\n \r\n /**\r\n * Handle context menu (right-click on desktop) to trigger long press action\r\n */\r\n handleContextMenu(event: Event): void {\r\n if (!this.clickable()) return;\r\n event.preventDefault();\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileListItemStaticComponent\r\n * \r\n * A read-only version of the interactive list item component.\r\n * Used for displaying static information without interaction.\r\n * \r\n * This component has the same structure as the interactive list item but without:\r\n * - Padding\r\n * - Rounded corners\r\n * - Hover states\r\n * - Click interactions\r\n * - Background fill (transparent)\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-list-item-static\r\n * [leadingSize]=\"'40px'\">\r\n * \r\n * <div content-leading>\r\n * <ds-avatar initials=\"JD\" />\r\n * </div>\r\n * \r\n * <div content-main>\r\n * <h3>Main Content</h3>\r\n * <p>Supporting text goes here...</p>\r\n * </div>\r\n * \r\n * <div content-trailing>\r\n * <span>Info</span>\r\n * </div>\r\n * </ds-mobile-list-item-static>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-list-item-static',\r\n standalone: true,\r\n imports: [CommonModule],\r\n host: {\r\n '[style.--leading-size]': 'leadingSize()'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: row;\r\n align-items: flex-start;\r\n background: transparent;\r\n padding: 0;\r\n gap: 12px;\r\n position: relative;\r\n --leading-size: 32px;\r\n }\r\n \r\n :host::after {\r\n content: '';\r\n position: absolute;\r\n bottom: -10px;\r\n left: calc(var(--leading-size) + 12px);\r\n right: 0;\r\n height: 1px;\r\n background: var(--border-color-default);\r\n }\r\n \r\n :host:last-child::after {\r\n display: none;\r\n }\r\n \r\n .content-leading {\r\n flex-shrink: 0;\r\n width: var(--leading-size);\r\n min-height: var(--leading-size);\r\n height: auto;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .content-main {\r\n flex: 1;\r\n min-width: 0;\r\n min-height: var(--leading-size);\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: flex-start;\r\n gap: 8px;\r\n }\r\n \r\n .content-trailing {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: flex-start;\r\n }\r\n `],\r\n template: `\r\n @if (hasLeadingContent()) {\r\n <div class=\"content-leading\">\r\n <ng-content select=\"[content-leading]\" />\r\n </div>\r\n }\r\n \r\n <div class=\"content-main\">\r\n <ng-content select=\"[content-main]\" />\r\n <ng-content />\r\n </div>\r\n \r\n @if (hasTrailingContent()) {\r\n <div class=\"content-trailing\">\r\n <ng-content select=\"[content-trailing]\" />\r\n </div>\r\n }\r\n `\r\n})\r\nexport class DsMobileListItemStaticComponent {\r\n /**\r\n * CSS size value for the leading content area (e.g., '32px', '40px', '48px')\r\n * Defaults to '32px' for standard list item avatars\r\n */\r\n leadingSize = input<string>('32px');\r\n \r\n /**\r\n * Check if leading content slot has content\r\n */\r\n hasLeadingContent = computed(() => true); // Always render slot container for consistency\r\n \r\n /**\r\n * Check if trailing content slot has content\r\n */\r\n hasTrailingContent = computed(() => true); // Always render slot container for consistency\r\n}\r\n\r\n","import { Component, input, output, signal, model } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsMobileListItemComponent } from '../list-item';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge/ds-avatar-with-badge';\r\n\r\n/**\r\n * DsMobileInteractiveListItemPostComponent\r\n * \r\n * Specialized interactive list item for displaying social media posts.\r\n * Built on top of ds-mobile-interactive-list-item base component.\r\n * Displays user posts with avatar, content, media, and action buttons.\r\n * Follows Threads-inspired design with clean layout and interactions.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-interactive-list-item-post\r\n * [authorName]=\"'John Doe'\"\r\n * [authorRole]=\"'Tenant'\"\r\n * [timestamp]=\"'2h ago'\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [clickable]=\"true\"\r\n * (postClick)=\"openPost()\">\r\n * \r\n * <post-content>\r\n * <post-text>This is a sample post...</post-text>\r\n * </post-content>\r\n * \r\n * <post-actions>\r\n * <action-like [active]=\"true\" count=\"42\" />\r\n * <action-comment count=\"12\" />\r\n * </post-actions>\r\n * </ds-mobile-interactive-list-item-post>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-interactive-list-item-post',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarWithBadgeComponent, DsMobileListItemComponent],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n /* Hide divider on last child */\r\n :host:last-child {\r\n --divider-display: none;\r\n --item-padding-bottom: 0;\r\n }\r\n \r\n .post-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: 32px;\r\n margin-bottom: 8px;\r\n }\r\n \r\n .author-details {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 2px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .author-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .author-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-tertiary, #626B78);\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n \r\n .menu-slot {\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-list-item\r\n [leadingSize]=\"'32px'\"\r\n [variant]=\"variant()\"\r\n [interactive]=\"clickable()\"\r\n (itemClick)=\"handlePostClick()\"\r\n (longPress)=\"handleLongPress()\"\r\n (moreButtonClick)=\"handleMoreButtonClick($event)\">\r\n \r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [type]=\"avatarType()\"\r\n [initials]=\"avatarInitials()\"\r\n [src]=\"avatarSrc()\"\r\n [iconName]=\"avatarIconName()\"\r\n [size]=\"'md'\"\r\n [showBadge]=\"showBadge()\"\r\n [badgePosition]=\"'bottom-right'\"\r\n />\r\n </div>\r\n \r\n <div content-main>\r\n <div class=\"post-header\">\r\n <div class=\"author-details\">\r\n <div class=\"author-name\">{{ authorName() }}</div>\r\n <div class=\"author-meta\">{{ authorRole() }} · {{ timestamp() }}</div>\r\n </div>\r\n \r\n <div class=\"menu-slot\">\r\n <ng-content select=\"post-menu\" />\r\n </div>\r\n </div>\r\n \r\n <ng-content select=\"post-content\" />\r\n <ng-content select=\"post-actions\" />\r\n </div>\r\n </ds-mobile-list-item>\r\n `\r\n})\r\nexport class DsMobileInteractiveListItemPostComponent {\r\n /**\r\n * Author's display name\r\n */\r\n authorName = input.required<string>();\r\n \r\n /**\r\n * Author's role (e.g., \"Tenant\", \"Property Manager\")\r\n */\r\n authorRole = input.required<string>();\r\n \r\n /**\r\n * Timestamp text (e.g., \"2h ago\", \"1d ago\")\r\n */\r\n timestamp = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (for initials type)\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Icon name (for icon type avatars)\r\n */\r\n avatarIconName = input<string>('remixUser3Fill');\r\n \r\n /**\r\n * Show badge on avatar (e.g., for property managers)\r\n */\r\n showBadge = input<boolean>(false);\r\n \r\n /**\r\n * Display variant\r\n * - undefined (default) - Standard display\r\n * - 'compact' - Compact display for nested/related posts\r\n */\r\n variant = input<'compact' | undefined>(undefined);\r\n \r\n /**\r\n * Whether the post card is clickable\r\n */\r\n clickable = input<boolean>(false);\r\n \r\n /**\r\n * Emits when the post card is clicked (if clickable)\r\n */\r\n postClick = output<void>();\r\n \r\n /**\r\n * Emits when the comment button is clicked\r\n */\r\n commentClick = output<void>();\r\n \r\n /**\r\n * Emits when the post card is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n handlePostClick(): void {\r\n console.log('[InteractiveListItemPost] handlePostClick called, emitting postClick');\r\n this.postClick.emit();\r\n }\r\n \r\n handleCommentClick(): void {\r\n this.commentClick.emit();\r\n }\r\n \r\n handleLongPress(): void {\r\n this.longPress.emit();\r\n }\r\n \r\n handleMoreButtonClick(event: Event): void {\r\n // Desktop more button click - trigger the same action as long press\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n/**\r\n * PostContentComponent\r\n * \r\n * Main content section of the post.\r\n * \r\n * Contains:\r\n * - `<post-text>` - Text content\r\n * - `<post-media>` - Optional images/videos\r\n * - `<post-attachments>` - Optional file attachments\r\n */\r\n@Component({\r\n selector: 'post-content',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n margin-bottom: 8px;\r\n }\r\n `],\r\n template: `\r\n <ng-content select=\"post-text\" />\r\n <ng-content select=\"post-media\" />\r\n <ng-content select=\"ds-mobile-inline-photo\" />\r\n <ng-content select=\"post-attachments\" />\r\n `\r\n})\r\nexport class PostContentComponent {}\r\n\r\n/**\r\n * PostTextComponent\r\n * \r\n * Text content of the post.\r\n */\r\n@Component({\r\n selector: 'post-text',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n display: block;\r\n white-space: pre-wrap;\r\n word-wrap: break-word;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostTextComponent {}\r\n\r\n/**\r\n * PostMediaComponent\r\n * \r\n * Media container for images/videos.\r\n */\r\n@Component({\r\n selector: 'post-media',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: block;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n }\r\n \r\n ::ng-deep img {\r\n width: 100%;\r\n height: auto;\r\n display: block;\r\n }\r\n \r\n ::ng-deep video {\r\n width: 100%;\r\n height: auto;\r\n display: block;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostMediaComponent {}\r\n\r\n/**\r\n * PostAttachmentsComponent\r\n * \r\n * Container for file attachments, links, etc.\r\n */\r\n@Component({\r\n selector: 'post-attachments',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostAttachmentsComponent {}\r\n\r\n/**\r\n * PostActionsComponent\r\n * \r\n * Action buttons container (like, comment, share).\r\n * \r\n * Contains:\r\n * - `<action-like>` - Like button with count\r\n * - `<action-comment>` - Comment button with count\r\n * - `<action-share>` - Share button\r\n */\r\n@Component({\r\n selector: 'post-actions',\r\n standalone: true,\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n padding-top: 4px;\r\n }\r\n `],\r\n template: `<ng-content />`\r\n})\r\nexport class PostActionsComponent {}\r\n\r\n/**\r\n * ActionLikeComponent\r\n * \r\n * Like action button with count display and animated heart icon.\r\n */\r\n@Component({\r\n selector: 'action-like',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n host: {\r\n '[class.active]': 'active()',\r\n '(click)': 'handleClick($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n \r\n :host.active {\r\n color: #f91880;\r\n }\r\n \r\n .icon-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .icon-pulse {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n opacity: 0;\r\n pointer-events: none;\r\n }\r\n \r\n .icon-pulse.animating {\r\n animation: pulse 0.4s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n \r\n @keyframes pulse {\r\n 0% {\r\n transform: translate(-50%, -50%) scale(1);\r\n opacity: 0.8;\r\n }\r\n 100% {\r\n transform: translate(-50%, -50%) scale(2.5);\r\n opacity: 0;\r\n }\r\n }\r\n \r\n .count {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 20px;\r\n letter-spacing: -0.28px;\r\n }\r\n `],\r\n template: `\r\n <div class=\"icon-wrapper\">\r\n <ds-icon \r\n #pulseIcon\r\n class=\"icon-pulse\"\r\n [class.animating]=\"isPulsing()\"\r\n [name]=\"active() ? 'remixHeart3Fill' : 'remixHeart3Line'\" \r\n size=\"20px\" />\r\n <ds-icon \r\n [name]=\"active() ? 'remixHeart3Fill' : 'remixHeart3Line'\" \r\n size=\"20px\" />\r\n </div>\r\n @if (count() > 0) {\r\n <span class=\"count\">{{ count() }}</span>\r\n }\r\n `\r\n})\r\nexport class ActionLikeComponent {\r\n /**\r\n * Whether the like is active (user has liked)\r\n * Using model() for two-way binding\r\n */\r\n active = model<boolean>(false);\r\n \r\n /**\r\n * Number of likes\r\n * Using model() for two-way binding\r\n */\r\n count = model<number>(0);\r\n \r\n /**\r\n * Emits when the like button is clicked\r\n */\r\n likeClick = output<{ active: boolean; count: number }>();\r\n \r\n /**\r\n * Signal to control pulse animation\r\n */\r\n isPulsing = signal(false);\r\n \r\n async handleClick(event: Event): Promise<void> {\r\n event.stopPropagation();\r\n \r\n // Toggle active state\r\n const newActive = !this.active();\r\n this.active.set(newActive);\r\n \r\n // Update count\r\n const newCount = newActive ? this.count() + 1 : this.count() - 1;\r\n this.count.set(Math.max(0, newCount));\r\n \r\n // Trigger pulse animation only when liking\r\n if (newActive) {\r\n this.isPulsing.set(true);\r\n setTimeout(() => this.isPulsing.set(false), 400);\r\n }\r\n \r\n // Haptic feedback for like/unlike\r\n try {\r\n await Haptics.impact({ style: ImpactStyle.Light });\r\n } catch {\r\n // Fallback to Web Vibration API if Capacitor Haptics is not available\r\n if ('vibrate' in navigator) {\r\n navigator.vibrate(50);\r\n }\r\n }\r\n \r\n // Emit the event with the new state\r\n this.likeClick.emit({ active: newActive, count: newCount });\r\n }\r\n}\r\n\r\n/**\r\n * ActionCommentComponent\r\n * \r\n * Comment action button with count display.\r\n */\r\n@Component({\r\n selector: 'action-comment',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n host: {\r\n '(click)': 'handleClick($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n color: var(--color-text-secondary, #737373);\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n \r\n :host:active {\r\n transform: scale(0.95);\r\n }\r\n \r\n :host:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .count {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 20px;\r\n letter-spacing: -0.28px;\r\n }\r\n `],\r\n template: `\r\n <ds-icon name=\"remixChat3Line\" size=\"20px\" />\r\n @if (count() > 0) {\r\n <span class=\"count\">{{ count() }}</span>\r\n }\r\n `\r\n})\r\nexport class ActionCommentComponent {\r\n /**\r\n * Number of comments\r\n */\r\n count = input<number>(0);\r\n \r\n /**\r\n * Emits when the comment button is clicked\r\n */\r\n commentClick = output<void>();\r\n \r\n handleClick(event: Event): void {\r\n event.stopPropagation();\r\n this.commentClick.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * PostPdfAttachmentComponent\r\n * \r\n * PDF file attachment display for posts.\r\n * Shows PDF info card with icon, filename, and file size.\r\n * Emits click event to open PDF in viewer.\r\n */\r\n@Component({\r\n selector: 'post-pdf-attachment',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent],\r\n host: {\r\n '(click)': 'handleClick($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 10px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n }\r\n \r\n :host:hover {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n :host:active {\r\n transform: scale(0.98);\r\n }\r\n \r\n .pdf-avatar {\r\n flex-shrink: 0;\r\n }\r\n \r\n .pdf-avatar::ng-deep .avatar--icon {\r\n background-color: #ff5757 !important;\r\n }\r\n \r\n .pdf-info {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n \r\n .pdf-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .pdf-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n }\r\n \r\n .open-icon {\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"pdf-avatar\">\r\n <ds-avatar\r\n type=\"icon\"\r\n iconName=\"remixFileTextLine\"\r\n size=\"md\"\r\n />\r\n </div>\r\n \r\n <div class=\"pdf-info\">\r\n <div class=\"pdf-name\">{{ fileName() }}</div>\r\n <div class=\"pdf-meta\">PDF · {{ fileSize() }}</div>\r\n </div>\r\n \r\n <ds-icon \r\n name=\"remixArrowRightSLine\" \r\n size=\"24px\"\r\n class=\"open-icon\"\r\n />\r\n `\r\n})\r\nexport class PostPdfAttachmentComponent {\r\n /**\r\n * PDF file name\r\n */\r\n fileName = input<string>('Document.pdf');\r\n \r\n /**\r\n * File size display (e.g., \"1.2 MB\")\r\n */\r\n fileSize = input<string>('');\r\n \r\n /**\r\n * Emits when the PDF attachment is clicked\r\n */\r\n pdfClick = output<void>();\r\n \r\n handleClick(event: Event): void {\r\n event.stopPropagation();\r\n this.pdfClick.emit();\r\n }\r\n}\r\n\r\n","// Export the main component and shared post components without the indent\r\nexport {\r\n DsMobileInteractiveListItemPostComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent\r\n} from './ds-mobile-interactive-list-item-post';\r\nexport { PostPdfAttachmentComponent } from './ds-mobile-post-pdf-attachment';\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsShapeIndicatorComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsMobileListItemComponent } from '../list-item';\r\n\r\n/**\r\n * DsMobileInteractiveListItemInquiryComponent\r\n * \r\n * Specialized interactive list item for displaying inquiries/tickets.\r\n * Built on top of ds-mobile-interactive-list-item base component.\r\n * Displays inquiry title, description, status, and timestamp.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-interactive-list-item-inquiry\r\n * [title]=\"'Tumble dryer is not working'\"\r\n * [description]=\"'For the past three days, I have been experiencing...'\"\r\n * [status]=\"'open'\"\r\n * [timestamp]=\"'12 days ago'\"\r\n * [iconName]=\"'remixCalendarLine'\"\r\n * [clickable]=\"true\"\r\n * (inquiryClick)=\"openInquiry()\">\r\n * </ds-mobile-interactive-list-item-inquiry>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-interactive-list-item-inquiry',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsShapeIndicatorComponent, DsAvatarComponent, DsMobileListItemComponent],\r\n styleUrls: ['./ds-mobile-interactive-list-item-inquiry.css'],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n /* Hide divider on last child */\r\n :host:last-child {\r\n --divider-display: none;\r\n --item-padding-bottom: 0;\r\n }\r\n \r\n .inquiry-avatar {\r\n flex-shrink: 0;\r\n }\r\n \r\n /* Default/Open inquiries: brand-primary surface with brand-primary content */\r\n .inquiry-avatar:not(.closed)::ng-deep .avatar--icon {\r\n background-color: var(--color-primary-surface, #5d5fef) !important;\r\n }\r\n \r\n .inquiry-avatar:not(.closed)::ng-deep .avatar--icon ds-icon,\r\n .inquiry-avatar:not(.closed)::ng-deep .avatar--icon ds-icon::ng-deep svg {\r\n color: var(--color-primary-content, #ffffff) !important;\r\n fill: var(--color-primary-content, #ffffff) !important;\r\n }\r\n \r\n /* Closed inquiries: content tertiary surface with white icon */\r\n .inquiry-avatar.closed::ng-deep .avatar--icon {\r\n background-color: var(--text-color-default-tertiary, #737373) !important;\r\n }\r\n \r\n .inquiry-avatar.closed::ng-deep .avatar--icon ds-icon,\r\n .inquiry-avatar.closed::ng-deep .avatar--icon ds-icon::ng-deep svg {\r\n color: #ffffff !important;\r\n fill: #ffffff !important;\r\n }\r\n \r\n .inquiry-content {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .inquiry-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .inquiry-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n margin: 0;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n }\r\n \r\n .inquiry-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-top: 4px;\r\n }\r\n \r\n .inquiry-status {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 500;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n }\r\n \r\n .inquiry-status.open {\r\n color: var(--text-color-default-tertiary, #737373);\r\n }\r\n \r\n .inquiry-status.closed {\r\n color: var(--text-color-default-tertiary, #737373);\r\n }\r\n \r\n .inquiry-timestamp {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n }\r\n \r\n .inquiry-trailing {\r\n display: flex;\r\n align-items: center;\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-list-item\r\n [leadingSize]=\"'32px'\"\r\n [variant]=\"variant()\"\r\n [interactive]=\"clickable()\"\r\n (itemClick)=\"handleInquiryClick()\"\r\n (longPress)=\"handleLongPress()\"\r\n (moreButtonClick)=\"handleMoreButtonClick($event)\">\r\n \r\n <div content-leading>\r\n <div class=\"inquiry-avatar\" [class.closed]=\"status() === 'closed'\">\r\n <ds-avatar\r\n type=\"icon\"\r\n [iconName]=\"iconName()\"\r\n size=\"md\"\r\n />\r\n </div>\r\n </div>\r\n \r\n <div content-main>\r\n <div class=\"inquiry-content\">\r\n <h3 class=\"inquiry-title\">{{ title() }}</h3>\r\n \r\n @if (description()) {\r\n <p class=\"inquiry-description\">{{ description() }}</p>\r\n }\r\n \r\n <div class=\"inquiry-meta\">\r\n <div class=\"inquiry-status\" [class.open]=\"status() === 'open'\" [class.closed]=\"status() === 'closed'\">\r\n <ds-shape-indicator \r\n shape=\"circle\" \r\n [variant]=\"status() === 'open' ? 'brand' : 'grey'\">\r\n </ds-shape-indicator>\r\n <span>{{ computedStatusLabel() }}</span>\r\n </div>\r\n \r\n <div class=\"inquiry-timestamp\">\r\n <ds-icon name=\"remixTimeLine\" size=\"14px\" color=\"--color-text-secondary\" />\r\n <span>{{ timestamp() }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n @if (showChevron()) {\r\n <div content-trailing>\r\n <div class=\"inquiry-trailing\">\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n </div>\r\n }\r\n </ds-mobile-list-item>\r\n `\r\n})\r\nexport class DsMobileInteractiveListItemInquiryComponent {\r\n /**\r\n * Inquiry title\r\n */\r\n title = input.required<string>();\r\n \r\n /**\r\n * Inquiry description/preview text\r\n */\r\n description = input<string>('');\r\n \r\n /**\r\n * Inquiry status\r\n */\r\n status = input<'open' | 'closed'>('open');\r\n \r\n /**\r\n * Status label (defaults to capitalized status)\r\n */\r\n statusLabel = input<string>('');\r\n \r\n /**\r\n * Timestamp text (e.g., \"12 days ago\", \"2 months ago\")\r\n */\r\n timestamp = input.required<string>();\r\n \r\n /**\r\n * Icon name for the leading icon\r\n */\r\n iconName = input<string>('remixTodoLine');\r\n \r\n /**\r\n * Icon color\r\n */\r\n iconColor = input<string>('secondary');\r\n \r\n /**\r\n * Display variant\r\n * - undefined (default) - Standard display\r\n * - 'compact' - Compact display\r\n */\r\n variant = input<'compact' | undefined>(undefined);\r\n \r\n /**\r\n * Whether the inquiry item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Whether to show chevron icon\r\n */\r\n showChevron = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the inquiry item is clicked (if clickable)\r\n */\r\n inquiryClick = output<void>();\r\n \r\n /**\r\n * Emits when the inquiry item is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n /**\r\n * Get computed status label\r\n */\r\n computedStatusLabel(): string {\r\n if (this.statusLabel()) {\r\n return this.statusLabel();\r\n }\r\n return this.status() === 'open' ? 'Åben' : 'Lukket';\r\n }\r\n \r\n handleInquiryClick(): void {\r\n this.inquiryClick.emit();\r\n }\r\n \r\n handleLongPress(): void {\r\n this.longPress.emit();\r\n }\r\n \r\n handleMoreButtonClick(event: Event): void {\r\n // Desktop more button click - trigger the same action as long press\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsMobileListItemComponent } from '../list-item';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge';\r\n\r\n/**\r\n * DsMobileInteractiveListItemMessageComponent\r\n * \r\n * Specialized interactive list item for displaying message threads.\r\n * Built on top of ds-mobile-interactive-list-item base component.\r\n * Displays message preview with sender info - simplified version without actions.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-interactive-list-item-message\r\n * [senderName]=\"'John Doe'\"\r\n * [senderRole]=\"'Tenant'\"\r\n * [timestamp]=\"'2h ago'\"\r\n * [message]=\"'Hey, when is the maintenance scheduled?'\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [unread]=\"true\"\r\n * [clickable]=\"true\"\r\n * (messageClick)=\"openThread()\">\r\n * </ds-mobile-interactive-list-item-message>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-interactive-list-item-message',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarWithBadgeComponent, DsMobileListItemComponent],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n /* Hide divider on last child */\r\n :host:last-child {\r\n --divider-display: none;\r\n --item-padding-bottom: 0;\r\n }\r\n \r\n .message-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: 32px;\r\n margin-bottom: 8px;\r\n }\r\n \r\n .sender-details {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 2px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .sender-name-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n flex-shrink: 0;\r\n }\r\n \r\n .sender-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-primary, #202227);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n flex-shrink: 0;\r\n }\r\n \r\n .sender-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--text-color-default-tertiary, #737373);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n flex-shrink: 1;\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n \r\n .meta-separator {\r\n color: var(--text-color-default-tertiary, #737373);\r\n opacity: 0.5;\r\n }\r\n \r\n .unread-indicator {\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n background: var(--color-brand-primary, #5d5fef);\r\n flex-shrink: 0;\r\n }\r\n \r\n .message-preview {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--text-color-default-secondary, #545B66);\r\n margin: 0;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-list-item\r\n [leadingSize]=\"'32px'\"\r\n [interactive]=\"clickable()\"\r\n [enableLongPress]=\"false\"\r\n [showDesktopMoreButton]=\"false\"\r\n (itemClick)=\"handleMessageClick()\">\r\n \r\n <div content-leading>\r\n <ds-avatar-with-badge \r\n [initials]=\"avatarInitials()\"\r\n [type]=\"avatarType()\"\r\n [src]=\"avatarSrc()\"\r\n size=\"md\" />\r\n </div>\r\n \r\n <div content-main>\r\n <div class=\"message-header\">\r\n <div class=\"sender-details\">\r\n <div class=\"sender-name-row\">\r\n <span class=\"sender-name\">{{ senderName() }}</span>\r\n @if (unread()) {\r\n <div class=\"unread-indicator\"></div>\r\n }\r\n </div>\r\n <span class=\"sender-meta\">\r\n {{ senderRole() }}\r\n @if (timestamp()) {\r\n <span class=\"meta-separator\">·</span>\r\n <span>{{ timestamp() }}</span>\r\n }\r\n </span>\r\n </div>\r\n </div>\r\n \r\n <p class=\"message-preview\">{{ message() }}</p>\r\n </div>\r\n </ds-mobile-list-item>\r\n `\r\n})\r\nexport class DsMobileInteractiveListItemMessageComponent {\r\n /**\r\n * Sender's display name\r\n */\r\n senderName = input.required<string>();\r\n \r\n /**\r\n * Sender's role (e.g., \"Tenant\", \"Property Manager\")\r\n */\r\n senderRole = input.required<string>();\r\n \r\n /**\r\n * Timestamp for the message (e.g., \"2h ago\", \"2t siden\")\r\n */\r\n timestamp = input<string>('');\r\n \r\n /**\r\n * Message preview text\r\n */\r\n message = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (for initials type)\r\n */\r\n avatarInitials = input<string>('');\r\n \r\n /**\r\n * Avatar type\r\n */\r\n avatarType = input<'initials' | 'photo' | 'icon'>('initials');\r\n \r\n /**\r\n * Avatar photo source (for photo type)\r\n */\r\n avatarSrc = input<string>('');\r\n \r\n /**\r\n * Whether the message is unread\r\n */\r\n unread = input<boolean>(false);\r\n \r\n /**\r\n * Whether the message item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the message item is clicked\r\n */\r\n messageClick = output<void>();\r\n \r\n /**\r\n * Emits when the message item is long-pressed\r\n */\r\n longPress = output<void>();\r\n \r\n handleMessageClick(): void {\r\n this.messageClick.emit();\r\n }\r\n \r\n handleLongPress(): void {\r\n this.longPress.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileContactListItemComponent\r\n * \r\n * Specialized interactive component for displaying contacts.\r\n * Displays contact name with avatar initials and metadata (person name + phone number).\r\n * Similar styling to file attachments with rounded corners and hover states.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-contact-list-item\r\n * [name]=\"'Mortensen & Søn ApS'\"\r\n * [initials]=\"'M'\"\r\n * [contactPerson]=\"'John Mortensen'\"\r\n * [phoneNumber]=\"'+45 12 34 56 78'\"\r\n * [clickable]=\"true\"\r\n * (contactClick)=\"openContact()\">\r\n * </ds-mobile-contact-list-item>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-contact-list-item',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsAvatarComponent],\r\n host: {\r\n '[class.clickable]': 'clickable()',\r\n '(click)': 'handleContactClick()'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 10px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n transition: all 0.2s ease;\r\n }\r\n \r\n :host.clickable {\r\n cursor: pointer;\r\n }\r\n \r\n :host.clickable:hover {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n :host.clickable:active {\r\n transform: scale(0.98);\r\n }\r\n \r\n .contact-avatar {\r\n flex-shrink: 0;\r\n }\r\n\r\n .contact-content {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 2px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .contact-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n \r\n .contact-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n margin: 0;\r\n }\r\n \r\n .meta-separator {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n \r\n .contact-trailing {\r\n display: flex;\r\n align-items: center;\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"contact-avatar\">\r\n <ds-avatar\r\n [initials]=\"initials()\"\r\n type=\"initials\"\r\n size=\"md\"\r\n />\r\n </div>\r\n \r\n <div class=\"contact-content\">\r\n <div class=\"contact-name\">{{ name() }}</div>\r\n \r\n @if (contactPerson() || phoneNumber()) {\r\n <div class=\"contact-meta\">\r\n @if (contactPerson()) {\r\n <span>{{ contactPerson() }}</span>\r\n }\r\n @if (contactPerson() && phoneNumber()) {\r\n <span class=\"meta-separator\">·</span>\r\n }\r\n @if (phoneNumber()) {\r\n <span>{{ phoneNumber() }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n \r\n @if (showChevron()) {\r\n <div class=\"contact-trailing\">\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n }\r\n `\r\n})\r\nexport class DsMobileContactListItemComponent {\r\n /**\r\n * Contact/company name\r\n */\r\n name = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (usually 1-2 letters)\r\n */\r\n initials = input.required<string>();\r\n \r\n /**\r\n * Contact person name (optional)\r\n */\r\n contactPerson = input<string>('');\r\n \r\n /**\r\n * Phone number (optional)\r\n */\r\n phoneNumber = input<string>('');\r\n \r\n /**\r\n * Whether the contact item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Whether to show chevron icon\r\n */\r\n showChevron = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the contact item is clicked (if clickable)\r\n */\r\n contactClick = output<void>();\r\n \r\n handleContactClick(): void {\r\n if (this.clickable()) {\r\n this.contactClick.emit();\r\n }\r\n }\r\n}\r\n\r\n","import { Component, Input, Output, EventEmitter, signal, OnInit, AfterViewInit, OnDestroy, ElementRef, computed, inject, effect } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { Router, NavigationEnd } from '@angular/router';\r\nimport { filter } from 'rxjs/operators';\r\nimport { \r\n IonTabBar, \r\n IonTabButton, \r\n IonLabel,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsLogoComponent } from '../logo/ds-logo';\r\nimport { DsMobileActionsBottomSheetComponent, ActionResult, ActionGroup } from '../bottom-sheet';\r\nimport { UserService } from '../../services/user.service';\r\n\r\nexport interface TabConfig {\r\n id: string;\r\n label: string;\r\n route: string;\r\n icon: string;\r\n iconActive: string;\r\n}\r\n\r\n/**\r\n * DsMobileTabBarComponent\r\n * \r\n * Responsive navigation tab bar that adapts from mobile to desktop:\r\n * - Mobile (< 768px): Bottom tab bar with icons + labels\r\n * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar\r\n * \r\n * Use this component INSIDE your own `ion-tabs` when Angular routing\r\n * requires `ion-tabs` to be a direct child in your component.\r\n * \r\n * @example\r\n * ```html\r\n * <!-- In your component with child routes -->\r\n * <!-- IMPORTANT: Add class=\"ds-tabs-wrapper\" to ion-tabs for proper styling -->\r\n * <ion-tabs class=\"ds-tabs-wrapper\">\r\n * <ds-mobile-tab-bar\r\n * [tabs]=\"tabs\"\r\n * [avatarInitials]=\"'JD'\"\r\n * [profileMenuItems]=\"profileMenuItems\"\r\n * (profileActionSelected)=\"handleProfileAction($event)\"\r\n * />\r\n * </ion-tabs>\r\n * ```\r\n * \r\n * @example With profile menu configuration\r\n * ```typescript\r\n * profileMenuItems: ActionGroup[] = [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'My Profile', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Settings', icon: 'remixSettings3Line' }\r\n * ]\r\n * },\r\n * {\r\n * actions: [\r\n * { action: 'logout', title: 'Log Out', icon: 'remixLogoutBoxLine', destructive: true }\r\n * ]\r\n * }\r\n * ];\r\n * \r\n * handleProfileAction(result: ActionResult): void {\r\n * switch (result.action) {\r\n * case 'profile': // Navigate to profile\r\n * case 'settings': // Navigate to settings\r\n * case 'logout': // Handle logout\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @note When using this component, you must add the class \"ds-tabs-wrapper\" \r\n * to your `ion-tabs` element, or manually apply these styles:\r\n * ```css\r\n * ion-tabs {\r\n * height: 100%;\r\n * background: var(--color-brand-secondary);\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-tab-bar',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonTabBar,\r\n IonTabButton,\r\n IonLabel,\r\n DsIconComponent,\r\n DsAvatarComponent,\r\n DsLogoComponent\r\n ],\r\n styleUrls: ['./ds-mobile-tab-bar.css'],\r\n template: `\r\n <ion-tab-bar \r\n [attr.slot]=\"isDesktop() ? 'top' : 'bottom'\" \r\n class=\"ds-tab-bar\"\r\n [class.ds-tab-bar--desktop]=\"isDesktop()\">\r\n \r\n <!-- Logo (desktop only, positioned via CSS) -->\r\n <div class=\"ds-tab-bar__logo\">\r\n <ds-logo variant=\"mark\" size=\"lg\" />\r\n </div>\r\n \r\n <!-- Tab buttons container -->\r\n <div class=\"ds-tab-bar__tabs\" *ngIf=\"tabs\">\r\n <ion-tab-button \r\n *ngFor=\"let tab of tabs; trackBy: trackByTabId\"\r\n [tab]=\"tab.route\"\r\n [attr.data-icon]=\"tab.icon\"\r\n [attr.data-icon-active]=\"tab.iconActive\"\r\n [attr.aria-label]=\"tab.label\"\r\n class=\"ds-tab-button ion-activatable\"\r\n [class.tab-selected]=\"isTabActive(tab.route)\">\r\n <div class=\"tab-icon-ripple\"></div>\r\n <div class=\"tab-icon-wrapper\">\r\n <ds-icon \r\n [name]=\"tab.icon\"\r\n [size]=\"isDesktop() ? '20px' : '24px'\"\r\n class=\"tab-icon-inactive\"\r\n />\r\n <ds-icon \r\n [name]=\"tab.iconActive\"\r\n [size]=\"isDesktop() ? '20px' : '24px'\"\r\n class=\"tab-icon-active\"\r\n />\r\n </div>\r\n <ion-label [attr.aria-hidden]=\"true\">{{ tab.label }}</ion-label>\r\n </ion-tab-button>\r\n </div>\r\n \r\n <!-- Avatar (desktop only, positioned via CSS) -->\r\n <div class=\"ds-tab-bar__actions\">\r\n <ds-avatar\r\n [size]=\"'md'\"\r\n [type]=\"avatarType\"\r\n [initials]=\"avatarInitials\"\r\n [src]=\"avatarSrc\"\r\n [iconName]=\"avatarIconName\"\r\n (click)=\"handleAvatarClick()\"\r\n />\r\n </div>\r\n </ion-tab-bar>\r\n `\r\n})\r\nexport class DsMobileTabBarComponent implements OnInit, AfterViewInit, OnDestroy {\r\n // Inputs\r\n @Input() tabs: TabConfig[] = [];\r\n \r\n // Avatar inputs\r\n @Input() avatarType: 'initials' | 'photo' | 'icon' = 'initials';\r\n @Input() avatarInitials: string = 'U';\r\n @Input() avatarSrc: string = '';\r\n @Input() avatarIconName: string = 'remixUser3Line';\r\n \r\n /**\r\n * Profile menu action groups to display when avatar is clicked.\r\n * If not provided, only the avatarClick event will be emitted.\r\n * \r\n * @example\r\n * ```typescript\r\n * profileMenuItems: ActionGroup[] = [\r\n * {\r\n * actions: [\r\n * { action: 'profile', title: 'My Profile', icon: 'remixUser3Line' },\r\n * { action: 'settings', title: 'Settings', icon: 'remixSettings3Line' }\r\n * ]\r\n * }\r\n * ];\r\n * ```\r\n */\r\n @Input() profileMenuItems?: ActionGroup[];\r\n \r\n // Outputs\r\n @Output() avatarClick = new EventEmitter<void>();\r\n \r\n /**\r\n * Emitted when a profile menu action is selected.\r\n * Parent component should handle the action logic (navigation, logout, etc.).\r\n */\r\n @Output() profileActionSelected = new EventEmitter<ActionResult>();\r\n \r\n // Internal state - exposed for template binding\r\n activeTab = signal<string>('');\r\n isDesktop = signal<boolean>(false);\r\n \r\n private mutationObserver?: MutationObserver;\r\n private slotEnforcementObserver?: MutationObserver;\r\n private resizeObserver?: ResizeObserver;\r\n private mediaQuery?: MediaQueryList;\r\n private routerSubscription?: any;\r\n \r\n private router?: Router | null;\r\n private modalController = inject(ModalController);\r\n private userService = inject(UserService);\r\n \r\n constructor(\r\n private elementRef: ElementRef\r\n ) {\r\n // Inject Router optionally\r\n this.router = inject(Router, { optional: true }) || undefined;\r\n \r\n // Initialize breakpoint detection EARLY (before effect)\r\n // This ensures isDesktop() is set before the effect runs\r\n this.setupBreakpointDetection();\r\n \r\n // Debug: Log initial state\r\n setTimeout(() => {\r\n console.log('[ds-mobile-tab-bar] Initial state:', {\r\n isDesktop: this.isDesktop(),\r\n windowWidth: window.innerWidth,\r\n mediaQuery: this.mediaQuery?.matches,\r\n userAgent: navigator.userAgent\r\n });\r\n }, 100);\r\n \r\n // Watch for isDesktop changes and update slot reactively\r\n // effect() must be called in constructor (injection context)\r\n effect(() => {\r\n // This effect runs whenever isDesktop() changes\r\n const _ = this.isDesktop(); // Read the signal to create dependency\r\n console.log('[ds-mobile-tab-bar] effect() triggered, isDesktop:', this.isDesktop());\r\n if (this.elementRef.nativeElement) {\r\n // Use setTimeout to ensure DOM is ready\r\n setTimeout(() => this.updateSlot(), 0);\r\n }\r\n });\r\n }\r\n \r\n ngOnInit(): void {\r\n \r\n // Listen to router events to detect active tab from URL\r\n if (this.router) {\r\n this.routerSubscription = this.router.events\r\n .pipe(filter(event => event instanceof NavigationEnd))\r\n .subscribe((event: any) => {\r\n const url = event.urlAfterRedirects || event.url;\r\n // Extract the route segment (e.g., /tab-bar-test/home -> home)\r\n const segments = url.split('/').filter((s: string) => s);\r\n const lastSegment = segments[segments.length - 1];\r\n \r\n // Find matching tab by route\r\n if (this.tabs && lastSegment) {\r\n const matchingTab = this.tabs.find(tab => tab.route === lastSegment);\r\n if (matchingTab) {\r\n this.activeTab.set(matchingTab.route);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Initial removal\r\n this.removeTitleAttributes();\r\n \r\n // Set up mutation observer to continuously remove title attributes\r\n this.setupTitleRemovalObserver();\r\n \r\n // Set up active tab detection\r\n this.setupActiveTabDetection();\r\n \r\n // Ensure slot is set correctly on initial render (with retries)\r\n this.updateSlot();\r\n \r\n // Set up slot enforcement to prevent Ionic from overriding\r\n setTimeout(() => {\r\n this.setupSlotEnforcement();\r\n // Also retry updateSlot a few times to ensure it sticks\r\n setTimeout(() => this.updateSlot(), 100);\r\n setTimeout(() => this.updateSlot(), 300);\r\n }, 0);\r\n }\r\n \r\n private updateSlot(): void {\r\n // CRITICAL: Set slot on the HOST element (ds-mobile-tab-bar) first\r\n // Ionic positions children based on the wrapper's slot, not the inner element's slot\r\n const hostElement = this.elementRef.nativeElement;\r\n const hostSlotValue = this.isDesktop() ? 'top' : 'bottom';\r\n const currentHostSlot = hostElement.getAttribute('slot');\r\n \r\n if (currentHostSlot !== hostSlotValue) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Setting HOST slot from', currentHostSlot, 'to', hostSlotValue);\r\n hostElement.setAttribute('slot', hostSlotValue);\r\n (hostElement as any).slot = hostSlotValue;\r\n }\r\n \r\n // Get the ion-tab-bar element\r\n const tabBar = this.elementRef.nativeElement.querySelector('ion-tab-bar');\r\n if (!tabBar) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: tabBar not found, retrying...');\r\n // Retry if element not found yet\r\n setTimeout(() => this.updateSlot(), 50);\r\n return;\r\n }\r\n \r\n const slotValue = this.isDesktop() ? 'top' : 'bottom';\r\n const currentSlot = tabBar.getAttribute('slot');\r\n const currentSlotProperty = (tabBar as any).slot;\r\n \r\n // Debug logging\r\n console.log('[ds-mobile-tab-bar] updateSlot:', {\r\n isDesktop: this.isDesktop(),\r\n windowWidth: window.innerWidth,\r\n slotValue,\r\n currentSlotAttribute: currentSlot,\r\n currentSlotProperty: currentSlotProperty,\r\n tabBarElement: tabBar,\r\n tabBarParent: tabBar.parentElement?.tagName,\r\n tabBarInIonTabs: tabBar.closest('ion-tabs') !== null\r\n });\r\n \r\n // Only update if different to avoid unnecessary DOM manipulation\r\n if (currentSlot !== slotValue || currentSlotProperty !== slotValue) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Setting slot from', currentSlot, 'to', slotValue);\r\n \r\n // Set both attribute and property to ensure it works\r\n tabBar.setAttribute('slot', slotValue);\r\n (tabBar as any).slot = slotValue;\r\n \r\n // Also try setting it on the parent ion-tabs\r\n const parentIonTabs = tabBar.closest('ion-tabs');\r\n if (parentIonTabs) {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Found parent ion-tabs');\r\n // Force Ionic to recognize the slot change\r\n (parentIonTabs as any).forceUpdate?.();\r\n }\r\n \r\n // Force a reflow to ensure Ionic processes the change\r\n void tabBar.offsetHeight;\r\n \r\n // Verify it was set\r\n const verifySlot = tabBar.getAttribute('slot');\r\n const verifySlotProperty = (tabBar as any).slot;\r\n console.log('[ds-mobile-tab-bar] updateSlot: After update, slot attribute:', verifySlot, 'slot property:', verifySlotProperty);\r\n \r\n // Check computed styles\r\n const computedStyle = window.getComputedStyle(tabBar);\r\n const parentComputedStyle = tabBar.parentElement ? window.getComputedStyle(tabBar.parentElement) : null;\r\n const ionTabsForStyles = tabBar.closest('ion-tabs');\r\n const ionTabsComputedStyle = ionTabsForStyles ? window.getComputedStyle(ionTabsForStyles) : null;\r\n \r\n console.log('[ds-mobile-tab-bar] updateSlot: Computed styles:', {\r\n tabBar: {\r\n position: computedStyle.position,\r\n top: computedStyle.top,\r\n bottom: computedStyle.bottom,\r\n order: computedStyle.order,\r\n display: computedStyle.display,\r\n zIndex: computedStyle.zIndex,\r\n transform: computedStyle.transform\r\n },\r\n parent: parentComputedStyle ? {\r\n display: parentComputedStyle.display,\r\n flexDirection: parentComputedStyle.flexDirection,\r\n gridTemplateRows: parentComputedStyle.gridTemplateRows\r\n } : null,\r\n ionTabs: ionTabsComputedStyle ? {\r\n display: ionTabsComputedStyle.display,\r\n flexDirection: ionTabsComputedStyle.flexDirection,\r\n gridTemplateRows: ionTabsComputedStyle.gridTemplateRows,\r\n position: ionTabsComputedStyle.position\r\n } : null,\r\n tabBarRect: tabBar.getBoundingClientRect(),\r\n windowHeight: window.innerHeight\r\n });\r\n } else {\r\n console.log('[ds-mobile-tab-bar] updateSlot: Slot already correct, no update needed');\r\n \r\n // Even if slot is correct, check computed styles to see why it's not at top\r\n const computedStyle = window.getComputedStyle(tabBar);\r\n const ionTabsForStyles = tabBar.closest('ion-tabs');\r\n const ionTabsComputedStyle = ionTabsForStyles ? window.getComputedStyle(ionTabsForStyles) : null;\r\n const tabBarRect = tabBar.getBoundingClientRect();\r\n \r\n // Log key values directly so they're always visible\r\n console.log('[ds-mobile-tab-bar] KEY VALUES:');\r\n console.log(' tabBar.position:', computedStyle.position);\r\n console.log(' tabBar.top:', computedStyle.top);\r\n console.log(' tabBar.bottom:', computedStyle.bottom);\r\n console.log(' tabBar.order:', computedStyle.order);\r\n console.log(' tabBar.display:', computedStyle.display);\r\n console.log(' tabBarRect.top:', tabBarRect.top, 'px from top');\r\n console.log(' tabBarRect.bottom:', tabBarRect.bottom, 'px from top');\r\n console.log(' window.innerHeight:', window.innerHeight);\r\n if (ionTabsComputedStyle) {\r\n console.log(' ionTabs.display:', ionTabsComputedStyle.display);\r\n console.log(' ionTabs.flexDirection:', ionTabsComputedStyle.flexDirection);\r\n console.log(' ionTabs.gridTemplateRows:', ionTabsComputedStyle.gridTemplateRows);\r\n }\r\n if (ionTabsForStyles) {\r\n const children = Array.from(ionTabsForStyles.children);\r\n console.log(' ionTabs children count:', children.length);\r\n children.forEach((child: any, index) => {\r\n console.log(` [${index}] ${child.tagName} slot=\"${child.getAttribute('slot')}\" order=\"${window.getComputedStyle(child).order}\"`);\r\n });\r\n }\r\n \r\n console.log('[ds-mobile-tab-bar] updateSlot: Computed styles (slot correct but visually wrong):', {\r\n tabBar: {\r\n position: computedStyle.position,\r\n top: computedStyle.top,\r\n bottom: computedStyle.bottom,\r\n order: computedStyle.order,\r\n display: computedStyle.display,\r\n zIndex: computedStyle.zIndex,\r\n transform: computedStyle.transform,\r\n marginTop: computedStyle.marginTop,\r\n marginBottom: computedStyle.marginBottom,\r\n width: computedStyle.width,\r\n height: computedStyle.height\r\n },\r\n ionTabs: ionTabsComputedStyle ? {\r\n display: ionTabsComputedStyle.display,\r\n flexDirection: ionTabsComputedStyle.flexDirection,\r\n gridTemplateRows: ionTabsComputedStyle.gridTemplateRows,\r\n gridTemplateColumns: ionTabsComputedStyle.gridTemplateColumns,\r\n position: ionTabsComputedStyle.position,\r\n alignItems: ionTabsComputedStyle.alignItems,\r\n justifyContent: ionTabsComputedStyle.justifyContent,\r\n height: ionTabsComputedStyle.height,\r\n minHeight: ionTabsComputedStyle.minHeight\r\n } : null,\r\n tabBarRect: {\r\n top: tabBarRect.top,\r\n bottom: tabBarRect.bottom,\r\n height: tabBarRect.height,\r\n y: tabBarRect.y,\r\n left: tabBarRect.left,\r\n right: tabBarRect.right,\r\n width: tabBarRect.width\r\n },\r\n windowHeight: window.innerHeight,\r\n distanceFromTop: tabBarRect.top,\r\n distanceFromBottom: window.innerHeight - tabBarRect.bottom,\r\n // Check if tab bar is actually in the DOM at the right position\r\n tabBarParent: tabBar.parentElement?.tagName,\r\n tabBarNextSibling: tabBar.nextElementSibling?.tagName,\r\n tabBarPreviousSibling: tabBar.previousElementSibling?.tagName,\r\n // Check all children of ion-tabs to see DOM order\r\n ionTabsChildren: ionTabsForStyles ? Array.from(ionTabsForStyles.children).map((child: any) => ({\r\n tagName: child.tagName,\r\n slot: child.getAttribute('slot'),\r\n order: window.getComputedStyle(child).order\r\n })) : null\r\n });\r\n }\r\n }\r\n \r\n private setupSlotEnforcement(): void {\r\n const hostElement = this.elementRef.nativeElement;\r\n const tabBar = this.elementRef.nativeElement.querySelector('ion-tab-bar');\r\n if (!tabBar) {\r\n console.log('[ds-mobile-tab-bar] setupSlotEnforcement: tabBar not found, retrying...');\r\n // Retry if element not found yet\r\n setTimeout(() => this.setupSlotEnforcement(), 50);\r\n return;\r\n }\r\n \r\n console.log('[ds-mobile-tab-bar] setupSlotEnforcement: Setting up MutationObserver');\r\n \r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && mutation.attributeName === 'slot') {\r\n const target = mutation.target as HTMLElement;\r\n const expectedSlot = this.isDesktop() ? 'top' : 'bottom';\r\n \r\n // Check both host element and tab bar\r\n if (target === hostElement || target === tabBar) {\r\n const currentSlot = target.getAttribute('slot');\r\n \r\n console.log('[ds-mobile-tab-bar] Slot changed by external source:', {\r\n target: target.tagName,\r\n currentSlot,\r\n expectedSlot,\r\n isDesktop: this.isDesktop()\r\n });\r\n \r\n // If Ionic or something else changed it, force it back\r\n if (currentSlot !== expectedSlot) {\r\n console.log('[ds-mobile-tab-bar] Enforcing slot back to:', expectedSlot);\r\n // Use requestAnimationFrame to avoid infinite loops\r\n requestAnimationFrame(() => {\r\n target.setAttribute('slot', expectedSlot);\r\n (target as any).slot = expectedSlot;\r\n });\r\n }\r\n }\r\n }\r\n });\r\n });\r\n \r\n // Observe both host element and tab bar for slot changes\r\n observer.observe(hostElement, {\r\n attributes: true,\r\n attributeFilter: ['slot']\r\n });\r\n \r\n observer.observe(tabBar, {\r\n attributes: true,\r\n attributeFilter: ['slot']\r\n });\r\n \r\n // Store observer for cleanup\r\n this.slotEnforcementObserver = observer;\r\n }\r\n \r\n ngOnDestroy(): void {\r\n if (this.mutationObserver) {\r\n this.mutationObserver.disconnect();\r\n }\r\n if (this.slotEnforcementObserver) {\r\n this.slotEnforcementObserver.disconnect();\r\n }\r\n if (this.mediaQuery) {\r\n this.mediaQuery.removeEventListener('change', this.handleBreakpointChange);\r\n }\r\n if (this.routerSubscription) {\r\n this.routerSubscription.unsubscribe();\r\n }\r\n }\r\n \r\n private setupBreakpointDetection(): void {\r\n // Use matchMedia for responsive breakpoint detection\r\n this.mediaQuery = window.matchMedia('(min-width: 768px)');\r\n this.isDesktop.set(this.mediaQuery.matches);\r\n \r\n this.handleBreakpointChange = this.handleBreakpointChange.bind(this);\r\n this.mediaQuery.addEventListener('change', this.handleBreakpointChange);\r\n }\r\n \r\n private handleBreakpointChange = (e: MediaQueryListEvent): void => {\r\n console.log('[ds-mobile-tab-bar] handleBreakpointChange:', {\r\n matches: e.matches,\r\n windowWidth: window.innerWidth,\r\n previousIsDesktop: this.isDesktop()\r\n });\r\n this.isDesktop.set(e.matches);\r\n // Force update the slot when breakpoint changes\r\n this.updateSlot();\r\n };\r\n \r\n private setupTitleRemovalObserver(): void {\r\n const config = { \r\n attributes: true, \r\n attributeFilter: ['title'],\r\n subtree: true,\r\n childList: true\r\n };\r\n \r\n this.mutationObserver = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && mutation.attributeName === 'title') {\r\n const target = mutation.target as HTMLElement;\r\n if (target.tagName === 'ION-TAB-BUTTON' && target.hasAttribute('title')) {\r\n target.removeAttribute('title');\r\n }\r\n }\r\n });\r\n // Also do a sweep after any changes\r\n this.removeTitleAttributes();\r\n });\r\n \r\n this.mutationObserver.observe(this.elementRef.nativeElement, config);\r\n }\r\n \r\n private removeTitleAttributes(): void {\r\n const tabButtons = this.elementRef.nativeElement.querySelectorAll('ion-tab-button');\r\n tabButtons.forEach((button: HTMLElement) => {\r\n if (button.hasAttribute('title')) {\r\n button.removeAttribute('title');\r\n }\r\n // Also remove from the native button inside shadow DOM\r\n const nativeButton = button.shadowRoot?.querySelector('button');\r\n if (nativeButton?.hasAttribute('title')) {\r\n nativeButton.removeAttribute('title');\r\n }\r\n });\r\n }\r\n \r\n private setupActiveTabDetection(): void {\r\n // Find the parent ion-tabs element\r\n const ionTabs = this.elementRef.nativeElement.closest('ion-tabs');\r\n if (!ionTabs) {\r\n console.warn('ds-mobile-tab-bar: Could not find parent ion-tabs element');\r\n return;\r\n }\r\n \r\n // Listen for tab changes using Ionic events\r\n ionTabs.addEventListener('ionTabsDidChange', (event: any) => {\r\n const tabRoute = event.detail?.tab;\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n } else {\r\n // Fallback: check DOM immediately after event\r\n setTimeout(() => this.updateActiveTabFromDOM(), 0);\r\n }\r\n });\r\n \r\n // Also listen for tab button clicks\r\n this.elementRef.nativeElement.addEventListener('click', (event: any) => {\r\n const button = event.target.closest('ion-tab-button');\r\n if (button) {\r\n setTimeout(() => this.updateActiveTabFromDOM(), 50);\r\n }\r\n });\r\n \r\n // Get initial selected tab\r\n this.updateActiveTabFromDOM();\r\n \r\n // Watch for selected attribute changes on tab buttons (more reliable)\r\n const observer = new MutationObserver(() => {\r\n this.updateActiveTabFromDOM();\r\n });\r\n \r\n observer.observe(this.elementRef.nativeElement, {\r\n attributes: true,\r\n attributeFilter: ['selected', 'tab'],\r\n subtree: true,\r\n childList: true\r\n });\r\n \r\n // Also watch the parent ion-tabs for changes\r\n observer.observe(ionTabs, {\r\n attributes: true,\r\n attributeFilter: ['selected', 'tab'],\r\n subtree: true\r\n });\r\n \r\n // Periodic check as fallback (in case events don't fire)\r\n setInterval(() => {\r\n this.updateActiveTabFromDOM();\r\n }, 100);\r\n }\r\n \r\n private updateActiveTabFromDOM(): void {\r\n // Check parent ion-tabs for selected tab (most reliable)\r\n const ionTabs = this.elementRef.nativeElement.closest('ion-tabs');\r\n if (ionTabs) {\r\n // Method 1: Check for ion-tab with selected attribute\r\n const selectedTab = ionTabs.querySelector('ion-tab[selected]');\r\n if (selectedTab) {\r\n const tabRoute = selectedTab.getAttribute('tab');\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n return;\r\n }\r\n }\r\n \r\n // Method 2: Check for ion-tab without tab-hidden class (Ionic shows active tab)\r\n const visibleTab = ionTabs.querySelector('ion-tab:not(.tab-hidden)');\r\n if (visibleTab) {\r\n const tabRoute = visibleTab.getAttribute('tab');\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n return;\r\n }\r\n }\r\n }\r\n \r\n // Method 3: Check tab buttons for selected state\r\n const tabButtons = this.elementRef.nativeElement.querySelectorAll('ion-tab-button');\r\n tabButtons.forEach((button: any) => {\r\n // Check Ionic's native selected property\r\n if (button.selected === true) {\r\n const tabRoute = button.getAttribute('tab');\r\n if (tabRoute) {\r\n this.activeTab.set(tabRoute);\r\n }\r\n }\r\n });\r\n }\r\n \r\n trackByTabId(index: number, tab: TabConfig): string {\r\n return tab.id;\r\n }\r\n \r\n isTabActive(tabRoute: string): boolean {\r\n const currentActive = this.activeTab();\r\n // Match by route (primary) or by checking if the tab button is selected\r\n if (currentActive === tabRoute) {\r\n return true;\r\n }\r\n \r\n // Fallback: check if this button is actually selected in the DOM\r\n const tabButtons = this.elementRef.nativeElement.querySelectorAll('ion-tab-button');\r\n for (let i = 0; i < tabButtons.length; i++) {\r\n const button = tabButtons[i] as any;\r\n if (button.getAttribute('tab') === tabRoute && button.selected === true) {\r\n return true;\r\n }\r\n }\r\n \r\n return false;\r\n }\r\n \r\n /**\r\n * Handle avatar click - opens profile menu if configured, otherwise just emits avatarClick\r\n */\r\n async handleAvatarClick(): Promise<void> {\r\n // Emit the basic click event (for backwards compatibility)\r\n this.avatarClick.emit();\r\n \r\n // Use input if provided, otherwise fall back to service\r\n const menuItems = this.profileMenuItems || this.userService.profileMenuItems();\r\n \r\n // If no menu items configured, just emit and return\r\n if (!menuItems || menuItems.length === 0) {\r\n return;\r\n }\r\n \r\n // Open the bottom sheet with configured menu items\r\n const sheet = await this.modalController.create({\r\n component: DsMobileActionsBottomSheetComponent,\r\n componentProps: {\r\n customActionGroups: menuItems\r\n },\r\n // Auto-height: no breakpoints, no handle\r\n cssClass: 'ds-bottom-sheet auto-height'\r\n });\r\n \r\n await sheet.present();\r\n \r\n const result = await sheet.onWillDismiss<ActionResult>();\r\n if (result.data?.action) {\r\n // Emit the selected action to parent\r\n this.profileActionSelected.emit(result.data);\r\n }\r\n }\r\n}\r\n\r\n","import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { \r\n IonTabs, \r\n IonTab\r\n} from '@ionic/angular/standalone';\r\nimport { DsMobileTabBarComponent, TabConfig } from '../tab-bar';\r\n\r\n// Re-export TabConfig for backwards compatibility\r\nexport type { TabConfig } from '../tab-bar';\r\n\r\n/**\r\n * DsMobileTabsComponent\r\n * \r\n * Responsive tab navigation that adapts from mobile to desktop:\r\n * - Mobile (< 768px): Bottom tab bar with icons + labels\r\n * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar\r\n * \r\n * Wraps ion-tabs to maintain native routing functionality while\r\n * providing a responsive navigation experience with branding.\r\n * \r\n * NOTE: This component wraps `ion-tabs` internally. If your Angular\r\n * routing requires `ion-tabs` to be a direct child in your component\r\n * (e.g., when using `ion-router-outlet` in app.html), use the\r\n * `DsMobileTabBarComponent` directly inside your own `ion-tabs` instead.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-tabs\r\n * [tabs]=\"tabsConfig\"\r\n * [avatarInitials]=\"'JD'\"\r\n * (avatarClick)=\"handleAvatarClick()\"\r\n * />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-tabs',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonTabs,\r\n IonTab,\r\n DsMobileTabBarComponent\r\n ],\r\n styleUrls: ['./ds-mobile-tabs.css'],\r\n template: `\r\n <ion-tabs>\r\n <ng-container *ngIf=\"tabs && tabs.length > 0\">\r\n <ion-tab *ngFor=\"let tab of tabs; trackBy: trackByTabId\" [tab]=\"tab.id\"></ion-tab>\r\n </ng-container>\r\n \r\n <ds-mobile-tab-bar\r\n [tabs]=\"tabs\"\r\n [avatarType]=\"avatarType\"\r\n [avatarInitials]=\"avatarInitials\"\r\n [avatarSrc]=\"avatarSrc\"\r\n [avatarIconName]=\"avatarIconName\"\r\n (avatarClick)=\"handleAvatarClick()\"\r\n />\r\n </ion-tabs>\r\n `\r\n})\r\nexport class DsMobileTabsComponent implements OnInit {\r\n // Inputs\r\n @Input() tabs: TabConfig[] = [];\r\n \r\n // Avatar inputs\r\n @Input() avatarType: 'initials' | 'photo' | 'icon' = 'initials';\r\n @Input() avatarInitials: string = 'U';\r\n @Input() avatarSrc: string = '';\r\n @Input() avatarIconName: string = 'remixUser3Line';\r\n \r\n // Outputs\r\n @Output() avatarClick = new EventEmitter<void>();\r\n \r\n constructor() {}\r\n \r\n ngOnInit(): void {\r\n console.log('DsMobileTabsComponent initialized');\r\n }\r\n \r\n trackByTabId(index: number, tab: TabConfig): string {\r\n return tab.id;\r\n }\r\n \r\n handleAvatarClick(): void {\r\n this.avatarClick.emit();\r\n }\r\n}\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\nexport interface InlineTabItem {\r\n id: string;\r\n label: string;\r\n badge?: number;\r\n}\r\n\r\n/**\r\n * DsMobileInlineTabsComponent\r\n * \r\n * Pill-style inline tabs for filtering/switching views\r\n * Used in the purple header section of pages\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-inline-tabs\r\n * [tabs]=\"[\r\n * { id: 'all', label: 'All' },\r\n * { id: 'open', label: 'Open' },\r\n * { id: 'closed', label: 'Closed' }\r\n * ]\"\r\n * [activeTab]=\"'all'\"\r\n * (tabChange)=\"handleTabChange($event)\">\r\n * </ds-mobile-inline-tabs>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-inline-tabs',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n .filter-tabs {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex-wrap: wrap;\r\n height: 40px;\r\n }\r\n \r\n .filter-tab {\r\n min-width: 48px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n padding: 0px 12px;\r\n height: 32px;\r\n border-radius: 20px;\r\n background: transparent;\r\n border: none;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n color: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.6);\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n white-space: nowrap;\r\n }\r\n \r\n .filter-tab.active {\r\n background: var(--color-background-brand, #5d5fef);\r\n color: var(--color-primary-content, white);\r\n }\r\n \r\n .filter-tab:hover:not(.active) {\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.1);\r\n }\r\n \r\n .tab-badge {\r\n min-width: 24px;\r\n height: 16px;\r\n padding: 0 6px;\r\n border-radius: 10px;\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.2);\r\n color: var(--header-content-color, white);\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 600;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n line-height: 1;\r\n }\r\n \r\n .filter-tab.active .tab-badge {\r\n background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.3);\r\n color: var(--header-content-color, white);\r\n }\r\n `],\r\n template: `\r\n <div class=\"filter-tabs\">\r\n @for (tab of tabs(); track tab.id) {\r\n <button \r\n class=\"filter-tab\"\r\n [class.active]=\"activeTab() === tab.id\"\r\n (click)=\"handleTabClick(tab.id)\"\r\n [attr.aria-label]=\"tab.label\"\r\n [attr.aria-selected]=\"activeTab() === tab.id\">\r\n {{ tab.label }}\r\n @if (tab.badge && tab.badge > 0) {\r\n <span class=\"tab-badge\">{{ tab.badge }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n `\r\n})\r\nexport class DsMobileInlineTabsComponent {\r\n /**\r\n * Array of tab items to display\r\n */\r\n tabs = input.required<InlineTabItem[]>();\r\n \r\n /**\r\n * Currently active tab ID\r\n */\r\n activeTab = input.required<string>();\r\n \r\n /**\r\n * Emitted when a tab is clicked\r\n */\r\n tabChange = output<string>();\r\n \r\n handleTabClick(tabId: string): void {\r\n this.tabChange.emit(tabId);\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport type { LightboxAuthor } from './ds-mobile-lightbox.service';\r\n\r\n/**\r\n * DsMobileLightboxHeaderComponent\r\n * \r\n * Shared header component for all lightbox types (image, PDF, etc.)\r\n * Displays author information and close button with consistent styling.\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-header',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent, DsAvatarComponent],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n template: `\r\n <div class=\"lightbox-header lightbox-context\">\r\n <div class=\"header-content\">\r\n <!-- Post author info -->\r\n @if (author()) {\r\n <div class=\"post-author-info\">\r\n <ds-avatar\r\n [initials]=\"author()!.avatarInitials ?? ''\"\r\n [type]=\"author()!.avatarType ?? 'initials'\"\r\n [src]=\"author()!.avatarSrc ?? ''\"\r\n size=\"md\"\r\n />\r\n <div class=\"author-details\">\r\n <div class=\"author-name\">{{ author()!.name }}</div>\r\n <div class=\"author-meta\">\r\n @if (author()!.role) {\r\n <span>{{ author()!.role }}</span>\r\n }\r\n @if (author()!.role && author()!.timestamp) {\r\n <span class=\"separator\">·</span>\r\n }\r\n @if (author()!.timestamp) {\r\n <span>{{ author()!.timestamp }}</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Action buttons - always visible -->\r\n <div class=\"header-actions\">\r\n <ds-icon-button\r\n icon=\"remixShare2Line\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (clicked)=\"shareClick.emit()\"\r\n class=\"share-button\"\r\n [ariaLabel]=\"'Share'\">\r\n </ds-icon-button>\r\n \r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (clicked)=\"closeClick.emit()\"\r\n class=\"close-button\"\r\n [ariaLabel]=\"'Close'\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n .lightbox-header {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 1000;\r\n padding: 0 16px;\r\n background: linear-gradient(to bottom, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.4) 80%, transparent 100%);\r\n pointer-events: none;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-end;\r\n gap: 12px;\r\n pointer-events: auto;\r\n }\r\n\r\n .post-author-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n margin-right: auto;\r\n }\r\n\r\n .author-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n .author-name {\r\n color: white;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n }\r\n\r\n .author-meta {\r\n color: rgba(255, 255, 255, 0.7);\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n\r\n .author-meta .separator {\r\n color: rgba(255, 255, 255, 0.5);\r\n }\r\n\r\n .header-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex-shrink: 0;\r\n }\r\n\r\n .close-button,\r\n .share-button {\r\n pointer-events: auto;\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n\r\n .close-button::ng-deep button,\r\n .share-button::ng-deep button {\r\n color: white !important;\r\n background: rgba(255, 255, 255, 0.1) !important;\r\n border-radius: 50%;\r\n transition: background 0.2s ease;\r\n border: none;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .close-button::ng-deep button:hover,\r\n .share-button::ng-deep button:hover {\r\n background: rgba(255, 255, 255, 0.15) !important;\r\n }\r\n\r\n .close-button::ng-deep button:active,\r\n .share-button::ng-deep button:active {\r\n background: rgba(255, 255, 255, 0.15) !important;\r\n }\r\n\r\n .close-button::ng-deep svg,\r\n .share-button::ng-deep svg {\r\n color: white !important;\r\n fill: white !important;\r\n }\r\n\r\n /* Safe area support for notched devices */\r\n @supports (padding-top: env(safe-area-inset-top)) {\r\n .lightbox-header {\r\n padding-top: calc(16px + env(safe-area-inset-top));\r\n }\r\n }\r\n `]\r\n})\r\nexport class DsMobileLightboxHeaderComponent {\r\n /**\r\n * Author information to display\r\n */\r\n author = input<LightboxAuthor>();\r\n\r\n /**\r\n * Emitted when close button is clicked\r\n */\r\n closeClick = output<void>();\r\n \r\n /**\r\n * Emitted when share button is clicked\r\n */\r\n shareClick = output<void>();\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileLightboxFooterComponent\r\n * \r\n * Shared footer component for all lightbox types (image, PDF, etc.)\r\n * Displays navigation controls (for multiple images) and action buttons.\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-footer',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent],\r\n template: `\r\n <div class=\"lightbox-footer\">\r\n <!-- Navigation controls (only shown for multiple images) -->\r\n @if (showNavigation() && totalImages() > 1) {\r\n <div class=\"footer-navigation\">\r\n <button \r\n class=\"nav-button prev\"\r\n (click)=\"prevClick.emit()\"\r\n [disabled]=\"currentIndex() === 0\"\r\n aria-label=\"Previous image\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M15 18L9 12L15 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n \r\n <div class=\"counter\">\r\n {{ currentIndex() + 1 }} / {{ totalImages() }}\r\n </div>\r\n \r\n <button \r\n class=\"nav-button next\"\r\n (click)=\"nextClick.emit()\"\r\n [disabled]=\"currentIndex() === totalImages() - 1\"\r\n aria-label=\"Next image\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M9 18L15 12L9 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n }\r\n \r\n <!-- Action buttons -->\r\n @if (showActions()) {\r\n <div class=\"footer-actions\">\r\n <div class=\"action-buttons-left\">\r\n <!-- Like button -->\r\n <ds-icon-button\r\n [icon]=\"isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (click)=\"likeClick.emit()\"\r\n [attr.data-liked]=\"isLiked()\"\r\n class=\"action-button-like\"\r\n [ariaLabel]=\"'Like'\">\r\n </ds-icon-button>\r\n \r\n <!-- Comment button -->\r\n <ds-icon-button\r\n icon=\"remixChat3Line\"\r\n variant=\"ghost\"\r\n size=\"md\"\r\n (click)=\"commentClick.emit()\"\r\n class=\"action-button-comment\"\r\n [ariaLabel]=\"'Comment'\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n .lightbox-footer {\r\n position: fixed;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 100;\r\n padding: 16px 20px 20px 20px;\r\n background: linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 50%, rgba(0, 0, 0, 0.4) 75%, transparent 100%);\r\n pointer-events: none;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n\r\n /* Navigation controls */\r\n .footer-navigation {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 24px;\r\n pointer-events: auto;\r\n }\r\n\r\n .nav-button {\r\n background: rgba(255, 255, 255, 0.1);\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n border-radius: 50%;\r\n color: white;\r\n width: 40px;\r\n height: 40px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n backdrop-filter: blur(10px);\r\n -webkit-backdrop-filter: blur(10px);\r\n padding: 0;\r\n }\r\n\r\n .nav-button:hover:not(:disabled) {\r\n background: rgba(255, 255, 255, 0.2);\r\n transform: scale(1.05);\r\n }\r\n\r\n .nav-button:active:not(:disabled) {\r\n transform: scale(0.95);\r\n }\r\n\r\n .nav-button:disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n }\r\n\r\n .nav-button svg {\r\n width: 24px;\r\n height: 24px;\r\n flex-shrink: 0;\r\n }\r\n\r\n .counter {\r\n background: rgba(255, 255, 255, 0.1);\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n backdrop-filter: blur(10px);\r\n -webkit-backdrop-filter: blur(10px);\r\n border-radius: 100px;\r\n padding: 8px 16px;\r\n color: white;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 1;\r\n letter-spacing: -0.3px;\r\n pointer-events: auto;\r\n user-select: none;\r\n }\r\n\r\n .footer-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n pointer-events: auto;\r\n }\r\n\r\n .action-buttons-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n }\r\n\r\n /* Style the action buttons to match the ghost/transparent look */\r\n .action-button-like::ng-deep button,\r\n .action-button-comment::ng-deep button {\r\n background: rgba(255, 255, 255, 0.1) !important;\r\n border: 1px solid rgba(255, 255, 255, 0.2) !important;\r\n color: white !important;\r\n backdrop-filter: blur(10px);\r\n -webkit-backdrop-filter: blur(10px);\r\n transition: all 0.2s ease;\r\n }\r\n\r\n .action-button-like::ng-deep button:hover,\r\n .action-button-comment::ng-deep button:hover {\r\n background: rgba(255, 255, 255, 0.2) !important;\r\n transform: scale(1.02);\r\n }\r\n\r\n .action-button-like::ng-deep button:active,\r\n .action-button-comment::ng-deep button:active {\r\n transform: scale(0.98);\r\n }\r\n\r\n /* Icon and label colors */\r\n .action-button-like::ng-deep button svg,\r\n .action-button-comment::ng-deep button svg,\r\n .action-button-like::ng-deep button .btn__icon,\r\n .action-button-comment::ng-deep button .btn__icon,\r\n .action-button-like::ng-deep button .btn__content,\r\n .action-button-comment::ng-deep button .btn__content {\r\n color: white !important;\r\n fill: white !important;\r\n }\r\n\r\n /* Make sure icons are visible */\r\n .action-button-like::ng-deep button .btn__icon svg,\r\n .action-button-comment::ng-deep button .btn__icon svg {\r\n color: white !important;\r\n fill: white !important;\r\n display: block !important;\r\n opacity: 1 !important;\r\n visibility: visible !important;\r\n width: 20px !important;\r\n height: 20px !important;\r\n }\r\n\r\n /* Ensure icon wrapper is visible */\r\n .action-button-like::ng-deep button .btn__icon,\r\n .action-button-comment::ng-deep button .btn__icon {\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n flex-shrink: 0 !important;\r\n }\r\n\r\n /* Like button active state (pink heart) */\r\n .action-button-like[data-liked=\"true\"]::ng-deep button svg {\r\n fill: #f91880 !important;\r\n color: #f91880 !important;\r\n }\r\n\r\n .action-button-like[data-liked=\"true\"]::ng-deep button {\r\n border-color: rgba(249, 24, 128, 0.3) !important;\r\n }\r\n\r\n /* All action buttons should have same circular styling */\r\n .action-button-like,\r\n .action-button-comment {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n\r\n .action-button-like::ng-deep button,\r\n .action-button-comment::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 44px !important;\r\n height: 44px !important;\r\n min-width: 44px !important;\r\n min-height: 44px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n /* Safe area support for footer */\r\n @supports (padding-bottom: env(safe-area-inset-bottom)) {\r\n .lightbox-footer {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n `]\r\n})\r\nexport class DsMobileLightboxFooterComponent {\r\n /**\r\n * Whether to show navigation controls\r\n */\r\n showNavigation = input<boolean>(false);\r\n\r\n /**\r\n * Current image index (0-based)\r\n */\r\n currentIndex = input<number>(0);\r\n\r\n /**\r\n * Total number of images\r\n */\r\n totalImages = input<number>(1);\r\n\r\n /**\r\n * Whether to show like & comment action buttons\r\n * @default false\r\n */\r\n showActions = input<boolean>(false);\r\n \r\n /**\r\n * Whether the content is liked\r\n */\r\n isLiked = input<boolean>(false);\r\n \r\n /**\r\n * Number of likes\r\n */\r\n likeCount = input<number>(0);\r\n \r\n /**\r\n * Number of comments\r\n */\r\n commentCount = input<number>(0);\r\n\r\n /**\r\n * Emitted when previous button is clicked\r\n */\r\n prevClick = output<void>();\r\n\r\n /**\r\n * Emitted when next button is clicked\r\n */\r\n nextClick = output<void>();\r\n\r\n /**\r\n * Emitted when like button is clicked\r\n */\r\n likeClick = output<void>();\r\n\r\n /**\r\n * Emitted when comment button is clicked\r\n */\r\n commentClick = output<void>();\r\n}\r\n\r\n","import {\r\n Component,\r\n signal,\r\n computed,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n OnInit,\r\n CUSTOM_ELEMENTS_SCHEMA,\r\n HostListener\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonSpinner,\r\n GestureController,\r\n Gesture\r\n} from '@ionic/angular/standalone';\r\nimport { Share } from '@capacitor/share';\r\nimport { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';\r\nimport { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';\r\nimport type { LightboxImage, LightboxAuthor } from './ds-mobile-lightbox.service';\r\nimport Swiper from 'swiper';\r\nimport type { SwiperOptions } from 'swiper/types';\r\n\r\n/**\r\n * DsMobileLightboxImageComponent\r\n * \r\n * Full-screen image lightbox component with Swiper.js navigation and pinch-zoom.\r\n * \r\n * This component is typically not used directly - use DsMobileLightboxService instead.\r\n * \r\n * Features:\r\n * - Swiper.js for smooth image navigation\r\n * - Pinch to zoom in/out\r\n * - Double-tap to toggle zoom\r\n * - Swipe down to close (when not zoomed)\r\n * - Image counter and navigation controls\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private lightbox: DsMobileLightboxService) {}\r\n * \r\n * openImage() {\r\n * this.lightbox.openImages({\r\n * images: [{ type: 'image', src: 'image.jpg', title: 'My Image' }]\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-image',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonSpinner,\r\n DsMobileLightboxHeaderComponent,\r\n DsMobileLightboxFooterComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <div class=\"lightbox-overlay\" \r\n [class.zoomed]=\"isZoomed()\">\r\n \r\n <div class=\"lightbox-wrapper\">\r\n <!-- Header with author info and action buttons -->\r\n <ds-mobile-lightbox-header \r\n [author]=\"author\"\r\n (closeClick)=\"close()\"\r\n (shareClick)=\"onShare()\"\r\n />\r\n\r\n <!-- Swiper container -->\r\n <div class=\"swiper-container\" #swiperContainer>\r\n <div class=\"swiper-wrapper\">\r\n @for (image of images; track image.src; let i = $index) {\r\n <div class=\"swiper-slide\">\r\n <div class=\"image-zoom-container\" [attr.data-index]=\"i\">\r\n <img \r\n [src]=\"image.src\"\r\n [alt]=\"image.alt || 'Lightbox image'\"\r\n class=\"lightbox-image\"\r\n (load)=\"onImageLoad(i)\"\r\n (error)=\"onImageError(i)\">\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n \r\n <!-- Loading indicator -->\r\n @if (isLoading()) {\r\n <div class=\"loading-spinner\">\r\n <ion-spinner name=\"crescent\"></ion-spinner>\r\n </div>\r\n }\r\n\r\n <!-- Footer with navigation and actions -->\r\n <ds-mobile-lightbox-footer\r\n [showNavigation]=\"showControls && images.length > 1\"\r\n [showActions]=\"showActions\"\r\n [currentIndex]=\"currentIndex()\"\r\n [totalImages]=\"images.length\"\r\n [isLiked]=\"isLiked()\"\r\n [likeCount]=\"likeCount()\"\r\n [commentCount]=\"commentCount()\"\r\n (prevClick)=\"previousImage()\"\r\n (nextClick)=\"nextImage()\"\r\n (likeClick)=\"onLikeToggle()\"\r\n (commentClick)=\"onReply()\"\r\n />\r\n </div>\r\n </div>\r\n `,\r\n styleUrl: './ds-mobile-lightbox.css'\r\n})\r\nexport class DsMobileLightboxImageComponent implements OnInit, AfterViewInit, OnDestroy {\r\n // Inputs (passed from service as regular properties, not signals)\r\n images!: LightboxImage[];\r\n author?: LightboxAuthor;\r\n initialIndex: number = 0;\r\n enableZoom: boolean = true;\r\n showControls: boolean = true;\r\n enableSwipe: boolean = true;\r\n showInfo: boolean = true;\r\n showActions: boolean = false;\r\n animation: 'fade' | 'zoom' | 'slide' = 'fade';\r\n onCloseRequested?: () => void;\r\n\r\n // View children\r\n @ViewChild('swiperContainer', { read: ElementRef }) swiperContainer!: ElementRef<HTMLDivElement>;\r\n\r\n // State\r\n currentIndex = signal(0);\r\n scale = signal(1);\r\n isZoomed = signal(false);\r\n isLoading = signal(true);\r\n hasError = signal(false);\r\n \r\n // Action states\r\n isLiked = signal(false);\r\n likeCount = signal(0);\r\n commentCount = signal(0);\r\n\r\n // Computed\r\n currentImage = computed(() => this.images[this.currentIndex()]);\r\n\r\n // Swiper instance\r\n private swiper?: Swiper;\r\n private zoomData: Map<number, { scale: number; x: number; y: number }> = new Map();\r\n\r\n constructor(\r\n private gestureCtrl: GestureController\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n // Set initial index from the passed property\r\n if (this.initialIndex !== undefined) {\r\n this.currentIndex.set(this.initialIndex);\r\n }\r\n \r\n // Initialize action states from current image\r\n const currentImg = this.images[this.currentIndex()];\r\n if (currentImg) {\r\n this.isLiked.set(currentImg.isLiked ?? false);\r\n this.likeCount.set(currentImg.likeCount ?? 0);\r\n this.commentCount.set(currentImg.commentCount ?? 0);\r\n }\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n setTimeout(() => {\r\n this.initializeSwiper();\r\n this.initializeZoomGestures();\r\n }, 100);\r\n }\r\n\r\n ngOnDestroy(): void {\r\n // Clean up Swiper\r\n if (this.swiper) {\r\n this.swiper.destroy();\r\n this.swiper = undefined;\r\n }\r\n }\r\n /**\r\n * Initialize Swiper for image navigation\r\n */\r\n private initializeSwiper(): void {\r\n if (!this.swiperContainer) {\r\n console.error('[Lightbox] Swiper container not found');\r\n return;\r\n }\r\n\r\n const swiperOptions: SwiperOptions = {\r\n initialSlide: this.initialIndex,\r\n speed: 300,\r\n resistance: true,\r\n resistanceRatio: 0.85,\r\n slidesPerView: 1,\r\n spaceBetween: 0,\r\n touchRatio: 1,\r\n longSwipesRatio: 0.5,\r\n threshold: 10,\r\n on: {\r\n slideChange: (swiper) => {\r\n this.currentIndex.set(swiper.activeIndex);\r\n this.updateActionStates();\r\n \r\n // Check if the image is already loaded\r\n const currentSlide = swiper.slides[swiper.activeIndex];\r\n const img = currentSlide?.querySelector('img');\r\n if (img && img.complete && img.naturalHeight !== 0) {\r\n // Image is already loaded\r\n this.isLoading.set(false);\r\n }\r\n },\r\n slideChangeTransitionStart: () => {\r\n // Don't show loading spinner if image is already loaded\r\n const currentSlide = this.swiper?.slides[this.swiper.activeIndex];\r\n const img = currentSlide?.querySelector('img');\r\n if (!img || !img.complete || img.naturalHeight === 0) {\r\n this.isLoading.set(true);\r\n }\r\n }\r\n }\r\n };\r\n\r\n this.swiper = new Swiper(this.swiperContainer.nativeElement, swiperOptions);\r\n \r\n // Check if the initial image is already loaded\r\n setTimeout(() => {\r\n const currentSlide = this.swiper?.slides[this.currentIndex()];\r\n const img = currentSlide?.querySelector('img');\r\n if (img && img.complete && img.naturalHeight !== 0) {\r\n this.isLoading.set(false);\r\n }\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Initialize pinch-zoom gestures for all slides\r\n */\r\n private initializeZoomGestures(): void {\r\n if (!this.enableZoom) return;\r\n\r\n const slides = this.swiperContainer.nativeElement.querySelectorAll('.image-zoom-container');\r\n \r\n slides.forEach((slide, index) => {\r\n this.initializeZoomForSlide(slide as HTMLElement, index);\r\n });\r\n }\r\n\r\n /**\r\n * Initialize zoom gestures for a specific slide\r\n */\r\n private initializeZoomForSlide(container: HTMLElement, index: number): void {\r\n let initialDistance = 0;\r\n let initialScale = 1;\r\n let currentScale = 1;\r\n let lastTap = 0;\r\n\r\n // Double-tap to zoom\r\n container.addEventListener('click', (event: MouseEvent) => {\r\n const now = Date.now();\r\n const timeSinceLastTap = now - lastTap;\r\n\r\n if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {\r\n event.preventDefault();\r\n this.toggleZoom(container, index);\r\n }\r\n\r\n lastTap = now;\r\n });\r\n\r\n // Pinch to zoom\r\n const getTouchDistance = (touches: TouchList) => {\r\n const dx = touches[0].clientX - touches[1].clientX;\r\n const dy = touches[0].clientY - touches[1].clientY;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n };\r\n\r\n container.addEventListener('touchstart', (event: TouchEvent) => {\r\n if (event.touches.length === 2) {\r\n event.preventDefault();\r\n initialDistance = getTouchDistance(event.touches);\r\n const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };\r\n initialScale = zoomData.scale;\r\n \r\n // Disable Swiper when zooming\r\n if (this.swiper) {\r\n this.swiper.allowTouchMove = false;\r\n }\r\n }\r\n }, { passive: false });\r\n\r\n container.addEventListener('touchmove', (event: TouchEvent) => {\r\n if (event.touches.length === 2) {\r\n event.preventDefault();\r\n \r\n const currentDistance = getTouchDistance(event.touches);\r\n const pinchScale = currentDistance / initialDistance;\r\n \r\n currentScale = Math.max(1, Math.min(initialScale * pinchScale, 4));\r\n \r\n const img = container.querySelector('img');\r\n if (img) {\r\n img.style.transform = `scale(${currentScale})`;\r\n }\r\n \r\n if (currentScale > 1) {\r\n this.isZoomed.set(true);\r\n } else {\r\n this.isZoomed.set(false);\r\n }\r\n }\r\n }, { passive: false });\r\n\r\n container.addEventListener('touchend', (event: TouchEvent) => {\r\n if (event.touches.length < 2) {\r\n // Save zoom state\r\n this.zoomData.set(index, { scale: currentScale, x: 0, y: 0 });\r\n \r\n // Re-enable Swiper if not zoomed\r\n if (this.swiper && currentScale <= 1) {\r\n this.swiper.allowTouchMove = true;\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Toggle zoom on double-tap\r\n */\r\n private toggleZoom(container: HTMLElement, index: number): void {\r\n const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };\r\n const img = container.querySelector('img');\r\n \r\n if (!img) return;\r\n\r\n if (zoomData.scale > 1) {\r\n // Zoom out\r\n img.style.transform = 'scale(1)';\r\n this.zoomData.set(index, { scale: 1, x: 0, y: 0 });\r\n this.isZoomed.set(false);\r\n if (this.swiper) {\r\n this.swiper.allowTouchMove = true;\r\n }\r\n } else {\r\n // Zoom in\r\n img.style.transform = 'scale(2)';\r\n this.zoomData.set(index, { scale: 2, x: 0, y: 0 });\r\n this.isZoomed.set(true);\r\n if (this.swiper) {\r\n this.swiper.allowTouchMove = false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Update action states (like, comments) when slide changes\r\n */\r\n private updateActionStates(): void {\r\n const currentImg = this.images[this.currentIndex()];\r\n if (currentImg) {\r\n this.isLiked.set(currentImg.isLiked ?? false);\r\n this.likeCount.set(currentImg.likeCount ?? 0);\r\n this.commentCount.set(currentImg.commentCount ?? 0);\r\n }\r\n }\r\n\r\n /**\r\n * Close the lightbox\r\n */\r\n close(): void {\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Handle share button click\r\n */\r\n async onShare(): Promise<void> {\r\n console.log('[Lightbox] Share button clicked');\r\n const currentImg = this.currentImage();\r\n \r\n if (!currentImg?.src) {\r\n console.warn('[Lightbox] No image to share');\r\n return;\r\n }\r\n \r\n try {\r\n // Check if Web Share API is available (for browser)\r\n if (navigator.share) {\r\n await navigator.share({\r\n title: currentImg.title || 'Shared Image',\r\n text: currentImg.description || '',\r\n url: currentImg.src,\r\n });\r\n console.log('[Lightbox] Shared via Web Share API');\r\n } else {\r\n // Fallback to Capacitor Share API (for native apps)\r\n await Share.share({\r\n title: currentImg.title || 'Shared Image',\r\n url: currentImg.src,\r\n dialogTitle: 'Share Image',\r\n });\r\n console.log('[Lightbox] Shared via Capacitor Share API');\r\n }\r\n } catch (error: any) {\r\n // User cancellation is expected and not an error\r\n if (error?.message?.includes('cancel') || error?.code === 'USER_CANCELLED') {\r\n console.log('[Lightbox] Share cancelled by user');\r\n return;\r\n }\r\n console.error('[Lightbox] Share failed:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Handle like button toggle\r\n */\r\n onLikeToggle(): void {\r\n console.log('[Lightbox] Like button toggled');\r\n this.isLiked.update(liked => !liked);\r\n \r\n if (this.isLiked()) {\r\n this.likeCount.update(count => count + 1);\r\n } else {\r\n this.likeCount.update(count => Math.max(0, count - 1));\r\n }\r\n }\r\n\r\n /**\r\n * Handle reply/comment button click\r\n */\r\n onReply(): void {\r\n console.log('[Lightbox] Reply button clicked');\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Navigate to the next image\r\n */\r\n nextImage(): void {\r\n if (this.swiper && this.currentIndex() < this.images.length - 1) {\r\n this.swiper.slideNext();\r\n }\r\n }\r\n\r\n /**\r\n * Navigate to the previous image\r\n */\r\n previousImage(): void {\r\n if (this.swiper && this.currentIndex() > 0) {\r\n this.swiper.slidePrev();\r\n }\r\n }\r\n\r\n /**\r\n * Handle image load success\r\n */\r\n onImageLoad(index: number): void {\r\n if (index === this.currentIndex()) {\r\n this.isLoading.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * Handle image load error\r\n */\r\n onImageError(index: number): void {\r\n if (index === this.currentIndex()) {\r\n console.error(`[Lightbox] Image ${index} failed to load`);\r\n this.isLoading.set(false);\r\n this.hasError.set(true);\r\n }\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n OnInit,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonContent,\r\n IonSpinner\r\n} from '@ionic/angular/standalone';\r\nimport { Filesystem, Directory } from '@capacitor/filesystem';\r\nimport { Browser } from '@capacitor/browser';\r\nimport { Share } from '@capacitor/share';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsButtonComponent } from '@propbinder/design-system';\r\nimport { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';\r\nimport { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';\r\nimport type { LightboxPdf, LightboxAuthor } from './ds-mobile-lightbox.service';\r\n\r\n/**\r\n * DsMobileLightboxPdfComponent\r\n * \r\n * PDF viewer component that displays PDF info and allows users to open PDFs in the native device viewer.\r\n * Shows a lightbox with PDF details first, then user can choose to open in native viewer.\r\n * \r\n * This component is typically not used directly - use DsMobileLightboxService instead.\r\n * \r\n * Features:\r\n * - PDF info preview (title, size, icon)\r\n * - User-initiated native PDF viewing (iOS/Android)\r\n * - Download and cache support\r\n * - Share functionality\r\n * - Loading states\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private lightbox: DsMobileLightboxService) {}\r\n * \r\n * openPdf() {\r\n * this.lightbox.openPdf({\r\n * pdf: { type: 'pdf', src: 'document.pdf', title: 'My Document' }\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-lightbox-pdf',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n IonSpinner,\r\n DsAvatarComponent,\r\n DsButtonComponent,\r\n DsMobileLightboxHeaderComponent,\r\n DsMobileLightboxFooterComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content \r\n [fullscreen]=\"true\"\r\n class=\"lightbox-content pdf-viewer\">\r\n \r\n <div class=\"lightbox-wrapper\">\r\n <!-- Header with author info and close button -->\r\n <ds-mobile-lightbox-header \r\n [author]=\"author\"\r\n (closeClick)=\"close()\"\r\n />\r\n\r\n <!-- PDF Info & Actions -->\r\n <div class=\"pdf-container\">\r\n @if (isLoading) {\r\n <div class=\"loading-state\">\r\n <ion-spinner name=\"crescent\"></ion-spinner>\r\n <p>Loading PDF...</p>\r\n </div>\r\n } @else if (hasError) {\r\n <div class=\"error-state\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M12 8V12M12 16H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n <h3>Failed to Load PDF</h3>\r\n <p>{{ errorMessage }}</p>\r\n <button class=\"retry-button\" (click)=\"openPdfInNativeViewer()\">\r\n Try Again\r\n </button>\r\n </div>\r\n } @else {\r\n <div class=\"pdf-content\">\r\n <!-- PDF Icon -->\r\n <ds-avatar\r\n type=\"icon\"\r\n iconName=\"remixFileTextLine\"\r\n size=\"xl\"\r\n />\r\n \r\n <!-- PDF Title (same as attachment fileName) -->\r\n <h2 class=\"pdf-title\">{{ getDisplayTitle() }}</h2>\r\n \r\n <!-- PDF Metadata (same format as attachment: PDF · fileSize) -->\r\n <div class=\"pdf-meta\">\r\n PDF · {{ pdf.fileSize ? formatFileSize(pdf.fileSize) : '' }}\r\n </div>\r\n \r\n <!-- Open Button -->\r\n <ds-button\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (clicked)=\"openPdfInNativeViewer()\"\r\n class=\"open-pdf-button\">\r\n Open Preview\r\n </ds-button>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Bottom actions -->\r\n <ds-mobile-lightbox-footer\r\n [isLiked]=\"false\"\r\n [likeCount]=\"0\"\r\n [commentCount]=\"0\"\r\n (likeClick)=\"onLikeToggle()\"\r\n (commentClick)=\"onReply()\"\r\n (shareClick)=\"onShare()\"\r\n />\r\n </div>\r\n </ion-content>\r\n `,\r\n styleUrl: './ds-mobile-lightbox-pdf.css'\r\n})\r\nexport class DsMobileLightboxPdfComponent implements OnInit {\r\n // Inputs (passed from service as regular properties)\r\n pdf!: LightboxPdf;\r\n author?: LightboxAuthor;\r\n onCloseRequested?: () => void;\r\n\r\n // State\r\n isLoading = false;\r\n hasError = false;\r\n errorMessage = '';\r\n cachedFilePath?: string;\r\n\r\n constructor() {}\r\n\r\n ngOnInit(): void {\r\n console.log('[PDF Lightbox] Initializing with PDF:', this.pdf);\r\n \r\n // Don't automatically open - let user click the \"Open\" button\r\n // this.openPdfInNativeViewer();\r\n }\r\n\r\n /**\r\n * Open the PDF in the native device viewer\r\n */\r\n async openPdfInNativeViewer(): Promise<void> {\r\n if (!this.pdf?.src) {\r\n console.error('[PDF Lightbox] No PDF source provided');\r\n this.hasError = true;\r\n this.errorMessage = 'No PDF file provided';\r\n return;\r\n }\r\n\r\n this.isLoading = true;\r\n this.hasError = false;\r\n this.errorMessage = '';\r\n\r\n try {\r\n console.log('[PDF Lightbox] Opening PDF:', this.pdf.src);\r\n \r\n // Check if it's already a full URL\r\n let pdfUrl: string;\r\n \r\n if (this.pdf.src.startsWith('http://') || this.pdf.src.startsWith('https://')) {\r\n // Already a full URL\r\n pdfUrl = this.pdf.src;\r\n } else {\r\n // Relative path - construct full URL\r\n // Use current origin (which includes the dev server URL in Capacitor)\r\n // Remove leading slash if present to avoid double slashes\r\n const cleanPath = this.pdf.src.startsWith('/') ? this.pdf.src.slice(1) : this.pdf.src;\r\n pdfUrl = `${window.location.origin}/${cleanPath}`;\r\n }\r\n \r\n console.log('[PDF Lightbox] Opening PDF at URL:', pdfUrl);\r\n \r\n // Use Browser to open the PDF\r\n await Browser.open({ \r\n url: pdfUrl,\r\n presentationStyle: 'fullscreen'\r\n });\r\n \r\n this.isLoading = false;\r\n \r\n // Close the modal after opening browser\r\n setTimeout(() => {\r\n this.close();\r\n }, 500);\r\n } catch (error: any) {\r\n console.error('[PDF Lightbox] Error opening PDF:', error);\r\n this.isLoading = false;\r\n this.hasError = true;\r\n this.errorMessage = error?.message || 'Failed to open PDF';\r\n }\r\n }\r\n\r\n /**\r\n * Download a remote PDF and open it\r\n */\r\n private async downloadAndOpenPdf(): Promise<void> {\r\n try {\r\n console.log('[PDF Lightbox] Downloading PDF from:', this.pdf.src);\r\n \r\n // Fetch the PDF\r\n const response = await fetch(this.pdf.src);\r\n if (!response.ok) {\r\n throw new Error(`Failed to download PDF: ${response.statusText}`);\r\n }\r\n \r\n const blob = await response.blob();\r\n const base64Data = await this.blobToBase64(blob);\r\n \r\n // Generate a filename\r\n const fileName = this.pdf.title \r\n ? `${this.pdf.title.replace(/[^a-z0-9]/gi, '_')}.pdf`\r\n : 'document.pdf';\r\n \r\n // Save to cache directory\r\n const result = await Filesystem.writeFile({\r\n path: fileName,\r\n data: base64Data,\r\n directory: Directory.Cache\r\n });\r\n \r\n console.log('[PDF Lightbox] PDF saved to cache:', result.uri);\r\n this.cachedFilePath = result.uri;\r\n \r\n // Open using Browser\r\n await Browser.open({ \r\n url: result.uri,\r\n presentationStyle: 'fullscreen'\r\n });\r\n \r\n console.log('[PDF Lightbox] PDF opened successfully');\r\n } catch (error) {\r\n console.error('[PDF Lightbox] Error downloading/opening PDF:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Open a local PDF file\r\n */\r\n private async openLocalPdf(): Promise<void> {\r\n try {\r\n // Remove leading slash if present to avoid double slashes\r\n const cleanPath = this.pdf.src.startsWith('/') ? this.pdf.src.slice(1) : this.pdf.src;\r\n const fullUrl = window.location.origin + '/' + cleanPath;\r\n \r\n await Browser.open({ \r\n url: fullUrl,\r\n presentationStyle: 'fullscreen'\r\n });\r\n \r\n console.log('[PDF Lightbox] Local PDF opened successfully');\r\n } catch (error) {\r\n console.error('[PDF Lightbox] Error opening local PDF:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Convert Blob to base64 string\r\n */\r\n private blobToBase64(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => {\r\n const base64String = reader.result as string;\r\n // Remove the data URL prefix\r\n const base64Data = base64String.split(',')[1];\r\n resolve(base64Data);\r\n };\r\n reader.onerror = reject;\r\n reader.readAsDataURL(blob);\r\n });\r\n }\r\n\r\n /**\r\n * Get display title with file extension\r\n * If title is provided, ensure it has .pdf extension\r\n * Otherwise, extract filename from src\r\n */\r\n getDisplayTitle(): string {\r\n if (this.pdf.title) {\r\n // If title doesn't end with .pdf, add it\r\n return this.pdf.title.endsWith('.pdf') ? this.pdf.title : `${this.pdf.title}.pdf`;\r\n }\r\n \r\n // Extract filename from src\r\n if (this.pdf.src) {\r\n const filename = this.pdf.src.split('/').pop() || 'PDF Document.pdf';\r\n return filename;\r\n }\r\n \r\n return 'PDF Document.pdf';\r\n }\r\n\r\n /**\r\n * Format file size for display\r\n */\r\n formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 Bytes';\r\n \r\n const k = 1024;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n \r\n return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];\r\n }\r\n\r\n /**\r\n * Share the PDF\r\n */\r\n async onShare(): Promise<void> {\r\n console.log('[PDF Lightbox] Share button clicked');\r\n \r\n if (!this.pdf?.src) return;\r\n \r\n try {\r\n await Share.share({\r\n title: this.pdf.title || 'PDF Document',\r\n text: this.pdf.description || '',\r\n url: this.pdf.src,\r\n dialogTitle: 'Share PDF'\r\n });\r\n \r\n console.log('[PDF Lightbox] PDF shared successfully');\r\n } catch (error) {\r\n console.error('[PDF Lightbox] Error sharing PDF:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Close the PDF viewer\r\n */\r\n close(): void {\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Handle like toggle\r\n */\r\n onLikeToggle(): void {\r\n console.log('[PDF Lightbox] Like toggled');\r\n // TODO: Implement like logic for PDFs if needed\r\n }\r\n\r\n /**\r\n * Handle reply/comment\r\n * Close the lightbox and signal to open post detail with comment focus\r\n */\r\n onReply(): void {\r\n console.log('[PDF Lightbox] Reply button clicked');\r\n if (this.onCloseRequested) {\r\n this.onCloseRequested();\r\n // The calling code should handle opening the post detail modal\r\n }\r\n }\r\n}\r\n\r\n","import { Injectable, ApplicationRef, ComponentRef, createComponent, EnvironmentInjector, Injector } from '@angular/core';\r\nimport { DsMobileLightboxImageComponent } from './ds-mobile-lightbox-image';\r\nimport { DsMobileLightboxPdfComponent } from './ds-mobile-lightbox-pdf';\r\n\r\n/**\r\n * Media file types supported by the lightbox\r\n */\r\nexport type LightboxMediaType = 'image' | 'pdf';\r\n\r\n/**\r\n * Base media file interface\r\n */\r\nexport interface LightboxMediaFile {\r\n /** File source URL */\r\n src: string;\r\n /** Media type - determines which viewer to use */\r\n type: LightboxMediaType;\r\n /** File title */\r\n title?: string;\r\n /** File description */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Image data for lightbox display\r\n */\r\nexport interface LightboxImage extends LightboxMediaFile {\r\n type: 'image';\r\n /** Alt text for accessibility */\r\n alt?: string;\r\n /** Thumbnail URL for faster loading (optional) */\r\n thumbnail?: string;\r\n /** Whether the image is liked */\r\n isLiked?: boolean;\r\n /** Number of likes */\r\n likeCount?: number;\r\n /** Number of comments */\r\n commentCount?: number;\r\n}\r\n\r\n/**\r\n * PDF document data for lightbox display\r\n */\r\nexport interface LightboxPdf extends LightboxMediaFile {\r\n type: 'pdf';\r\n /** File size in bytes (optional, for display) */\r\n fileSize?: number;\r\n /** Number of pages (optional, for display) */\r\n pageCount?: number;\r\n}\r\n\r\n/**\r\n * Author metadata for the lightbox\r\n */\r\nexport interface LightboxAuthor {\r\n /** Author name */\r\n name: string;\r\n /** Author role/subtitle */\r\n role?: string;\r\n /** Author avatar URL */\r\n avatarSrc?: string;\r\n /** Author avatar initials (if no photo) */\r\n avatarInitials?: string;\r\n /** Avatar type */\r\n avatarType?: 'photo' | 'initials';\r\n /** Timestamp */\r\n timestamp?: string;\r\n}\r\n\r\n/**\r\n * Configuration options for image lightbox\r\n */\r\nexport interface LightboxImageOptions {\r\n /** Array of images to display */\r\n images: LightboxImage[];\r\n /** Author information to display in header */\r\n author?: LightboxAuthor;\r\n /** Initial image index to show (0-based) */\r\n initialIndex?: number;\r\n /** Enable pinch-to-zoom and double-tap zoom */\r\n enableZoom?: boolean;\r\n /** Show navigation controls (arrows, counter) */\r\n showControls?: boolean;\r\n /** Enable swipe gestures to navigate between images */\r\n enableSwipe?: boolean;\r\n /** Show image info (title, description) */\r\n showInfo?: boolean;\r\n /** Show like & comment action buttons */\r\n showActions?: boolean;\r\n /** Animation type for opening */\r\n animation?: 'fade' | 'zoom' | 'slide';\r\n}\r\n\r\n/**\r\n * Configuration options for PDF lightbox\r\n */\r\nexport interface LightboxPdfOptions {\r\n /** PDF document to display */\r\n pdf: LightboxPdf;\r\n /** Author information to display */\r\n author?: LightboxAuthor;\r\n}\r\n\r\n/**\r\n * Generic lightbox options (for backward compatibility)\r\n */\r\nexport type LightboxOptions = LightboxImageOptions;\r\n\r\n/**\r\n * DsMobileLightboxService\r\n * \r\n * Service for displaying media files (images and PDFs) in full-screen viewers.\r\n * - Images: Full-screen modal with gestures (pinch-zoom, swipe navigation)\r\n * - PDFs: Native device PDF viewer (iOS/Android)\r\n * \r\n * Features:\r\n * - Full-screen image viewing with gestures\r\n * - Native PDF viewing\r\n * - Swipe navigation between images\r\n * - Pinch-to-zoom and double-tap zoom for images\r\n * - Mobile-optimized touch gestures\r\n * - Share functionality\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private lightbox: DsMobileLightboxService) {}\r\n * \r\n * // Open images\r\n * async openImages() {\r\n * const modal = await this.lightbox.openImages({\r\n * images: [\r\n * {\r\n * type: 'image',\r\n * src: 'https://example.com/image1.jpg',\r\n * title: 'Beautiful Sunset'\r\n * }\r\n * ]\r\n * });\r\n * \r\n * // Listen for when lightbox is dismissed\r\n * const { data } = await modal.onDidDismiss();\r\n * if (data?.action === 'comment') {\r\n * // Open post detail modal with comment focus\r\n * this.openPostDetail({ focusComment: true });\r\n * }\r\n * }\r\n * \r\n * // Open PDF\r\n * async openPdf() {\r\n * await this.lightbox.openPdf({\r\n * pdf: {\r\n * type: 'pdf',\r\n * src: 'https://example.com/document.pdf',\r\n * title: 'Document'\r\n * }\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileLightboxService {\r\n private currentLightbox: ComponentRef<any> | null = null;\r\n\r\n constructor(\r\n private appRef: ApplicationRef,\r\n private injector: EnvironmentInjector\r\n ) {}\r\n\r\n /**\r\n * Open the lightbox with images (backward compatible method)\r\n * \r\n * @param options Configuration options for the image lightbox\r\n * @returns Promise that resolves to a dismiss function\r\n */\r\n async open(options: LightboxOptions): Promise<() => void> {\r\n return this.openImages(options);\r\n }\r\n\r\n /**\r\n * Open the image lightbox with one or more images\r\n * \r\n * @param options Configuration options for the image lightbox\r\n * @returns Promise that resolves to a dismiss function\r\n */\r\n async openImages(options: LightboxImageOptions): Promise<() => void> {\r\n console.log('[Lightbox] Opening images with options:', options);\r\n \r\n // Close any existing lightbox\r\n if (this.currentLightbox) {\r\n this.close();\r\n }\r\n\r\n // Create the component\r\n const componentRef = createComponent(DsMobileLightboxImageComponent, {\r\n environmentInjector: this.injector\r\n });\r\n\r\n // Set component props\r\n componentRef.instance.images = options.images;\r\n componentRef.instance.author = options.author;\r\n componentRef.instance.initialIndex = options.initialIndex ?? 0;\r\n componentRef.instance.enableZoom = options.enableZoom !== false;\r\n componentRef.instance.showControls = options.showControls !== false;\r\n componentRef.instance.enableSwipe = options.enableSwipe !== false;\r\n componentRef.instance.showInfo = options.showInfo !== false;\r\n componentRef.instance.showActions = options.showActions ?? false;\r\n componentRef.instance.animation = options.animation ?? 'fade';\r\n \r\n // Set up close callback\r\n componentRef.instance.onCloseRequested = () => {\r\n this.close();\r\n };\r\n\r\n // Attach to application\r\n this.appRef.attachView(componentRef.hostView);\r\n \r\n // Append to body\r\n const domElem = (componentRef.hostView as any).rootNodes[0] as HTMLElement;\r\n document.body.appendChild(domElem);\r\n \r\n // Store reference\r\n this.currentLightbox = componentRef;\r\n\r\n console.log('[Lightbox] Image lightbox rendered');\r\n \r\n // Return dismiss function\r\n return () => this.close();\r\n }\r\n\r\n /**\r\n * Open the PDF lightbox (opens native PDF viewer)\r\n * \r\n * @param options Configuration options for the PDF lightbox\r\n * @returns Promise that resolves to a dismiss function\r\n */\r\n async openPdf(options: LightboxPdfOptions): Promise<() => void> {\r\n console.log('[Lightbox] Opening PDF with options:', options);\r\n \r\n // Close any existing lightbox\r\n if (this.currentLightbox) {\r\n this.close();\r\n }\r\n\r\n // Create the component\r\n const componentRef = createComponent(DsMobileLightboxPdfComponent, {\r\n environmentInjector: this.injector\r\n });\r\n\r\n // Set component props\r\n componentRef.instance.pdf = options.pdf;\r\n componentRef.instance.author = options.author;\r\n \r\n // Set up close callback\r\n componentRef.instance.onCloseRequested = () => {\r\n this.close();\r\n };\r\n\r\n // Attach to application\r\n this.appRef.attachView(componentRef.hostView);\r\n \r\n // Append to body\r\n const domElem = (componentRef.hostView as any).rootNodes[0] as HTMLElement;\r\n document.body.appendChild(domElem);\r\n \r\n // Store reference\r\n this.currentLightbox = componentRef;\r\n\r\n console.log('[Lightbox] PDF lightbox rendered');\r\n \r\n // Return dismiss function\r\n return () => this.close();\r\n }\r\n\r\n /**\r\n * Close the currently open lightbox\r\n */\r\n close(): void {\r\n if (this.currentLightbox) {\r\n const domElem = (this.currentLightbox.hostView as any).rootNodes[0] as HTMLElement;\r\n domElem.remove();\r\n this.appRef.detachView(this.currentLightbox.hostView);\r\n this.currentLightbox.destroy();\r\n this.currentLightbox = null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if a lightbox is currently open\r\n */\r\n isOpen(): boolean {\r\n return this.currentLightbox !== null;\r\n }\r\n}\r\n\r\n","// Components\r\nexport { DsMobileLightboxImageComponent } from './ds-mobile-lightbox-image';\r\nexport { DsMobileLightboxPdfComponent } from './ds-mobile-lightbox-pdf';\r\nexport { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';\r\nexport { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';\r\n\r\n// Service and Types\r\nexport { \r\n DsMobileLightboxService,\r\n type LightboxImage,\r\n type LightboxPdf,\r\n type LightboxMediaFile,\r\n type LightboxMediaType,\r\n type LightboxAuthor,\r\n type LightboxOptions,\r\n type LightboxImageOptions,\r\n type LightboxPdfOptions\r\n} from './ds-mobile-lightbox.service';\r\n\r\n// Legacy export for backward compatibility\r\nexport { DsMobileLightboxImageComponent as DsMobileLightboxComponent } from './ds-mobile-lightbox-image';\r\n\r\n","import { Component, Input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsMobileLightboxService, LightboxImage } from '../lightbox/ds-mobile-lightbox.service';\r\n\r\n/**\r\n * DsMobileInlinePhotoComponent\r\n * \r\n * Displays one or multiple photos in a grid layout optimized for social feeds.\r\n * Supports up to 5 visible images with automatic grid layouts.\r\n * \r\n * Features:\r\n * - Automatic grid layouts for 1-5 images\r\n * - Shows \"+N more\" overlay if more than 5 images\r\n * - Opens lightbox with all images (including hidden ones) when clicked\r\n * - Optimized layouts: 1 full, 2 split, 3 masonry, 4 grid, 5 grid\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-inline-photo\r\n * [images]=\"['img1.jpg', 'img2.jpg', 'img3.jpg']\"\r\n * [author]=\"authorInfo\"\r\n * />\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-inline-photo',\r\n standalone: true,\r\n imports: [CommonModule],\r\n template: `\r\n <div \r\n class=\"photo-grid\" \r\n [attr.data-count]=\"visibleImages.length\"\r\n [class.has-more]=\"hiddenCount > 0\">\r\n @for (image of visibleImages; track image; let i = $index) {\r\n <div \r\n class=\"photo-item\"\r\n [class.last]=\"i === visibleImages.length - 1\"\r\n (click)=\"openLightbox(i, $event)\">\r\n <img \r\n [src]=\"image\" \r\n [alt]=\"'Photo ' + (i + 1)\"\r\n loading=\"lazy\">\r\n \r\n <!-- Show \"+N more\" overlay on last image if there are hidden images -->\r\n @if (i === visibleImages.length - 1 && hiddenCount > 0) {\r\n <div class=\"more-overlay\">\r\n <span class=\"more-text\">+{{ hiddenCount }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n\r\n .photo-grid {\r\n display: grid;\r\n gap: 4px;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n background: var(--ds-color-neutral-100);\r\n width: 100%;\r\n }\r\n\r\n .photo-item {\r\n position: relative;\r\n overflow: hidden;\r\n cursor: pointer;\r\n background: var(--ds-color-neutral-200);\r\n aspect-ratio: 1;\r\n }\r\n\r\n .photo-item img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n display: block;\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n .photo-item:active img {\r\n transform: scale(0.98);\r\n }\r\n\r\n .more-overlay {\r\n position: absolute;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.6);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n pointer-events: none;\r\n }\r\n\r\n .more-text {\r\n color: white;\r\n font-size: 32px;\r\n font-weight: 600;\r\n font-family: var(--ds-font-family-medium);\r\n }\r\n\r\n /* 1 image: full width, 4:3 ratio */\r\n .photo-grid[data-count=\"1\"] {\r\n grid-template-columns: 1fr;\r\n }\r\n \r\n .photo-grid[data-count=\"1\"] .photo-item {\r\n aspect-ratio: 4/3;\r\n }\r\n\r\n /* 2 images: side by side */\r\n .photo-grid[data-count=\"2\"] {\r\n grid-template-columns: 1fr 1fr;\r\n }\r\n\r\n /* 3 images: 1 large left, 2 stacked right */\r\n .photo-grid[data-count=\"3\"] {\r\n grid-template-columns: 2fr 1fr;\r\n grid-auto-rows: 1fr;\r\n }\r\n \r\n .photo-grid[data-count=\"3\"] .photo-item:first-child {\r\n grid-row: 1 / 3;\r\n aspect-ratio: auto;\r\n }\r\n \r\n /* Right side images remain 1:1 squares */\r\n .photo-grid[data-count=\"3\"] .photo-item:nth-child(2),\r\n .photo-grid[data-count=\"3\"] .photo-item:nth-child(3) {\r\n aspect-ratio: 1;\r\n }\r\n\r\n /* 4 images: 2x2 grid */\r\n .photo-grid[data-count=\"4\"] {\r\n grid-template-columns: 1fr 1fr;\r\n grid-template-rows: 1fr 1fr;\r\n }\r\n\r\n /* 5 images: 2 on top, 3 on bottom */\r\n .photo-grid[data-count=\"5\"] {\r\n grid-template-columns: repeat(6, 1fr);\r\n grid-template-rows: auto auto;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item {\r\n aspect-ratio: 1;\r\n width: 100%;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(1) {\r\n grid-column: 1 / 4;\r\n grid-row: 1;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(2) {\r\n grid-column: 4 / 7;\r\n grid-row: 1;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(3) {\r\n grid-column: 1 / 3;\r\n grid-row: 2;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(4) {\r\n grid-column: 3 / 5;\r\n grid-row: 2;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(5) {\r\n grid-column: 5 / 7;\r\n grid-row: 2;\r\n }\r\n\r\n /* Round bottom corners for 5-image layout */\r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(3) {\r\n border-bottom-left-radius: 8px;\r\n overflow: hidden;\r\n }\r\n \r\n .photo-grid[data-count=\"5\"] .photo-item:nth-child(5) {\r\n border-bottom-right-radius: 8px;\r\n overflow: hidden;\r\n }\r\n `]\r\n})\r\nexport class DsMobileInlinePhotoComponent {\r\n /**\r\n * Array of image URLs to display\r\n */\r\n @Input() images: string[] = [];\r\n\r\n /**\r\n * Author information (passed to lightbox)\r\n */\r\n @Input() author?: {\r\n name: string;\r\n role?: string;\r\n avatarSrc?: string;\r\n avatarInitials?: string;\r\n avatarType?: 'photo' | 'initials';\r\n timestamp?: string;\r\n };\r\n\r\n /**\r\n * Maximum number of images to show inline (default: 5)\r\n * Remaining images shown in lightbox only\r\n */\r\n @Input() maxVisible: number = 5;\r\n\r\n /**\r\n * Event emitted when lightbox is opened\r\n */\r\n photoClick = output<{ index: number; totalImages: number }>();\r\n\r\n constructor(private lightboxService: DsMobileLightboxService) {}\r\n\r\n /**\r\n * Get the first N images to display inline\r\n */\r\n get visibleImages(): string[] {\r\n return this.images.slice(0, this.maxVisible);\r\n }\r\n\r\n /**\r\n * Calculate how many images are hidden\r\n */\r\n get hiddenCount(): number {\r\n return Math.max(0, this.images.length - this.maxVisible);\r\n }\r\n\r\n /**\r\n * Open lightbox with all images, starting at the clicked index\r\n */\r\n openLightbox(index: number, event?: Event): void {\r\n // Stop event propagation to prevent triggering parent click handlers\r\n if (event) {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n\r\n // Emit event\r\n this.photoClick.emit({\r\n index,\r\n totalImages: this.images.length\r\n });\r\n\r\n // Convert image URLs to LightboxImage format\r\n const lightboxImages: LightboxImage[] = this.images.map((src, i) => ({\r\n type: 'image',\r\n src,\r\n alt: `Photo ${i + 1}`\r\n }));\r\n\r\n // Open lightbox with all images (not just visible ones)\r\n this.lightboxService.openImages({\r\n images: lightboxImages,\r\n initialIndex: index,\r\n author: this.author,\r\n enableZoom: true,\r\n showControls: true,\r\n enableSwipe: true\r\n });\r\n }\r\n}\r\n\r\n","import { Injectable, Type } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * Configuration options for modal presentation\r\n */\r\nexport interface ModalOptions<T = any> {\r\n /** The component to display in the modal */\r\n component: Type<T>;\r\n /** Props to pass to the component */\r\n componentProps?: Record<string, any>;\r\n /** CSS class(es) to apply to the modal */\r\n cssClass?: string | string[];\r\n /** Modal presentation style */\r\n presentationStyle?: 'fullscreen' | 'card' | 'sheet';\r\n /** Enable backdrop dismiss (tap outside to close) */\r\n backdropDismiss?: boolean;\r\n /** Show backdrop */\r\n showBackdrop?: boolean;\r\n /** Enable keyboard close (ESC key) */\r\n keyboardClose?: boolean;\r\n /** Enable swipe to close */\r\n swipeToClose?: boolean;\r\n /** Initial breakpoint (0-1) for sheet presentation */\r\n initialBreakpoint?: number;\r\n /** Available breakpoints for sheet presentation */\r\n breakpoints?: number[];\r\n /** Animation type */\r\n animated?: boolean;\r\n /** Mode (ios or md) */\r\n mode?: 'ios' | 'md';\r\n /** Whether to handle navigation back button */\r\n handleNavigationBack?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobileModalService\r\n * \r\n * Generic service for displaying any component as a modal.\r\n * Built on Ionic's modal system with customizable presentation styles.\r\n * \r\n * Features:\r\n * - Open any component as a modal\r\n * - Fullscreen, card, or sheet presentation styles\r\n * - Customizable backdrop and dismissal behavior\r\n * - Native gestures and animations\r\n * - Type-safe component props\r\n * \r\n * @example\r\n * ```typescript\r\n * import { MobilePostDetailPageComponent } from './post-detail.page';\r\n * \r\n * constructor(private modal: DsMobileModalService) {}\r\n * \r\n * async openPostModal() {\r\n * await this.modal.open({\r\n * component: MobilePostDetailPageComponent,\r\n * componentProps: {\r\n * postId: '123',\r\n * authorName: 'John Doe'\r\n * },\r\n * presentationStyle: 'card',\r\n * backdropDismiss: true\r\n * });\r\n * }\r\n * ```\r\n * \r\n * @example Sheet presentation with breakpoints\r\n * ```typescript\r\n * async openSheet() {\r\n * await this.modal.open({\r\n * component: CommentsComponent,\r\n * presentationStyle: 'sheet',\r\n * initialBreakpoint: 0.5,\r\n * breakpoints: [0, 0.5, 0.75, 1],\r\n * swipeToClose: true\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open a component as a modal\r\n * \r\n * @param options Configuration options for the modal\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.open({\r\n * component: MyComponent,\r\n * componentProps: { data: 'value' },\r\n * presentationStyle: 'fullscreen'\r\n * });\r\n * ```\r\n */\r\n async open<T = any>(options: ModalOptions<T>): Promise<HTMLIonModalElement> {\r\n console.log('[Modal] Opening modal with options:', options);\r\n \r\n const {\r\n component,\r\n componentProps,\r\n cssClass,\r\n presentationStyle = 'card',\r\n backdropDismiss = true,\r\n showBackdrop = true,\r\n keyboardClose = true,\r\n swipeToClose,\r\n initialBreakpoint,\r\n breakpoints,\r\n animated = true,\r\n mode = 'ios',\r\n handleNavigationBack = true\r\n } = options;\r\n\r\n // Build modal configuration\r\n const modalConfig: any = {\r\n component,\r\n componentProps: componentProps || {},\r\n cssClass: this.buildCssClasses(cssClass, presentationStyle),\r\n mode,\r\n backdropDismiss,\r\n showBackdrop,\r\n animated,\r\n keyboardClose,\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n handle: presentationStyle === 'sheet', // Show handle for sheet presentation\r\n };\r\n\r\n // Add swipe to close for sheet presentation\r\n if (swipeToClose !== undefined) {\r\n modalConfig.canDismiss = swipeToClose;\r\n }\r\n\r\n // Add breakpoints for sheet presentation\r\n if (presentationStyle === 'sheet' && breakpoints) {\r\n modalConfig.breakpoints = breakpoints;\r\n if (initialBreakpoint !== undefined) {\r\n modalConfig.initialBreakpoint = initialBreakpoint;\r\n }\r\n }\r\n\r\n // Handle navigation back button\r\n if (handleNavigationBack) {\r\n modalConfig.canDismiss = async () => {\r\n // You can add custom logic here if needed\r\n return true;\r\n };\r\n }\r\n\r\n const modal = await this.modalController.create(modalConfig);\r\n\r\n console.log('[Modal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[Modal] Modal presented');\r\n\r\n return modal;\r\n }\r\n\r\n /**\r\n * Open a component as a fullscreen modal\r\n * \r\n * @param component Component to display\r\n * @param componentProps Props to pass to the component\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.openFullscreen(PostDetailPage, { postId: '123' });\r\n * ```\r\n */\r\n async openFullscreen<T = any>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>\r\n ): Promise<HTMLIonModalElement> {\r\n return this.open({\r\n component,\r\n componentProps,\r\n presentationStyle: 'fullscreen',\r\n backdropDismiss: false,\r\n showBackdrop: false\r\n });\r\n }\r\n\r\n /**\r\n * Open a component as a card modal\r\n * \r\n * @param component Component to display\r\n * @param componentProps Props to pass to the component\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.openCard(DetailComponent, { itemId: '456' });\r\n * ```\r\n */\r\n async openCard<T = any>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>\r\n ): Promise<HTMLIonModalElement> {\r\n return this.open({\r\n component,\r\n componentProps,\r\n presentationStyle: 'card',\r\n backdropDismiss: true,\r\n showBackdrop: true\r\n });\r\n }\r\n\r\n /**\r\n * Open a component as a bottom sheet\r\n * \r\n * @param component Component to display\r\n * @param componentProps Props to pass to the component\r\n * @param options Additional sheet options (breakpoints, etc.)\r\n * @returns Promise that resolves when the modal is presented\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.openSheet(\r\n * CommentsComponent,\r\n * { postId: '789' },\r\n * { initialBreakpoint: 0.5, breakpoints: [0, 0.5, 1] }\r\n * );\r\n * ```\r\n */\r\n async openSheet<T = any>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>,\r\n options?: {\r\n initialBreakpoint?: number;\r\n breakpoints?: number[];\r\n swipeToClose?: boolean;\r\n }\r\n ): Promise<HTMLIonModalElement> {\r\n return this.open({\r\n component,\r\n componentProps,\r\n presentationStyle: 'sheet',\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n swipeToClose: options?.swipeToClose ?? true,\r\n initialBreakpoint: options?.initialBreakpoint ?? 0.5,\r\n breakpoints: options?.breakpoints ?? [0, 0.5, 0.75, 1]\r\n });\r\n }\r\n\r\n /**\r\n * Close the currently open modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @param role Optional role (e.g., 'cancel', 'confirm')\r\n * @returns Promise that resolves when the modal is dismissed\r\n * \r\n * @example\r\n * ```typescript\r\n * await this.modal.dismiss({ saved: true }, 'confirm');\r\n * ```\r\n */\r\n async dismiss(data?: any, role?: string): Promise<boolean> {\r\n return this.modalController.dismiss(data, role);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n * \r\n * @example\r\n * ```typescript\r\n * const topModal = await this.modal.getTop();\r\n * if (topModal) {\r\n * await topModal.dismiss();\r\n * }\r\n * ```\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n\r\n /**\r\n * Get all currently open modals\r\n * \r\n * @returns Promise that resolves to an array of modal elements\r\n */\r\n async getAll(): Promise<HTMLIonModalElement[]> {\r\n const modals: HTMLIonModalElement[] = [];\r\n let modal = await this.modalController.getTop();\r\n \r\n while (modal) {\r\n modals.push(modal);\r\n // Get the next modal in the stack\r\n await modal.dismiss();\r\n modal = await this.modalController.getTop();\r\n }\r\n \r\n return modals;\r\n }\r\n\r\n /**\r\n * Build CSS classes for the modal\r\n */\r\n private buildCssClasses(\r\n customClass?: string | string[],\r\n presentationStyle?: string\r\n ): string[] {\r\n const classes: string[] = ['ds-mobile-modal'];\r\n \r\n if (presentationStyle) {\r\n classes.push(`ds-modal-${presentationStyle}`);\r\n }\r\n \r\n if (customClass) {\r\n if (Array.isArray(customClass)) {\r\n classes.push(...customClass);\r\n } else {\r\n classes.push(customClass);\r\n }\r\n }\r\n \r\n return classes;\r\n }\r\n}\r\n\r\n","/**\r\n * Mobile Modal Module\r\n * \r\n * Generic service for opening any component as a modal\r\n */\r\n\r\nexport * from './ds-mobile-modal.service';\r\n\r\n","import { Component, signal, computed, CUSTOM_ELEMENTS_SCHEMA, Input, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { IonContent, ModalController } from '@ionic/angular/standalone';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { PostContentComponent, PostTextComponent, PostMediaComponent, PostActionsComponent, ActionLikeComponent, ActionCommentComponent } from '../interactive-list-item-post';\r\nimport { DsMobileCommentComponent } from '../comment/ds-mobile-comment';\r\nimport { DsMobileLightboxService, LightboxAuthor } from '../lightbox';\r\nimport { DsMobileBottomSheetService, DsMobileCommentActionsBottomSheetComponent, CommentActionResult } from '../bottom-sheet';\r\n\r\n/**\r\n * Post data interface for the modal\r\n *\r\n * Represents a post with its content, author info, and comments.\r\n * Use this interface to map your API response data to the component.\r\n *\r\n * @example\r\n * ```typescript\r\n * const postData: PostDetailData = {\r\n * postId: '123',\r\n * authorName: 'John Doe',\r\n * authorRole: 'Tenant',\r\n * timestamp: '2h ago',\r\n * avatarInitials: 'JD',\r\n * content: 'Post content here...',\r\n * likeCount: 42,\r\n * commentCount: 12,\r\n * comments: [...]\r\n * };\r\n * ```\r\n */\r\nexport interface PostDetailData {\r\n /** Unique post identifier */\r\n postId: string;\r\n /** Post author name */\r\n authorName: string;\r\n /** Author role (e.g., 'Tenant', 'Manager') */\r\n authorRole: string;\r\n /** Post timestamp (e.g., '2h ago', 'Yesterday') */\r\n timestamp: string;\r\n /** Author avatar initials (1-2 letters) */\r\n avatarInitials?: string;\r\n /** Avatar display type */\r\n avatarType?: 'photo' | 'initials';\r\n /** Author avatar image URL */\r\n avatarSrc?: string;\r\n /** Post text content */\r\n content: string;\r\n /** Optional post image URL */\r\n imageSrc?: string;\r\n /** Image alt text */\r\n imageAlt?: string;\r\n /** Whether the current user has liked this post */\r\n isLiked?: boolean;\r\n /** Number of likes */\r\n likeCount?: number;\r\n /** Number of comments */\r\n commentCount?: number;\r\n /** Array of comments */\r\n comments?: CommentData[];\r\n /** Auto-focus comment input when modal opens */\r\n focusComment?: boolean;\r\n}\r\n\r\n/**\r\n * Comment data interface\r\n *\r\n * Represents a single comment on a post.\r\n *\r\n * @example\r\n * ```typescript\r\n * const comment: CommentData = {\r\n * authorName: 'Jane Smith',\r\n * authorRole: 'Tenant',\r\n * timestamp: '1h ago',\r\n * avatarInitials: 'JS',\r\n * content: 'Great post!',\r\n * isLiked: false,\r\n * likeCount: 5,\r\n * isOwnComment: false\r\n * };\r\n * ```\r\n */\r\nexport interface CommentData {\r\n /** Unique comment identifier */\r\n id?: string;\r\n /** Comment author name */\r\n authorName: string;\r\n /** Author role */\r\n authorRole: string;\r\n /** Comment timestamp */\r\n timestamp: string;\r\n /** Author avatar initials */\r\n avatarInitials: string;\r\n /** Comment text content */\r\n content: string;\r\n /** Whether the current user has liked this comment */\r\n isLiked?: boolean;\r\n /** Number of likes on this comment */\r\n likeCount?: number;\r\n /** Whether this comment belongs to the current user */\r\n isOwnComment?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobilePostDetailModalComponent\r\n *\r\n * Modal wrapper for displaying post details with comments.\r\n * Follows the same pattern as the lightbox modal for consistent behavior.\r\n *\r\n * Features:\r\n * - Full post content display\r\n * - Comments section\r\n * - Image lightbox integration\r\n * - Native modal controls (close, swipe down)\r\n * - Safe area support\r\n *\r\n * This component is typically not used directly - use DsMobilePostDetailModalService instead.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private postModal: DsMobilePostDetailModalService) {}\r\n *\r\n * openPost() {\r\n * this.postModal.open({\r\n * postId: '123',\r\n * authorName: 'John Doe',\r\n * content: 'Post content...'\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-post-detail-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsIconComponent,\r\n DsAvatarComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCommentComponent,\r\n ],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"post-modal-content\">\r\n <div class=\"post-modal-wrapper\">\r\n <!-- Header with post author info -->\r\n <div class=\"post-modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Post author info -->\r\n <div class=\"post-author-info\">\r\n <ds-avatar [initials]=\"post().avatarInitials || ''\" [type]=\"post().avatarType || 'initials'\" [src]=\"post().avatarSrc || ''\" size=\"md\" />\r\n <div class=\"author-details\">\r\n <div class=\"author-name\">{{ post().authorName }}</div>\r\n <div class=\"author-meta\">\r\n <span>{{ post().authorRole }}</span>\r\n <span class=\"separator\">·</span>\r\n <span>{{ post().timestamp }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Close button -->\r\n <ds-icon-button icon=\"remixCloseLine\" variant=\"secondary\" size=\"lg\" (click)=\"close()\" class=\"close-button\" aria-label=\"Luk opslag\"> </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Post content -->\r\n <div class=\"post-detail-container\">\r\n @if (loading) {\r\n <!-- Loading State -->\r\n <div class=\"post-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading post...</p>\r\n </div>\r\n } @else if (error) {\r\n <!-- Error State -->\r\n <div class=\"post-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error loading post</h3>\r\n <p class=\"error-state-description\">{{ error }}</p>\r\n </div>\r\n } @else {\r\n <!-- Post Section -->\r\n <div class=\"post-section\">\r\n <div class=\"post-content-only\">\r\n <post-text>\r\n <div [innerHTML]=\"post().content\"></div>\r\n </post-text>\r\n @if (post().imageSrc) {\r\n <post-media>\r\n <img [src]=\"post().imageSrc\" [alt]=\"post().imageAlt || 'Post image'\" class=\"clickable-image\" (click)=\"openImageLightbox()\" />\r\n </post-media>\r\n }\r\n </div>\r\n\r\n <!-- Post actions -->\r\n <div class=\"post-actions\">\r\n <action-like [active]=\"post().isLiked || false\" [count]=\"post().likeCount || 0\" />\r\n <action-comment [count]=\"post().commentCount || 0\" (commentClick)=\"focusCommentInput()\" />\r\n </div>\r\n </div>\r\n\r\n <!-- Comments Section -->\r\n <div class=\"comments-section\">\r\n @if (post().comments && post().comments!.length > 0) {\r\n <h2 class=\"comments-header\">{{ post().comments!.length }} {{ post().comments!.length === 1 ? 'reply' : 'replies' }}</h2>\r\n\r\n <div class=\"comments-list\">\r\n @for (comment of post().comments!; track comment.id || comment.authorName + comment.timestamp) {\r\n <ds-mobile-comment\r\n [authorName]=\"comment.authorName\"\r\n [authorRole]=\"comment.authorRole\"\r\n [timestamp]=\"comment.timestamp\"\r\n [avatarInitials]=\"comment.avatarInitials\"\r\n [content]=\"comment.content\"\r\n [isLiked]=\"comment.isLiked || false\"\r\n [likeCount]=\"comment.likeCount || 0\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"comment.isOwnComment || false\"\r\n (likeToggled)=\"handleCommentLikeToggle(comment, $event)\"\r\n (replyClick)=\"handleReply(comment.authorName, comment.content)\"\r\n (editClick)=\"handleEditComment(comment)\"\r\n (longPress)=\"handleCommentLongPress(comment.authorName, comment.content, comment.isOwnComment || false)\" />\r\n }\r\n </div>\r\n } @else {\r\n <!-- Empty State -->\r\n <div class=\"comments-empty-state\">\r\n <img src=\"/Assets/Empty%20state-chat.png\" alt=\"Ingen kommentarer endnu\" class=\"empty-state-image\" />\r\n <h3 class=\"empty-state-title\">Ingen svar endnu</h3>\r\n <p class=\"empty-state-description\">Vær den første til at svare på dette opslag</p>\r\n </div>\r\n }\r\n\r\n <!-- Bottom spacer for fixed composer -->\r\n <div class=\"composer-spacer\"></div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n\r\n <!-- Fixed comment composer -->\r\n @if (!loading && !error) {\r\n <div class=\"comment-composer-fixed\">\r\n <div class=\"comment-composer\">\r\n <!-- Edit indicator -->\r\n @if (editingComment()) {\r\n <div class=\"edit-indicator\">\r\n <div class=\"edit-indicator-content\">\r\n <ds-icon name=\"remixEditLine\" size=\"16px\" />\r\n <span class=\"edit-text\">Redigerer kommentar</span>\r\n </div>\r\n <button class=\"cancel-edit\" (click)=\"cancelEdit()\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n } @else if (replyingTo()) {\r\n <!-- Reply indicator -->\r\n <div class=\"reply-indicator\">\r\n <div class=\"reply-indicator-content\">\r\n <ds-icon name=\"remixReplyLine\" size=\"16px\" />\r\n <span class=\"reply-to-text\">\r\n Svarer til <span class=\"reply-author\">{{ replyingTo()!.authorName }}</span>\r\n </span>\r\n </div>\r\n <button class=\"cancel-reply\" (click)=\"cancelReply()\">\r\n <ds-icon name=\"remixCloseLine\" size=\"16px\" />\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"composer-content\">\r\n <ds-avatar [initials]=\"currentUserInitials()\" [type]=\"'initials'\" size=\"md\" />\r\n <div class=\"composer-input-wrapper\">\r\n <!-- Mention menu -->\r\n @if (showMentionMenu() && filteredUsers().length > 0 && !editingComment()) {\r\n <div class=\"mention-menu\">\r\n @for (user of filteredUsers(); track user.name) {\r\n <button class=\"mention-menu-item\" (click)=\"selectMention(user.name)\">\r\n <ds-avatar [initials]=\"user.initials\" [type]=\"'initials'\" size=\"sm\" />\r\n <div class=\"mention-user-info\">\r\n <span class=\"mention-user-name\">{{ user.name }}</span>\r\n <span class=\"mention-user-role\">{{ user.role }}</span>\r\n </div>\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <textarea\r\n #commentInput\r\n class=\"composer-input\"\r\n [placeholder]=\"editingComment() ? 'Rediger din kommentar...' : replyingTo() ? 'Tilføj et svar...' : 'Tilføj et svar...'\"\r\n [ngModel]=\"commentText()\"\r\n (ngModelChange)=\"commentText.set($event)\"\r\n (input)=\"handleInput($event)\"\r\n (focus)=\"showKeyboard()\"\r\n (click)=\"showKeyboard()\"\r\n rows=\"1\"></textarea>\r\n </div>\r\n @if (commentText().trim().length > 0) {\r\n <ds-icon-button icon=\"remixCheckLine\" variant=\"primary\" size=\"sm\" (clicked)=\"submitComment()\" aria-label=\"Send kommentar\" class=\"send-button-fixed\"> </ds-icon-button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n `,\r\n styles: [\r\n `\r\n :host {\r\n display: block;\r\n position: relative;\r\n height: 100%;\r\n width: 100%;\r\n }\r\n\r\n .post-modal-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .post-modal-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n min-height: 100dvh; /* Use dynamic viewport height for proper iOS safe area handling */\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .post-modal-header {\r\n position: sticky;\r\n top: 0;\r\n z-index: 10;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 16px;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 72px;\r\n /* No padding needed - StatusBar.setOverlaysWebView(false) handles all spacing */\r\n }\r\n\r\n .post-author-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .author-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n /* Author name and meta styles imported from mobile-common.css */\r\n\r\n .author-meta .separator {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n\r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n\r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .post-detail-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n padding: 16px 0 20px 0;\r\n flex: 1;\r\n }\r\n\r\n .post-section {\r\n width: 100%;\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 0 16px 0;\r\n }\r\n\r\n .post-content-only {\r\n font-size: var(--font-size-sm);\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin-bottom: 16px;\r\n padding: 0 20px;\r\n }\r\n\r\n .post-content-only post-media {\r\n margin-top: 16px;\r\n }\r\n\r\n .post-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n padding: 0 20px;\r\n }\r\n\r\n .clickable-image {\r\n cursor: pointer;\r\n transition: transform 0.2s ease, opacity 0.2s ease;\r\n border-radius: 8px;\r\n display: block;\r\n width: 100%;\r\n aspect-ratio: 16/9;\r\n object-fit: cover;\r\n }\r\n\r\n .clickable-image:active {\r\n transform: scale(0.98);\r\n opacity: 0.9;\r\n }\r\n\r\n .comments-section {\r\n display: flex;\r\n flex-direction: column;\r\n margin-left: 0;\r\n margin-right: 0;\r\n padding: 0 20px;\r\n padding-bottom: 0;\r\n }\r\n\r\n .comments-header {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0 0 16px 0;\r\n padding-left: 0;\r\n padding-right: 0;\r\n }\r\n\r\n .comments-list {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n /* Empty State */\r\n .comments-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n\r\n .empty-state-image {\r\n width: 96px;\r\n height: 96px;\r\n margin-bottom: 24px;\r\n }\r\n\r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0 0 8px 0;\r\n }\r\n\r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n\r\n .composer-spacer {\r\n /* Match full composer height + safe area:\r\n - Composer height: ~81px + safe area\r\n - Top offset is handled by margin-top on modal content, not needed here */\r\n height: calc(81px + env(safe-area-inset-bottom, 0px));\r\n }\r\n\r\n .bottom-spacer {\r\n height: 0px;\r\n }\r\n\r\n /* Fixed Comment Composer Container */\r\n .comment-composer-fixed {\r\n position: fixed;\r\n bottom: 0; /* Align with bottom of viewport - modal content has margin-top for top offset */\r\n left: 0;\r\n right: 0;\r\n z-index: 1000;\r\n pointer-events: none;\r\n /* Slide up with keyboard on native apps */\r\n transform: translateY(calc(-1 * var(--keyboard-height, 0px)));\r\n transition: transform 0.3s ease-out;\r\n /* Ensure it's within the modal viewport */\r\n max-width: 100vw;\r\n }\r\n\r\n /* Comment Composer */\r\n .comment-composer {\r\n pointer-events: auto;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-top: 1px solid var(--border-color-default);\r\n padding: 12px 16px;\r\n /* Use dynamic viewport height safe area - matches tabs fix */\r\n /* For web browsers: 12px default; for native iOS: env(safe-area-inset-bottom) */\r\n padding-bottom: max(12px, env(safe-area-inset-bottom, 0px));\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n /* White box shadow to cover content gap between keyboard and composer */\r\n box-shadow: 100px 150px 0 150px var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n /* Edit indicator */\r\n .edit-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-brand-subtle, #f0edfe);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n\r\n .edit-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: var(--color-brand-base, #6b5ff5);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .edit-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 500;\r\n line-height: 18px;\r\n color: var(--color-brand-base, #6b5ff5);\r\n }\r\n\r\n .cancel-edit {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-brand-base, #6b5ff5);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .cancel-edit:active {\r\n background: var(--color-brand-subtle, #e0dbfe);\r\n }\r\n\r\n /* Reply indicator */\r\n .reply-indicator {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 8px;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n\r\n .reply-indicator-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n color: var(--color-text-secondary, #737373);\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .reply-to-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .reply-author {\r\n color: var(--color-brand-base, #6b5ff5);\r\n font-weight: 600;\r\n }\r\n\r\n .cancel-reply {\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-text-secondary, #737373);\r\n border-radius: 4px;\r\n transition: background 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .cancel-reply:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n\r\n @keyframes slideDown {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .composer-content {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n width: 100%;\r\n position: relative;\r\n }\r\n\r\n .composer-content ds-avatar {\r\n position: relative;\r\n top: 6px;\r\n }\r\n\r\n .composer-input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 8px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 24px;\r\n padding: 12px 16px;\r\n padding-right: 48px; /* Extra padding for fixed send button */\r\n min-height: 44px;\r\n position: relative;\r\n }\r\n\r\n /* Mention menu */\r\n .mention-menu {\r\n position: absolute;\r\n bottom: 100%;\r\n left: 0;\r\n right: 0;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-radius: 12px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n margin-bottom: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n z-index: 10;\r\n animation: slideUp 0.2s ease-out;\r\n }\r\n\r\n @keyframes slideUp {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .mention-menu-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 12px;\r\n border: none;\r\n background: none;\r\n width: 100%;\r\n text-align: left;\r\n cursor: pointer;\r\n transition: background 0.2s ease;\r\n border-bottom: 1px solid var(--border-color-default);\r\n }\r\n\r\n .mention-menu-item:last-child {\r\n border-bottom: none;\r\n }\r\n\r\n .mention-menu-item:active {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n }\r\n\r\n .mention-user-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .mention-user-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n\r\n .mention-user-role {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 18px;\r\n color: var(--color-text-secondary, #737373);\r\n }\r\n\r\n .composer-input {\r\n flex: 1;\r\n border: none;\r\n background: transparent;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n outline: none;\r\n resize: none;\r\n min-height: 20px;\r\n max-height: 120px;\r\n overflow-y: auto;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n\r\n .composer-input::placeholder {\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n font-size: var(--font-size-sm);\r\n }\r\n\r\n /* Style the send button (ds-icon-button) - positioned in top right corner */\r\n .send-button-fixed {\r\n position: absolute;\r\n top: 6px;\r\n right: 6px;\r\n z-index: 10;\r\n flex-shrink: 0;\r\n animation: slideInFromRight 0.2s ease-out;\r\n }\r\n\r\n .send-button-fixed::ng-deep button {\r\n width: 32px !important;\r\n height: 32px !important;\r\n min-width: 32px !important;\r\n min-height: 32px !important;\r\n padding: 0 !important;\r\n border-radius: 50% !important;\r\n }\r\n\r\n /* Keep old style for reference but won't be used */\r\n .composer-input-wrapper ds-icon-button {\r\n flex-shrink: 0;\r\n animation: slideInFromRight 0.2s ease-out;\r\n }\r\n\r\n .composer-input-wrapper ds-icon-button::ng-deep button {\r\n width: 32px !important;\r\n height: 32px !important;\r\n min-width: 32px !important;\r\n min-height: 32px !important;\r\n padding: 0 !important;\r\n border-radius: 50% !important;\r\n }\r\n\r\n /* Slide in animation from right */\r\n @keyframes slideInFromRight {\r\n from {\r\n opacity: 0;\r\n transform: translateX(20px) scale(0.8);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateX(0) scale(1);\r\n }\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .post-detail-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n\r\n /* Loading State */\r\n .post-loading-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n\r\n .loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 3px solid var(--color-background-neutral-secondary, #f0f0f0);\r\n border-top-color: var(--color-primary-base, #2563eb);\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n\r\n @keyframes spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n\r\n .loading-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin-top: 16px;\r\n }\r\n\r\n /* Error State */\r\n .post-error-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n gap: 16px;\r\n }\r\n\r\n .error-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n\r\n .error-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class DsMobilePostDetailModalComponent implements AfterViewInit, OnDestroy {\r\n // Post data passed from service\r\n @Input() postData!: PostDetailData;\r\n\r\n // Current user info for comment composer\r\n @Input() currentUserName: string = '';\r\n @Input() currentUserInitialsInput: string = '';\r\n\r\n // Callback for submitting a new comment\r\n @Input() onSubmitComment?: (payload: { postId: string; text: string }) => void;\r\n\r\n // Callback for liking/unliking a comment\r\n @Input() onToggleCommentLike?: (payload: { commentId: string; active: boolean }) => void;\r\n\r\n // Callback for editing a comment\r\n @Input() onEditComment?: (payload: { commentId: string; newText: string }) => void;\r\n\r\n // Callback for deleting a comment\r\n @Input() onDeleteComment?: (payload: { commentId: string }) => void;\r\n\r\n /**\r\n * Loading state - when true, shows loading indicator\r\n * Set this to true while fetching post data from your API\r\n */\r\n @Input() loading: boolean = false;\r\n\r\n /**\r\n * Error state - when set, shows error message\r\n * Set this to an error message string if API call fails\r\n */\r\n @Input() error?: string;\r\n\r\n // ViewChild for comment input\r\n @ViewChild('commentInput') commentInput?: ElementRef<HTMLTextAreaElement>;\r\n\r\n // Signal for reactive post data\r\n post = signal<PostDetailData>({\r\n postId: '',\r\n authorName: '',\r\n authorRole: '',\r\n timestamp: '',\r\n content: '',\r\n comments: [],\r\n });\r\n\r\n // Comment composer state\r\n commentText = signal('');\r\n currentUserInitials = signal('');\r\n replyingTo = signal<{ authorName: string; content: string } | null>(null);\r\n editingComment = signal<{ id?: string; authorName: string; originalContent: string; timestamp: string } | null>(null);\r\n\r\n // Mention menu state\r\n showMentionMenu = signal(false);\r\n mentionQuery = signal('');\r\n\r\n // Get available users to mention (post author + commenters)\r\n availableUsers = computed(() => {\r\n const post = this.post();\r\n const users: Array<{ name: string; initials: string; role: string }> = [];\r\n\r\n // Add post author\r\n users.push({\r\n name: post.authorName,\r\n initials:\r\n post.avatarInitials ||\r\n post.authorName\r\n .split(' ')\r\n .map((n) => n[0])\r\n .join(''),\r\n role: post.authorRole,\r\n });\r\n\r\n // Add unique commenters\r\n const commenterNames = new Set<string>();\r\n post.comments?.forEach((comment) => {\r\n if (!commenterNames.has(comment.authorName)) {\r\n commenterNames.add(comment.authorName);\r\n users.push({\r\n name: comment.authorName,\r\n initials: comment.avatarInitials,\r\n role: comment.authorRole,\r\n });\r\n }\r\n });\r\n\r\n return users;\r\n });\r\n\r\n // Filtered users based on mention query\r\n filteredUsers = computed(() => {\r\n const query = this.mentionQuery().toLowerCase();\r\n if (!query) return this.availableUsers();\r\n return this.availableUsers().filter((user) => user.name.toLowerCase().includes(query));\r\n });\r\n\r\n constructor(private modalController: ModalController, private lightbox: DsMobileLightboxService, private bottomSheet: DsMobileBottomSheetService) {}\r\n\r\n ngOnInit(): void {\r\n // Initialize post data from input\r\n if (this.postData) {\r\n this.post.set(this.postData);\r\n }\r\n\r\n // Set current user initials\r\n if (this.currentUserInitialsInput) {\r\n this.currentUserInitials.set(this.currentUserInitialsInput);\r\n } else if (this.currentUserName) {\r\n // fallback: derive from name\r\n const initials = this.currentUserName\r\n .trim()\r\n .split(/\\s+/)\r\n .map((p) => p[0])\r\n .join('')\r\n .substring(0, 2)\r\n .toUpperCase();\r\n this.currentUserInitials.set(initials);\r\n }\r\n\r\n // Set up keyboard listeners to update CSS variable for composer positioning\r\n this.setupKeyboardListeners();\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n // Auto-focus comment input if requested\r\n if (this.postData?.focusComment) {\r\n // Small delay to ensure modal animation is complete\r\n setTimeout(() => {\r\n this.commentInput?.nativeElement.focus();\r\n // Show keyboard on mobile\r\n this.showKeyboard();\r\n }, 300);\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n // Clean up keyboard listeners when modal is destroyed\r\n this.cleanupKeyboardListeners();\r\n }\r\n\r\n /**\r\n * Set up keyboard event listeners to adjust composer position\r\n * The CSS uses --keyboard-height variable to translate the composer up\r\n */\r\n private setupKeyboardListeners(): void {\r\n Keyboard.addListener('keyboardWillShow', (info) => {\r\n document.documentElement.style.setProperty('--keyboard-height', `${info.keyboardHeight}px`);\r\n }).catch((e) => console.log('Keyboard listeners not available:', e));\r\n\r\n Keyboard.addListener('keyboardWillHide', () => {\r\n document.documentElement.style.setProperty('--keyboard-height', '0px');\r\n }).catch((e) => console.log('Keyboard listeners not available:', e));\r\n }\r\n\r\n /**\r\n * Clean up keyboard event listeners\r\n */\r\n private cleanupKeyboardListeners(): void {\r\n Keyboard.removeAllListeners().catch((e) => console.log('Keyboard cleanup not available:', e));\r\n }\r\n\r\n /**\r\n * Show the keyboard when user interacts with input\r\n */\r\n showKeyboard(): void {\r\n Keyboard.show().catch((e) => console.log('Keyboard.show() not available'));\r\n }\r\n\r\n /**\r\n * Focus the comment input when comment icon is tapped\r\n */\r\n focusCommentInput(): void {\r\n // Focus the input\r\n this.commentInput?.nativeElement.focus();\r\n // Show keyboard on mobile\r\n this.showKeyboard();\r\n }\r\n\r\n /**\r\n * Handle input changes and detect @ mentions\r\n */\r\n handleInput(event: Event): void {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n const text = textarea.value;\r\n const cursorPosition = textarea.selectionStart || 0;\r\n\r\n // Auto-resize textarea\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n\r\n // Find the last @ before cursor\r\n const textBeforeCursor = text.substring(0, cursorPosition);\r\n const lastAtIndex = textBeforeCursor.lastIndexOf('@');\r\n\r\n if (lastAtIndex !== -1) {\r\n // Check if there's a space after @\r\n const textAfterAt = textBeforeCursor.substring(lastAtIndex + 1);\r\n const hasSpace = textAfterAt.includes(' ');\r\n\r\n if (!hasSpace) {\r\n // Show mention menu\r\n this.showMentionMenu.set(true);\r\n this.mentionQuery.set(textAfterAt);\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n } else {\r\n this.showMentionMenu.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * Select a user from mention menu - show as reply indicator instead of inline mention\r\n */\r\n selectMention(userName: string): void {\r\n // Set as reply (similar to clicking Reply on a comment)\r\n this.replyingTo.set({ authorName: userName, content: '' });\r\n\r\n // Clear the @ from the input\r\n const currentText = this.commentText();\r\n const textWithoutMention = currentText.substring(0, currentText.lastIndexOf('@'));\r\n this.commentText.set(textWithoutMention);\r\n\r\n // Hide mention menu\r\n this.showMentionMenu.set(false);\r\n\r\n // Focus back on input\r\n setTimeout(() => {\r\n this.commentInput?.nativeElement.focus();\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Handle reply to a comment\r\n */\r\n handleReply(authorName: string, content: string): void {\r\n this.replyingTo.set({ authorName, content });\r\n // Focus the input and show keyboard\r\n setTimeout(() => {\r\n this.commentInput?.nativeElement.focus();\r\n this.showKeyboard();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Cancel reply\r\n */\r\n cancelReply(): void {\r\n this.replyingTo.set(null);\r\n }\r\n\r\n /**\r\n * Cancel edit\r\n */\r\n cancelEdit(): void {\r\n this.editingComment.set(null);\r\n this.commentText.set('');\r\n }\r\n\r\n /**\r\n * Handle edit comment\r\n */\r\n handleEditComment(comment: CommentData): void {\r\n // Clear reply state if active\r\n this.replyingTo.set(null);\r\n\r\n // Remove @mention from the content if it exists\r\n let contentToEdit = comment.content;\r\n const mentionMatch = contentToEdit.match(/^@([A-Za-z]+(?:\\s+[A-Za-z]+)?)\\s+/);\r\n if (mentionMatch) {\r\n contentToEdit = contentToEdit.substring(mentionMatch[0].length);\r\n }\r\n\r\n // Set edit state\r\n this.editingComment.set({\r\n id: comment.id,\r\n authorName: comment.authorName,\r\n originalContent: comment.content,\r\n timestamp: comment.timestamp,\r\n });\r\n\r\n // Populate the input with existing content\r\n this.commentText.set(contentToEdit);\r\n\r\n // Focus the input, show keyboard, and auto-resize\r\n setTimeout(() => {\r\n if (this.commentInput?.nativeElement) {\r\n const textarea = this.commentInput.nativeElement;\r\n textarea.focus();\r\n\r\n // Auto-resize textarea to fit content\r\n textarea.style.height = 'auto';\r\n textarea.style.height = textarea.scrollHeight + 'px';\r\n\r\n this.showKeyboard();\r\n }\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Handle comment like/unlike toggle\r\n * @param comment The comment being liked/unliked\r\n * @param ev Event data with active state and new count\r\n */\r\n handleCommentLikeToggle(comment: CommentData, ev: { active: boolean; count: number }): void {\r\n // Update local state immediately for responsiveness\r\n const currentPost = this.post();\r\n const updatedComments = currentPost.comments?.map((c) => (c.id === comment.id ? { ...c, isLiked: ev.active, likeCount: ev.count } : c));\r\n\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedComments,\r\n });\r\n\r\n // Call the callback if provided\r\n if (this.onToggleCommentLike) {\r\n this.onToggleCommentLike({\r\n commentId: comment.id!,\r\n active: ev.active,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n\r\n /**\r\n * Submit a comment\r\n */\r\n submitComment(): void {\r\n const text = this.commentText().trim();\r\n if (!text) return;\r\n\r\n const currentPost = this.post();\r\n const postId = currentPost.postId;\r\n\r\n // Create new comment\r\n const finalText = this.replyingTo() ? `@${this.replyingTo()!.authorName} ${text}` : text;\r\n\r\n // Check if we're editing an existing comment\r\n if (this.editingComment()) {\r\n console.log('[PostDetailModal] Updating comment:', text);\r\n\r\n const editing = this.editingComment()!;\r\n\r\n const updatedComments = currentPost.comments?.map((comment) => {\r\n if (comment.id && editing.id && comment.id === editing.id) {\r\n return {\r\n ...comment,\r\n content: text,\r\n timestamp: 'Just now (edited)',\r\n };\r\n }\r\n return comment;\r\n });\r\n\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedComments,\r\n });\r\n\r\n // Call the edit callback\r\n if (this.onEditComment && editing.id) {\r\n this.onEditComment({\r\n commentId: editing.id,\r\n newText: finalText, // or finalText if you want to include @mention\r\n });\r\n }\r\n\r\n this.editingComment.set(null);\r\n } else {\r\n console.log('[PostDetailModal] Submitting comment:', finalText);\r\n console.log('[PostDetailModal] onSubmitComment =', this.onSubmitComment);\r\n\r\n const newComment: CommentData = {\r\n authorName: this.currentUserName || 'Dig',\r\n authorRole: 'Dig',\r\n timestamp: 'Just now',\r\n avatarInitials: this.currentUserInitials(),\r\n content: finalText,\r\n isLiked: false,\r\n likeCount: 0,\r\n isOwnComment: true,\r\n };\r\n\r\n // Add comment to the list\r\n const updatedComments = [...(currentPost.comments || []), newComment];\r\n\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedComments,\r\n commentCount: updatedComments.length,\r\n });\r\n\r\n // Clear reply state\r\n this.replyingTo.set(null);\r\n }\r\n\r\n // Clear the input\r\n this.commentText.set('');\r\n this.showMentionMenu.set(false);\r\n\r\n if (this.commentInput?.nativeElement) {\r\n // Reset textarea height to initial state\r\n this.commentInput.nativeElement.style.height = 'auto';\r\n // Blur the input to hide the keyboard\r\n this.commentInput?.nativeElement.blur();\r\n }\r\n\r\n // Hide keyboard explicitly\r\n Keyboard.hide().catch(() => {});\r\n\r\n // In a real app, you would also send this to your backend\r\n // this.commentService.addComment(currentPost.postId, text);\r\n if (this.onSubmitComment) {\r\n this.onSubmitComment({ postId, text: finalText });\r\n }\r\n }\r\n\r\n /**\r\n * Open image in lightbox\r\n */\r\n openImageLightbox(): void {\r\n const postData = this.post();\r\n\r\n if (!postData.imageSrc) return;\r\n\r\n const authorMeta: LightboxAuthor = {\r\n name: postData.authorName,\r\n role: postData.authorRole,\r\n avatarInitials: postData.avatarInitials || '',\r\n avatarType: postData.avatarType || 'initials',\r\n avatarSrc: postData.avatarSrc || '',\r\n timestamp: postData.timestamp,\r\n };\r\n\r\n this.lightbox.open({\r\n images: [\r\n {\r\n type: 'image',\r\n src: postData.imageSrc,\r\n alt: postData.imageAlt || 'Post image',\r\n title: postData.imageAlt || '',\r\n description: postData.content,\r\n isLiked: postData.isLiked || false,\r\n likeCount: postData.likeCount || 0,\r\n commentCount: postData.commentCount || 0,\r\n },\r\n ],\r\n author: authorMeta,\r\n enableZoom: true,\r\n showControls: false,\r\n showInfo: true,\r\n });\r\n }\r\n\r\n /**\r\n * Handle long press on a comment to show action sheet\r\n */\r\n async handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void> {\r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobileCommentActionsBottomSheetComponent,\r\n componentProps: {\r\n isOwnContent: isOwnComment,\r\n },\r\n breakpoints: [0, 1],\r\n initialBreakpoint: 1,\r\n handle: true,\r\n backdropDismiss: true,\r\n cssClass: 'auto-height',\r\n });\r\n\r\n const result = await sheet.onWillDismiss();\r\n\r\n if (result.role === 'select' && result.data) {\r\n const action = (result.data as CommentActionResult).action;\r\n const currentPost = this.post();\r\n\r\n switch (action) {\r\n case 'like':\r\n console.log('Like comment by', authorName);\r\n let toggledCommentId: string | null = null;\r\n let newActive = false;\r\n // Update the comment like state locally\r\n const updatedComments = currentPost.comments?.map((comment) => {\r\n if (comment.authorName === authorName && comment.content === content) {\r\n newActive = !comment.isLiked;\r\n toggledCommentId = comment.id!;\r\n\r\n return {\r\n ...comment,\r\n isLiked: newActive,\r\n likeCount: newActive ? (comment.likeCount || 0) + 1 : Math.max(0, (comment.likeCount || 0) - 1),\r\n };\r\n }\r\n return comment;\r\n });\r\n\r\n this.post.set({ ...currentPost, comments: updatedComments });\r\n\r\n // Call the like callback\r\n if (toggledCommentId && this.onToggleCommentLike) {\r\n this.onToggleCommentLike({\r\n commentId: toggledCommentId,\r\n active: newActive,\r\n });\r\n }\r\n break;\r\n case 'reply':\r\n console.log('Reply to comment by', authorName);\r\n this.handleReply(authorName, content);\r\n break;\r\n case 'edit':\r\n console.log('Edit comment by', authorName);\r\n // Find the full comment data to get timestamp\r\n const commentToEdit = currentPost.comments?.find((comment) => comment.authorName === authorName && comment.content === content);\r\n if (commentToEdit) {\r\n this.handleEditComment(commentToEdit);\r\n }\r\n break;\r\n case 'delete':\r\n console.log('Delete comment by', authorName);\r\n // Show confirmation before deleting\r\n if (confirm('Are you sure you want to delete this comment?')) {\r\n const commentToDelete = currentPost.comments?.find((comment) => comment.authorName === authorName && comment.content === content);\r\n const updatedCommentsAfterDelete = currentPost.comments?.filter((comment) => !(comment.authorName === authorName && comment.content === content));\r\n this.post.set({\r\n ...currentPost,\r\n comments: updatedCommentsAfterDelete,\r\n commentCount: updatedCommentsAfterDelete?.length || 0,\r\n });\r\n\r\n // Call the delete callback\r\n if (commentToDelete?.id && this.onDeleteComment) {\r\n this.onDeleteComment({ commentId: commentToDelete.id });\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobilePostDetailModalComponent, PostDetailData } from './ds-mobile-post-detail-modal';\r\n\r\n/**\r\n * DsMobilePostDetailModalService\r\n *\r\n * Service for displaying post details in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * Follows the same pattern as DsMobileLightboxService for consistent behavior.\r\n *\r\n * Features:\r\n * - Full post content display\r\n * - Comments section\r\n * - Like/comment actions\r\n * - Image lightbox integration\r\n * - Native modal animations\r\n * - Safe area support\r\n *\r\n * @example\r\n * ```typescript\r\n * constructor(private postModal: DsMobilePostDetailModalService) {}\r\n *\r\n * async openPost() {\r\n * await this.postModal.open({\r\n * postId: '123',\r\n * authorName: 'John Doe',\r\n * authorRole: 'Tenant',\r\n * timestamp: '2h ago',\r\n * avatarInitials: 'JD',\r\n * content: 'Just moved into my new apartment!',\r\n * isLiked: false,\r\n * likeCount: 42,\r\n * commentCount: 12,\r\n * comments: [\r\n * {\r\n * authorName: 'Jane Smith',\r\n * authorRole: 'Tenant',\r\n * timestamp: '1h ago',\r\n * avatarInitials: 'JS',\r\n * content: 'Welcome to the community!'\r\n * }\r\n * ]\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class DsMobilePostDetailModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the post detail modal\r\n *\r\n * @param postData Post data to display\r\n * @param options Optional loading and error states\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(\r\n postData: PostDetailData,\r\n options?: {\r\n loading?: boolean;\r\n error?: string;\r\n onSubmitComment?: (payload: { postId: string; text: string }) => void;\r\n onToggleCommentLike?: (payload: { commentId: string; active: boolean }) => void;\r\n onEditComment?: (payload: { commentId: string; newText: string }) => void;\r\n onDeleteComment?: (payload: { commentId: string }) => void;\r\n currentUserName?: string;\r\n currentUserInitials?: string;\r\n }\r\n ): Promise<void> {\r\n console.log('[PostDetailModal] Opening with data:', postData);\r\n console.log('[PostDetailModal] options.onSubmitComment =', options?.onSubmitComment);\r\n\r\n const modal = await this.modalController.create({\r\n component: DsMobilePostDetailModalComponent,\r\n componentProps: {\r\n postData: postData,\r\n loading: options?.loading ?? false,\r\n error: options?.error,\r\n onSubmitComment: options?.onSubmitComment,\r\n onToggleCommentLike: options?.onToggleCommentLike,\r\n currentUserName: options?.currentUserName ?? '',\r\n currentUserInitialsInput: options?.currentUserInitials ?? '',\r\n },\r\n cssClass: 'ds-post-detail-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n // Control the presenting element animation\r\n enterAnimation: undefined, // Use default\r\n leaveAnimation: undefined, // Use default\r\n });\r\n\r\n console.log('[PostDetailModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[PostDetailModal] Modal presented');\r\n }\r\n\r\n /**\r\n * Close the currently open post detail modal\r\n *\r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n *\r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n","/**\r\n * Mobile Post Detail Modal Module\r\n * \r\n * Service and component for displaying posts in a modal\r\n */\r\n\r\nexport * from './ds-mobile-post-detail-modal';\r\nexport * from './ds-mobile-post-detail-modal.service';\r\n\r\n","import {\r\n Component,\r\n signal,\r\n Input,\r\n ViewChild,\r\n ElementRef,\r\n OnInit,\r\n AfterViewInit,\r\n OnDestroy,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonContent,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileMessageComposerComponent } from '../message-composer';\r\nimport { DsMobileMessageBubbleComponent, ChatAttachment } from '../message-bubble';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge';\r\n\r\n/**\r\n * Chat message data interface\r\n */\r\nexport interface ChatMessage {\r\n id: string;\r\n content: string;\r\n senderId: string;\r\n senderName: string;\r\n senderRole?: string;\r\n timestamp: string;\r\n avatarInitials?: string;\r\n avatarType?: 'initials' | 'photo' | 'icon';\r\n avatarSrc?: string;\r\n isOwnMessage: boolean;\r\n attachments?: ChatAttachment[];\r\n}\r\n\r\n/**\r\n * Chat participant interface\r\n */\r\nexport interface ChatParticipant {\r\n id: string;\r\n name: string;\r\n role?: string;\r\n avatarInitials?: string;\r\n avatarType?: 'initials' | 'photo' | 'icon';\r\n avatarSrc?: string;\r\n}\r\n\r\n/**\r\n * Chat modal data interface\r\n * \r\n * Represents the data needed to display a chat conversation.\r\n * \r\n * @example\r\n * ```typescript\r\n * const chatData: ChatModalData = {\r\n * participant: {\r\n * id: '123',\r\n * name: 'Ricki Meihlen',\r\n * role: 'Inquiry assignee',\r\n * avatarInitials: 'RM'\r\n * },\r\n * messages: [\r\n * {\r\n * id: '1',\r\n * content: 'We have received your case...',\r\n * senderId: '123',\r\n * senderName: 'Ricki Meihlen',\r\n * timestamp: '12:34',\r\n * isOwnMessage: false,\r\n * avatarInitials: 'RM'\r\n * }\r\n * ],\r\n * currentUserId: '456'\r\n * };\r\n * ```\r\n */\r\nexport interface ChatModalData {\r\n /** The other participant in the conversation */\r\n participant: ChatParticipant;\r\n /** Array of messages in the conversation */\r\n messages: ChatMessage[];\r\n /** Current user's ID */\r\n currentUserId: string;\r\n /** Current user's avatar initials */\r\n currentUserInitials?: string;\r\n /** Current user's avatar type */\r\n currentUserAvatarType?: 'initials' | 'photo' | 'icon';\r\n /** Current user's avatar source */\r\n currentUserAvatarSrc?: string;\r\n /** Auto-focus input when modal opens */\r\n autoFocus?: boolean;\r\n}\r\n\r\n/**\r\n * DsMobileChatModalComponent\r\n * \r\n * Modal component for displaying and managing chat conversations.\r\n * Follows the same pattern as post-detail-modal for consistent behavior.\r\n * \r\n * Features:\r\n * - Header with participant info and close button\r\n * - Scrollable message thread\r\n * - Fixed message composer at bottom\r\n * - Keyboard handling\r\n * - Safe area support\r\n * \r\n * This component is typically not used directly - use DsMobileChatModalService instead.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private chatModal: DsMobileChatModalService) {}\r\n * \r\n * openChat() {\r\n * this.chatModal.open({\r\n * participant: { id: '123', name: 'Ricki Meihlen' },\r\n * messages: [...],\r\n * currentUserId: '456'\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-chat-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsIconComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsMobileMessageComposerComponent,\r\n DsMobileMessageBubbleComponent\r\n ],\r\n styleUrls: ['../shared/mobile-common.css'],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"chat-modal-content\">\r\n <div class=\"chat-modal-wrapper\">\r\n <!-- Header with participant info -->\r\n <div class=\"chat-modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Participant info -->\r\n <div class=\"participant-info\">\r\n <ds-avatar-with-badge\r\n [initials]=\"participant().avatarInitials || ''\"\r\n [type]=\"participant().avatarType || 'initials'\"\r\n [src]=\"participant().avatarSrc || ''\"\r\n size=\"md\"\r\n />\r\n <div class=\"participant-details\">\r\n <div class=\"author-name\">{{ participant().name }}</div>\r\n @if (participant().role) {\r\n <div class=\"author-meta\">{{ participant().role }}</div>\r\n }\r\n </div>\r\n </div>\r\n \r\n <!-- Close button -->\r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (clicked)=\"close()\"\r\n class=\"close-button\"\r\n aria-label=\"Close chat\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Messages thread -->\r\n <div class=\"chat-messages-container\">\r\n @if (loading) {\r\n <!-- Loading State -->\r\n <div class=\"chat-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading messages...</p>\r\n </div>\r\n } @else if (error) {\r\n <!-- Error State -->\r\n <div class=\"chat-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error loading messages</h3>\r\n <p class=\"error-state-description\">{{ error }}</p>\r\n </div>\r\n } @else {\r\n <!-- Messages List -->\r\n <div class=\"messages-list\">\r\n @if (messages().length === 0) {\r\n <!-- Empty State -->\r\n <div class=\"messages-empty-state\">\r\n <h3 class=\"empty-state-title\">No messages yet</h3>\r\n <p class=\"empty-state-description\">Start the conversation by sending a message</p>\r\n </div>\r\n } @else {\r\n @for (message of messages(); track message.id) {\r\n <ds-mobile-message-bubble\r\n [content]=\"message.content\"\r\n [isOwnMessage]=\"message.isOwnMessage\"\r\n [timestamp]=\"message.timestamp\"\r\n [avatarInitials]=\"message.avatarInitials || ''\"\r\n [avatarType]=\"message.avatarType || 'initials'\"\r\n [avatarSrc]=\"message.avatarSrc || ''\"\r\n [attachments]=\"message.attachments\"\r\n [clickable]=\"true\"\r\n (attachmentClick)=\"handleAttachmentClick($event)\"\r\n (longPress)=\"handleMessageLongPress(message)\">\r\n </ds-mobile-message-bubble>\r\n }\r\n }\r\n </div>\r\n \r\n <!-- Bottom spacer for fixed composer -->\r\n <div class=\"composer-spacer\"></div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n \r\n <!-- Fixed message composer -->\r\n @if (!loading && !error) {\r\n <div class=\"message-composer-fixed\">\r\n <ds-mobile-message-composer\r\n [avatarInitials]=\"currentUserInitials()\"\r\n [avatarType]=\"currentUserAvatarType()\"\r\n [avatarSrc]=\"currentUserAvatarSrc()\"\r\n [placeholder]=\"'Write a message...'\"\r\n [autoFocus]=\"autoFocus()\"\r\n (messageSent)=\"handleMessageSent($event)\">\r\n </ds-mobile-message-composer>\r\n </div>\r\n }\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n position: relative;\r\n height: 100%;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n }\r\n\r\n .chat-modal-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .chat-modal-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n min-height: 100dvh;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n width: 100%;\r\n }\r\n\r\n .chat-modal-header {\r\n position: sticky;\r\n top: 0;\r\n z-index: 10;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 16px;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 72px;\r\n /* No padding needed - StatusBar.setOverlaysWebView(false) handles all spacing */\r\n }\r\n\r\n .participant-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .participant-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n /* Participant name and meta styles imported from mobile-common.css */\r\n\r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n \r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .chat-messages-container {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n padding: 16px 0 20px 0;\r\n flex: 1;\r\n }\r\n \r\n .messages-list {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n padding: 0 20px;\r\n align-items: stretch; /* Ensure messages take full width for proper alignment */\r\n }\r\n \r\n /* Ensure message bubbles can align properly */\r\n .messages-list ds-mobile-message-bubble {\r\n width: 100%;\r\n display: flex;\r\n }\r\n \r\n /* Empty State */\r\n .messages-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0 0 8px 0;\r\n }\r\n \r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n \r\n .composer-spacer {\r\n /* Match full composer height + safe area */\r\n height: calc(81px + env(safe-area-inset-bottom, 0px));\r\n }\r\n\r\n /* Fixed Message Composer Container */\r\n .message-composer-fixed {\r\n position: fixed;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 1000;\r\n pointer-events: none;\r\n /* Slide up with keyboard on native apps */\r\n transform: translateY(calc(-1 * var(--keyboard-height, 0px)));\r\n transition: transform 0.3s ease-out;\r\n max-width: 100vw;\r\n }\r\n\r\n .message-composer-fixed ds-mobile-message-composer {\r\n pointer-events: auto;\r\n /* White box shadow to cover content gap between keyboard and composer */\r\n box-shadow: 100px 150px 0 150px var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n /* Loading State */\r\n .chat-loading-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 3px solid var(--color-background-neutral-secondary, #f0f0f0);\r\n border-top-color: var(--color-primary-base, #2563eb);\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n \r\n @keyframes spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n \r\n .loading-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin-top: 16px;\r\n }\r\n\r\n /* Error State */\r\n .chat-error-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n gap: 16px;\r\n }\r\n \r\n .error-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n \r\n .error-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .chat-messages-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n `]\r\n})\r\nexport class DsMobileChatModalComponent implements OnInit, AfterViewInit, OnDestroy {\r\n // Chat data passed from service\r\n @Input() chatData!: ChatModalData;\r\n \r\n /**\r\n * Loading state - when true, shows loading indicator\r\n */\r\n @Input() loading: boolean = false;\r\n \r\n /**\r\n * Error state - when set, shows error message\r\n */\r\n @Input() error?: string;\r\n \r\n // Signal for reactive chat data\r\n participant = signal<ChatParticipant>({\r\n id: '',\r\n name: '',\r\n avatarInitials: ''\r\n });\r\n \r\n messages = signal<ChatMessage[]>([]);\r\n currentUserInitials = signal<string>('');\r\n currentUserAvatarType = signal<'initials' | 'photo' | 'icon'>('initials');\r\n currentUserAvatarSrc = signal<string>('');\r\n autoFocus = signal<boolean>(false);\r\n \r\n constructor(private modalController: ModalController) {}\r\n \r\n ngOnInit(): void {\r\n // Initialize chat data from input\r\n if (this.chatData) {\r\n this.participant.set(this.chatData.participant);\r\n this.messages.set(this.chatData.messages || []);\r\n this.currentUserInitials.set(this.chatData.currentUserInitials || '');\r\n this.currentUserAvatarType.set(this.chatData.currentUserAvatarType || 'initials');\r\n this.currentUserAvatarSrc.set(this.chatData.currentUserAvatarSrc || '');\r\n this.autoFocus.set(this.chatData.autoFocus || false);\r\n }\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Scroll to bottom when messages load\r\n if (this.messages().length > 0) {\r\n setTimeout(() => {\r\n this.scrollToBottom();\r\n }, 300);\r\n }\r\n }\r\n \r\n ngOnDestroy(): void {\r\n // Cleanup if needed\r\n }\r\n \r\n /**\r\n * Scroll to bottom of messages\r\n */\r\n private scrollToBottom(): void {\r\n const container = document.querySelector('.chat-messages-container');\r\n if (container) {\r\n container.scrollTop = container.scrollHeight;\r\n }\r\n }\r\n \r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n \r\n /**\r\n * Handle message sent from composer\r\n */\r\n handleMessageSent(event: { content: string; isReply?: boolean; replyTo?: string; isEdit?: boolean }): void {\r\n const newMessage: ChatMessage = {\r\n id: Date.now().toString(),\r\n content: event.content,\r\n senderId: this.chatData.currentUserId,\r\n senderName: 'You',\r\n timestamp: new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }),\r\n isOwnMessage: true,\r\n avatarInitials: this.currentUserInitials(),\r\n avatarType: this.currentUserAvatarType(),\r\n avatarSrc: this.currentUserAvatarSrc()\r\n };\r\n \r\n // Add message to list\r\n const updatedMessages = [...this.messages(), newMessage];\r\n this.messages.set(updatedMessages);\r\n \r\n // Scroll to bottom\r\n setTimeout(() => {\r\n this.scrollToBottom();\r\n }, 100);\r\n \r\n // In a real app, you would send this to your backend\r\n // this.chatService.sendMessage(this.chatData.participant.id, event.content);\r\n }\r\n \r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: ChatAttachment): void {\r\n console.log('[ChatModal] Attachment clicked:', attachment);\r\n // In a real app, you would open the attachment (image viewer, PDF viewer, etc.)\r\n }\r\n \r\n /**\r\n * Handle message long press\r\n */\r\n handleMessageLongPress(message: ChatMessage): void {\r\n console.log('[ChatModal] Message long pressed:', message);\r\n // In a real app, you would show an action sheet with options (copy, delete, etc.)\r\n }\r\n}\r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobileChatModalComponent, ChatModalData } from './ds-mobile-chat-modal';\r\n\r\n/**\r\n * DsMobileChatModalService\r\n * \r\n * Service for displaying chat conversations in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * Follows the same pattern as DsMobilePostDetailModalService for consistent behavior.\r\n * \r\n * Features:\r\n * - Full conversation display\r\n * - Message thread with bubbles\r\n * - Message composer\r\n * - Native modal animations\r\n * - Safe area support\r\n * - Keyboard handling\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private chatModal: DsMobileChatModalService) {}\r\n * \r\n * async openChat() {\r\n * await this.chatModal.open({\r\n * participant: {\r\n * id: '123',\r\n * name: 'Ricki Meihlen',\r\n * role: 'Inquiry assignee',\r\n * avatarInitials: 'RM'\r\n * },\r\n * messages: [\r\n * {\r\n * id: '1',\r\n * content: 'We have received your case...',\r\n * senderId: '123',\r\n * senderName: 'Ricki Meihlen',\r\n * timestamp: '12:34',\r\n * isOwnMessage: false,\r\n * avatarInitials: 'RM'\r\n * },\r\n * {\r\n * id: '2',\r\n * content: 'Thank you!',\r\n * senderId: '456',\r\n * senderName: 'You',\r\n * timestamp: '12:35',\r\n * isOwnMessage: true,\r\n * avatarInitials: 'JD',\r\n * readStatus: true\r\n * }\r\n * ],\r\n * currentUserId: '456',\r\n * currentUserInitials: 'JD',\r\n * autoFocus: true\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileChatModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the chat modal\r\n * \r\n * @param chatData Chat data to display\r\n * @param options Optional loading and error states\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(\r\n chatData: ChatModalData,\r\n options?: { loading?: boolean; error?: string }\r\n ): Promise<void> {\r\n console.log('[ChatModal] Opening with data:', chatData);\r\n \r\n const modal = await this.modalController.create({\r\n component: DsMobileChatModalComponent,\r\n componentProps: {\r\n chatData: chatData,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n cssClass: 'ds-chat-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n // Control the presenting element animation\r\n enterAnimation: undefined, // Use default\r\n leaveAnimation: undefined // Use default\r\n });\r\n\r\n console.log('[ChatModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[ChatModal] Modal presented');\r\n }\r\n\r\n /**\r\n * Close the currently open chat modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, Input } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * DsMobileHandbookFolderMiniComponent\r\n * \r\n * A minimized folder icon component for use in headers and small spaces.\r\n * Simplified version without animations or page sheets - just folder and icon.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-handbook-folder-mini\r\n * [variant]=\"'pink'\"\r\n * [iconName]=\"'remixLightbulbLine'\">\r\n * </ds-mobile-handbook-folder-mini>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-handbook-folder-mini',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n styles: [`\r\n :host {\r\n display: inline-block;\r\n width: 32px;\r\n height: 32px;\r\n flex-shrink: 0;\r\n }\r\n \r\n .mini-folder-container {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n .mini-folder-tab {\r\n width: 50%;\r\n height: auto;\r\n display: block;\r\n }\r\n \r\n .mini-folder-back {\r\n height: 28px;\r\n border-radius: 0px 4px 4px 4px;\r\n position: relative;\r\n margin-top: -1px;\r\n }\r\n \r\n .mini-folder-front {\r\n position: absolute;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n height: 24px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 2;\r\n box-shadow: inset 0 8px 8px rgba(255, 255, 255, 0.2), \r\n inset 0 0.5px 0.5px rgba(255, 255, 255, 0.3);\r\n }\r\n `],\r\n template: `\r\n <div class=\"mini-folder-container\">\r\n <!-- Folder Tab SVG -->\r\n <svg \r\n class=\"mini-folder-tab\" \r\n width=\"101\" \r\n height=\"24\" \r\n viewBox=\"0 0 101 24\" \r\n fill=\"none\" \r\n xmlns=\"http://www.w3.org/2000/svg\">\r\n <path \r\n d=\"M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z\" \r\n [attr.fill]=\"getColorVar('strong')\"/>\r\n </svg>\r\n \r\n <!-- Folder Back -->\r\n <div class=\"mini-folder-back\" [style.background-color]=\"getColorVar('strong')\">\r\n <!-- Folder Front -->\r\n <div \r\n class=\"mini-folder-front\" \r\n [style.background-color]=\"getColorVar('base')\">\r\n <ds-icon \r\n [name]=\"iconName\" \r\n [size]=\"'14px'\"\r\n [style.color]=\"'white'\" />\r\n </div>\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileHandbookFolderMiniComponent {\r\n /**\r\n * Color variant for the folder\r\n * Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey\r\n */\r\n @Input() variant: string = 'light-purple';\r\n \r\n /**\r\n * Icon name from the design system icon library\r\n */\r\n @Input() iconName: string = 'remixFolder3Line';\r\n \r\n /**\r\n * Get the CSS variable name for the color variant\r\n */\r\n getColorVar(suffix: 'base' | 'strong'): string {\r\n const variantMap: Record<string, string> = {\r\n 'success': 'success',\r\n 'warning': 'warning',\r\n 'destructive': 'destructive',\r\n 'blue': 'blue',\r\n 'light-purple': 'light-purple',\r\n 'pink': 'pink',\r\n 'salmon-orange': 'salmon-orange',\r\n 'orange': 'orange',\r\n 'lime-green': 'lime-green',\r\n 'grey': 'grey'\r\n };\r\n \r\n const colorName = variantMap[this.variant] || 'light-purple';\r\n return `var(--color-${colorName}-${suffix})`;\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileCardInlineComponent\r\n * \r\n * A versatile, always-interactive inline card component for standalone or small-group usage.\r\n * Designed for tappable card-like elements such as file attachments, contact cards, etc.\r\n * Not intended for long scrolling lists - use ds-mobile-list-item for that purpose.\r\n * \r\n * Features:\r\n * - Always interactive/tappable (unless disabled)\r\n * - Two layout variants: default (column) and compact (row)\r\n * - Flexible content projection with leading/main/trailing slots\r\n * - Consistent styling with rounded corners and neutral background\r\n * - Built-in hover and active states\r\n * - Accessibility features (role, tabindex, aria attributes)\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Default variant (column layout) -->\r\n * <ds-mobile-card-inline\r\n * [variant]=\"'default'\"\r\n * (cardClick)=\"handleClick()\">\r\n * \r\n * <div content-leading>\r\n * <ds-avatar initials=\"JD\" />\r\n * </div>\r\n * \r\n * <div content-main>\r\n * <div class=\"title\">Document Title</div>\r\n * <div class=\"subtitle\">PDF · 1.2 MB</div>\r\n * </div>\r\n * \r\n * <ds-icon content-trailing name=\"remixArrowRightSLine\" />\r\n * </ds-mobile-card-inline>\r\n * \r\n * <!-- Compact variant (row layout) -->\r\n * <ds-mobile-card-inline\r\n * [variant]=\"'compact'\"\r\n * (cardClick)=\"handleClick()\">\r\n * \r\n * <ds-avatar content-leading size=\"sm\" />\r\n * \r\n * <div content-main>\r\n * <span class=\"name\">File.pdf</span>\r\n * <span class=\"size\">245 KB</span>\r\n * </div>\r\n * \r\n * <ds-icon content-trailing name=\"remixArrowRightSLine\" />\r\n * </ds-mobile-card-inline>\r\n * \r\n * <!-- Disabled state -->\r\n * <ds-mobile-card-inline [disabled]=\"true\">\r\n * <div content-main>Disabled card</div>\r\n * </ds-mobile-card-inline>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline',\r\n standalone: true,\r\n imports: [CommonModule],\r\n host: {\r\n '[class.disabled]': 'disabled()',\r\n '[class.variant-compact]': 'variant() === \"compact\"',\r\n '[class.variant-default]': 'variant() === \"default\"',\r\n '[attr.role]': '\"button\"',\r\n '[attr.tabindex]': 'disabled() ? null : \"0\"',\r\n '[attr.aria-disabled]': 'disabled() ? \"true\" : null',\r\n '(click)': 'handleClick($event)',\r\n '(keydown.enter)': 'handleKeyDown($event)',\r\n '(keydown.space)': 'handleKeyDown($event)'\r\n },\r\n styles: [`\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n box-sizing: border-box;\r\n }\r\n \r\n /* Default variant - column layout with more padding */\r\n :host(.variant-default) {\r\n gap: 12px;\r\n padding: 10px 12px;\r\n }\r\n \r\n /* Compact variant - row layout with less padding */\r\n :host(.variant-compact) {\r\n gap: 8px;\r\n padding: 10px;\r\n }\r\n \r\n /* Hover state (desktop only) */\r\n @media (hover: hover) and (pointer: fine) {\r\n :host(:hover):not(.disabled) {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n }\r\n \r\n /* Active state */\r\n :host(:active):not(.disabled) {\r\n transform: scale(0.98);\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n /* Focus visible for keyboard navigation */\r\n :host(:focus-visible):not(.disabled) {\r\n outline: 2px solid var(--color-brand-primary, #5d5fef);\r\n outline-offset: 2px;\r\n }\r\n \r\n /* Disabled state */\r\n :host(.disabled) {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n }\r\n \r\n /* Inner container */\r\n .card-inline-inner {\r\n display: flex;\r\n align-items: center;\r\n gap: inherit;\r\n width: 100%;\r\n min-width: 0;\r\n }\r\n \r\n /* Content slots */\r\n .content-leading {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .content-main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n align-items: center;\r\n }\r\n \r\n /* Compact variant - main content flows inline */\r\n :host(.variant-compact) .content-main {\r\n flex-direction: row;\r\n gap: 8px;\r\n }\r\n \r\n /* Default variant - main content flows column */\r\n :host(.variant-default) .content-main {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 2px;\r\n }\r\n \r\n .content-trailing {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n }\r\n \r\n /* ============================================\r\n Shared item styles for child components\r\n ============================================ */\r\n \r\n /* Item avatar container */\r\n ::ng-deep .item-avatar {\r\n flex-shrink: 0;\r\n }\r\n \r\n /* Item content wrapper - default stacks vertically */\r\n ::ng-deep .item-content {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n gap: 2px;\r\n }\r\n \r\n /* Compact layout - content flows inline */\r\n :host(.variant-compact) ::ng-deep .item-content {\r\n flex-direction: row;\r\n align-items: center;\r\n justify-content: flex-start;\r\n gap: 8px;\r\n }\r\n \r\n /* Item name - primary text with truncation */\r\n ::ng-deep .item-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n text-align: left;\r\n }\r\n \r\n /* Item meta - secondary text */\r\n ::ng-deep .item-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n margin: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-start;\r\n gap: 4px;\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n }\r\n \r\n /* Item trailing icon */\r\n ::ng-deep .item-trailing {\r\n display: flex;\r\n align-items: center;\r\n color: var(--color-text-tertiary, #a3a3a3);\r\n flex-shrink: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"card-inline-inner\">\r\n <div class=\"content-leading\">\r\n <ng-content select=\"[content-leading]\" />\r\n </div>\r\n \r\n <div class=\"content-main\">\r\n <ng-content select=\"[content-main]\" />\r\n <ng-content />\r\n </div>\r\n \r\n <div class=\"content-trailing\">\r\n <ng-content select=\"[content-trailing]\" />\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileCardInlineComponent {\r\n /**\r\n * Display variant\r\n * - 'default' - Column layout with standard padding (gap: 12px, padding: 10px 12px)\r\n * - 'compact' - Row layout with reduced padding (gap: 8px, padding: 10px)\r\n */\r\n variant = input<'default' | 'compact'>('default');\r\n \r\n /**\r\n * Whether the card is disabled\r\n * Disables all interactions and reduces opacity\r\n */\r\n disabled = input<boolean>(false);\r\n \r\n /**\r\n * Emits when the card is clicked (if not disabled)\r\n */\r\n cardClick = output<void>();\r\n \r\n /**\r\n * Handle click events\r\n */\r\n handleClick(event: Event): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n \r\n // Don't emit click if it came from an interactive child element\r\n const target = event.target as HTMLElement;\r\n const closestInteractive = target.closest('button, a, input, select, textarea, [role=\"button\"]');\r\n \r\n // Check if the interactive element is a child, not the host itself\r\n if (closestInteractive && closestInteractive !== event.currentTarget) {\r\n return;\r\n }\r\n \r\n this.cardClick.emit();\r\n }\r\n \r\n /**\r\n * Handle keyboard events (Enter/Space)\r\n */\r\n handleKeyDown(event: KeyboardEvent): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n \r\n event.preventDefault();\r\n this.cardClick.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileCardInlineComponent } from '../card-inline';\r\n\r\n/**\r\n * DsMobileCardInlineFileComponent\r\n * \r\n * File attachment display for various document types.\r\n * Shows file info card with icon, filename, and file size.\r\n * Supports PDF and generic document formats.\r\n * Emits click event to open file in viewer.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-card-inline-file\r\n * [fileName]=\"'Document.pdf'\"\r\n * [fileSize]=\"'1.2 MB'\"\r\n * [variant]=\"'pdf'\"\r\n * [layout]=\"'compact'\"\r\n * (fileClick)=\"openFile()\">\r\n * </ds-mobile-card-inline-file>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline-file',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent, DsIconComponent, DsMobileCardInlineComponent],\r\n styles: [`\r\n /* PDF variant - red icon background */\r\n .item-avatar.pdf ::ng-deep .avatar--icon {\r\n background-color: #ff5757 !important;\r\n }\r\n \r\n /* Doc variant - blue icon background */\r\n .item-avatar.doc ::ng-deep .avatar--icon {\r\n background-color: var(--color-blue-base, #3B82F6) !important;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-card-inline\r\n [variant]=\"layout()\"\r\n (cardClick)=\"handleClick()\">\r\n \r\n <div content-leading class=\"item-avatar\" [class.pdf]=\"variant() === 'pdf'\" [class.doc]=\"variant() === 'doc'\">\r\n <ds-avatar\r\n type=\"icon\"\r\n [iconName]=\"getIconName()\"\r\n [size]=\"layout() === 'compact' ? 'sm' : 'md'\"\r\n />\r\n </div>\r\n \r\n <div content-main class=\"item-content\">\r\n <div class=\"item-name\">{{ fileName() }}</div>\r\n @if (fileSize()) {\r\n <div class=\"item-meta\">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>\r\n } @else {\r\n <div class=\"item-meta\">{{ getFileTypeLabel() }}</div>\r\n }\r\n </div>\r\n \r\n <ds-icon \r\n content-trailing\r\n name=\"remixArrowRightSLine\" \r\n size=\"20px\"\r\n class=\"item-trailing\"\r\n />\r\n </ds-mobile-card-inline>\r\n `\r\n})\r\nexport class DsMobileCardInlineFileComponent {\r\n /**\r\n * File name\r\n */\r\n fileName = input<string>('Document');\r\n \r\n /**\r\n * File size display (e.g., \"1.2 MB\")\r\n */\r\n fileSize = input<string>('');\r\n \r\n /**\r\n * File type variant\r\n * - 'pdf' - PDF document (red icon)\r\n * - 'doc' - Generic document (blue icon)\r\n */\r\n variant = input<'pdf' | 'doc'>('doc');\r\n \r\n /**\r\n * Layout variant\r\n * - 'default' - Standard padding and column layout\r\n * - 'compact' - Reduced padding and row layout\r\n */\r\n layout = input<'default' | 'compact'>('default');\r\n \r\n /**\r\n * Emits when the file attachment is clicked\r\n */\r\n fileClick = output<void>();\r\n \r\n /**\r\n * Get the appropriate icon name based on variant\r\n */\r\n getIconName(): string {\r\n return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';\r\n }\r\n \r\n /**\r\n * Get the file type label based on variant\r\n */\r\n getFileTypeLabel(): string {\r\n return this.variant() === 'pdf' ? 'PDF' : 'DOC';\r\n }\r\n \r\n handleClick(): void {\r\n this.fileClick.emit();\r\n }\r\n}\r\n\r\n","import { Component, input, output } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsAvatarComponent } from '@propbinder/design-system';\r\nimport { DsMobileCardInlineComponent } from '../card-inline';\r\n\r\n/**\r\n * DsMobileCardInlineContactComponent\r\n * \r\n * Specialized interactive component for displaying contacts.\r\n * Displays contact name with avatar initials and metadata (person name + phone number).\r\n * Similar styling to file attachments with rounded corners and hover states.\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-card-inline-contact\r\n * [name]=\"'Mortensen & Søn ApS'\"\r\n * [initials]=\"'M'\"\r\n * [contactPerson]=\"'John Mortensen'\"\r\n * [phoneNumber]=\"'+45 12 34 56 78'\"\r\n * [clickable]=\"true\"\r\n * (contactClick)=\"openContact()\">\r\n * </ds-mobile-card-inline-contact>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline-contact',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent, DsAvatarComponent, DsMobileCardInlineComponent],\r\n styles: [`\r\n /* Component-specific styles only - shared styles come from base component */\r\n `],\r\n template: `\r\n <ds-mobile-card-inline\r\n [variant]=\"layout()\"\r\n [disabled]=\"!clickable()\"\r\n (cardClick)=\"handleContactClick()\">\r\n \r\n <div content-leading class=\"item-avatar\">\r\n <ds-avatar\r\n [initials]=\"initials()\"\r\n type=\"initials\"\r\n [size]=\"layout() === 'compact' ? 'sm' : 'md'\"\r\n />\r\n </div>\r\n \r\n <div content-main class=\"item-content\">\r\n <div class=\"item-name\">{{ name() }}</div>\r\n \r\n @if (contactPerson() || phoneNumber()) {\r\n <div class=\"item-meta\">\r\n @if (contactPerson()) {\r\n <span>{{ contactPerson() }}</span>\r\n }\r\n @if (contactPerson() && phoneNumber()) {\r\n <span>·</span>\r\n }\r\n @if (phoneNumber()) {\r\n <span>{{ phoneNumber() }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n \r\n @if (showChevron()) {\r\n <div content-trailing class=\"item-trailing\">\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n }\r\n </ds-mobile-card-inline>\r\n `\r\n})\r\nexport class DsMobileCardInlineContactComponent {\r\n /**\r\n * Contact/company name\r\n */\r\n name = input.required<string>();\r\n \r\n /**\r\n * Avatar initials (usually 1-2 letters)\r\n */\r\n initials = input.required<string>();\r\n \r\n /**\r\n * Contact person name (optional)\r\n */\r\n contactPerson = input<string>('');\r\n \r\n /**\r\n * Phone number (optional)\r\n */\r\n phoneNumber = input<string>('');\r\n \r\n /**\r\n * Layout variant\r\n * - 'default' - Standard padding and column layout\r\n * - 'compact' - Reduced padding and row layout\r\n */\r\n layout = input<'default' | 'compact'>('default');\r\n \r\n /**\r\n * Whether the contact item is clickable\r\n */\r\n clickable = input<boolean>(true);\r\n \r\n /**\r\n * Whether to show chevron icon\r\n */\r\n showChevron = input<boolean>(true);\r\n \r\n /**\r\n * Emits when the contact item is clicked (if clickable)\r\n */\r\n contactClick = output<void>();\r\n \r\n handleContactClick(): void {\r\n this.contactClick.emit();\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n input,\r\n AfterViewInit,\r\n OnDestroy,\r\n ElementRef,\r\n ViewChild,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport Swiper from 'swiper';\r\n\r\n/**\r\n * DsMobileSwiperComponent\r\n * \r\n * A reusable swiper/carousel component with configurable child width and spacing.\r\n * \r\n * Features:\r\n * - First slide is left-aligned\r\n * - Middle slides are centered when active\r\n * - Last slide is right-aligned\r\n * - Configurable slide width and gap\r\n * - Content projection via ng-content\r\n * \r\n * Usage:\r\n * ```html\r\n * <ds-mobile-swiper [slideWidth]=\"'75vw'\" [gap]=\"16\">\r\n * <div class=\"swiper-slide\">Slide 1</div>\r\n * <div class=\"swiper-slide\">Slide 2</div>\r\n * <div class=\"swiper-slide\">Slide 3</div>\r\n * </ds-mobile-swiper>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-swiper',\r\n standalone: true,\r\n imports: [CommonModule],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <div class=\"swiper-container\" #swiperContainer>\r\n <div class=\"swiper-wrapper\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n width: 100%;\r\n }\r\n\r\n .swiper-container {\r\n width: 100%;\r\n position: relative;\r\n overflow: hidden;\r\n border-radius: 12px;\r\n }\r\n\r\n .swiper-wrapper {\r\n display: flex;\r\n transition-property: transform;\r\n box-sizing: content-box;\r\n }\r\n\r\n :host ::ng-deep .swiper-slide {\r\n flex-shrink: 0;\r\n height: 100%;\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n `]\r\n})\r\nexport class DsMobileSwiperComponent implements AfterViewInit, OnDestroy {\r\n /**\r\n * Width of each slide (e.g., '75vw', '300px', '80%')\r\n */\r\n slideWidth = input<string>('75vw');\r\n\r\n /**\r\n * Gap between slides in pixels\r\n */\r\n gap = input<number>(16);\r\n\r\n @ViewChild('swiperContainer', { static: false }) swiperContainer!: ElementRef;\r\n\r\n private swiperInstance: Swiper | null = null;\r\n\r\n ngAfterViewInit(): void {\r\n setTimeout(() => {\r\n this.initializeSwiper();\r\n }, 100);\r\n }\r\n\r\n private initializeSwiper(): void {\r\n if (!this.swiperContainer) return;\r\n\r\n // Apply slide width to all slides\r\n const slides = this.swiperContainer.nativeElement.querySelectorAll('.swiper-slide');\r\n slides.forEach((slide: HTMLElement) => {\r\n slide.style.width = this.slideWidth();\r\n });\r\n\r\n this.swiperInstance = new Swiper(this.swiperContainer.nativeElement, {\r\n slidesPerView: 'auto',\r\n spaceBetween: this.gap(),\r\n centeredSlides: true,\r\n centeredSlidesBounds: true,\r\n speed: 300,\r\n resistance: true,\r\n resistanceRatio: 0.85,\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n if (this.swiperInstance) {\r\n this.swiperInstance.destroy();\r\n this.swiperInstance = null;\r\n }\r\n }\r\n}\r\n\r\n","import {\r\n Component,\r\n signal,\r\n Input,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n IonContent,\r\n ModalController\r\n} from '@ionic/angular/standalone';\r\nimport { DsIconButtonComponent } from '@propbinder/design-system';\r\nimport { DsMobileHandbookFolderMiniComponent } from '../handbook-folder/ds-mobile-handbook-folder-mini';\r\nimport { DsMobileCardInlineFileComponent } from '../card-inline-file';\r\nimport { DsMobileCardInlineContactComponent } from '../card-inline-contact';\r\nimport { DsMobileSwiperComponent } from '../swiper';\r\n\r\n/**\r\n * Handbook detail data interface\r\n * \r\n * Represents a handbook category/folder with its sections/items.\r\n * Use this interface to map your API response data to the component.\r\n * \r\n * @example\r\n * ```typescript\r\n * const handbookData: HandbookDetailData = {\r\n * title: 'Access Systems',\r\n * variant: 'blue',\r\n * iconName: 'remixKey2Line',\r\n * itemCount: 5,\r\n * items: [...]\r\n * };\r\n * ```\r\n */\r\nexport interface HandbookDetailData {\r\n /** Category/folder title */\r\n title: string;\r\n /** Color variant: 'success', 'warning', 'destructive', 'blue', 'light-purple', 'pink', 'salmon-orange', 'orange', 'lime-green', 'grey' */\r\n variant: string;\r\n /** Icon name from design system (e.g., 'remixKey2Line', 'remixLightbulbLine') */\r\n iconName: string;\r\n /** Total number of items/sections in this category */\r\n itemCount: number;\r\n /** Array of handbook sections/items */\r\n items?: HandbookItem[];\r\n}\r\n\r\n/**\r\n * Handbook section/item interface\r\n * \r\n * Represents a single section within a handbook category.\r\n * Each section can have a title, description, images, contacts, and attachments.\r\n * \r\n * @example\r\n * ```typescript\r\n * const item: HandbookItem = {\r\n * title: 'Key Box Entrance',\r\n * description: 'Key box located at main entrance...',\r\n * images: ['https://api.example.com/images/keybox.jpg'],\r\n * contacts: [{ name: 'Security Co', initials: 'S', phoneNumber: '+45 12345678' }],\r\n * attachments: [{ name: 'Manual.pdf', type: 'pdf', url: 'https://...' }]\r\n * };\r\n * ```\r\n */\r\nexport interface HandbookItem {\r\n /** Section title */\r\n title: string;\r\n /** Optional section description */\r\n description?: string;\r\n /** Array of image URLs to display */\r\n images?: string[];\r\n /** Array of file attachments */\r\n attachments?: AttachmentItem[];\r\n /** Array of contact information */\r\n contacts?: ContactItem[];\r\n}\r\n\r\n/**\r\n * File attachment interface\r\n * \r\n * Represents a file attachment in a handbook section.\r\n * \r\n * @example\r\n * ```typescript\r\n * const attachment: AttachmentItem = {\r\n * name: 'Installation_Manual.pdf',\r\n * type: 'pdf',\r\n * url: 'https://api.example.com/files/manual.pdf'\r\n * };\r\n * ```\r\n */\r\nexport interface AttachmentItem {\r\n /** File name to display */\r\n name: string;\r\n /** File type: 'pdf', 'doc', etc. (used for icon display) */\r\n type?: string;\r\n /** Optional URL for downloading/opening the file */\r\n url?: string;\r\n}\r\n\r\n/**\r\n * Contact information interface\r\n * \r\n * Represents contact information in a handbook section.\r\n * \r\n * @example\r\n * ```typescript\r\n * const contact: ContactItem = {\r\n * name: 'Propbinder ApS',\r\n * initials: 'P',\r\n * contactPerson: 'John Doe',\r\n * phoneNumber: '+45 12345678',\r\n * email: 'support@propbinder.dk'\r\n * };\r\n * ```\r\n */\r\nexport interface ContactItem {\r\n /** Company or contact name */\r\n name: string;\r\n /** Initials for avatar (1-2 letters) */\r\n initials: string;\r\n /** Optional contact person name */\r\n contactPerson?: string;\r\n /** Optional phone number */\r\n phoneNumber?: string;\r\n /** Optional email address */\r\n email?: string;\r\n}\r\n\r\n/**\r\n * DsMobileHandbookDetailModalComponent\r\n * \r\n * Modal wrapper for displaying handbook folder details.\r\n * \r\n * Features:\r\n * - Folder content display\r\n * - Items list with descriptions\r\n * - Images and attachments\r\n * - Contact information\r\n * - Native modal controls (close, swipe down)\r\n * - Safe area support\r\n * \r\n * This component is typically not used directly - use DsMobileHandbookDetailModalService instead.\r\n */\r\n@Component({\r\n selector: 'ds-mobile-handbook-detail-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsMobileHandbookFolderMiniComponent,\r\n DsMobileCardInlineFileComponent,\r\n DsMobileCardInlineContactComponent,\r\n DsMobileSwiperComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"handbook-modal-content\">\r\n <div class=\"handbook-modal-wrapper\">\r\n <!-- Header -->\r\n <div class=\"handbook-modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Handbook folder info -->\r\n <div class=\"handbook-folder-info\">\r\n <ds-mobile-handbook-folder-mini\r\n [variant]=\"handbook().variant\"\r\n [iconName]=\"handbook().iconName\">\r\n </ds-mobile-handbook-folder-mini>\r\n <div class=\"folder-details\">\r\n <div class=\"folder-name\">{{ handbook().title }}</div>\r\n <div class=\"folder-meta\">\r\n <span>{{ handbook().itemCount }} emner</span>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Close button -->\r\n <ds-icon-button\r\n icon=\"remixCloseLine\"\r\n variant=\"secondary\"\r\n size=\"lg\"\r\n (click)=\"close()\"\r\n class=\"close-button\"\r\n aria-label=\"Luk\">\r\n </ds-icon-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Content -->\r\n <div class=\"handbook-detail-container\">\r\n @if (loading) {\r\n <!-- Loading State -->\r\n <div class=\"handbook-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading...</p>\r\n </div>\r\n } @else if (error) {\r\n <!-- Error State -->\r\n <div class=\"handbook-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error loading content</h3>\r\n <p class=\"error-state-description\">{{ error }}</p>\r\n </div>\r\n } @else if (handbook().items && handbook().items!.length > 0) {\r\n @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {\r\n <div class=\"handbook-item\" [class.last-item]=\"isLast\">\r\n <div class=\"item-text-group\">\r\n <h2 class=\"item-title\">{{ item.title }}</h2>\r\n \r\n @if (item.description) {\r\n <p class=\"item-description\">{{ item.description }}</p>\r\n }\r\n </div>\r\n \r\n <!-- Images -->\r\n @if (item.images && item.images.length > 0) {\r\n <ds-mobile-swiper [slideWidth]=\"item.images.length === 1 ? '100%' : '85%'\" [gap]=\"16\">\r\n @for (image of item.images; track image) {\r\n <div class=\"swiper-slide\">\r\n <img \r\n [src]=\"image\" \r\n [alt]=\"item.title\"\r\n class=\"item-image\"\r\n />\r\n </div>\r\n }\r\n </ds-mobile-swiper>\r\n }\r\n \r\n <!-- Contacts -->\r\n @if (item.contacts && item.contacts.length > 0) {\r\n <div class=\"contacts-list\">\r\n @for (contact of item.contacts; track contact.name) {\r\n <ds-mobile-card-inline-contact\r\n [name]=\"contact.name\"\r\n [initials]=\"contact.initials\"\r\n [contactPerson]=\"contact.contactPerson || ''\"\r\n [phoneNumber]=\"contact.phoneNumber || ''\"\r\n [clickable]=\"true\"\r\n (contactClick)=\"handleContactClick(contact)\">\r\n </ds-mobile-card-inline-contact>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Attachments -->\r\n @if (item.attachments && item.attachments.length > 0) {\r\n <div class=\"attachments-list\">\r\n @for (attachment of item.attachments; track attachment.name) {\r\n <ds-mobile-card-inline-file\r\n [fileName]=\"attachment.name\"\r\n [variant]=\"attachment.type === 'pdf' ? 'pdf' : 'doc'\"\r\n (fileClick)=\"handleAttachmentClick(attachment)\">\r\n </ds-mobile-card-inline-file>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <!-- Empty State -->\r\n <div class=\"handbook-empty-state\">\r\n <img \r\n src=\"/Assets/Empty%20state-chat.png\" \r\n alt=\"No items yet\" \r\n class=\"empty-state-image\"\r\n />\r\n <h3 class=\"empty-state-title\">No items yet</h3>\r\n <p class=\"empty-state-description\">This folder is empty</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n `,\r\n styles: [`\r\n .handbook-modal-content {\r\n --background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .handbook-modal-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 100%;\r\n min-height: 100dvh;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n }\r\n\r\n .handbook-modal-header {\r\n position: sticky;\r\n top: 0;\r\n z-index: 10;\r\n background: var(--color-background-neutral-primary, #ffffff);\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding: 0 16px;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n min-height: 72px;\r\n }\r\n\r\n .handbook-folder-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .folder-details {\r\n display: flex;\r\n flex-direction: column;\r\n min-width: 0;\r\n flex: 1;\r\n }\r\n\r\n .folder-name {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .folder-meta {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-xs);\r\n font-weight: 400;\r\n line-height: 1.2;\r\n letter-spacing: -0.26px;\r\n color: var(--color-text-tertiary, #737373);\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n\r\n .close-button {\r\n flex-shrink: 0;\r\n border-radius: 50%;\r\n }\r\n \r\n .close-button::ng-deep button {\r\n border-radius: 50% !important;\r\n width: 36px !important;\r\n height: 36px !important;\r\n min-width: 36px !important;\r\n min-height: 36px !important;\r\n padding: 0 !important;\r\n display: flex !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n }\r\n\r\n .handbook-detail-container {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n max-width: 640px;\r\n margin: 0 auto;\r\n flex: 1;\r\n }\r\n \r\n .handbook-item {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 24px;\r\n padding: 24px 20px 24px 20px;\r\n border-bottom: 1px solid var(--border-color-default);\r\n }\r\n \r\n .handbook-item.last-item {\r\n border-bottom: none;\r\n }\r\n\r\n .item-text-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n\r\n .item-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 16px;\r\n font-weight: 600;\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n\r\n .item-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n line-height: 20px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n\r\n .item-image {\r\n width: 100%;\r\n max-width: 100%;\r\n height: 280px;\r\n object-fit: cover;\r\n border-radius: 12px;\r\n display: block;\r\n }\r\n\r\n .contacts-list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n \r\n .attachments-list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n \r\n\r\n /* Empty State */\r\n .handbook-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-image {\r\n width: 96px;\r\n height: 96px;\r\n }\r\n \r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n }\r\n\r\n /* Safe area support */\r\n @supports (padding: env(safe-area-inset-bottom)) {\r\n .handbook-detail-container {\r\n padding-bottom: calc(20px + env(safe-area-inset-bottom));\r\n }\r\n }\r\n\r\n /* Loading State */\r\n .handbook-loading-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 3px solid var(--color-background-neutral-secondary, #f0f0f0);\r\n border-top-color: var(--color-primary-base, #2563eb);\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n \r\n @keyframes spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n \r\n .loading-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin-top: 16px;\r\n }\r\n\r\n /* Error State */\r\n .handbook-error-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n gap: 16px;\r\n }\r\n \r\n .error-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n line-height: 1.3;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin: 0;\r\n }\r\n \r\n .error-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-text-secondary, #737373);\r\n margin: 0;\r\n }\r\n `]\r\n})\r\nexport class DsMobileHandbookDetailModalComponent {\r\n // Handbook data passed from service\r\n @Input() handbookData!: HandbookDetailData;\r\n \r\n /**\r\n * Loading state - when true, shows loading indicator\r\n */\r\n @Input() loading: boolean = false;\r\n \r\n /**\r\n * Error state - when set, shows error message\r\n */\r\n @Input() error?: string;\r\n \r\n // Signal for reactive handbook data\r\n handbook = signal<HandbookDetailData>({\r\n title: '',\r\n variant: 'light-purple',\r\n iconName: 'remixFolder3Line',\r\n itemCount: 0,\r\n items: []\r\n });\r\n\r\n constructor(\r\n private modalController: ModalController\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n // Initialize handbook data from input\r\n if (this.handbookData) {\r\n this.handbook.set(this.handbookData);\r\n }\r\n }\r\n\r\n /**\r\n * Split handbook items to enforce content structure rules:\r\n * - Never mix photos and documents (attachments) in the same section\r\n * - Never mix contact persons and attachments together in the same section\r\n * \r\n * This method splits items that violate these rules into multiple display items.\r\n * Each resulting item will have only compatible content types.\r\n */\r\n splitItemsByContentRules(item: HandbookItem): HandbookItem[] {\r\n const displayItems: HandbookItem[] = [];\r\n \r\n const hasImages = item.images && item.images.length > 0;\r\n const hasContacts = item.contacts && item.contacts.length > 0;\r\n const hasAttachments = item.attachments && item.attachments.length > 0;\r\n \r\n // Case 1: Only one type of content - keep as is\r\n const contentTypeCount = [hasImages, hasContacts, hasAttachments].filter(Boolean).length;\r\n if (contentTypeCount <= 1) {\r\n return [item];\r\n }\r\n \r\n // Case 2: Has images + contacts (allowed together) but no attachments\r\n if (hasImages && hasContacts && !hasAttachments) {\r\n return [item];\r\n }\r\n \r\n // Case 3: Violates rules - need to split\r\n \r\n // First item: Text + Images (if present)\r\n if (hasImages) {\r\n displayItems.push({\r\n title: item.title,\r\n description: item.description,\r\n images: item.images\r\n });\r\n }\r\n \r\n // Second item: Text + Contacts (if present and no images shown yet)\r\n if (hasContacts) {\r\n displayItems.push({\r\n title: item.title,\r\n description: hasImages ? undefined : item.description, // Only show description if not shown before\r\n contacts: item.contacts\r\n });\r\n }\r\n \r\n // Third item: Text + Attachments (if present)\r\n if (hasAttachments) {\r\n displayItems.push({\r\n title: item.title,\r\n description: (!hasImages && !hasContacts) ? item.description : undefined, // Only show description if not shown before\r\n attachments: item.attachments\r\n });\r\n }\r\n \r\n return displayItems;\r\n }\r\n \r\n /**\r\n * Get all display items with enforced content structure rules applied\r\n */\r\n getDisplayItems(): HandbookItem[] {\r\n const items = this.handbook().items || [];\r\n const displayItems: HandbookItem[] = [];\r\n \r\n for (const item of items) {\r\n const splitItems = this.splitItemsByContentRules(item);\r\n displayItems.push(...splitItems);\r\n }\r\n \r\n return displayItems;\r\n }\r\n\r\n /**\r\n * Close the modal\r\n */\r\n close(): void {\r\n this.modalController.dismiss();\r\n }\r\n \r\n /**\r\n * Handle contact click\r\n */\r\n handleContactClick(contact: ContactItem): void {\r\n console.log('Contact clicked:', contact);\r\n // Implement contact action (e.g., show contact details, call, etc.)\r\n }\r\n \r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: AttachmentItem): void {\r\n console.log('Attachment clicked:', attachment);\r\n // Implement attachment action (e.g., open file viewer, download, etc.)\r\n }\r\n}\r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobileHandbookDetailModalComponent, HandbookDetailData } from './ds-mobile-handbook-detail-modal';\r\n\r\n/**\r\n * DsMobileHandbookDetailModalService\r\n * \r\n * Service for displaying handbook folder details in a full-screen modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * \r\n * Features:\r\n * - Full handbook content display\r\n * - Items list with descriptions\r\n * - Images and attachments\r\n * - Contact information\r\n * - Native modal animations\r\n * - Safe area support\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private handbookModal: DsMobileHandbookDetailModalService) {}\r\n * \r\n * async openHandbook() {\r\n * await this.handbookModal.open({\r\n * title: 'Utilities',\r\n * variant: 'pink',\r\n * iconName: 'remixLightbulbLine',\r\n * itemCount: 8,\r\n * items: [\r\n * {\r\n * title: 'Hjertestarter',\r\n * description: 'Installed on the 4th floor...',\r\n * images: ['/path/to/image.jpg'],\r\n * contacts: [\r\n * { name: 'Mortensen & Søn ApS', initials: 'M' }\r\n * ]\r\n * }\r\n * ]\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileHandbookDetailModalService {\r\n constructor(private modalController: ModalController) {}\r\n\r\n /**\r\n * Open the handbook detail modal\r\n * \r\n * @param handbookData Handbook data to display\r\n * @param options Optional loading and error states\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(\r\n handbookData: HandbookDetailData,\r\n options?: { loading?: boolean; error?: string }\r\n ): Promise<void> {\r\n console.log('[HandbookDetailModal] Opening with data:', handbookData);\r\n \r\n const modal = await this.modalController.create({\r\n component: DsMobileHandbookDetailModalComponent,\r\n componentProps: {\r\n handbookData: handbookData,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n cssClass: 'ds-handbook-detail-modal',\r\n mode: 'ios',\r\n presentingElement: document.querySelector('ion-router-outlet') || undefined,\r\n backdropDismiss: true,\r\n showBackdrop: true,\r\n animated: true,\r\n keyboardClose: true,\r\n enterAnimation: undefined,\r\n leaveAnimation: undefined\r\n });\r\n\r\n console.log('[HandbookDetailModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[HandbookDetailModal] Modal presented');\r\n }\r\n\r\n /**\r\n * Close the currently open handbook detail modal\r\n * \r\n * @param data Optional data to pass back when dismissing\r\n * @returns Promise that resolves when the modal is dismissed\r\n */\r\n async close(data?: any): Promise<boolean> {\r\n return this.modalController.dismiss(data);\r\n }\r\n\r\n /**\r\n * Get the top-most modal if one exists\r\n * \r\n * @returns Promise that resolves to the modal element or undefined\r\n */\r\n async getTop(): Promise<HTMLIonModalElement | undefined> {\r\n return this.modalController.getTop();\r\n }\r\n}\r\n\r\n","import { Component, Input, signal, HostListener } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobileHandbookDetailModalService, HandbookDetailData, HandbookItem } from '../handbook-detail-modal';\r\n\r\n/**\r\n * DsMobileHandbookFolderComponent\r\n * \r\n * A visually rich folder component for displaying handbook categories or sections.\r\n * Features a two-layer folder design with customizable colors, icon, item count, and label.\r\n * \r\n * Design Details:\r\n * - Folder back: 72px height with a decorative notch\r\n * - Folder front: 64px height overlaying the back\r\n * - Item count displayed in bottom-left corner\r\n * - Icon displayed in bottom-right corner\r\n * - Label text centered below the folder\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-handbook-folder\r\n * [colorBase]=\"'#d244cf'\"\r\n * [colorWeak]=\"'#f9e6f9'\"\r\n * [iconName]=\"'remixLightbulbLine'\"\r\n * [itemCount]=\"8\"\r\n * [label]=\"'Utilities'\">\r\n * </ds-mobile-handbook-folder>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-handbook-folder',\r\n standalone: true,\r\n imports: [CommonModule, DsIconComponent],\r\n styles: [`\r\n :host {\r\n display: inline-flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 16px;\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n padding: 16px;\r\n border-radius: 16px;\r\n background: var(--color-background-neutral-secondary, #f0f0f0);\r\n transition: background 0.2s ease;\r\n }\r\n \r\n :host:active {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n \r\n @media (hover: hover) {\r\n :host:hover {\r\n background: var(--color-background-neutral-secondary-hover, #ebebeb);\r\n }\r\n }\r\n \r\n .folder-container {\r\n position: relative;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n perspective: 800px;\r\n -webkit-perspective: 800px;\r\n max-width: 160px;\r\n /* Safari optimization: Ensure proper 3D rendering context */\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n }\r\n \r\n .folder-container.open .page-sheet {\r\n -webkit-transform: translateY(-8px);\r\n transform: translateY(-8px);\r\n transition-delay: 0.2s;\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(1) {\r\n -webkit-transform: scale(1) translateY(-8px) rotateX(-45deg) translateZ(0.1px);\r\n transform: scale(1) translateY(-8px) rotateX(-45deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(2) {\r\n -webkit-transform: scale(0.98) translateY(-12px) rotateX(-36deg) translateZ(0.1px);\r\n transform: scale(0.98) translateY(-12px) rotateX(-36deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(3) {\r\n -webkit-transform: scale(0.96) translateY(-16px) rotateX(-27deg) translateZ(0.1px);\r\n transform: scale(0.96) translateY(-16px) rotateX(-27deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(4) {\r\n -webkit-transform: scale(0.94) translateY(-20px) rotateX(-18deg) translateZ(0.1px);\r\n transform: scale(0.94) translateY(-20px) rotateX(-18deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(5) {\r\n -webkit-transform: scale(0.92) translateY(-24px) rotateX(-9deg) translateZ(0.1px);\r\n transform: scale(0.92) translateY(-24px) rotateX(-9deg) translateZ(0.1px);\r\n }\r\n \r\n .folder-container.open .page-sheet:nth-child(6) {\r\n -webkit-transform: scale(0.90) translateY(-28px) rotateX(0deg) translateZ(0.1px);\r\n transform: scale(0.90) translateY(-28px) rotateX(0.1px);\r\n }\r\n \r\n .folder-container.open .folder-front {\r\n -webkit-transform: translate3d(0, 0, 0) rotateX(-45deg);\r\n transform: translate3d(0, 0, 0) rotateX(-45deg);\r\n }\r\n \r\n .folder-tab {\r\n width: 50%;\r\n height: auto;\r\n display: block;\r\n }\r\n \r\n .folder-back {\r\n height: 128px;\r\n border-radius: 0px 12px 12px 12px;\r\n position: relative;\r\n margin-top: -1px;\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n backface-visibility: hidden;\r\n -webkit-backface-visibility: hidden;\r\n /* Safari optimization: Force GPU acceleration */\r\n -webkit-transform: translateZ(0);\r\n transform: translateZ(0);\r\n }\r\n \r\n .page-sheet {\r\n position: absolute;\r\n width: 80%;\r\n height: 120px;\r\n background: #ffffff;\r\n border-radius: 8px;\r\n box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);\r\n border: 1px solid var(--border-color-default);\r\n transition: transform 0.3s ease-out;\r\n -webkit-transition: -webkit-transform 0.3s ease-out;\r\n left: 10%;\r\n /* Safari optimization: Force hardware acceleration and proper 3D rendering */\r\n -webkit-transform: translateZ(0);\r\n transform: translateZ(0);\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n backface-visibility: hidden;\r\n -webkit-backface-visibility: hidden;\r\n /* Safari optimization: Prevent subpixel rendering issues */\r\n -webkit-font-smoothing: antialiased;\r\n /* Safari optimization: Ensure proper layer creation */\r\n will-change: transform;\r\n }\r\n \r\n .page-sheet:nth-child(1) {\r\n bottom: 2px;\r\n z-index: 6;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(1) translateZ(0.1px);\r\n transform: scale(1) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(2) {\r\n bottom: 8px;\r\n z-index: 5;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.98) translateZ(0.1px);\r\n transform: scale(0.98) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(3) {\r\n bottom: 14px;\r\n z-index: 4;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.96) translateZ(0.1px);\r\n transform: scale(0.96) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(4) {\r\n bottom: 20px;\r\n z-index: 3;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.94) translateZ(0.1px);\r\n transform: scale(0.94) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(5) {\r\n bottom: 26px;\r\n z-index: 2;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.92) translateZ(0.1px);\r\n transform: scale(0.92) translateZ(0.1px);\r\n }\r\n \r\n .page-sheet:nth-child(6) {\r\n bottom: 32px;\r\n z-index: 1;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n -webkit-transform: scale(0.90) translateZ(0.1px);\r\n transform: scale(0.90) translateZ(0.1px);\r\n }\r\n \r\n .folder-front {\r\n position: absolute;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n height: 116px;\r\n border-radius: 12px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 8px;\r\n z-index: 2;\r\n transform-origin: bottom center;\r\n -webkit-transform-origin: bottom center;\r\n transform-style: preserve-3d;\r\n -webkit-transform-style: preserve-3d;\r\n transition: transform 0.4s ease-in-out, -webkit-transform 0.4s ease-in-out;\r\n -webkit-transition: -webkit-transform 0.4s ease-in-out;\r\n will-change: transform;\r\n backface-visibility: hidden;\r\n -webkit-backface-visibility: hidden;\r\n -webkit-font-smoothing: antialiased;\r\n /* Safari optimization: Use more specific transform to avoid render glitches */\r\n -webkit-transform: rotateX(-20deg) translateZ(0.1px);\r\n transform: rotateX(-20deg) translateZ(0.1px);\r\n /* Safari optimization: Force layer creation for smoother animations */\r\n -webkit-transform: translate3d(0, 0, 0) rotateX(-20deg);\r\n transform: translate3d(0, 0, 0) rotateX(-20deg);\r\n box-shadow: inset 0 64px 48px rgba(255, 255, 255, 0.2), \r\n inset 0 2px 4px rgba(255, 255, 255, 0.3),\r\n inset 0 1px 1px rgba(255, 255, 255, 0.3);\r\n }\r\n \r\n .item-count {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n \r\n .item-count-label {\r\n letter-spacing: 0.5px;\r\n }\r\n \r\n .folder-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n \r\n .folder-label-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 4px;\r\n }\r\n \r\n .folder-label {\r\n text-align: center;\r\n }\r\n\r\n .loading-indicator,\r\n .error-indicator {\r\n font-size: var(--font-size-xs);\r\n }\r\n `],\r\n template: `\r\n <div class=\"folder-container\" \r\n [class.open]=\"isOpen()\">\r\n <!-- Folder Tab SVG -->\r\n <svg \r\n class=\"folder-tab\" \r\n width=\"101\" \r\n height=\"24\" \r\n viewBox=\"0 0 101 24\" \r\n fill=\"none\" \r\n xmlns=\"http://www.w3.org/2000/svg\">\r\n <path \r\n d=\"M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z\" \r\n [attr.fill]=\"getColorVar('strong')\"/>\r\n </svg>\r\n \r\n <!-- Folder Back -->\r\n <div class=\"folder-back\" [style.background-color]=\"getColorVar('strong')\">\r\n <!-- Page Sheets -->\r\n @for (sheet of getPageSheets(); track $index) {\r\n <div class=\"page-sheet\"></div>\r\n }\r\n \r\n <!-- Folder Front -->\r\n <div \r\n class=\"folder-front\" \r\n [style.--border-color]=\"getColorVar('strong')\"\r\n [style.background-color]=\"getColorVar('base')\">\r\n <!-- Icon (Centered) -->\r\n <div class=\"folder-icon\">\r\n <ds-icon \r\n [name]=\"iconName\" \r\n [size]=\"'32px'\"\r\n [style.color]=\"'white'\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Label and Item Count -->\r\n <div class=\"folder-label-container\">\r\n <div class=\"folder-label ui-sm-semiBold\">{{ label }}</div>\r\n <div class=\"item-count ui-sm-regular\" [style.color]=\"'var(--color-text-secondary, #6b7280)'\">\r\n @if (loading) {\r\n <span class=\"loading-indicator\">Loading...</span>\r\n } @else if (error) {\r\n <span class=\"error-indicator\" [style.color]=\"'var(--color-destructive-base)'\">Error</span>\r\n } @else {\r\n <span>{{ itemCount }}</span>\r\n <span class=\"item-count-label\">emner</span>\r\n }\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileHandbookFolderComponent {\r\n /**\r\n * Color variant for the folder\r\n * Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey\r\n * Example: 'pink', 'success', 'blue'\r\n */\r\n @Input() variant: string = 'light-purple';\r\n \r\n /**\r\n * Icon name from the design system icon library\r\n * Example: 'remixLightbulbLine', 'remixFolder3Line'\r\n */\r\n @Input() iconName: string = 'remixFolder3Line';\r\n \r\n /**\r\n * Number of items in the folder\r\n * This should match the length of the items array when data is loaded\r\n */\r\n @Input() itemCount: number = 0;\r\n \r\n /**\r\n * Label text displayed below the folder (category name)\r\n */\r\n @Input() label: string = 'Folder';\r\n \r\n /**\r\n * Optional items data for the handbook folder\r\n * Pass the HandbookItem[] array from your API response here\r\n */\r\n @Input() items?: HandbookItem[];\r\n \r\n /**\r\n * Loading state - when true, shows \"Loading...\" indicator instead of item count\r\n * Set this to true while fetching data from your API\r\n */\r\n @Input() loading: boolean = false;\r\n \r\n /**\r\n * Error state - when set, shows \"Error\" indicator instead of item count\r\n * Set this to an error message string if API call fails\r\n */\r\n @Input() error?: string;\r\n \r\n /**\r\n * Track open/closed state for animation\r\n */\r\n isOpen = signal(false);\r\n \r\n /**\r\n * Get the CSS variable name for the color variant\r\n */\r\n getColorVar(suffix: 'base' | 'strong'): string {\r\n const variantMap: Record<string, string> = {\r\n 'success': 'success',\r\n 'warning': 'warning',\r\n 'destructive': 'destructive',\r\n 'blue': 'blue',\r\n 'light-purple': 'light-purple',\r\n 'pink': 'pink',\r\n 'salmon-orange': 'salmon-orange',\r\n 'orange': 'orange',\r\n 'lime-green': 'lime-green',\r\n 'grey': 'grey'\r\n };\r\n \r\n const colorName = variantMap[this.variant] || 'light-purple';\r\n return `var(--color-${colorName}-${suffix})`;\r\n }\r\n \r\n /**\r\n * Open folder animation\r\n */\r\n @HostListener('mouseenter')\r\n open(): void {\r\n this.isOpen.set(true);\r\n }\r\n \r\n /**\r\n * Close folder animation\r\n */\r\n @HostListener('mouseleave')\r\n close(): void {\r\n this.isOpen.set(false);\r\n }\r\n \r\n /**\r\n * Handle touch start - open animation\r\n */\r\n @HostListener('touchstart', ['$event'])\r\n onTouchStart(event: TouchEvent): void {\r\n this.isOpen.set(true);\r\n }\r\n \r\n /**\r\n * Handle touch end - close animation\r\n */\r\n @HostListener('touchend')\r\n onTouchEnd(): void {\r\n this.isOpen.set(false);\r\n }\r\n \r\n /**\r\n * Handle touch cancel - close animation\r\n */\r\n @HostListener('touchcancel')\r\n onTouchCancel(): void {\r\n this.isOpen.set(false);\r\n }\r\n \r\n /**\r\n * Handle click - open modal\r\n * Only opens modal if not in loading or error state\r\n */\r\n @HostListener('click')\r\n async onClick(): Promise<void> {\r\n // Don't open modal if loading or in error state\r\n if (this.loading || this.error) {\r\n return;\r\n }\r\n\r\n const handbookData: HandbookDetailData = {\r\n title: this.label,\r\n variant: this.variant,\r\n iconName: this.iconName,\r\n itemCount: this.itemCount,\r\n items: this.items\r\n };\r\n\r\n await this.handbookModal.open(handbookData, {\r\n loading: this.loading,\r\n error: this.error\r\n });\r\n }\r\n \r\n /**\r\n * Calculate the number of page sheets to display\r\n * Max 6 sheets regardless of item count\r\n */\r\n getPageSheets(): number[] {\r\n const count = Math.min(this.itemCount, 6);\r\n return Array(count).fill(0);\r\n }\r\n\r\n constructor(\r\n private handbookModal: DsMobileHandbookDetailModalService\r\n ) {}\r\n}\r\n\r\n","import { Component, input, output, signal, computed, forwardRef } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';\r\n\r\n/**\r\n * DsTextInputComponent\r\n * \r\n * Mobile-first text input field component following the design system.\r\n * Supports email, phone, text, and other input types.\r\n * \r\n * Features:\r\n * - All design system states (default, hover, focus, error, disabled)\r\n * - Validation error state with destructive border color\r\n * - Automatic error clearing when input becomes valid (configurable)\r\n * - Built-in validation based on input type or custom validator function\r\n * - Accessible with proper ARIA attributes\r\n * - ControlValueAccessor for Angular forms integration\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Basic usage -->\r\n * <ds-text-input\r\n * type=\"email\"\r\n * placeholder=\"Enter your email\"\r\n * [(ngModel)]=\"email\">\r\n * </ds-text-input>\r\n * \r\n * <!-- With validation error and auto-clear -->\r\n * <ds-text-input\r\n * type=\"email\"\r\n * placeholder=\"Enter your email\"\r\n * [hasError]=\"emailInvalid\"\r\n * errorMessage=\"Please enter a valid email\"\r\n * [autoClearError]=\"true\"\r\n * (errorCleared)=\"emailInvalid = false\"\r\n * [(ngModel)]=\"email\">\r\n * </ds-text-input>\r\n * \r\n * <!-- With custom validator -->\r\n * <ds-text-input\r\n * type=\"text\"\r\n * placeholder=\"Enter phone number\"\r\n * [validator]=\"phoneValidator\"\r\n * [hasError]=\"phoneInvalid\"\r\n * (errorCleared)=\"phoneInvalid = false\"\r\n * [(ngModel)]=\"phone\">\r\n * </ds-text-input>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-text-input',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => DsTextInputComponent),\r\n multi: true\r\n }\r\n ],\r\n styles: [`\r\n :host {\r\n display: block;\r\n width: 100%;\r\n }\r\n\r\n .text-input-wrapper {\r\n position: relative;\r\n width: 100%;\r\n }\r\n\r\n .text-input {\r\n width: 100%;\r\n height: 48px;\r\n padding: 0 16px;\r\n box-sizing: border-box;\r\n \r\n /* Typography */\r\n font-family: 'Brockmann', system-ui, -apple-system, sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--text-color-default-primary);\r\n \r\n /* Background & Border */\r\n background-color: var(--color-background-neutral-primary);\r\n border: 1px solid var(--border-color-default);\r\n border-radius: 8px;\r\n \r\n /* Transitions */\r\n transition: \r\n border-color var(--transition-duration-fast) var(--ease-smooth),\r\n background-color var(--transition-duration-fast) var(--ease-smooth),\r\n box-shadow var(--transition-duration-fast) var(--ease-smooth);\r\n \r\n /* Remove default browser styles */\r\n outline: none;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n }\r\n\r\n /* Placeholder styling */\r\n .text-input::placeholder {\r\n color: var(--text-color-default-tertiary);\r\n }\r\n\r\n /* Default state - no additional styles needed */\r\n\r\n /* Hover state */\r\n .text-input:hover:not(:disabled):not(:focus) {\r\n border-color: var(--border-color-default);\r\n background-color: var(--color-background-neutral-primary-hover);\r\n }\r\n\r\n /* Focus state */\r\n .text-input:focus {\r\n border-color: var(--color-brand-base);\r\n background-color: var(--color-background-neutral-primary);\r\n box-shadow: 0 0 0 3px var(--outline-color-default);\r\n }\r\n\r\n /* Error state */\r\n .text-input.error {\r\n border-color: var(--color-destructive-base);\r\n }\r\n\r\n .text-input.error:focus {\r\n border-color: var(--color-destructive-base);\r\n box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);\r\n }\r\n\r\n /* Disabled state */\r\n .text-input:disabled {\r\n background-color: var(--color-background-neutral-disabled);\r\n border-color: var(--border-color-default);\r\n color: var(--text-color-default-disabled);\r\n cursor: not-allowed;\r\n }\r\n\r\n .text-input:disabled::placeholder {\r\n color: var(--text-color-default-disabled);\r\n }\r\n\r\n /* Error message */\r\n .error-message {\r\n margin-top: 8px;\r\n font-family: 'Brockmann', system-ui, -apple-system, sans-serif;\r\n font-size: var(--font-size-sm);\r\n font-weight: 400;\r\n line-height: 1.4;\r\n color: var(--color-destructive-base);\r\n }\r\n `],\r\n template: `\r\n <div class=\"text-input-wrapper\">\r\n <input\r\n [type]=\"type()\"\r\n [placeholder]=\"placeholder()\"\r\n [value]=\"value()\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [required]=\"required()\"\r\n [autocomplete]=\"autocomplete() || null\"\r\n [attr.inputmode]=\"inputmode() || null\"\r\n [class.error]=\"hasError()\"\r\n [attr.aria-invalid]=\"hasError()\"\r\n [attr.aria-describedby]=\"hasError() && errorMessage() ? 'error-' + inputId : null\"\r\n class=\"text-input\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onBlur()\"\r\n (focus)=\"onFocus()\"\r\n [id]=\"inputId\">\r\n \r\n @if (hasError() && errorMessage()) {\r\n <div \r\n class=\"error-message\"\r\n [id]=\"'error-' + inputId\"\r\n role=\"alert\">\r\n {{ errorMessage() }}\r\n </div>\r\n }\r\n </div>\r\n `\r\n})\r\nexport class DsTextInputComponent implements ControlValueAccessor {\r\n // Input properties\r\n type = input<'text' | 'email' | 'tel' | 'password' | 'url' | 'search'>('text');\r\n placeholder = input<string>('');\r\n disabled = input<boolean>(false);\r\n readonly = input<boolean>(false);\r\n required = input<boolean>(false);\r\n hasError = input<boolean>(false);\r\n errorMessage = input<string>('');\r\n autocomplete = input<string>('');\r\n inputmode = input<'text' | 'email' | 'tel' | 'numeric' | 'url' | 'search' | undefined>(undefined);\r\n autoClearError = input<boolean>(true);\r\n validator = input<((value: string) => boolean) | null>(null);\r\n\r\n // Output events\r\n valueChange = output<string>();\r\n blur = output<FocusEvent>();\r\n focus = output<FocusEvent>();\r\n errorCleared = output<void>();\r\n\r\n // Internal state\r\n private _value = signal<string>('');\r\n value = computed(() => this._value());\r\n \r\n // Generate unique ID for accessibility\r\n inputId = `ds-text-input-${Math.random().toString(36).substring(2, 9)}`;\r\n\r\n // ControlValueAccessor implementation\r\n private onChange = (value: string) => {};\r\n private onTouched = () => {};\r\n\r\n onInput(event: Event): void {\r\n const target = event.target as HTMLInputElement;\r\n const newValue = target.value;\r\n this._value.set(newValue);\r\n this.onChange(newValue);\r\n this.valueChange.emit(newValue);\r\n \r\n // Auto-clear error if input becomes valid\r\n if (this.autoClearError() && this.hasError()) {\r\n const isValid = this.validateInput(newValue);\r\n if (isValid) {\r\n this.errorCleared.emit();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Validates the input value based on type or custom validator\r\n */\r\n private validateInput(value: string): boolean {\r\n // Use custom validator if provided\r\n const customValidator = this.validator();\r\n if (customValidator) {\r\n return customValidator(value);\r\n }\r\n\r\n // Use built-in validation based on input type\r\n const inputType = this.type();\r\n const inputElement = document.createElement('input');\r\n inputElement.type = inputType;\r\n inputElement.value = value;\r\n \r\n // For email type, use HTML5 validation\r\n if (inputType === 'email') {\r\n return inputElement.validity.valid;\r\n }\r\n \r\n // For required fields, check if value exists\r\n if (this.required() && !value.trim()) {\r\n return false;\r\n }\r\n \r\n // Default: valid if HTML5 validation passes\r\n return inputElement.validity.valid;\r\n }\r\n\r\n onBlur(): void {\r\n this.onTouched();\r\n }\r\n\r\n onFocus(): void {\r\n // Focus event can be emitted if needed\r\n }\r\n\r\n // ControlValueAccessor methods\r\n writeValue(value: string): void {\r\n this._value.set(value || '');\r\n }\r\n\r\n registerOnChange(fn: (value: string) => void): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: () => void): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n // Angular forms will handle this via the disabled input\r\n }\r\n}\r\n\r\n","// Mobile Page Components\r\nexport * from './page-main';\r\nexport * from './page-details';\r\n\r\n// Mobile Content Components\r\nexport * from './content';\r\nexport * from './header-content';\r\n\r\n// Mobile Community Components\r\nexport * from './comment';\r\nexport * from './post-composer';\r\nexport * from './message-composer';\r\nexport * from './message-bubble';\r\n\r\n// Mobile List Components\r\nexport * from './list-item';\r\nexport * from './list-item-static';\r\nexport { \r\n DsMobileInteractiveListItemPostComponent, \r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n PostPdfAttachmentComponent \r\n} from './interactive-list-item-post';\r\nexport { DsMobileInteractiveListItemInquiryComponent } from './interactive-list-item-inquiry';\r\nexport { DsMobileInteractiveListItemMessageComponent } from './interactive-list-item-message';\r\nexport { DsMobileContactListItemComponent } from './contact-list-item';\r\n\r\n// Mobile Layout Components\r\nexport { DsMobileTabsComponent } from './tabs';\r\nexport { DsMobileTabBarComponent, type TabConfig } from './tab-bar';\r\nexport { DsMobileInlineTabsComponent, type InlineTabItem } from './inline-tabs';\r\n\r\n// Mobile Bottom Sheet Components\r\nexport * from './bottom-sheet';\r\n\r\n// Mobile Lightbox Components\r\nexport * from './lightbox';\r\n\r\n// Mobile Inline Photo Component\r\nexport * from './inline-photo';\r\n\r\n// Mobile Modal Service\r\nexport * from './modal';\r\n\r\n// Mobile Post Detail Modal\r\nexport * from './post-detail-modal';\r\n\r\n// Mobile Chat Modal\r\nexport * from './chat-modal';\r\n\r\n// Mobile Handbook Components\r\nexport * from './handbook-folder';\r\nexport * from './handbook-detail-modal';\r\n\r\n// Text Input Component\r\nexport * from './text-input';\r\n\r\n// Mobile Avatar Component\r\nexport * from './avatar-with-badge';\r\n\r\n// Shared directives\r\nexport * from './shared';\r\n","import { Component, signal, computed } from '@angular/core';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { DsMobileContentComponent } from '../components/content';\r\nimport { DsMobileInteractiveListItemPostComponent } from '../components/interactive-list-item-post';\r\nimport { DsMobileCardInlineFileComponent } from '../components/card-inline-file';\r\nimport { \r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent\r\n} from '../components/interactive-list-item-post';\r\nimport { DsMobilePostComposerComponent } from '../components/post-composer';\r\nimport { DsMobileBottomSheetService } from '../components/bottom-sheet/ds-mobile-bottom-sheet.service';\r\nimport { DsMobilePostCreateBottomSheetComponent } from '../components/bottom-sheet/ds-mobile-post-create-bottom-sheet';\r\nimport { DsMobilePostActionsBottomSheetComponent, PostActionResult } from '../components/bottom-sheet';\r\nimport { DsMobileLightboxService, LightboxAuthor } from '../components/lightbox';\r\nimport { DsMobilePostDetailModalService } from '../components/post-detail-modal';\r\nimport { DsMobileInlinePhotoComponent } from '../components/inline-photo';\r\nimport { UserService } from '../services/user.service';\r\n\r\n@Component({\r\n selector: 'app-mobile-community-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageMainComponent,\r\n DsMobileContentComponent,\r\n DsMobileInteractiveListItemPostComponent,\r\n DsMobilePostComposerComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostAttachmentsComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCardInlineFileComponent,\r\n DsIconComponent,\r\n DsMobileInlinePhotoComponent\r\n ],\r\n styles: [`\r\n .post-feed {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n .post-list-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n /* Remove custom dividers - now handled by ds-mobile-list-item */\r\n \r\n .pinned-posts-section {\r\n margin: -12px -12px 12px -12px;\r\n padding: 0 12px 12px 12px;\r\n box-shadow: var(--box-shadow-sm);\r\n border-radius: 16px;\r\n border: 1px solid var(--border-color-default);\r\n }\r\n \r\n .clickable-image {\r\n cursor: pointer;\r\n transition: transform 0.2s ease, opacity 0.2s ease;\r\n border-radius: 8px;\r\n display: block;\r\n width: 100%;\r\n aspect-ratio: 16/9;\r\n object-fit: cover;\r\n }\r\n \r\n .clickable-image:active {\r\n transform: scale(0.98);\r\n opacity: 0.9;\r\n }\r\n \r\n /* Empty State */\r\n .community-empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-image {\r\n width: 96px;\r\n height: 96px;\r\n margin-bottom: 24px;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Fællesskab\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n (refresh)=\"handleRefresh($event)\">\r\n \r\n <!-- Post Composer in header-expandable -->\r\n <ds-mobile-post-composer\r\n header-content\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n [avatarSrc]=\"userService.avatarSrc()\"\r\n (composerClick)=\"openPostCreator()\"\r\n />\r\n \r\n <ds-mobile-content>\r\n <div class=\"post-feed\">\r\n <!-- Pinned Posts Section -->\r\n <div class=\"pinned-posts-section\">\r\n <h2 class=\"section-headline\">\r\n <ds-icon name=\"remixPushpinFill\" size=\"16px\" color=\"primary\" />\r\n Fastgjorte opslag\r\n </h2>\r\n \r\n <!-- Pinned: Maintenance Announcement -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Karen Nielsen'\"\r\n [authorRole]=\"'Ejendomsadministrator'\"\r\n [timestamp]=\"'2d siden'\"\r\n [avatarInitials]=\"'KN'\"\r\n [showBadge]=\"true\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('4')\"\r\n (commentClick)=\"openPost('4', true)\"\r\n (longPress)=\"handlePostLongPress('4', false)\">\r\n \r\n <post-content>\r\n <post-text>📢 Påmindelse: Bygningsvedligeholdelse planlagt til denne lørdag fra kl. 9 til 14. Vandet vil være midlertidigt lukket. Vær venlig at planlægge derefter!</post-text>\r\n \r\n <post-attachments>\r\n <ds-mobile-card-inline-file\r\n [fileName]=\"'Husregler.pdf'\"\r\n [fileSize]=\"'245 KB'\"\r\n [variant]=\"'pdf'\"\r\n [layout]=\"'compact'\"\r\n (fileClick)=\"openHouseRulesPdf()\">\r\n </ds-mobile-card-inline-file>\r\n </post-attachments>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"89\" />\r\n <action-comment [count]=\"67\" (commentClick)=\"openPost('4', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n </div>\r\n \r\n <!-- All Posts Section -->\r\n <h2 class=\"section-headline\">Alle opslag</h2>\r\n \r\n @if (hasAnyPosts()) {\r\n <div class=\"post-list-wrapper\">\r\n <!-- User Created Posts -->\r\n @for (post of userPosts(); track $index) {\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"post.authorName\"\r\n [authorRole]=\"post.authorRole\"\r\n [timestamp]=\"post.timestamp\"\r\n [avatarType]=\"post.avatarType\"\r\n [avatarSrc]=\"post.avatarSrc\"\r\n [avatarInitials]=\"post.avatarInitials\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openUserPost($index)\"\r\n (commentClick)=\"openUserPost($index, true)\"\r\n (longPress)=\"handlePostLongPress($index, post.authorRole === 'Dig')\">\r\n \r\n <post-content>\r\n @if (post.content) {\r\n <post-text>{{ post.content }}</post-text>\r\n }\r\n @if (post.imageSrc) {\r\n <post-media>\r\n <img \r\n [src]=\"post.imageSrc\" \r\n [alt]=\"post.imageAlt || 'Posted image'\" \r\n class=\"clickable-image\"\r\n (click)=\"openImageLightbox(post.imageSrc, post.imageAlt || 'Posted image', post.content, $event)\"\r\n />\r\n </post-media>\r\n }\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"post.likeCount\" [active]=\"post.isLiked\" />\r\n <action-comment [count]=\"post.commentCount\" (commentClick)=\"openUserPost($index, true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n }\r\n \r\n <!-- Post 1: Text only -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Anders Jensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'2t siden'\"\r\n [avatarType]=\"'photo'\"\r\n [avatarSrc]=\"'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=face'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('1')\"\r\n (commentClick)=\"openPost('1', true)\"\r\n (longPress)=\"handlePostLongPress('1', false)\">\r\n \r\n <post-content>\r\n <post-text>Lige flyttet ind i min nye lejlighed! Udlejeren var super hjælpsom gennem hele processen. Virkelig begejstret for at være en del af dette fællesskab! 🏠</post-text>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"42\" />\r\n <action-comment [count]=\"12\" (commentClick)=\"openPost('1', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 2: With multiple images (grid layout) -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Sophie Andersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'4t siden'\"\r\n [avatarInitials]=\"'SA'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('2')\"\r\n (commentClick)=\"openPost('2', true)\"\r\n (longPress)=\"handlePostLongPress('2', false)\">\r\n \r\n <post-content>\r\n <post-text>Jeg har taget nogle billeder af vores smukke ejendom i løbet af det sidste par måneder. Fra altanudsigten om morgenen til den nye trappe og fællesområderne. Elsker virkelig at bo her! 🏡✨</post-text>\r\n <ds-mobile-inline-photo\r\n [images]=\"[\r\n '/Assets/Dummy-photos/balcony-view.jpg',\r\n '/Assets/Dummy-photos/staircase.jpg',\r\n '/Assets/Dummy-photos/park.jpg',\r\n '/Assets/Dummy-photos/yard.jpg'\r\n ]\"\r\n [author]=\"{\r\n name: 'Sophie Andersen',\r\n role: 'Lejer',\r\n avatarInitials: 'SA',\r\n avatarType: 'initials',\r\n timestamp: '4t siden'\r\n }\"\r\n />\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [active]=\"true\" [count]=\"156\" />\r\n <action-comment [count]=\"34\" (commentClick)=\"openPost('2', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 3: Question -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Thomas Hansen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'1d siden'\"\r\n [avatarType]=\"'photo'\"\r\n [avatarSrc]=\"'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('3')\"\r\n (commentClick)=\"openPost('3', true)\"\r\n (longPress)=\"handlePostLongPress('3', false)\">\r\n \r\n <post-content>\r\n <post-text>Kender nogen et fælles fitnesscenter i nærheden? Leder efter anbefalinger til gode træningscentre i området. 🏋️</post-text>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"23\" />\r\n <action-comment [count]=\"45\" (commentClick)=\"openPost('3', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 3.5: Property Manager showcase with 6+ photos -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Karen Nielsen'\"\r\n [authorRole]=\"'Ejendomsadministrator'\"\r\n [timestamp]=\"'2d siden'\"\r\n [avatarInitials]=\"'KN'\"\r\n [showBadge]=\"true\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('3.5')\"\r\n (commentClick)=\"openPost('3.5', true)\"\r\n (longPress)=\"handlePostLongPress('3.5', false)\">\r\n \r\n <post-content>\r\n <post-text>Her er et kig på vores nyligt renoverede fællesområder! Vi har opgraderet postkasserne, trappeafsatsen og gårdområdet. Der er også blevet ansat en ny vicevært. Glæd dig over forbedringerne! 🏢✨</post-text>\r\n <ds-mobile-inline-photo\r\n [images]=\"[\r\n '/Assets/Dummy-photos/mailboxes.jpg',\r\n '/Assets/Dummy-photos/staircase.jpg',\r\n '/Assets/Dummy-photos/yard.jpg',\r\n '/Assets/Dummy-photos/park.jpg',\r\n '/Assets/Dummy-photos/balcony-view.jpg',\r\n '/Assets/Dummy-photos/handyman.jpg'\r\n ]\"\r\n [author]=\"{\r\n name: 'Karen Nielsen',\r\n role: 'Ejendomsadministrator',\r\n avatarInitials: 'KN',\r\n avatarType: 'initials',\r\n timestamp: '2d siden'\r\n }\"\r\n [maxVisible]=\"5\"\r\n />\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [count]=\"234\" />\r\n <action-comment [count]=\"89\" (commentClick)=\"openPost('3.5', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n\r\n <!-- Post 5: Event -->\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Emma Petersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'3d siden'\"\r\n [avatarType]=\"'photo'\"\r\n [avatarSrc]=\"'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face'\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost('5')\"\r\n (commentClick)=\"openPost('5', true)\"\r\n (longPress)=\"handlePostLongPress('5', false)\">\r\n \r\n <post-content>\r\n <post-text>Arrangerer en fælles BBQ næste weekend! Alle er inviteret. Tag din yndlingsret med til at dele. Lad os lære hinanden bedre at kende! 🍔🌭</post-text>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [active]=\"true\" [count]=\"124\" />\r\n <action-comment [count]=\"89\" (commentClick)=\"openPost('5', true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n </div>\r\n } @else {\r\n <!-- Empty State -->\r\n <div class=\"community-empty-state\">\r\n <img \r\n src=\"/Assets/Empty%20state-chat.png\" \r\n alt=\"Ingen opslag endnu\" \r\n class=\"empty-state-image\"\r\n />\r\n <h3 class=\"empty-state-title\">Ingen opslag endnu</h3>\r\n <p class=\"empty-state-description\">Vær den første til at dele noget med dit fællesskab</p>\r\n </div>\r\n }\r\n </div>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileCommunityPageComponent {\r\n // Store user-created posts\r\n userPosts = signal<any[]>([\r\n {\r\n id: 'user-post-1',\r\n authorName: 'Lars Mikkelsen',\r\n authorRole: 'Dig',\r\n timestamp: '5m siden',\r\n avatarType: 'initials' as 'photo' | 'initials' | 'icon',\r\n avatarInitials: 'LM',\r\n content: 'Dette er mit første opslag! Ser frem til at forbinde med alle i bygningen. 🏠',\r\n isLiked: false,\r\n likeCount: 3,\r\n commentCount: 1\r\n }\r\n ]);\r\n \r\n // Flag to control whether static demo posts are shown\r\n // Set to false to see the empty state\r\n showStaticPosts = signal(true);\r\n \r\n // Computed to check if there are any posts to display\r\n hasAnyPosts = computed(() => {\r\n return this.userPosts().length > 0 || this.showStaticPosts();\r\n });\r\n \r\n constructor(\r\n private router: Router,\r\n private route: ActivatedRoute,\r\n private bottomSheet: DsMobileBottomSheetService,\r\n private lightbox: DsMobileLightboxService,\r\n private postModal: DsMobilePostDetailModalService,\r\n public userService: UserService\r\n ) {}\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n \r\n /**\r\n * Open post detail modal\r\n * This provides a better UX than route navigation:\r\n * - Maintains scroll position\r\n * - Native iOS-style modal feel\r\n * - Proper close button that works\r\n */\r\n async openPost(postId: string, focusComment: boolean = false): Promise<void> {\r\n console.log('[Community] ===== openPost called =====', postId, 'Focus comment:', focusComment);\r\n \r\n // Map post ID to post data (in real app, fetch from service)\r\n const postDataMap: Record<string, any> = {\r\n '1': {\r\n postId: '1',\r\n authorName: 'Anders Jensen',\r\n authorRole: 'Lejer',\r\n timestamp: '2t siden',\r\n avatarType: 'photo' as const,\r\n avatarSrc: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=face',\r\n content: 'Lige flyttet ind i min nye lejlighed! Udlejeren var super hjælpsom gennem hele processen. Virkelig begejstret for at være en del af dette fællesskab! 🏠',\r\n isLiked: false,\r\n likeCount: 42,\r\n commentCount: 12,\r\n comments: [\r\n {\r\n authorName: 'Mette Larsen',\r\n authorRole: 'Lejer',\r\n timestamp: '1t siden',\r\n avatarInitials: 'ML',\r\n content: 'Velkommen til fællesskabet!',\r\n likeCount: 5,\r\n isOwnComment: false\r\n },\r\n {\r\n authorName: 'Lars Mikkelsen',\r\n authorRole: 'Dig',\r\n timestamp: 'Lige nu',\r\n avatarInitials: 'LM',\r\n content: 'Vxhknbh',\r\n likeCount: 0,\r\n isOwnComment: true\r\n }\r\n ]\r\n },\r\n '2': {\r\n postId: '2',\r\n authorName: 'Sophie Andersen',\r\n authorRole: 'Lejer',\r\n timestamp: '4t siden',\r\n avatarInitials: 'SA',\r\n content: 'Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️',\r\n imageSrc: '/Assets/Dummy-photos/balcony-view.jpg',\r\n imageAlt: 'Altanudsigt',\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 34,\r\n comments: [\r\n {\r\n authorName: 'Anders Jensen',\r\n authorRole: 'Lejer',\r\n timestamp: '3t siden',\r\n avatarInitials: 'AJ',\r\n content: 'Wow, den udsigt er fantastisk! Hvilken etage er du på?',\r\n likeCount: 12,\r\n isOwnComment: false\r\n },\r\n {\r\n authorName: 'Thomas Hansen',\r\n authorRole: 'Lejer',\r\n timestamp: '3t siden',\r\n avatarInitials: 'TH',\r\n content: 'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆',\r\n isLiked: true,\r\n likeCount: 8,\r\n isOwnComment: false\r\n },\r\n {\r\n authorName: 'Lars Mikkelsen',\r\n authorRole: 'Dig',\r\n timestamp: 'Lige nu',\r\n avatarInitials: 'LM',\r\n content: 'Vxhknbh',\r\n likeCount: 0,\r\n isOwnComment: true\r\n }\r\n ]\r\n },\r\n '3': {\r\n postId: '3',\r\n authorName: 'Thomas Hansen',\r\n authorRole: 'Lejer',\r\n timestamp: '1d siden',\r\n avatarType: 'photo' as const,\r\n avatarSrc: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face',\r\n content: 'Kender nogen et fælles fitnesscenter i nærheden? Leder efter anbefalinger til gode træningscentre i området. 🏋️',\r\n isLiked: false,\r\n likeCount: 23,\r\n commentCount: 45,\r\n comments: []\r\n },\r\n '4': {\r\n postId: '4',\r\n authorName: 'Karen Nielsen',\r\n authorRole: 'Ejendomsadministrator',\r\n timestamp: '2d siden',\r\n avatarInitials: 'KN',\r\n content: '📢 Påmindelse: Bygningsvedligeholdelse planlagt til denne lørdag fra kl. 9 til 14. Vandet vil være midlertidigt lukket. Vær venlig at planlægge derefter!',\r\n isLiked: false,\r\n likeCount: 89,\r\n commentCount: 67,\r\n comments: []\r\n },\r\n '5': {\r\n postId: '5',\r\n authorName: 'Emma Petersen',\r\n authorRole: 'Lejer',\r\n timestamp: '3d siden',\r\n avatarType: 'photo' as const,\r\n avatarSrc: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face',\r\n content: 'Arrangerer en fælles BBQ næste weekend! Alle er inviteret. Tag din yndlingsret med til at dele. Lad os lære hinanden bedre at kende! 🍔🌭',\r\n isLiked: true,\r\n likeCount: 124,\r\n commentCount: 89,\r\n comments: []\r\n }\r\n };\r\n\r\n const postData = postDataMap[postId];\r\n \r\n if (postData) {\r\n // Add focusComment flag to postData\r\n await this.postModal.open({ ...postData, focusComment });\r\n }\r\n }\r\n \r\n /**\r\n * Open user-created post detail modal\r\n */\r\n async openUserPost(index: number, focusComment: boolean = false): Promise<void> {\r\n const posts = this.userPosts();\r\n const post = posts[index];\r\n \r\n if (post) {\r\n console.log('[Community] Opening user post modal:', index, 'Focus comment:', focusComment);\r\n \r\n // Convert user post to modal format with empty comments array\r\n const postData = {\r\n ...post,\r\n postId: `user-${index}`,\r\n comments: [] // User posts don't have comments yet\r\n };\r\n \r\n await this.postModal.open({ ...postData, focusComment });\r\n }\r\n }\r\n \r\n async openPostCreator(): Promise<void> {\r\n // Open the post creator as a bottom sheet modal\r\n // Using 95% initial height to maximize keyboard auto-open chances\r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobilePostCreateBottomSheetComponent,\r\n componentProps: {\r\n // This helps the component know it should auto-focus\r\n autoFocus: true\r\n },\r\n breakpoints: [0, 0.95, 1],\r\n initialBreakpoint: 0.95,\r\n handle: true\r\n });\r\n \r\n // Handle the result when the sheet is dismissed\r\n const result = await sheet.onWillDismiss();\r\n if (result.role === 'post' && result.data) {\r\n console.log('New post created:', result.data);\r\n \r\n // Create a new post object\r\n const newPost = {\r\n id: `user-post-${Date.now()}`, // Generate unique ID\r\n authorName: 'Lars Mikkelsen', // Current user name\r\n authorRole: 'Dig',\r\n timestamp: 'Lige nu',\r\n avatarType: this.userService.avatarType() as 'photo' | 'initials' | 'icon',\r\n avatarSrc: this.userService.avatarSrc(),\r\n avatarInitials: this.userService.avatarInitials(),\r\n content: result.data.content,\r\n imageSrc: result.data.images && result.data.images.length > 0 ? result.data.images[0] : undefined,\r\n imageAlt: result.data.images && result.data.images.length > 0 ? 'Slået billede op' : undefined,\r\n isLiked: false,\r\n likeCount: 0,\r\n commentCount: 0\r\n };\r\n \r\n // Add to the beginning of the posts array\r\n this.userPosts.update(posts => [newPost, ...posts]);\r\n }\r\n }\r\n \r\n /**\r\n * Open an image in the lightbox viewer\r\n * Prevents the post click event from firing\r\n */\r\n async openImageLightbox(imageSrc: string, title: string, description: string, event: Event): Promise<void> {\r\n console.log('[Community] Opening lightbox for image:', imageSrc);\r\n \r\n // Prevent the post card click event from firing\r\n event.stopPropagation();\r\n \r\n const authorMeta: LightboxAuthor = {\r\n name: 'Sophie Andersen',\r\n role: 'Lejer',\r\n avatarInitials: 'SA',\r\n timestamp: '4t siden'\r\n };\r\n \r\n // Open the lightbox with the image\r\n await this.lightbox.open({\r\n images: [\r\n {\r\n type: 'image',\r\n src: imageSrc,\r\n alt: title,\r\n title: title,\r\n description: description,\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 34\r\n }\r\n ],\r\n author: authorMeta,\r\n enableZoom: true,\r\n showControls: false, // Single image, no need for controls\r\n showActions: true, // Show like & comment actions\r\n showInfo: true\r\n });\r\n }\r\n\r\n async openHouseRulesPdf(): Promise<void> {\r\n console.log('[Community] Opening House Rules PDF');\r\n \r\n // Author metadata\r\n const authorMeta: LightboxAuthor = {\r\n name: 'Karen Nielsen',\r\n role: 'Ejendomsadministrator',\r\n avatarInitials: 'KN',\r\n timestamp: '2d siden'\r\n };\r\n \r\n // Open the PDF lightbox\r\n // Use absolute path for production deployment (Vercel, etc.)\r\n await this.lightbox.openPdf({\r\n pdf: {\r\n type: 'pdf',\r\n src: '/Assets/House_Rules.pdf', // Capital A to match public/Assets folder structure\r\n title: 'House Rules',\r\n description: 'Building regulations and community guidelines',\r\n fileSize: 250880, // 245 KB in bytes\r\n pageCount: 8\r\n },\r\n author: authorMeta\r\n });\r\n }\r\n \r\n /**\r\n * Handle long press on a post to show action sheet\r\n */\r\n async handlePostLongPress(postIdOrIndex: string | number, isOwnPost: boolean): Promise<void> {\r\n console.log('[Community] Post long pressed:', postIdOrIndex, 'isOwn:', isOwnPost);\r\n \r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobilePostActionsBottomSheetComponent,\r\n componentProps: {\r\n isOwnContent: isOwnPost\r\n },\r\n breakpoints: [0, 1],\r\n initialBreakpoint: 1,\r\n handle: true,\r\n backdropDismiss: true,\r\n cssClass: 'auto-height'\r\n });\r\n \r\n const result = await sheet.onWillDismiss();\r\n \r\n if (result.role === 'select' && result.data) {\r\n const action = (result.data as PostActionResult).action;\r\n \r\n switch (action) {\r\n case 'edit':\r\n console.log('Edit post:', postIdOrIndex);\r\n // Open the post create bottom sheet in edit mode\r\n let postContent = '';\r\n let postId = '';\r\n \r\n // Get post content based on postIdOrIndex\r\n if (typeof postIdOrIndex === 'number') {\r\n const post = this.userPosts()[postIdOrIndex];\r\n if (post) {\r\n postContent = post.content || '';\r\n postId = post.id || postIdOrIndex.toString();\r\n }\r\n } else {\r\n // For static posts, we'll need to determine content\r\n // For now, use a placeholder\r\n postId = postIdOrIndex.toString();\r\n postContent = 'Edit this post...';\r\n }\r\n \r\n // Open the bottom sheet in edit mode\r\n const editSheet = await this.bottomSheet.create({\r\n component: DsMobilePostCreateBottomSheetComponent,\r\n componentProps: {\r\n autoFocus: true,\r\n isEditMode: true,\r\n postId: postId,\r\n initialContent: postContent\r\n },\r\n breakpoints: [0, 0.95, 1],\r\n initialBreakpoint: 0.95,\r\n handle: true,\r\n backdropBlur: true,\r\n backdropOpacity: 0.6\r\n });\r\n \r\n // Handle the result when the sheet is dismissed\r\n const editResult = await editSheet.onWillDismiss();\r\n if (editResult.role === 'post' && editResult.data) {\r\n console.log('Post updated:', editResult.data);\r\n \r\n // Update the post in the array\r\n if (typeof postIdOrIndex === 'number') {\r\n const currentPosts = this.userPosts();\r\n const updatedPosts = currentPosts.map((post, index) => \r\n index === postIdOrIndex \r\n ? { ...post, content: editResult.data.content, timestamp: 'Just now' }\r\n : post\r\n );\r\n this.userPosts.set(updatedPosts);\r\n }\r\n }\r\n break;\r\n case 'delete':\r\n console.log('Delete post:', postIdOrIndex);\r\n if (confirm('Er du sikker på, at du vil slette dette opslag?')) {\r\n // If it's a user post (number index), remove it from the array\r\n if (typeof postIdOrIndex === 'number') {\r\n const currentPosts = this.userPosts();\r\n const updatedPosts = currentPosts.filter((_, index) => index !== postIdOrIndex);\r\n this.userPosts.set(updatedPosts);\r\n }\r\n // Otherwise it's a static post, just show confirmation\r\n else {\r\n alert('Opslag slettet!');\r\n }\r\n }\r\n break;\r\n case 'like':\r\n console.log('Like post:', postIdOrIndex);\r\n // Toggle like - in a real app, this would call an API\r\n alert('Opslag liket!');\r\n break;\r\n case 'reply':\r\n console.log('Reply to post:', postIdOrIndex);\r\n // Open the post detail modal with comment input focused\r\n if (typeof postIdOrIndex === 'number') {\r\n await this.openUserPost(postIdOrIndex, true);\r\n } else {\r\n await this.openPost(postIdOrIndex, true);\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n","import { Component } from '@angular/core';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { \r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n} from '../components/content';\r\nimport { DsMobileHandbookFolderComponent } from '../components/handbook-folder';\r\nimport { UserService } from '../services/user.service';\r\nimport { HandbookItem } from '../components/handbook-detail-modal/ds-mobile-handbook-detail-modal';\r\n\r\n@Component({\r\n selector: 'app-mobile-handbook-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageMainComponent,\r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n DsMobileHandbookFolderComponent\r\n ],\r\n styles: [`\r\n .folders-grid {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 20px;\r\n justify-items: center;\r\n }\r\n\r\n /* 3 columns at tablet breakpoint (md: 768px) and above\r\n Content area at this breakpoint is ~864px max */\r\n @media (min-width: 768px) {\r\n .folders-grid {\r\n grid-template-columns: repeat(3, 1fr);\r\n }\r\n }\r\n \r\n ds-mobile-handbook-folder {\r\n width: 100%;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Håndbog\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n (refresh)=\"handleRefresh($event)\">\r\n \r\n <ds-mobile-content>\r\n <ds-mobile-content-section>\r\n <div class=\"folders-grid\">\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'pink'\"\r\n [iconName]=\"'remixLightbulbLine'\"\r\n [itemCount]=\"8\"\r\n [label]=\"'Forsyninger'\"\r\n [items]=\"utilitiesItems\">\r\n </ds-mobile-handbook-folder>\r\n\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'success'\"\r\n [iconName]=\"'remixKey2Line'\"\r\n [itemCount]=\"4\"\r\n [label]=\"'Sikkerhedsudstyr'\"\r\n [items]=\"sikkerhedsudstyrItems\">\r\n </ds-mobile-handbook-folder>\r\n\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'blue'\"\r\n [iconName]=\"'remixFileList3Line'\"\r\n [itemCount]=\"8\"\r\n [label]=\"'Servicekontrakter'\"\r\n [items]=\"serviceContractsItems\">\r\n </ds-mobile-handbook-folder>\r\n\r\n <ds-mobile-handbook-folder\r\n [variant]=\"'warning'\"\r\n [iconName]=\"'remixToolsLine'\"\r\n [itemCount]=\"5\"\r\n [label]=\"'Udstyr'\"\r\n [items]=\"equipmentItems\">\r\n </ds-mobile-handbook-folder>\r\n </div>\r\n </ds-mobile-content-section>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileHandbookPageComponent {\r\n // Utilities folder data\r\n utilitiesItems: HandbookItem[] = [\r\n {\r\n title: 'El',\r\n description: 'Hovedeltavle placeret i kælderrum B-12. Nødafbryderknap er ved hovedindgangen. Alle kredsløb er mærket.',\r\n contacts: [\r\n { name: 'ElektroTek ApS', initials: 'E', contactPerson: 'Lars Nielsen', phoneNumber: '+45 23 45 67 89' }\r\n ]\r\n },\r\n {\r\n title: 'Elektrisk diagram',\r\n description: 'Komplet diagram over bygningens elektriske installation med alle kredsløb og afbrydere.',\r\n attachments: [\r\n { name: 'Elektrisk_Diagram.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Vandforsyning',\r\n description: 'Hovedvandhane er placeret i kælderens tekniske rum. Individuelle lejlighedsafspærringer er i gangpanelerne. Vandtryk overvåges automatisk.',\r\n contacts: [\r\n { name: 'VVS Hansen', initials: 'V', contactPerson: 'Peter Hansen', phoneNumber: '+45 34 56 78 90' }\r\n ]\r\n },\r\n {\r\n title: 'Varmesystem',\r\n description: 'Fjernvarmetilslutning i kælder. Termostater i hver enhed kan justeres individuelt. Systemet vedligeholdes kvartalsvis af certificerede teknikere.',\r\n contacts: [\r\n { name: 'Varme Service A/S', initials: 'V', contactPerson: 'Maria Jensen', phoneNumber: '+45 45 67 89 01' }\r\n ]\r\n },\r\n {\r\n title: 'Varmeanlæg dokumentation',\r\n description: 'Teknisk dokumentation og vedligeholdelseshistorik for bygningens varmesystem.',\r\n attachments: [\r\n { name: 'Varmeplan.pdf', type: 'pdf' },\r\n { name: 'Vedligeholdelseslog.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Internet & TV',\r\n description: 'Fiberforbindelse i bygningen. Distributionspanel er i stueetageteknisk rum. Hver lejlighed har ethernet-stik i stue og soveværelser.',\r\n contacts: [\r\n { name: 'TeleCom Solutions', initials: 'T', contactPerson: 'Anders Petersen', phoneNumber: '+45 56 78 90 12' }\r\n ]\r\n },\r\n {\r\n title: 'Netværksopsætning guide',\r\n attachments: [\r\n { name: 'Netværksopsætning.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Affaldshåndtering',\r\n description: 'Affaldssorteringsstation placeret i gården. Afhentninger: Dagrenovation (man/tor), Genbrug (ons), Organisk (tir/fre). Storskrald kræver booking.',\r\n attachments: [\r\n { name: 'Affaldsretningslinjer.pdf', type: 'pdf' }\r\n ]\r\n }\r\n ];\r\n\r\n // Safety Equipment folder data\r\n sikkerhedsudstyrItems: HandbookItem[] = [\r\n {\r\n title: 'Fælles områder og sikkerhed',\r\n description: 'Trappeopgange med nødbelysning og brandsikre døre. Postkasser placeret i indgangspartiet. Hold altid flugtveje fri.',\r\n images: [\r\n '/Assets/Dummy-photos/staircase.jpg',\r\n '/Assets/Dummy-photos/mailboxes.jpg'\r\n ]\r\n },\r\n {\r\n title: 'Hjertestarter (AED)',\r\n description: 'Automatisk hjertestarter placeret i stueetagen ved hovedindgangen. Tilgængelig 24/7. Ingen særlig uddannelse kræves - enheden guider dig gennem processen.',\r\n contacts: [\r\n { name: 'MediTech Service', initials: 'M', contactPerson: 'John Mortensen', phoneNumber: '+45 12 34 56 78' }\r\n ]\r\n },\r\n {\r\n title: 'Brandslukningsudstyr',\r\n description: 'Brandslukkere placeret på hver etage. Eftersyn udføres årligt. Brandalarm aktiveres automatisk ved røg.',\r\n attachments: [\r\n { name: 'Brandplan.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Alarmsystem',\r\n description: 'Adgangskontrol med kodesystem ved alle indgange. Kode ændres kvartalsvis. Ved indbrud kontakt straks politiet og ejendomsadministrationen.',\r\n contacts: [\r\n { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 98 76 54 32' }\r\n ]\r\n }\r\n ];\r\n\r\n // Service Contracts folder data\r\n serviceContractsItems: HandbookItem[] = [\r\n {\r\n title: 'Rengøringsservice',\r\n description: 'Ugentlig rengøring af fællesarealer inklusiv indgangshal, trapper og elevatorer. Hovedrengøring kvartalsvis. Service leveres mandag-fredag, 6:00-9:00.',\r\n contacts: [\r\n { name: 'CleanCo Denmark', initials: 'C', contactPerson: 'Anne Kristensen', phoneNumber: '+45 89 01 23 45' }\r\n ]\r\n },\r\n {\r\n title: 'Rengøringskontrakt',\r\n attachments: [\r\n { name: 'Rengøringskontrakt_2024.pdf', type: 'pdf' },\r\n { name: 'Rengøringsplan.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Udendørs arealer',\r\n description: 'Fælles grønne områder med bede, siddepladser og terrasse. Beboere må frit benytte området. Respektér planterne og hold området pænt.',\r\n images: [\r\n '/Assets/Dummy-photos/park.jpg',\r\n '/Assets/Dummy-photos/yard.jpg'\r\n ]\r\n },\r\n {\r\n title: 'Havevedligeholdelse',\r\n description: 'Professionel havepleje inklusiv plæneklipning, hækklipning og blomsterbedvedligeholdelse. Vintersnefjerning inkluderet.',\r\n contacts: [\r\n { name: 'Green Gardens ApS', initials: 'G', contactPerson: 'Michael Olsen', phoneNumber: '+45 90 12 34 56' }\r\n ]\r\n },\r\n {\r\n title: 'Haveserviceaftale',\r\n attachments: [\r\n { name: 'Haveserviceaftale.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Vinduespolering',\r\n description: 'Professionel vinduespoleringsservice for alle udvendige vinduer to gange årligt - forår og efterår.',\r\n contacts: [\r\n { name: 'Crystal Clear Windows', initials: 'C', contactPerson: 'Lene Schmidt', phoneNumber: '+45 01 23 45 67' }\r\n ]\r\n },\r\n {\r\n title: 'Sikkerhedsservice',\r\n description: '24/7 overvågningsservice med alarmrespons. Direkte forbindelse til politi og brandvæsen.',\r\n contacts: [\r\n { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 12 34 56 78' }\r\n ]\r\n },\r\n {\r\n title: 'Sikkerhedskontrakt og procedurer',\r\n attachments: [\r\n { name: 'Sikkerhedskontrakt.pdf', type: 'pdf' },\r\n { name: 'Nødprocedurer.pdf', type: 'pdf' }\r\n ]\r\n }\r\n ];\r\n\r\n // Equipment folder data\r\n equipmentItems: HandbookItem[] = [\r\n {\r\n title: 'Balkon udsigt',\r\n description: 'Eksempel på udsigt fra øverste etagers balkoner. Flere lejligheder har privat altan med fantastisk udsyn.',\r\n images: [\r\n '/Assets/Dummy-photos/balcony-view.jpg'\r\n ]\r\n },\r\n {\r\n title: 'Vaskerum',\r\n description: 'Fælles vaskerum med 4 vaskemaskiner og 4 tørretumblere. Bookingsystem tilgængeligt via beboerportal. Maskiner accepterer betalingskort. Åbningstider: 7:00-22:00.',\r\n contacts: [\r\n { name: 'WashTech Service', initials: 'W', contactPerson: 'Kirsten Berg', phoneNumber: '+45 34 56 78 90' }\r\n ]\r\n },\r\n {\r\n title: 'Vaskeri instruktioner',\r\n attachments: [\r\n { name: 'Vaskeinstruktioner.pdf', type: 'pdf' },\r\n { name: 'Bookingguide.pdf', type: 'pdf' }\r\n ]\r\n },\r\n {\r\n title: 'Vedligeholdelse og reparationer',\r\n description: 'Ved behov for reparationer eller vedligeholdelse i din lejlighed, kontakt vores hausmeister. Akutte problemer håndteres samme dag.',\r\n images: [\r\n '/Assets/Dummy-photos/handyman.jpg'\r\n ],\r\n contacts: [\r\n { name: 'Hausmeister Service', initials: 'H', contactPerson: 'Erik Sørensen', phoneNumber: '+45 56 78 90 12' }\r\n ]\r\n },\r\n {\r\n title: 'Værktøjsudlån',\r\n description: 'Basis håndværktøj tilgængeligt til beboerbrug. Kvittér for værktøj ved receptionen. Returnér inden for 48 timer.',\r\n attachments: [\r\n { name: 'Værktøjsliste.pdf', type: 'pdf' },\r\n { name: 'Udlånspolitik.pdf', type: 'pdf' }\r\n ]\r\n }\r\n ];\r\n \r\n constructor(public userService: UserService) {}\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n}\r\n\r\n","import { Component } from '@angular/core';\r\nimport { NavController } from '@ionic/angular/standalone';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { \r\n DsMobileHeaderContentComponent,\r\n DsMobileHeaderContentTileComponent,\r\n TileIconComponent,\r\n TileContentComponent,\r\n TileLabelComponent,\r\n TileValueComponent\r\n} from '../components/header-content';\r\nimport { \r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n SectionHeaderComponent,\r\n ContentRowComponent\r\n} from '../components/content';\r\nimport { UserService } from '../services/user.service';\r\n\r\n@Component({\r\n selector: 'app-home-page',\r\n standalone: true,\r\n imports: [\r\n DsIconComponent,\r\n DsMobilePageMainComponent,\r\n DsMobileHeaderContentComponent,\r\n DsMobileHeaderContentTileComponent,\r\n TileIconComponent,\r\n TileContentComponent,\r\n TileLabelComponent,\r\n TileValueComponent,\r\n DsMobileContentComponent,\r\n DsMobileContentSectionComponent,\r\n SectionHeaderComponent,\r\n ContentRowComponent\r\n ],\r\n styles: [`\r\n /* Placeholder grey boxes for content */\r\n .grey-box {\r\n height: 120px;\r\n border-radius: 12px;\r\n background: var(--color-background-neutral-tertiary);\r\n flex: 1;\r\n }\r\n\r\n .grey-box.clickable {\r\n background: var(--color-background-brand);\r\n cursor: pointer;\r\n transition: transform var(--transition-duration-fast) var(--ease-smooth);\r\n }\r\n\r\n .grey-box.clickable:active {\r\n transform: scale(0.98);\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Hjem\"\r\n headerTitle=\"Velkommen, Lars\"\r\n headerSubtitle=\"Din lejebolig på et øjeblik.\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n (refresh)=\"handleRefresh($event)\">\r\n \r\n <!-- Property info tiles in header -->\r\n <ds-mobile-header-content header-content>\r\n <ds-mobile-header-content-tile>\r\n <tile-icon>\r\n <ds-icon name=\"remixHome4Line\" size=\"20px\" />\r\n </tile-icon>\r\n <tile-content>\r\n <tile-label>Areal</tile-label>\r\n <tile-value>120 m²</tile-value>\r\n </tile-content>\r\n </ds-mobile-header-content-tile>\r\n\r\n <ds-mobile-header-content-tile>\r\n <tile-icon>\r\n <ds-icon name=\"remixCollageLine\" size=\"20px\" />\r\n </tile-icon>\r\n <tile-content>\r\n <tile-label>Værelser</tile-label>\r\n <tile-value>3 værelser</tile-value>\r\n </tile-content>\r\n </ds-mobile-header-content-tile>\r\n </ds-mobile-header-content>\r\n \r\n <!-- Main page content -->\r\n <ds-mobile-content>\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <!-- Purple box - clickable with brand background -->\r\n <content-row>\r\n <div class=\"grey-box clickable\" (click)=\"navigateToDetail()\"></div>\r\n </content-row>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"half\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"half\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"half\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n\r\n <ds-mobile-content-section>\r\n <section-header width=\"third\"></section-header>\r\n <content-row>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n <div class=\"grey-box\"></div>\r\n </content-row>\r\n </ds-mobile-content-section>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileHomePageComponent {\r\n constructor(\r\n private navCtrl: NavController,\r\n public userService: UserService\r\n ) {\r\n console.log('MobileHomePageComponent constructor');\r\n }\r\n\r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n\r\n navigateToDetail(): void {\r\n // Navigation removed - home/detail page was deleted\r\n console.log('Navigate to detail (page removed)');\r\n }\r\n}\r\n\r\n","import { Animation } from '@ionic/angular';\r\nimport { createAnimation } from '@ionic/core';\r\n\r\n/**\r\n * Custom page transition - iOS-style push/pop\r\n * \r\n * FORWARD (navigating TO detail):\r\n * - Entering page (detail): slides in from RIGHT, z-index 10 (on top)\r\n * - Leaving page (list): slides LEFT slightly, z-index 9 (underneath)\r\n * \r\n * REVERSE (swipe back FROM detail):\r\n * - Entering page (list): slides in from LEFT, z-index 9 (underneath)\r\n * - Leaving page (detail): slides out to RIGHT, z-index 10 (on top)\r\n */\r\nexport const customPageTransition = (_: HTMLElement, opts: any): Animation => {\r\n const DURATION = 400;\r\n const isBackDirection = opts.direction === 'back';\r\n \r\n const rootTransition = createAnimation()\r\n .duration(opts.duration || DURATION)\r\n .easing('cubic-bezier(0.32,0.72,0,1)');\r\n\r\n // Entering page animation\r\n const enteringPage = createAnimation()\r\n .addElement(opts.enteringEl)\r\n .beforeRemoveClass('ion-page-invisible')\r\n .beforeStyles({\r\n 'z-index': isBackDirection ? '9' : '10',\r\n 'opacity': '1'\r\n })\r\n .fromTo('transform', \r\n isBackDirection ? 'translateX(-20%)' : 'translateX(100%)', \r\n 'translateX(0)'\r\n );\r\n\r\n // Leaving page animation\r\n const leavingPage = createAnimation()\r\n .addElement(opts.leavingEl)\r\n .beforeStyles({\r\n 'z-index': isBackDirection ? '10' : '9'\r\n })\r\n .fromTo('transform', \r\n 'translateX(0)', \r\n isBackDirection ? 'translateX(100%)' : 'translateX(-20%)'\r\n );\r\n\r\n rootTransition.addAnimation([enteringPage, leavingPage]);\r\n \r\n return rootTransition;\r\n};\r\n\r\n/**\r\n * Custom back transition - iOS style where page slides out to reveal page underneath\r\n * The entering page (inquiries) slides in from the LEFT underneath\r\n * The leaving page (detail) slides out to the RIGHT on top\r\n */\r\nexport const customBackTransition = (_: HTMLElement, opts: any): Animation => {\r\n const DURATION = 400;\r\n \r\n const rootTransition = createAnimation()\r\n .duration(opts.duration || DURATION)\r\n .easing('cubic-bezier(0.32,0.72,0,1)');\r\n\r\n // Entering page: underneath, sliding in from LEFT (-20% to 0)\r\n const enteringPage = createAnimation()\r\n .addElement(opts.enteringEl)\r\n .beforeRemoveClass('ion-page-invisible')\r\n .beforeStyles({\r\n 'z-index': '9',\r\n 'opacity': '1'\r\n })\r\n .fromTo('transform', 'translateX(-20%)', 'translateX(0)');\r\n\r\n // Leaving page: on top, sliding out to the RIGHT (0 to 100%)\r\n const leavingPage = createAnimation()\r\n .addElement(opts.leavingEl)\r\n .beforeStyles({\r\n 'z-index': '10',\r\n })\r\n .fromTo('transform', 'translateX(0)', 'translateX(100%)');\r\n\r\n rootTransition.addAnimation([enteringPage, leavingPage]);\r\n \r\n return rootTransition;\r\n};\r\n\r\n","import { Component, signal, computed, effect } from '@angular/core';\r\nimport { NavController } from '@ionic/angular/standalone';\r\nimport { DsMobilePageMainComponent } from '../components/page-main';\r\nimport { DsMobileContentComponent } from '../components/content';\r\nimport { DsMobileInteractiveListItemInquiryComponent } from '../components/interactive-list-item-inquiry';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { UserService } from '../services/user.service';\r\nimport { customPageTransition } from '../animations/page-transitions';\r\nimport { DsMobileInlineTabsComponent, type InlineTabItem } from '../components/inline-tabs';\r\n\r\ninterface Inquiry {\r\n id: string;\r\n title: string;\r\n description: string;\r\n status: 'open' | 'closed';\r\n timestamp: string;\r\n category: 'maintenance' | 'plumbing' | 'electrical' | 'heating' | 'security' | 'appliance' | 'other';\r\n}\r\n\r\n@Component({\r\n selector: 'app-mobile-inquiries-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageMainComponent,\r\n DsMobileContentComponent,\r\n DsMobileInteractiveListItemInquiryComponent,\r\n DsIconComponent,\r\n DsMobileInlineTabsComponent\r\n ],\r\n host: {\r\n class: 'ion-page'\r\n },\r\n styles: [`\r\n .inquiries-container {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n \r\n .inquiry-list-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n margin-top: -8px;\r\n }\r\n \r\n /* Remove custom dividers - now handled by ds-mobile-list-item */\r\n \r\n .empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n text-align: center;\r\n }\r\n \r\n .empty-state-title {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n color: var(--color-text-primary);\r\n margin: 16px 0 8px 0;\r\n }\r\n \r\n .empty-state-description {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: var(--font-size-sm);\r\n color: var(--color-text-secondary);\r\n margin: 0;\r\n }\r\n \r\n\r\n `],\r\n template: `\r\n <ds-mobile-page-main\r\n title=\"Henvendelser\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\">\r\n \r\n <!-- Filter tabs in header -->\r\n <div header-content>\r\n <ds-mobile-inline-tabs\r\n [tabs]=\"tabItems\"\r\n [activeTab]=\"filterStatus()\"\r\n (tabChange)=\"setFilter($any($event))\">\r\n </ds-mobile-inline-tabs>\r\n </div>\r\n \r\n <ds-mobile-content>\r\n <div class=\"inquiries-container\">\r\n @if (filteredInquiries().length > 0) {\r\n <div class=\"inquiry-list-wrapper\">\r\n @for (inquiry of filteredInquiries(); track inquiry.id; let idx = $index) {\r\n <ds-mobile-interactive-list-item-inquiry\r\n [title]=\"inquiry.title\"\r\n [description]=\"inquiry.description\"\r\n [status]=\"inquiry.status\"\r\n [timestamp]=\"inquiry.timestamp\"\r\n [iconName]=\"getInquiryIcon(inquiry.category)\"\r\n [clickable]=\"true\"\r\n [showChevron]=\"false\"\r\n (inquiryClick)=\"openInquiryDetail(inquiry.id)\"\r\n (longPress)=\"showInquiryActions(inquiry.id)\">\r\n </ds-mobile-interactive-list-item-inquiry>\r\n\r\n }\r\n </div>\r\n } @else {\r\n <!-- Empty state -->\r\n <div class=\"empty-state\">\r\n <ds-icon name=\"remixInboxLine\" size=\"48px\" color=\"tertiary\" />\r\n <h3 class=\"empty-state-title\">Ingen henvendelser endnu</h3>\r\n <p class=\"empty-state-description\">\r\n @if (filterStatus() === 'open') {\r\n Du har ingen åbne henvendelser\r\n } @else if (filterStatus() === 'closed') {\r\n Du har ingen lukkede henvendelser\r\n } @else {\r\n Du har ikke oprettet nogen henvendelser endnu\r\n }\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </ds-mobile-content>\r\n </ds-mobile-page-main>\r\n `\r\n})\r\nexport class MobileInquiriesPageComponent {\r\n constructor(\r\n public userService: UserService,\r\n private navCtrl: NavController\r\n ) {}\r\n \r\n filterStatus = signal<'all' | 'open' | 'closed'>('all');\r\n \r\n tabItems: InlineTabItem[] = [\r\n { id: 'all', label: 'Alle' },\r\n { id: 'open', label: 'Åben' },\r\n { id: 'closed', label: 'Lukket' }\r\n ];\r\n \r\n inquiries = signal<Inquiry[]>([\r\n {\r\n id: '1',\r\n title: 'Tørretumbler virker ikke',\r\n description: 'I de sidste tre dage har jeg oplevet vedvarende problemer med tørretumbleren. Den starter, men stopper efter få minutter.',\r\n status: 'open',\r\n timestamp: '12 dage siden',\r\n category: 'appliance'\r\n },\r\n {\r\n id: '2',\r\n title: 'Problem med vandtryk',\r\n description: 'Lavt vandtryk i badeværelseshåndvasken. Det er blevet gradvist værre i løbet af den sidste uge.',\r\n status: 'open',\r\n timestamp: '5 dage siden',\r\n category: 'plumbing'\r\n },\r\n {\r\n id: '3',\r\n title: 'Varme virker ikke ordentligt',\r\n description: 'Varmesystemet holder ikke den indstillede temperatur. Lejligheden er meget koldere, end den burde være.',\r\n status: 'closed',\r\n timestamp: '2 måneder siden',\r\n category: 'heating'\r\n }\r\n ]);\r\n \r\n // Computed signals that automatically update when dependencies change\r\n filteredInquiries = computed(() => {\r\n const all = this.inquiries();\r\n const status = this.filterStatus();\r\n \r\n if (status === 'all') {\r\n return all;\r\n } else if (status === 'open') {\r\n return all.filter(i => i.status === 'open');\r\n } else {\r\n return all.filter(i => i.status === 'closed');\r\n }\r\n });\r\n \r\n openInquiries = computed(() => {\r\n return this.inquiries().filter(i => i.status === 'open');\r\n });\r\n \r\n closedInquiries = computed(() => {\r\n return this.inquiries().filter(i => i.status === 'closed');\r\n });\r\n \r\n setFilter(status: 'all' | 'open' | 'closed'): void {\r\n this.filterStatus.set(status);\r\n }\r\n \r\n getInquiryIcon(category: string): string {\r\n return 'remixTodoLine';\r\n }\r\n \r\n openInquiryDetail(inquiryId: string): void {\r\n console.log('Opening inquiry:', inquiryId);\r\n // Navigate to inquiry detail page with custom transition (absolute path outside tabs for animations)\r\n this.navCtrl.navigateForward([`/inquiry-detail/${inquiryId}`], {\r\n animation: customPageTransition\r\n });\r\n }\r\n \r\n showInquiryActions(inquiryId: string): void {\r\n console.log('Showing actions for inquiry:', inquiryId);\r\n // Show bottom sheet with actions (edit, delete, etc.)\r\n }\r\n}\r\n\r\n","import { Component, signal, computed, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { NavController, Platform } from '@ionic/angular/standalone';\r\nimport { \r\n IonHeader, \r\n IonToolbar, \r\n IonTitle,\r\n IonContent, \r\n IonRefresher, \r\n IonRefresherContent \r\n} from '@ionic/angular/standalone';\r\nimport { DsIconComponent, DsBadgeComponent } from '@propbinder/design-system';\r\nimport { DsMobileInlineTabsComponent, type InlineTabItem } from '../components/inline-tabs';\r\nimport { DsMobileInteractiveListItemMessageComponent } from '../components/interactive-list-item-message';\r\nimport { DsMobileListItemComponent } from '../components/list-item/ds-mobile-list-item';\r\nimport { DsMobileLightboxService, type LightboxImage } from '../components/lightbox';\r\nimport { DsMobileChatModalService, type ChatModalData, type ChatMessage } from '../components/chat-modal';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge';\r\nimport { UserService } from '../services/user.service';\r\nimport { MobilePageBase } from '../components/shared/mobile-page-base';\r\nimport { customBackTransition } from '../animations/page-transitions';\r\n\r\ninterface ActivityItem {\r\n id: string;\r\n type: 'assignment' | 'status_change' | 'creation';\r\n actor?: string;\r\n actorInitials?: string;\r\n title: string;\r\n description?: string;\r\n timestamp: string;\r\n date: string;\r\n iconName: string;\r\n iconBgColor?: string;\r\n}\r\n\r\ninterface MessageThread {\r\n id: string;\r\n senderName: string;\r\n senderAvatar: string;\r\n senderInitials: string;\r\n message: string;\r\n role: string;\r\n timestamp: string;\r\n unread: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'app-mobile-inquiry-detail-page',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonContent,\r\n IonRefresher,\r\n IonRefresherContent,\r\n DsIconComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsMobileInlineTabsComponent,\r\n DsMobileInteractiveListItemMessageComponent,\r\n DsMobileListItemComponent,\r\n DsBadgeComponent\r\n ],\r\n host: {\r\n class: 'ion-page'\r\n },\r\n styleUrls: [\r\n '../components/shared/mobile-page-base.css',\r\n './inquiry-detail.example.css'\r\n ],\r\n template: `\r\n <!-- Fixed header at top -->\r\n <ion-header>\r\n <ion-toolbar>\r\n <div class=\"header-details\">\r\n <!-- Back Button -->\r\n <button class=\"back-button\" (click)=\"goBack()\" [attr.aria-label]=\"'Go back'\">\r\n <ds-icon name=\"remixArrowLeftSLine\" size=\"24px\" color=\"white\" />\r\n </button>\r\n \r\n <!-- Title - fades in on scroll -->\r\n <ion-title class=\"header-title\">{{ inquiryTitle }}</ion-title>\r\n </div>\r\n </ion-toolbar>\r\n </ion-header>\r\n\r\n <!-- Content with expandable header -->\r\n <ion-content [scrollEvents]=\"true\" (ionScroll)=\"handleScroll($event)\">\r\n <!-- Pull to refresh (only on native iOS/Android) -->\r\n @if (isNativePlatform()) {\r\n <ion-refresher \r\n slot=\"fixed\" \r\n (ionRefresh)=\"handleRefresh($event)\"\r\n [pullFactor]=\"0.4\" \r\n [pullMin]=\"80\" \r\n [pullMax]=\"240\"\r\n closeDuration=\"600ms\">\r\n <ion-refresher-content\r\n pullingIcon=\"remixArrowDownS\"\r\n refreshingSpinner=\"lines\">\r\n </ion-refresher-content>\r\n </ion-refresher>\r\n }\r\n\r\n <!-- Expandable header section (purple background) -->\r\n <div class=\"header-expandable\">\r\n <div class=\"header-expandable-inner\">\r\n <div class=\"header-expandable__text\">\r\n <h1 class=\"header-expandable__title\">{{ inquiryTitle }}</h1>\r\n </div>\r\n \r\n <!-- Tabs in header -->\r\n <ds-mobile-inline-tabs\r\n [tabs]=\"tabItems\"\r\n [activeTab]=\"activeTab()\"\r\n (tabChange)=\"setActiveTab($event)\">\r\n </ds-mobile-inline-tabs>\r\n </div>\r\n </div>\r\n\r\n <!-- Content wrapper -->\r\n <div class=\"content-wrapper\">\r\n <div class=\"content-inner\">\r\n <!-- Activity Tab Content -->\r\n @if (activeTab() === 'activity') {\r\n <div class=\"activity-list\">\r\n @for (activity of activities; track activity.id) {\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"false\">\r\n @if (activity.actor) {\r\n <!-- Avatar with badge for actor activities -->\r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [type]=\"'initials'\"\r\n [initials]=\"activity.actorInitials || ''\"\r\n size=\"md\" />\r\n </div>\r\n } @else {\r\n <!-- Icon wrapper for non-actor activities -->\r\n <div content-leading class=\"activity-icon-wrapper\">\r\n <ds-icon \r\n [name]=\"activity.iconName\"\r\n size=\"18px\"\r\n color=\"secondary\" />\r\n </div>\r\n }\r\n \r\n <div content-main class=\"activity-content\">\r\n <p class=\"activity-title\">\r\n @if (activity.actor) {\r\n <span class=\"actor-name\">{{ activity.actor }}</span>\r\n <span class=\"activity-text\"> {{ activity.title }}</span>\r\n } @else {\r\n <span class=\"actor-name\">{{ activity.title }}</span>\r\n }\r\n </p>\r\n @if (activity.description) {\r\n <p class=\"activity-description\">{{ activity.description }}</p>\r\n }\r\n <div class=\"activity-timestamp\">\r\n <ds-icon name=\"remixCalendarLine\" size=\"12px\" color=\"--color-text-tertiary\" />\r\n <span>{{ activity.date }}</span>\r\n </div>\r\n </div>\r\n </ds-mobile-list-item>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Messages Tab Content -->\r\n @if (activeTab() === 'messages') {\r\n <div class=\"messages-list\">\r\n @for (message of messageThreads; track message.id) {\r\n <ds-mobile-interactive-list-item-message\r\n [senderName]=\"message.senderName\"\r\n [senderRole]=\"message.role\"\r\n [timestamp]=\"message.timestamp\"\r\n [message]=\"message.message\"\r\n [avatarInitials]=\"message.senderInitials\"\r\n [unread]=\"message.unread\"\r\n (messageClick)=\"openMessage(message.id)\">\r\n </ds-mobile-interactive-list-item-message>\r\n }\r\n </div>\r\n }\r\n \r\n <!-- Details Tab Content -->\r\n @if (activeTab() === 'details') {\r\n <div class=\"details-list\">\r\n <!-- Assignee -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [size]=\"'sm'\"\r\n [type]=\"'initials'\"\r\n [initials]=\"'R'\" />\r\n </div>\r\n <div content-main>\r\n <div class=\"detail-label\">Sagsbehandler</div>\r\n <div class=\"detail-value\">Ricki Meihlen</div>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Technician -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <div content-leading>\r\n <ds-avatar-with-badge\r\n [size]=\"'sm'\"\r\n [type]=\"'initials'\"\r\n [initials]=\"'M'\" />\r\n </div>\r\n <div content-main>\r\n <div class=\"detail-label\">Tekniker</div>\r\n <div class=\"detail-value\">Martin Smith</div>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Title -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\" [align]=\"'center'\">\r\n <ds-icon content-leading name=\"remixTextBlock\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"detail-value\">{{ inquiryTitle }}</div>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Description -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <ds-icon content-leading name=\"remixAlignLeft\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"detail-value description-text\">\r\n I de sidste tre dage har vi oplevet vedvarende problemer med tørretumbleren i vores lejlighed. På trods af at vi følger betjeningsvejledningen, fejler maskinen konsekvent i at fuldføre sine tørrecyklusser.\r\n </div>\r\n <ds-badge content=\"Husholdningsapparater\" size=\"sm\"/>\r\n </div>\r\n </ds-mobile-list-item>\r\n \r\n <!-- Photos -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\">\r\n <ds-icon content-leading name=\"remixCameraLine\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"photo-grid\">\r\n <button class=\"photo-add\">\r\n <ds-icon name=\"remixAddLine\" size=\"20px\" color=\"tertiary\" />\r\n </button>\r\n <!-- Photos -->\r\n @for (photo of photos; track photo.src; let i = $index) {\r\n <img \r\n class=\"photo-item\" \r\n [src]=\"photo.src\" \r\n [alt]=\"photo.alt\"\r\n (click)=\"openPhotoLightbox(i)\"\r\n style=\"cursor: pointer;\" />\r\n }\r\n </div>\r\n </div>\r\n </ds-mobile-list-item>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class MobileInquiryDetailPageComponent extends MobilePageBase implements AfterViewInit {\r\n @ViewChild(IonContent) ionContent?: IonContent;\r\n \r\n // Platform detection\r\n private platform = inject(Platform);\r\n \r\n // Computed property to check if running on native platform\r\n isNativePlatform = computed(() => \r\n this.platform.is('ios') || \r\n this.platform.is('android') || \r\n this.platform.is('capacitor')\r\n );\r\n \r\n inquiryTitle = 'Tørretumbler virker ikke';\r\n activeTab = signal<string>('activity');\r\n \r\n tabItems: InlineTabItem[] = [\r\n { id: 'activity', label: 'Aktivitet' },\r\n { id: 'messages', label: 'Beskeder', badge: 0 },\r\n { id: 'details', label: 'Detaljer' }\r\n ];\r\n \r\n activities: ActivityItem[] = [\r\n {\r\n id: '1',\r\n type: 'assignment',\r\n actor: 'Martin Smith',\r\n actorInitials: 'MS',\r\n title: 'er blevet tildelt som din dedikerede tekniker.',\r\n timestamp: '2 dage siden',\r\n date: '28. feb 2025',\r\n iconName: 'remixUserAddLine'\r\n },\r\n {\r\n id: '2',\r\n type: 'assignment',\r\n actor: 'Ricki Meihlen',\r\n actorInitials: 'RM',\r\n title: 'er blevet tildelt til at håndtere din henvendelse.',\r\n timestamp: '8 dage siden',\r\n date: '22. feb 2025',\r\n iconName: 'remixUserLine'\r\n },\r\n {\r\n id: '3',\r\n type: 'creation',\r\n title: 'Henvendelse oprettet',\r\n timestamp: '8 dage siden',\r\n date: '22. feb 2025',\r\n iconName: 'remixAddCircleLine'\r\n }\r\n ];\r\n \r\n messageThreads: MessageThread[] = [\r\n {\r\n id: '1',\r\n senderName: 'Ove Hindborg',\r\n senderAvatar: '',\r\n senderInitials: 'OH',\r\n message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',\r\n role: 'Sagsbehandler',\r\n timestamp: '2t siden',\r\n unread: true\r\n },\r\n {\r\n id: '2',\r\n senderName: 'Martin Smith',\r\n senderAvatar: '',\r\n senderInitials: 'MS',\r\n message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',\r\n role: 'Tekniker',\r\n timestamp: '4t siden',\r\n unread: true\r\n }\r\n ];\r\n \r\n unreadMessagesCount = computed(() => {\r\n const count = this.messageThreads.filter(m => m.unread).length;\r\n // Update badge in tab items\r\n const messagesTab = this.tabItems.find(t => t.id === 'messages');\r\n if (messagesTab) {\r\n messagesTab.badge = count;\r\n }\r\n return count;\r\n });\r\n \r\n // Photos for lightbox\r\n photos: LightboxImage[] = [\r\n { type: 'image', src: '/Assets/Dummy-photos/handyman.jpg', alt: 'Handyman', title: 'Handyman' },\r\n { type: 'image', src: '/Assets/Dummy-photos/balcony-view.jpg', alt: 'Balcony view', title: 'Balcony view' },\r\n { type: 'image', src: '/Assets/Dummy-photos/staircase.jpg', alt: 'Staircase', title: 'Staircase' },\r\n { type: 'image', src: '/Assets/Dummy-photos/yard.jpg', alt: 'Yard', title: 'Yard' },\r\n { type: 'image', src: '/Assets/Dummy-photos/mailboxes.jpg', alt: 'Mailboxes', title: 'Mailboxes' }\r\n ];\r\n \r\n constructor(\r\n public userService: UserService,\r\n private navCtrl: NavController,\r\n private elementRef: ElementRef,\r\n private lightbox: DsMobileLightboxService,\r\n private chatModal: DsMobileChatModalService\r\n ) {\r\n super();\r\n // Trigger initial badge update\r\n this.unreadMessagesCount();\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Initial setup if needed\r\n }\r\n \r\n setActiveTab(tabId: string): void {\r\n this.activeTab.set(tabId);\r\n }\r\n \r\n goBack(): void {\r\n this.navCtrl.back({ animation: customBackTransition });\r\n }\r\n \r\n handleScroll(event: any): void {\r\n const scrollTop = event.detail.scrollTop;\r\n const threshold = 160;\r\n const fadeDistance = 200;\r\n const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');\r\n const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');\r\n \r\n // Show title in fixed header when scrolled past threshold\r\n if (scrollTop > threshold) {\r\n header?.classList.add('header-scrolled');\r\n } else {\r\n header?.classList.remove('header-scrolled');\r\n }\r\n \r\n // Fade out header-expandable content based on scroll\r\n if (headerExpandable) {\r\n const fadeProgress = Math.min(scrollTop / fadeDistance, 1);\r\n \r\n // Calculate opacity (1 to 0)\r\n const opacity = 1 - fadeProgress;\r\n \r\n // Calculate transform (0px to -20px upward)\r\n const translateY = fadeProgress * -20;\r\n \r\n // Apply styles\r\n headerExpandable.style.opacity = opacity.toString();\r\n headerExpandable.style.transform = `translateY(${translateY}px)`;\r\n }\r\n }\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n setTimeout(() => {\r\n console.log('Refresh complete');\r\n event.target.complete();\r\n }, 1000);\r\n }\r\n \r\n async openMessage(messageId: string): Promise<void> {\r\n console.log('Opening message:', messageId);\r\n \r\n // Find the message thread\r\n const messageThread = this.messageThreads.find(m => m.id === messageId);\r\n if (!messageThread) {\r\n console.error('Message thread not found:', messageId);\r\n return;\r\n }\r\n \r\n // Prepare chat modal data\r\n // In a real app, you would fetch the actual messages from your API\r\n const chatData: ChatModalData = {\r\n participant: {\r\n id: messageId,\r\n name: messageThread.senderName,\r\n role: messageThread.role,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials'\r\n },\r\n messages: [\r\n // Example messages - in real app, fetch from API\r\n {\r\n id: '1',\r\n content: messageThread.message,\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: messageThread.timestamp,\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n // Add more messages as needed\r\n {\r\n id: '2',\r\n content: 'Thank you for the update!',\r\n senderId: 'current-user',\r\n senderName: 'You',\r\n timestamp: '1t siden',\r\n isOwnMessage: true,\r\n avatarInitials: this.userService.avatarInitials(),\r\n avatarType: 'initials',\r\n }\r\n ],\r\n currentUserId: 'current-user',\r\n currentUserInitials: this.userService.avatarInitials(),\r\n currentUserAvatarType: 'initials',\r\n autoFocus: false\r\n };\r\n \r\n // Open the chat modal\r\n await this.chatModal.open(chatData);\r\n }\r\n \r\n async openPhotoLightbox(index: number): Promise<void> {\r\n await this.lightbox.openImages({\r\n images: this.photos,\r\n initialIndex: index,\r\n showControls: true,\r\n enableSwipe: true,\r\n enableZoom: true,\r\n showInfo: false\r\n });\r\n }\r\n}\r\n\r\n","import { Component, OnInit, inject } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { IonTabs } from '@ionic/angular/standalone';\r\nimport { UserService } from '../services/user.service';\r\nimport { DsMobileTabBarComponent, TabConfig } from '../components/tab-bar';\r\nimport { ActionResult, ActionGroup } from '../components/bottom-sheet';\r\nimport { WhitelabelDemoModalService } from './whitelabel-demo-modal.service';\r\n\r\n/**\r\n * MobileTabsExampleComponent\r\n * \r\n * Example page using the TenantApp pattern:\r\n * - Uses ion-tabs as wrapper (required for Angular routing)\r\n * - Uses ds-mobile-tab-bar inside (not ds-mobile-tabs)\r\n * \r\n * This matches the pattern used in TenantApp for consistency.\r\n */\r\n@Component({\r\n selector: 'app-mobile-tabs-example',\r\n standalone: true,\r\n imports: [CommonModule, IonTabs, DsMobileTabBarComponent],\r\n styles: [`\r\n :host {\r\n display: block;\r\n height: 100vh;\r\n width: 100vw;\r\n position: relative;\r\n }\r\n `],\r\n template: `\r\n <ion-tabs class=\"ds-tabs-wrapper\">\r\n <!-- Tab bar with slot=\"top\" on desktop, slot=\"bottom\" on mobile -->\r\n <!-- Ionic automatically creates ion-tab elements from child routes -->\r\n <ds-mobile-tab-bar\r\n [tabs]=\"tabs\"\r\n [avatarInitials]=\"userService.avatarInitials()\"\r\n [avatarType]=\"userService.avatarType()\"\r\n [profileMenuItems]=\"profileMenuItems\"\r\n (profileActionSelected)=\"handleProfileAction($event)\">\r\n </ds-mobile-tab-bar>\r\n </ion-tabs>\r\n `\r\n})\r\nexport class MobileTabsExampleComponent implements OnInit {\r\n private whitelabelDemoModal = inject(WhitelabelDemoModalService);\r\n \r\n constructor(\r\n public userService: UserService,\r\n private router: Router\r\n ) {\r\n console.log('MobileTabsExampleComponent constructor');\r\n }\r\n \r\n ngOnInit() {\r\n console.log('MobileTabsExampleComponent ngOnInit');\r\n // Configure user avatar globally - this is now the single source of truth\r\n this.userService.setAvatarInitials('LM');\r\n this.userService.setAvatarType('initials');\r\n \r\n // Set profile menu items globally - this will be used by both tab bar and page-main components\r\n this.userService.setProfileMenuItems(this.profileMenuItems);\r\n }\r\n \r\n tabs: TabConfig[] = [\r\n {\r\n id: 'home',\r\n label: 'Hjem',\r\n route: 'home',\r\n icon: 'remixHomeSmile2Line',\r\n iconActive: 'remixHomeSmile2Fill'\r\n },\r\n {\r\n id: 'inquiries',\r\n label: 'Henvendelser',\r\n route: 'inquiries',\r\n icon: 'remixFileList3Line',\r\n iconActive: 'remixFileList3Fill'\r\n },\r\n {\r\n id: 'announcements',\r\n label: 'Fællesskab',\r\n route: 'announcements',\r\n icon: 'remixCommunityLine',\r\n iconActive: 'remixCommunityFill'\r\n },\r\n {\r\n id: 'handbook',\r\n label: 'Håndbog',\r\n route: 'handbook',\r\n icon: 'remixBook2Line',\r\n iconActive: 'remixBook2Fill'\r\n }\r\n ];\r\n \r\n /**\r\n * Profile menu items configuration.\r\n * Define once here - this is set globally in UserService in ngOnInit(),\r\n * so it will be used by both ds-mobile-tab-bar and ds-mobile-page-main components\r\n * throughout the entire application.\r\n */\r\n profileMenuItems: ActionGroup[] = [\r\n {\r\n actions: [\r\n {\r\n action: 'profile',\r\n title: 'Min profil',\r\n icon: 'remixUser3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'settings',\r\n title: 'Indstillinger',\r\n icon: 'remixSettings3Line',\r\n destructive: false\r\n },\r\n {\r\n action: 'whitelabel-demo',\r\n title: 'Whitelabel Demo',\r\n icon: 'remixPaletteLine',\r\n destructive: false\r\n }\r\n ]\r\n },\r\n {\r\n actions: [\r\n {\r\n action: 'logout',\r\n title: 'Log ud',\r\n icon: 'remixLogoutBoxLine',\r\n destructive: true\r\n }\r\n ]\r\n }\r\n ];\r\n \r\n /**\r\n * Handle profile menu action selection.\r\n * The tab bar component handles the UI (opening/closing menu),\r\n * this method handles the business logic.\r\n */\r\n handleProfileAction(result: ActionResult): void {\r\n console.log('Profile action selected:', result.action);\r\n \r\n switch (result.action) {\r\n case 'logout':\r\n console.log('Logging out...');\r\n // TODO: Implement logout logic\r\n break;\r\n case 'profile':\r\n console.log('Opening profile...');\r\n // TODO: Navigate to profile page\r\n break;\r\n case 'settings':\r\n console.log('Opening settings...');\r\n // TODO: Navigate to settings page\r\n break;\r\n case 'whitelabel-demo':\r\n console.log('Opening whitelabel demo...');\r\n // Small delay to ensure bottom sheet is fully dismissed\r\n setTimeout(async () => {\r\n try {\r\n await this.whitelabelDemoModal.open();\r\n } catch (error) {\r\n console.error('Failed to open whitelabel demo modal:', error);\r\n }\r\n }, 100);\r\n break;\r\n }\r\n }\r\n}\r\n","import { Component, signal, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n DsAvatarComponent,\r\n DsIconComponent,\r\n DsButtonComponent\r\n} from '@propbinder/design-system';\r\nimport { DsMobilePageDetailsComponent } from '../components/page-details';\r\nimport { UserService } from '../services/user.service';\r\n\r\n/**\r\n * PostCreatePageComponent\r\n * \r\n * Full-screen detail page for creating new posts in the community feed.\r\n * Features Threads-inspired interface with rich text editing capabilities.\r\n */\r\n@Component({\r\n selector: 'app-post-create-page',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n DsAvatarComponent,\r\n DsIconComponent,\r\n DsButtonComponent,\r\n DsMobilePageDetailsComponent\r\n ],\r\n styles: [`\r\n .post-create-container {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n max-width: 640px;\r\n }\r\n \r\n /* ============================================\r\n CONTENT AREA\r\n ============================================ */\r\n \r\n .content {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n }\r\n \r\n .post-composer {\r\n display: flex;\r\n gap: 12px;\r\n margin-bottom: 24px;\r\n align-items: flex-start;\r\n }\r\n \r\n .post-composer__avatar {\r\n flex-shrink: 0;\r\n padding-top: 2px;\r\n }\r\n \r\n .post-composer__main {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .post-composer__header {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n height: 32px;\r\n }\r\n \r\n .post-composer__username {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 15px;\r\n font-weight: 600;\r\n line-height: 20px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n .post-composer__textarea {\r\n width: 100%;\r\n min-height: 120px;\r\n border: none;\r\n outline: none;\r\n resize: none;\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 15px;\r\n font-weight: 400;\r\n line-height: 22px;\r\n letter-spacing: -0.3px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n background: transparent;\r\n padding: 0;\r\n }\r\n \r\n .post-composer__textarea::placeholder {\r\n color: var(--color-text-tertiary, #999999);\r\n }\r\n \r\n .post-composer__actions {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 16px;\r\n }\r\n \r\n .post-composer__action-btns {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n }\r\n \r\n .post-composer__action-btn {\r\n background: none;\r\n border: none;\r\n padding: 0;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--color-text-secondary, #737373);\r\n transition: color 0.2s ease;\r\n }\r\n \r\n .post-composer__action-btn:hover {\r\n color: var(--color-text-primary, #1a1a1a);\r\n }\r\n \r\n /* Thread connector line */\r\n .thread-line {\r\n position: absolute;\r\n left: 35px;\r\n top: 60px;\r\n bottom: 0;\r\n width: 2px;\r\n background: var(--border-color-default);\r\n }\r\n \r\n /* ============================================\r\n MOBILE OPTIMIZATIONS\r\n ============================================ */\r\n \r\n @media (max-width: 768px) {\r\n .content {\r\n padding: 12px 16px;\r\n }\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-details\r\n [title]=\"pageTitle()\"\r\n [backRoute]=\"'/mobile-tabs-example/announcements'\"\r\n (back)=\"handleCancel()\">\r\n \r\n <div class=\"post-create-container\">\r\n <div class=\"post-composer\">\r\n <div class=\"post-composer__avatar\">\r\n <ds-avatar \r\n [initials]=\"userService.avatarInitials()\"\r\n [type]=\"userService.avatarType()\"\r\n [src]=\"userService.avatarSrc()\"\r\n size=\"md\" />\r\n </div>\r\n \r\n <div class=\"post-composer__main\">\r\n <div class=\"post-composer__header\">\r\n <span class=\"post-composer__username\">{{ username() }}</span>\r\n </div>\r\n \r\n <textarea\r\n #textareaInput\r\n class=\"post-composer__textarea\"\r\n [(ngModel)]=\"postContent\"\r\n [placeholder]=\"placeholder()\"\r\n (input)=\"handleInput()\">\r\n </textarea>\r\n \r\n <div class=\"post-composer__actions\">\r\n <div class=\"post-composer__action-btns\">\r\n <button class=\"post-composer__action-btn\" (click)=\"handleAddImage()\">\r\n <ds-icon name=\"remixImageLine\" size=\"22px\" />\r\n </button>\r\n <button class=\"post-composer__action-btn\" (click)=\"handleAddEmoji()\">\r\n <ds-icon name=\"remixEmotionLine\" size=\"22px\" />\r\n </button>\r\n </div>\r\n \r\n <ds-button\r\n variant=\"primary\"\r\n size=\"md\"\r\n [disabled]=\"!canPost()\"\r\n (clicked)=\"handlePost()\">\r\n {{ submitButtonLabel() }}\r\n </ds-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ds-mobile-page-details>\r\n `\r\n})\r\nexport class PostCreatePageComponent implements AfterViewInit, OnInit {\r\n @ViewChild('textareaInput') textareaInput?: ElementRef<HTMLTextAreaElement>;\r\n \r\n postContent = '';\r\n username = signal('Lars Mikkelsen');\r\n placeholder = signal(\"What's new?\");\r\n \r\n // Edit mode state\r\n isEditMode = signal(false);\r\n postId = signal<string | null>(null);\r\n pageTitle = signal('New post');\r\n submitButtonLabel = signal('Post');\r\n \r\n constructor(\r\n private router: Router,\r\n private route: ActivatedRoute,\r\n public userService: UserService\r\n ) {}\r\n \r\n ngOnInit(): void {\r\n // Check for edit mode via query parameters\r\n this.route.queryParams.subscribe(params => {\r\n const editMode = params['edit'] === 'true';\r\n const postId = params['id'];\r\n const content = params['content'];\r\n \r\n if (editMode && postId) {\r\n this.isEditMode.set(true);\r\n this.postId.set(postId);\r\n this.pageTitle.set('Edit post');\r\n this.submitButtonLabel.set('Save');\r\n \r\n // Prefill content if provided\r\n if (content) {\r\n this.postContent = decodeURIComponent(content);\r\n }\r\n } else {\r\n // Reset to create mode\r\n this.isEditMode.set(false);\r\n this.postId.set(null);\r\n this.pageTitle.set('New post');\r\n this.submitButtonLabel.set('Post');\r\n this.postContent = '';\r\n }\r\n });\r\n }\r\n \r\n ngAfterViewInit(): void {\r\n // Focus the textarea after view initialization to trigger keyboard on mobile\r\n setTimeout(() => {\r\n this.textareaInput?.nativeElement.focus();\r\n }, 300);\r\n }\r\n \r\n handleInput(): void {\r\n // Handle text input changes\r\n }\r\n \r\n canPost(): boolean {\r\n return this.postContent.trim().length > 0;\r\n }\r\n \r\n handleCancel(): void {\r\n if (this.postContent.trim().length > 0) {\r\n // Show confirmation dialog\r\n const confirmed = confirm('Discard this post?');\r\n if (confirmed) {\r\n this.router.navigate(['/mobile-tabs-example/community']);\r\n }\r\n } else {\r\n this.router.navigate(['/mobile-tabs-example/community']);\r\n }\r\n }\r\n \r\n handlePost(): void {\r\n if (!this.canPost()) return;\r\n \r\n if (this.isEditMode()) {\r\n console.log('Updating post:', this.postId(), this.postContent);\r\n // TODO: Implement post update logic\r\n // this.postService.updatePost(this.postId(), this.postContent).subscribe(() => {\r\n // this.router.navigate(['/mobile-tabs-example/community']);\r\n // });\r\n } else {\r\n console.log('Creating post:', this.postContent);\r\n // TODO: Implement post creation logic\r\n // this.postService.createPost(this.postContent).subscribe(() => {\r\n // this.router.navigate(['/mobile-tabs-example/community']);\r\n // });\r\n }\r\n \r\n // For now, just navigate back\r\n this.router.navigate(['/mobile-tabs-example/community']);\r\n }\r\n \r\n handleAddImage(): void {\r\n console.log('Add image');\r\n // TODO: Open image picker\r\n }\r\n \r\n handleAddEmoji(): void {\r\n console.log('Add emoji');\r\n // TODO: Open emoji picker\r\n }\r\n}\r\n\r\n","import { Component } from '@angular/core';\r\nimport { DsMobilePageDetailsComponent } from '../components/page-details';\r\nimport { \r\n DsMobileInteractiveListItemPostComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent\r\n} from '../components/interactive-list-item-post';\r\nimport { DsMobileCommentComponent } from '../components/comment';\r\nimport { DsMobileLightboxService, LightboxAuthor } from '../components/lightbox';\r\nimport { DsMobileBottomSheetService } from '../components/bottom-sheet/ds-mobile-bottom-sheet.service';\r\nimport { DsMobileCommentActionsBottomSheetComponent, CommentActionResult } from '../components/bottom-sheet';\r\n\r\n@Component({\r\n selector: 'app-mobile-post-detail-page',\r\n standalone: true,\r\n imports: [\r\n DsMobilePageDetailsComponent,\r\n DsMobileInteractiveListItemPostComponent,\r\n PostContentComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n PostActionsComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCommentComponent\r\n ],\r\n styles: [`\r\n .post-detail-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n max-width: 640px;\r\n }\r\n \r\n .post-section {\r\n border-bottom: 1px solid var(--border-color-default);\r\n padding-bottom: 16px;\r\n }\r\n \r\n .clickable-image {\r\n cursor: pointer;\r\n transition: transform 0.2s ease, opacity 0.2s ease;\r\n border-radius: 8px;\r\n display: block;\r\n width: 100%;\r\n aspect-ratio: 16/9;\r\n object-fit: cover;\r\n }\r\n \r\n .clickable-image:active {\r\n transform: scale(0.98);\r\n opacity: 0.9;\r\n }\r\n \r\n .comments-section {\r\n display: flex;\r\n flex-direction: column;\r\n /* Negative margin to pull comments out by 8px on each side */\r\n /* Page has 20px padding, this makes comments effectively 12px from edge */\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n }\r\n \r\n .comments-header {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 18px;\r\n font-weight: 600;\r\n line-height: 24px;\r\n color: var(--color-text-primary, #1a1a1a);\r\n margin-bottom: 16px;\r\n /* Add padding to keep header at 20px from edge (8px to offset negative margin) */\r\n padding-left: 8px;\r\n padding-right: 8px;\r\n }\r\n \r\n .comments-list {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-page-details title=\"Opslag\">\r\n <div class=\"post-detail-container\">\r\n <!-- Post Section -->\r\n <div class=\"post-section\">\r\n <ds-mobile-interactive-list-item-post\r\n [authorName]=\"'Sophie Andersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'4t siden'\"\r\n [avatarInitials]=\"'SA'\"\r\n [clickable]=\"false\">\r\n \r\n <post-content>\r\n <post-text>Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️</post-text>\r\n <post-media>\r\n <img \r\n src=\"/Assets/Dummy-photos/balcony-view.jpg\" \r\n alt=\"Altanudsigt\" \r\n class=\"clickable-image\"\r\n (click)=\"openImageLightbox('/Assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')\"\r\n />\r\n </post-media>\r\n </post-content>\r\n \r\n <post-actions>\r\n <action-like [active]=\"true\" [count]=\"156\" />\r\n <action-comment [count]=\"34\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n </div>\r\n \r\n <!-- Comments Section -->\r\n <div class=\"comments-section\">\r\n <h2 class=\"comments-header\">{{ repliesCount }} svar</h2>\r\n \r\n <div class=\"comments-list\">\r\n <ds-mobile-comment\r\n [authorName]=\"'Anders Jensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'3t siden'\"\r\n [avatarInitials]=\"'AJ'\"\r\n [content]=\"'Wow, den udsigt er fantastisk! Hvilken etage er du på?'\"\r\n [likeCount]=\"12\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Anders Jensen', 'Wow, den udsigt er fantastisk! Hvilken etage er du på?', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Thomas Hansen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'3t siden'\"\r\n [avatarInitials]=\"'TH'\"\r\n [content]=\"'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆'\"\r\n [isLiked]=\"true\"\r\n [likeCount]=\"8\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"true\"\r\n (longPress)=\"handleCommentLongPress('Thomas Hansen', 'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆', true)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Emma Petersen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'2t siden'\"\r\n [avatarInitials]=\"'EP'\"\r\n [content]=\"'Dette er præcis derfor jeg elsker at bo her. Godt billede!'\"\r\n [likeCount]=\"15\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Emma Petersen', 'Dette er præcis derfor jeg elsker at bo her. Godt billede!', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Nikolaj Sørensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'2t siden'\"\r\n [avatarInitials]=\"'NS'\"\r\n [content]=\"'Solnedgangene fra den vinkel må være utrolige'\"\r\n [likeCount]=\"6\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Nikolaj Sørensen', 'Solnedgangene fra den vinkel må være utrolige', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Mette Larsen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'1t siden'\"\r\n [avatarInitials]=\"'ML'\"\r\n [content]=\"'Giver mig lyst til at få min morgenkaffe på altanen også! ☕'\"\r\n [likeCount]=\"9\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Mette Larsen', 'Giver mig lyst til at få min morgenkaffe på altanen også! ☕', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Frederik Nielsen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'1t siden'\"\r\n [avatarInitials]=\"'FN'\"\r\n [content]=\"'Heldig! Min altan vender den anden vej, men stadig pæn'\"\r\n [likeCount]=\"4\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Frederik Nielsen', 'Heldig! Min altan vender den anden vej, men stadig pæn', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Caroline Jensen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'45m siden'\"\r\n [avatarInitials]=\"'CJ'\"\r\n [content]=\"'Denne bygning har den bedste udsigt i byen, uden tvivl'\"\r\n [likeCount]=\"11\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Caroline Jensen', 'Denne bygning har den bedste udsigt i byen, uden tvivl', false)\" />\r\n \r\n <ds-mobile-comment\r\n [authorName]=\"'Anna Hansen'\"\r\n [authorRole]=\"'Lejer'\"\r\n [timestamp]=\"'30m siden'\"\r\n [avatarInitials]=\"'AH'\"\r\n [content]=\"'Jeg skal se din altan en dag! 😍'\"\r\n [clickable]=\"true\"\r\n [isOwnComment]=\"false\"\r\n (longPress)=\"handleCommentLongPress('Anna Hansen', 'Jeg skal se din altan en dag! 😍', false)\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ds-mobile-page-details>\r\n `\r\n})\r\nexport class MobilePostDetailPageComponent {\r\n repliesCount = 6;\r\n \r\n constructor(\r\n private lightbox: DsMobileLightboxService,\r\n private bottomSheet: DsMobileBottomSheetService\r\n ) {}\r\n \r\n /**\r\n * Open an image in the lightbox viewer\r\n */\r\n openImageLightbox(imageSrc: string, title: string, description: string): void {\r\n const authorMeta: LightboxAuthor = {\r\n name: 'Sophie Andersen',\r\n role: 'Lejer',\r\n avatarInitials: 'SA',\r\n timestamp: '4t siden'\r\n };\r\n \r\n this.lightbox.open({\r\n showActions: true, // Show like & comment actions\r\n images: [\r\n {\r\n type: 'image',\r\n src: imageSrc,\r\n alt: title,\r\n title: title,\r\n description: description,\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 34\r\n }\r\n ],\r\n author: authorMeta,\r\n enableZoom: true,\r\n showControls: false, // Single image, no need for controls\r\n showInfo: true\r\n });\r\n }\r\n \r\n /**\r\n * Handle long press on a comment to show action sheet\r\n */\r\n async handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void> {\r\n const sheet = await this.bottomSheet.create({\r\n component: DsMobileCommentActionsBottomSheetComponent,\r\n componentProps: {\r\n isOwnContent: isOwnComment\r\n },\r\n breakpoints: [0, 1],\r\n initialBreakpoint: 1,\r\n handle: true,\r\n backdropDismiss: true,\r\n cssClass: 'auto-height'\r\n });\r\n \r\n const result = await sheet.onWillDismiss();\r\n \r\n if (result.role === 'select' && result.data) {\r\n const action = (result.data as CommentActionResult).action;\r\n \r\n switch (action) {\r\n case 'like':\r\n console.log('Like comment by', authorName);\r\n // Implement like logic\r\n break;\r\n case 'reply':\r\n console.log('Reply to comment by', authorName);\r\n // Implement reply logic\r\n break;\r\n case 'edit':\r\n console.log('Edit comment by', authorName);\r\n // Implement edit logic\r\n break;\r\n case 'delete':\r\n console.log('Delete comment by', authorName);\r\n // Implement delete logic (with confirmation)\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n","import { Component, OnInit, inject } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { WhitelabelService } from '../services/whitelabel.service';\r\nimport { DsLogoComponent } from '../components/logo/ds-logo';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge/ds-avatar-with-badge';\r\nimport { IonContent, IonHeader, IonToolbar, IonTitle, IonButton } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * Whitelabel Demo Page\r\n * \r\n * Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.\r\n */\r\n@Component({\r\n selector: 'app-whitelabel-demo',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n IonContent,\r\n IonHeader,\r\n IonToolbar,\r\n IonTitle,\r\n IonButton,\r\n DsLogoComponent,\r\n DsAvatarWithBadgeComponent\r\n ],\r\n styles: [`\r\n :host {\r\n display: block;\r\n }\r\n \r\n ion-toolbar {\r\n --background: var(--color-brand-secondary);\r\n --color: var(--color-secondary-content);\r\n }\r\n \r\n ion-content {\r\n --background: #f5f5f5;\r\n }\r\n \r\n .demo-container {\r\n padding: 20px;\r\n max-width: 600px;\r\n margin: 0 auto;\r\n }\r\n \r\n .demo-section {\r\n margin-bottom: 32px;\r\n }\r\n \r\n .demo-section h2 {\r\n margin-bottom: 16px;\r\n font-size: 18px;\r\n font-weight: 600;\r\n color: #333;\r\n }\r\n \r\n /* Theme Selection */\r\n .theme-buttons {\r\n display: flex;\r\n gap: 12px;\r\n flex-wrap: wrap;\r\n }\r\n \r\n .theme-buttons ion-button {\r\n --background: #e0e0e0;\r\n --color: #333;\r\n --ripple-color: transparent;\r\n --background-activated: #e0e0e0;\r\n --background-focused: #e0e0e0;\r\n --background-hover: #d0d0d0;\r\n }\r\n \r\n .theme-buttons ion-button.active {\r\n --background: var(--color-secondary-surface);\r\n --color: var(--color-secondary-content);\r\n --background-activated: var(--color-secondary-surface);\r\n --background-focused: var(--color-secondary-surface);\r\n --background-hover: var(--color-secondary-surface);\r\n }\r\n \r\n .theme-buttons ion-button::part(native)::after {\r\n display: none;\r\n }\r\n \r\n /* Logo Preview */\r\n .logo-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: var(--color-brand-secondary);\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .logomark-preview {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 12px;\r\n min-height: 80px;\r\n }\r\n \r\n .preview-grid {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n }\r\n \r\n .preview-tile {\r\n background: white;\r\n border-radius: 12px;\r\n padding: 16px;\r\n }\r\n \r\n .preview-tile h3 {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #666;\r\n margin-bottom: 12px;\r\n }\r\n \r\n /* Brand Colors */\r\n .color-section {\r\n background: white;\r\n border-radius: 12px;\r\n padding: 20px;\r\n }\r\n \r\n .color-swatches {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n margin-bottom: 24px;\r\n }\r\n \r\n .swatch {\r\n padding: 16px;\r\n border-radius: 8px;\r\n text-align: center;\r\n }\r\n \r\n .swatch-label {\r\n font-size: 12px;\r\n font-weight: 600;\r\n margin-bottom: 4px;\r\n }\r\n \r\n .swatch-value {\r\n font-size: 11px;\r\n opacity: 0.8;\r\n font-family: monospace;\r\n }\r\n \r\n .swatch--primary-surface {\r\n background: var(--color-primary-surface);\r\n color: var(--color-primary-content);\r\n }\r\n \r\n .swatch--primary-content {\r\n background: var(--color-primary-content);\r\n color: var(--color-primary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n .swatch--secondary-surface {\r\n background: var(--color-secondary-surface);\r\n color: var(--color-secondary-content);\r\n }\r\n \r\n .swatch--secondary-content {\r\n background: var(--color-secondary-content);\r\n color: var(--color-secondary-surface);\r\n border: 1px solid #e0e0e0;\r\n }\r\n \r\n /* Color Inputs */\r\n .color-inputs {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n }\r\n \r\n .color-group-label {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #333;\r\n margin-top: 8px;\r\n }\r\n \r\n .color-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n }\r\n \r\n .color-row label {\r\n min-width: 70px;\r\n font-size: 13px;\r\n color: #666;\r\n }\r\n \r\n .color-row input[type=\"color\"] {\r\n width: 40px;\r\n height: 32px;\r\n border: none;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n padding: 0;\r\n }\r\n \r\n .color-row input[type=\"text\"] {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 6px;\r\n font-family: monospace;\r\n font-size: 13px;\r\n }\r\n `],\r\n template: `\r\n <ion-header>\r\n <ion-toolbar>\r\n <ion-title>Whitelabel</ion-title>\r\n </ion-toolbar>\r\n </ion-header>\r\n \r\n <ion-content>\r\n <div class=\"demo-container\">\r\n <!-- Theme Selection -->\r\n <div class=\"demo-section\">\r\n <h2>Theme</h2>\r\n <div class=\"theme-buttons\">\r\n <ion-button (click)=\"applyDefaultTheme()\" size=\"small\" [class.active]=\"currentTheme === 'default'\">\r\n Propbinder\r\n </ion-button>\r\n <ion-button (click)=\"applyCejTheme()\" size=\"small\" [class.active]=\"currentTheme === 'cej'\">\r\n CEJ\r\n </ion-button>\r\n <ion-button (click)=\"applyPkaTheme()\" size=\"small\" [class.active]=\"currentTheme === 'pka'\">\r\n PKA\r\n </ion-button>\r\n <ion-button (click)=\"applyClaveTheme()\" size=\"small\" [class.active]=\"currentTheme === 'clave'\">\r\n Clave\r\n </ion-button>\r\n <ion-button (click)=\"applyFreedomTheme()\" size=\"small\" [class.active]=\"currentTheme === 'freedom'\">\r\n Freedom\r\n </ion-button>\r\n </div>\r\n </div>\r\n \r\n <!-- Logo & Logomark Preview -->\r\n <div class=\"demo-section\">\r\n <h2>Logo Preview</h2>\r\n <div class=\"preview-grid\">\r\n <div class=\"preview-tile\">\r\n <h3>Logo</h3>\r\n <div class=\"logo-preview\">\r\n <ds-logo variant=\"full\" />\r\n </div>\r\n </div>\r\n <div class=\"preview-tile\">\r\n <h3>Logomark</h3>\r\n <div class=\"logomark-preview\">\r\n <ds-avatar-with-badge\r\n [type]=\"'initials'\"\r\n [initials]=\"'KN'\"\r\n [size]=\"'md'\"\r\n [badgePosition]=\"'bottom-right'\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Brand Colors -->\r\n <div class=\"demo-section\">\r\n <h2>Brand Colors</h2>\r\n <div class=\"color-section\">\r\n <div class=\"color-swatches\">\r\n <div class=\"swatch swatch--primary-surface\">\r\n <div class=\"swatch-label\">Primary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--primary-content\">\r\n <div class=\"swatch-label\">Primary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.primaryContent() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-surface\">\r\n <div class=\"swatch-label\">Secondary Surface</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondarySurface() }}</div>\r\n </div>\r\n <div class=\"swatch swatch--secondary-content\">\r\n <div class=\"swatch-label\">Secondary Content</div>\r\n <div class=\"swatch-value\">{{ whitelabelService.secondaryContent() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"color-inputs\">\r\n <div class=\"color-group-label\">Primary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customPrimaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n \r\n <div class=\"color-group-label\">Secondary</div>\r\n <div class=\"color-row\">\r\n <label>Surface</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondarySurface\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n <div class=\"color-row\">\r\n <label>Content</label>\r\n <input \r\n type=\"color\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"customSecondaryContent\"\r\n (change)=\"applyCustomColors()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class WhitelabelDemoPage implements OnInit {\r\n whitelabelService = inject(WhitelabelService);\r\n \r\n // Current active theme\r\n currentTheme = 'default';\r\n \r\n // Custom color inputs\r\n customPrimarySurface = '#6B5FF5';\r\n customPrimaryContent = '#FFFFFF';\r\n customSecondarySurface = '#221a4c';\r\n customSecondaryContent = '#FFFFFF';\r\n \r\n ngOnInit() {\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyDefaultTheme() {\r\n this.currentTheme = 'default';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',\r\n logoAlt: 'Propbinder',\r\n logoHeight: 28,\r\n primarySurface: '#6B5FF5',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#221a4c',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Propbinder',\r\n organizationId: 'default'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCejTheme() {\r\n this.currentTheme = 'cej';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/cej-logo.png',\r\n logoMarkUrl: '/Assets/logos/cej-logo.png',\r\n logoAlt: 'CEJ',\r\n logoHeight: 36,\r\n primarySurface: '#dc092c',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#A70923',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'CEJ',\r\n organizationId: 'cej'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyPkaTheme() {\r\n this.currentTheme = 'pka';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/pka-logo.svg',\r\n logoMarkUrl: '/Assets/logos/pka-logo.svg',\r\n logoAlt: 'PKA',\r\n logoHeight: 24,\r\n primarySurface: '#CC006C',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#660036',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'PKA',\r\n organizationId: 'pka'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyClaveTheme() {\r\n this.currentTheme = 'clave';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/clave-logo.svg',\r\n logoMarkUrl: '/Assets/logos/clave-logo.svg',\r\n logoAlt: 'Clave',\r\n logoHeight: 24,\r\n primarySurface: '#868764',\r\n primaryContent: '#FFFFFF',\r\n secondarySurface: '#262424',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Clave',\r\n organizationId: 'clave'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyFreedomTheme() {\r\n this.currentTheme = 'freedom';\r\n this.whitelabelService.updateConfig({\r\n logoUrl: '/Assets/logos/freedom-logo.svg',\r\n logoMarkUrl: '/Assets/logos/freedom-logomark.svg',\r\n logoAlt: 'Freedom',\r\n logoHeight: 28,\r\n primarySurface: '#AACFC3',\r\n primaryContent: '#1D4A49',\r\n secondarySurface: '#1D4A49',\r\n secondaryContent: '#FFFFFF',\r\n organizationName: 'Freedom',\r\n organizationId: 'freedom'\r\n });\r\n this.updateCustomColorInputs();\r\n }\r\n \r\n applyCustomColors() {\r\n this.whitelabelService.updateColors({\r\n primarySurface: this.customPrimarySurface,\r\n primaryContent: this.customPrimaryContent,\r\n secondarySurface: this.customSecondarySurface,\r\n secondaryContent: this.customSecondaryContent\r\n });\r\n }\r\n \r\n private updateCustomColorInputs() {\r\n this.customPrimarySurface = this.whitelabelService.primarySurface();\r\n this.customPrimaryContent = this.whitelabelService.primaryContent();\r\n this.customSecondarySurface = this.whitelabelService.secondarySurface();\r\n this.customSecondaryContent = this.whitelabelService.secondaryContent();\r\n }\r\n}\r\n","/* Auto-generated. Do not edit. */\nexport * from './components';\nexport * from './pages';\nexport * from './animations/page-transitions';\nexport * from './services/user.service';\nexport * from './services/whitelabel.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.DsMobileLongPressDirective","i2","i1","i1.DsMobileLightboxService","DsMobileCommentActionsBottomSheetComponent","i2.DsMobileLightboxService","i3.DsMobileBottomSheetService","i4","i1.DsMobileHandbookDetailModalService","DsMobilePostActionsBottomSheetComponent","i2.DsMobileBottomSheetService","i3.DsMobileLightboxService","i4.DsMobilePostDetailModalService","i5.UserService","i1.UserService","i2.UserService","i4.DsMobileChatModalService","i3"],"mappings":"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"}
|