@propbinder/mobile-design 0.2.3 → 0.2.5
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.
- package/fesm2022/propbinder-mobile-design.mjs +5536 -3010
- package/fesm2022/propbinder-mobile-design.mjs.map +1 -1
- package/index.d.ts +1084 -279
- package/package.json +1 -1
- package/styles/ionic.css +84 -73
- package/styles/mobile-common.css +41 -0
- package/styles/mobile-page-base.css +9 -7
|
@@ -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: Event): 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 `\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 /* Image attachment styling */\r\n .image-attachment {\r\n max-width: 180px;\r\n max-height: 140px;\r\n border-radius: 12px;\r\n object-fit: cover;\r\n cursor: pointer;\r\n border: 1px solid var(--border-color-default, #e5e5e5);\r\n }\r\n\r\n /* Image attachment border for user's messages */\r\n :host.is-own-message .image-attachment {\r\n border-color: rgba(255, 255, 255, 0.4);\r\n }\r\n `,\r\n ],\r\n template: `<div class=\"avatar-wrapper\">\r\n <ds-avatar [initials]=\"avatarInitials()\" [type]=\"avatarType()\" [src]=\"avatarSrc()\" size=\"sm\" />\r\n </div>\r\n\r\n <div class=\"message-content-wrapper\">\r\n <div class=\"message-bubble\">\r\n <!-- Text -->\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\r\n <!-- IMAGE attachment (thumbnail) -->\r\n @if (attachment.type === 'image') {\r\n <img class=\"image-attachment\" [src]=\"attachment.thumbnail || attachment.url\" [alt]=\"attachment.name\" (click)=\"handleAttachmentClick(attachment)\" />\r\n }\r\n\r\n <!-- PDF / FILE attachment -->\r\n @else {\r\n <div class=\"attachment-item\" (click)=\"handleAttachmentClick(attachment)\">\r\n <div class=\"attachment-icon\">\r\n @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\r\n <span class=\"attachment-name\">\r\n {{ attachment.name }}\r\n </span>\r\n </div>\r\n } }\r\n </div>\r\n }\r\n\r\n <!-- Timestamp -->\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\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","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';","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/inline-tabs/ds-mobile-inline-tabs.ts","../../../projects/mobile-design-lib/src/animations/page-transitions.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/attachment-preview/ds-mobile-attachment-preview.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/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/shared/mobile-modal-base.ts","../../../projects/mobile-design-lib/src/components/modal-base/ds-mobile-modal-base.ts","../../../projects/mobile-design-lib/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts","../../../projects/mobile-design-lib/src/services/base-modal.service.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/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/system-message-banner/ds-mobile-system-message-banner.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/new-inquiry-modal/ds-mobile-new-inquiry-modal.ts","../../../projects/mobile-design-lib/src/components/new-inquiry-modal/ds-mobile-new-inquiry-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-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/fab/ds-mobile-fab.ts","../../../projects/mobile-design-lib/src/components/index.ts","../../../projects/mobile-design-lib/src/services/posts.service.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/pages/inquiries.example.ts","../../../projects/mobile-design-lib/src/components/card-inline-banner/ds-mobile-card-inline-banner.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/sign-in.page.ts","../../../projects/mobile-design-lib/src/pages/whitelabel-demo.page.ts","../../../projects/mobile-design-lib/src/models/post.model.ts","../../../projects/mobile-design-lib/src/models/index.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-neutral-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: Event): 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=\"crescent\">\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 } 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 { Animation } from '@ionic/angular';\r\nimport { createAnimation } from '@ionic/core';\r\n\r\n/**\r\n * Custom page transition - iOS-style push/pop with dark overlay\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 * - Dark overlay: fades in on leaving page (opacity 0 to 0.70)\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 * - Dark overlay: fades out on entering page (main page underneath, opacity 0.70 to 0)\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 // Create overlay element\r\n // Forward: overlay on leaving page (main page underneath)\r\n // Back: overlay on entering page (main page underneath)\r\n const overlayEl = document.createElement('div');\r\n overlayEl.style.position = 'absolute';\r\n overlayEl.style.top = '0';\r\n overlayEl.style.left = '0';\r\n overlayEl.style.right = '0';\r\n overlayEl.style.bottom = '0';\r\n overlayEl.style.backgroundColor = '#000';\r\n overlayEl.style.opacity = isBackDirection ? '0.70' : '0';\r\n overlayEl.style.zIndex = '1';\r\n overlayEl.style.pointerEvents = 'none';\r\n \r\n // Add overlay to the page that should have it (main page underneath)\r\n // Forward: leaving page is main page\r\n // Back: entering page is main page\r\n const targetPageEl = isBackDirection ? opts.enteringEl : opts.leavingEl;\r\n if (targetPageEl) {\r\n const currentPosition = window.getComputedStyle(targetPageEl).position;\r\n if (currentPosition === 'static') {\r\n targetPageEl.style.position = 'relative';\r\n }\r\n targetPageEl.appendChild(overlayEl);\r\n }\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 // Overlay fade animation\r\n const overlayAnimation = createAnimation()\r\n .addElement(overlayEl)\r\n .fromTo('opacity',\r\n isBackDirection ? '0.70' : '0',\r\n isBackDirection ? '0' : '0.70'\r\n );\r\n\r\n // Clean up overlay after animation completes\r\n rootTransition.afterAddWrite(() => {\r\n if (overlayEl && overlayEl.parentNode) {\r\n overlayEl.parentNode.removeChild(overlayEl);\r\n }\r\n });\r\n\r\n rootTransition.addAnimation([enteringPage, leavingPage, overlayAnimation]);\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 * Dark overlay: fades out on entering page (main page underneath, opacity 0.70 to 0)\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 // Create overlay element for the entering page (main page underneath)\r\n // This page should already have an overlay from the forward transition, but we'll ensure it exists\r\n const overlayEl = document.createElement('div');\r\n overlayEl.style.position = 'absolute';\r\n overlayEl.style.top = '0';\r\n overlayEl.style.left = '0';\r\n overlayEl.style.right = '0';\r\n overlayEl.style.bottom = '0';\r\n overlayEl.style.backgroundColor = '#000';\r\n overlayEl.style.opacity = '0.70';\r\n overlayEl.style.zIndex = '1';\r\n overlayEl.style.pointerEvents = 'none';\r\n \r\n // Ensure entering page has relative positioning for overlay\r\n const enteringPageEl = opts.enteringEl as HTMLElement;\r\n if (enteringPageEl) {\r\n const currentPosition = window.getComputedStyle(enteringPageEl).position;\r\n if (currentPosition === 'static') {\r\n enteringPageEl.style.position = 'relative';\r\n }\r\n enteringPageEl.appendChild(overlayEl);\r\n }\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 // Overlay fade out animation on the entering page (main page)\r\n const overlayAnimation = createAnimation()\r\n .addElement(overlayEl)\r\n .fromTo('opacity', '0.70', '0');\r\n\r\n // Clean up overlay after animation completes\r\n rootTransition.afterAddWrite(() => {\r\n if (overlayEl && overlayEl.parentNode) {\r\n overlayEl.parentNode.removeChild(overlayEl);\r\n }\r\n });\r\n\r\n rootTransition.addAnimation([enteringPage, leavingPage, overlayAnimation]);\r\n \r\n return rootTransition;\r\n};\r\n\r\n","import { Component, input, output, ElementRef, ViewChild, AfterViewInit, computed, 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 { Haptics, ImpactStyle } from '@capacitor/haptics';\r\nimport { DsIconComponent } from '@propbinder/design-system';\r\nimport { MobilePageBase } from '../shared/mobile-page-base';\r\nimport { DsMobileInlineTabsComponent, type InlineTabItem } from '../inline-tabs';\r\nimport { customBackTransition } from '../../animations/page-transitions';\r\n\r\n/**\r\n * DsMobilePageDetailsComponent\r\n * \r\n * A complete mobile page layout for detail/drill-down pages with:\r\n * - Fixed header with back button + title (fades in on scroll)\r\n * - Purple expandable header section (scrolls with content)\r\n * - Optional inline tabs in expandable header\r\n * - White rounded content wrapper\r\n * - Pull-to-refresh support (native platforms only)\r\n * - Auto scroll title fade-in and header fade-out\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 tabs -->\r\n * <ds-mobile-page-details\r\n * title=\"Inquiry Details\"\r\n * [tabs]=\"tabItems\"\r\n * [activeTab]=\"activeTab()\"\r\n * (tabChange)=\"setActiveTab($event)\"\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 */\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 IonTitle,\r\n IonContent,\r\n IonRefresher,\r\n IonRefresherContent,\r\n DsIconComponent,\r\n DsMobileInlineTabsComponent\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 <!-- 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)=\"handleBack()\" [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\">{{ title() }}</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 (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\">{{ title() }}</h1>\r\n </div>\r\n \r\n <!-- Tabs in header (optional) -->\r\n @if (tabs() && tabs()!.length > 0) {\r\n <ds-mobile-inline-tabs\r\n [tabs]=\"tabs()!\"\r\n [activeTab]=\"activeTab()\"\r\n (tabChange)=\"handleTabChange($event)\">\r\n </ds-mobile-inline-tabs>\r\n }\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 <ng-content></ng-content>\r\n </div>\r\n </div>\r\n </ion-content>\r\n `\r\n})\r\nexport class DsMobilePageDetailsComponent 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 // Inputs\r\n title = input.required<string>();\r\n backRoute = input<string>(''); // Optional default back route\r\n \r\n // Inputs - Tabs (optional)\r\n tabs = input<InlineTabItem[] | undefined>(undefined);\r\n activeTab = input<string>('');\r\n \r\n // Inputs - Features\r\n showRefresh = input<boolean>(true);\r\n scrollThreshold = input<number>(160); // Pixels to scroll before title appears\r\n headerFadeDistance = input<number>(200); // Distance over which header fades out\r\n \r\n // Outputs\r\n back = output<void>();\r\n tabChange = output<string>();\r\n refresh = output<any>();\r\n scroll = output<any>();\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 ngAfterViewInit(): void {\r\n // Initial setup if needed\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 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({ animation: customBackTransition });\r\n }\r\n }\r\n \r\n /**\r\n * Handle tab change\r\n */\r\n handleTabChange(tabId: string): void {\r\n this.tabChange.emit(tabId);\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 threshold = this.scrollThreshold();\r\n const fadeDistance = this.headerFadeDistance();\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 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 } 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 { 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 * File type for attachment preview\r\n */\r\nexport type AttachmentFileType = 'image' | 'pdf' | 'doc' | 'docx' | 'xls' | 'xlsx' | 'other';\r\n\r\n/**\r\n * Attachment data interface\r\n */\r\nexport interface AttachmentData {\r\n id: string;\r\n src: string;\r\n type: AttachmentFileType;\r\n name?: string;\r\n size?: string;\r\n}\r\n\r\n/**\r\n * DsMobileAttachmentPreviewComponent\r\n * \r\n * Reusable component for displaying attachment previews.\r\n * Supports both image previews and file type indicators (PDF, DOCX, etc.).\r\n * \r\n * Features:\r\n * - Image preview for photos\r\n * - File type indicator box for documents\r\n * - Remove button overlay\r\n * - Consistent 96x96 size\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Image attachment -->\r\n * <ds-mobile-attachment-preview\r\n * [attachment]=\"{ id: '1', src: 'photo.jpg', type: 'image' }\"\r\n * (remove)=\"handleRemove($event)\">\r\n * </ds-mobile-attachment-preview>\r\n * \r\n * <!-- PDF attachment -->\r\n * <ds-mobile-attachment-preview\r\n * [attachment]=\"{ id: '2', src: 'doc.pdf', type: 'pdf', name: 'Document.pdf' }\"\r\n * (remove)=\"handleRemove($event)\">\r\n * </ds-mobile-attachment-preview>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-attachment-preview',\r\n standalone: true,\r\n imports: [CommonModule, DsAvatarComponent],\r\n styleUrls: ['./ds-mobile-attachment-preview.css'],\r\n template: `\r\n <div class=\"attachment-preview\">\r\n @if (attachment().type === 'image') {\r\n <!-- Image Preview -->\r\n <img \r\n [src]=\"attachment().src\" \r\n [alt]=\"attachment().name || 'Attachment'\" \r\n class=\"preview-image\" \r\n />\r\n } @else {\r\n <!-- File Type Preview -->\r\n <div class=\"preview-file\">\r\n <div class=\"file-avatar\">\r\n <ds-avatar\r\n type=\"icon\"\r\n [iconName]=\"getIconName()\"\r\n size=\"md\"\r\n [class]=\"'file-' + attachment().type\"\r\n />\r\n </div>\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"attachment().name || 'Unknown file'\">\r\n {{ attachment().name || 'Unknown file' }}\r\n </div>\r\n <div class=\"file-type-label\">{{ getFileTypeLabel() }}</div>\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Remove Button -->\r\n <button \r\n class=\"remove-btn\" \r\n (click)=\"handleRemove()\"\r\n type=\"button\"\r\n [attr.aria-label]=\"'Remove ' + (attachment().name || 'attachment')\">\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})\r\nexport class DsMobileAttachmentPreviewComponent {\r\n /**\r\n * Attachment data to display\r\n */\r\n attachment = input.required<AttachmentData>();\r\n \r\n /**\r\n * Emits when the remove button is clicked\r\n */\r\n remove = output<string>();\r\n \r\n /**\r\n * Get the file type label (PDF, DOCX, etc.)\r\n */\r\n getFileTypeLabel(): string {\r\n const type = this.attachment().type.toUpperCase();\r\n \r\n // Map common types to their display labels\r\n const labelMap: Record<string, string> = {\r\n 'PDF': 'PDF',\r\n 'DOC': 'DOC',\r\n 'DOCX': 'DOCX',\r\n 'XLS': 'XLS',\r\n 'XLSX': 'XLSX',\r\n 'OTHER': 'FILE'\r\n };\r\n \r\n return labelMap[type] || type;\r\n }\r\n \r\n /**\r\n * Get the appropriate icon name based on file type\r\n */\r\n getIconName(): string {\r\n const type = this.attachment().type;\r\n \r\n const iconMap: Record<AttachmentFileType, string> = {\r\n 'image': 'remixImageLine',\r\n 'pdf': 'remixFileTextLine',\r\n 'doc': 'remixFileTextLine',\r\n 'docx': 'remixFileTextLine',\r\n 'xls': 'remixFileList3Line',\r\n 'xlsx': 'remixFileList3Line',\r\n 'other': 'remixAttachmentLine'\r\n };\r\n \r\n return iconMap[type] || 'remixAttachmentLine';\r\n }\r\n \r\n /**\r\n * Handle remove button click\r\n */\r\n handleRemove(): void {\r\n this.remove.emit(this.attachment().id);\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\nimport { \r\n DsMobileAttachmentPreviewComponent, \r\n type AttachmentData, \r\n type AttachmentFileType \r\n} from '../attachment-preview/ds-mobile-attachment-preview';\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 DsMobileAttachmentPreviewComponent\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 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 /* Attachment previews section */\r\n .attachment-previews-section {\r\n padding: 0 0 8px 0;\r\n animation: slideDown 0.2s ease-out;\r\n }\r\n \r\n .attachment-previews {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\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 button on right */\r\n min-height: 44px;\r\n position: relative;\r\n }\r\n \r\n /* Adjust padding when both attachment and send buttons are present */\r\n .composer-input-wrapper.has-both-buttons {\r\n padding-right: 88px; /* Space for both buttons */\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 /* Attachment button - positioned in top right corner */\r\n .attachment-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 }\r\n \r\n .attachment-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 /* 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 /* When send button is visible, move attachment button to the left */\r\n .send-button-visible .attachment-button-fixed {\r\n right: 46px; /* Move to the left to make room for send button */\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 <!-- Attachment Previews (if any) -->\r\n @if (attachments().length > 0) {\r\n <div class=\"attachment-previews-section\">\r\n <div class=\"attachment-previews\">\r\n @for (attachment of attachments(); track attachment.id) {\r\n <ds-mobile-attachment-preview\r\n [attachment]=\"attachment\"\r\n (remove)=\"removeAttachment($event)\"\r\n />\r\n }\r\n </div>\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 \r\n class=\"composer-input-wrapper\"\r\n [class.send-button-visible]=\"messageText().trim().length > 0 || attachments().length > 0\"\r\n [class.has-both-buttons]=\"showAttachmentButton() && (messageText().trim().length > 0 || attachments().length > 0)\">\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 (keydown)=\"handleKeyDown($event)\"\r\n (focus)=\"showKeyboard()\"\r\n (click)=\"showKeyboard()\"\r\n rows=\"1\"\r\n ></textarea>\r\n \r\n <!-- Attachment button (optional) -->\r\n @if (showAttachmentButton()) {\r\n <ds-icon-button\r\n icon=\"remixAttachmentLine\"\r\n variant=\"secondary\"\r\n size=\"md\"\r\n (clicked)=\"handleAttachmentClick()\"\r\n [attr.aria-label]=\"attachmentButtonLabel()\"\r\n class=\"attachment-button-fixed\">\r\n </ds-icon-button>\r\n }\r\n \r\n <!-- Send button -->\r\n @if (messageText().trim().length > 0 || attachments().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 <!-- Hidden file input -->\r\n <input\r\n #fileInput\r\n type=\"file\"\r\n accept=\"*/*\"\r\n multiple\r\n aria-hidden=\"true\"\r\n style=\"display: none;\"\r\n (change)=\"handleFileSelect($event)\"\r\n />\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 * Attachment button aria label\r\n */\r\n attachmentButtonLabel = input<string>('Add attachment');\r\n \r\n /**\r\n * Whether to show the attachment button\r\n */\r\n showAttachmentButton = input<boolean>(false);\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 * ViewChild for file input\r\n */\r\n @ViewChild('fileInput') fileInput?: ElementRef<HTMLInputElement>;\r\n \r\n /**\r\n * Message text signal\r\n */\r\n messageText = signal('');\r\n \r\n /**\r\n * Attachments signal\r\n */\r\n attachments = signal<AttachmentData[]>([]);\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<{ \r\n content: string; \r\n isReply?: boolean; \r\n replyTo?: string; \r\n isEdit?: boolean;\r\n attachments?: AttachmentData[];\r\n }>();\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 /**\r\n * Emits when attachment button is clicked\r\n */\r\n attachmentClicked = output<void>();\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 keyboard shortcuts (Shift+Enter to send)\r\n */\r\n handleKeyDown(event: KeyboardEvent): void {\r\n // Shift+Enter sends the message\r\n if (event.key === 'Enter' && event.shiftKey) {\r\n event.preventDefault();\r\n const hasContent = this.messageText().trim().length > 0 || this.attachments().length > 0;\r\n if (hasContent) {\r\n this.sendMessage();\r\n }\r\n }\r\n // Regular Enter just creates a new line (default behavior)\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 this.attachments.set([]);\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 * Handle attachment button click\r\n */\r\n handleAttachmentClick(): void {\r\n // Trigger the hidden file input\r\n if (this.fileInput) {\r\n this.fileInput.nativeElement.click();\r\n }\r\n this.attachmentClicked.emit();\r\n }\r\n \r\n /**\r\n * Detect file type from file name or mime type\r\n */\r\n private detectFileType(file: File): AttachmentFileType {\r\n const fileName = file.name.toLowerCase();\r\n const mimeType = file.type.toLowerCase();\r\n \r\n // Check if it's an image\r\n if (mimeType.startsWith('image/')) {\r\n return 'image';\r\n }\r\n \r\n // Check file extension\r\n if (fileName.endsWith('.pdf')) {\r\n return 'pdf';\r\n } else if (fileName.endsWith('.doc')) {\r\n return 'doc';\r\n } else if (fileName.endsWith('.docx')) {\r\n return 'docx';\r\n } else if (fileName.endsWith('.xls')) {\r\n return 'xls';\r\n } else if (fileName.endsWith('.xlsx')) {\r\n return 'xlsx';\r\n }\r\n \r\n return 'other';\r\n }\r\n \r\n /**\r\n * Format file size for display\r\n */\r\n private formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 B';\r\n const k = 1024;\r\n const sizes = ['B', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];\r\n }\r\n \r\n /**\r\n * Handle file selection from file input\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 return;\r\n }\r\n \r\n // Process each selected file (up to 6 total)\r\n const remainingSlots = 6 - this.attachments().length;\r\n const filesToProcess = Array.from(files).slice(0, remainingSlots);\r\n \r\n filesToProcess.forEach(file => {\r\n const fileType = this.detectFileType(file);\r\n \r\n // Create a data URL for preview\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 const newAttachment: AttachmentData = {\r\n id: `file-${Date.now()}-${Math.random()}`,\r\n src: result,\r\n type: fileType,\r\n name: file.name,\r\n size: this.formatFileSize(file.size)\r\n };\r\n this.attachments.update(attachments => [...attachments, newAttachment]);\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 * Remove an attachment from the list\r\n */\r\n removeAttachment(attachmentId: string): void {\r\n this.attachments.update(attachments => \r\n attachments.filter(a => a.id !== attachmentId)\r\n );\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 const hasAttachments = this.attachments().length > 0;\r\n \r\n // Must have either text or attachments\r\n if (!text && !hasAttachments) 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 attachments: hasAttachments ? [...this.attachments()] : undefined\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: 4px;\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 .avatar-wrapper.hidden {\r\n display: none;\r\n }\r\n \r\n .message-content-wrapper {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0;\r\n max-width: 75%;\r\n min-width: 0;\r\n transition: gap 0.2s ease-out;\r\n }\r\n \r\n /* Add gap when timestamp is visible */\r\n .message-content-wrapper.has-timestamp {\r\n gap: 4px;\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: 8px 12px;\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 - neutral secondary background, no border */\r\n :host:not(.is-own-message) .message-bubble {\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\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 /* External timestamp below bubble */\r\n .message-timestamp-external {\r\n display: flex;\r\n height: 0;\r\n margin-top: 0;\r\n opacity: 0;\r\n transform: translateY(-4px);\r\n pointer-events: none;\r\n overflow: hidden;\r\n transition: height 0.2s ease-out, margin-top 0.2s ease-out, opacity 0.2s ease-out, transform 0.2s ease-out;\r\n }\r\n \r\n /* Visible state - fade in and expand height */\r\n .message-timestamp-external.visible {\r\n height: 14px;\r\n margin-top: 4px;\r\n opacity: 1;\r\n transform: translateY(0);\r\n pointer-events: auto;\r\n }\r\n \r\n /* Left-aligned for sender messages */\r\n :host:not(.is-own-message) .message-timestamp-external {\r\n justify-content: flex-start;\r\n padding-left: 12px;\r\n }\r\n \r\n /* Right-aligned for own messages */\r\n :host.is-own-message .message-timestamp-external {\r\n justify-content: flex-end;\r\n padding-right: 12px;\r\n }\r\n \r\n .message-timestamp-external .timestamp-text {\r\n font-family: 'Brockmann', sans-serif;\r\n font-size: 11px;\r\n font-weight: 400;\r\n line-height: 14px;\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n white-space: nowrap;\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\" [class.hidden]=\"isOwnMessage()\">\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\" [class.has-timestamp]=\"showTimestamp()\" (click)=\"handleClick($event)\">\r\n <div class=\"message-bubble\">\r\n <!-- Only show text if content is not empty -->\r\n @if (content().trim()) {\r\n <p class=\"message-text\">{{ content() }}</p>\r\n }\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); $event.stopPropagation()\">\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 </div>\r\n \r\n <!-- Timestamp below bubble, always rendered but visibility controlled by class -->\r\n <div class=\"message-timestamp-external\" [class.visible]=\"showTimestamp()\">\r\n <span class=\"timestamp-text\">{{ timestamp() }}</span>\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 * Whether to show the timestamp below the bubble\r\n */\r\n showTimestamp = input<boolean>(false);\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 * Emits when the message is clicked (to toggle timestamp)\r\n */\r\n messageClick = 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 private clickStartTime = 0;\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 click (for web/mouse support)\r\n */\r\n handleClick(event: MouseEvent): void {\r\n if (!this.clickable()) return;\r\n \r\n // Prevent double-firing on touch devices\r\n // Touch events will be handled by handleTouchEnd\r\n if ((event as any).sourceCapabilities?.firesTouchEvents) {\r\n return;\r\n }\r\n \r\n // Emit message click to toggle timestamp\r\n this.messageClick.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 if (!this.clickable()) return;\r\n \r\n this.longPressTriggered = false;\r\n this.clickStartTime = Date.now();\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 and detect short tap\r\n */\r\n handleTouchEnd(event: TouchEvent): void {\r\n const pressDuration = Date.now() - this.clickStartTime;\r\n \r\n if (this.longPressTimer) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n \r\n // If long press was triggered, prevent other actions\r\n if (this.longPressTriggered) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.longPressTriggered = false;\r\n return;\r\n }\r\n \r\n // Short tap (less than long press duration) - show timestamp\r\n if (this.clickable() && pressDuration < this.LONG_PRESS_DURATION) {\r\n // Check if moved too much\r\n const touch = event.changedTouches[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 if (deltaX <= this.MOVE_THRESHOLD && deltaY <= this.MOVE_THRESHOLD) {\r\n this.messageClick.emit();\r\n event.preventDefault();\r\n }\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\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 { input, output, Directive, OnInit, OnDestroy, inject, ViewChild } from '@angular/core';\r\nimport { ModalController, IonContent } from '@ionic/angular/standalone';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { Capacitor } from '@capacitor/core';\r\n\r\n/**\r\n * MobileModalBase\r\n * \r\n * Shared base class for mobile modal components.\r\n * Provides consistent modal behavior, state management, and keyboard handling.\r\n * \r\n * **Key Features:**\r\n * - Loading and error state management\r\n * - Header configuration (title, meta)\r\n * - Automatic keyboard height tracking (iOS/Android)\r\n * - Fixed bottom component support\r\n * - Consistent close behavior\r\n * \r\n * **Usage:**\r\n * ```typescript\r\n * export class MyModalComponent extends MobileModalBase {\r\n * constructor() {\r\n * super();\r\n * }\r\n * }\r\n * ```\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 MobileModalBase implements OnInit, OnDestroy {\r\n protected modalController = inject(ModalController);\r\n \r\n /**\r\n * Reference to IonContent for accessing scroll element\r\n */\r\n @ViewChild(IonContent, { read: IonContent }) protected ionContent?: IonContent;\r\n \r\n /**\r\n * ResizeObserver for tracking fixed bottom height\r\n */\r\n private fixedBottomObserver?: ResizeObserver;\r\n \r\n /**\r\n * Loading state - when true, shows loading indicator\r\n * @default false\r\n */\r\n loading = input<boolean>(false);\r\n \r\n /**\r\n * Error state - when set, shows error message\r\n * @default undefined\r\n */\r\n error = input<string | undefined>();\r\n \r\n /**\r\n * Modal header title\r\n * @default ''\r\n */\r\n headerTitle = input<string>('');\r\n \r\n /**\r\n * Modal header metadata (subtitle/secondary text)\r\n * @default ''\r\n */\r\n headerMeta = input<string>('');\r\n \r\n /**\r\n * Accessibility label for close button\r\n * @default 'Close'\r\n */\r\n closeButtonLabel = input<string>('Close');\r\n \r\n /**\r\n * Enable automatic keyboard height tracking\r\n * When enabled, sets --keyboard-height CSS variable for sliding content\r\n * @default false\r\n */\r\n enableKeyboardHandling = input<boolean>(false);\r\n \r\n /**\r\n * Whether modal has a fixed bottom component\r\n * Used to manage spacing and keyboard interactions\r\n * @default false\r\n */\r\n hasFixedBottom = input<boolean>(false);\r\n \r\n /**\r\n * Emitted when modal is closed\r\n */\r\n closed = output<void>();\r\n \r\n ngOnInit(): void {\r\n if (this.enableKeyboardHandling()) {\r\n this.setupKeyboardListeners();\r\n }\r\n \r\n if (this.hasFixedBottom()) {\r\n this.setupFixedBottomObserver();\r\n }\r\n }\r\n \r\n ngOnDestroy(): void {\r\n if (this.enableKeyboardHandling()) {\r\n this.cleanupKeyboardListeners();\r\n }\r\n \r\n if (this.fixedBottomObserver) {\r\n this.fixedBottomObserver.disconnect();\r\n }\r\n }\r\n \r\n /**\r\n * Close the modal\r\n * Emits closed event and dismisses the modal\r\n */\r\n close(): void {\r\n this.closed.emit();\r\n this.modalController.dismiss();\r\n }\r\n \r\n /**\r\n * Set up keyboard event listeners to adjust component position\r\n * Uses --keyboard-height for fixed bottom composer and adds padding to scroll area\r\n * @protected\r\n */\r\n protected setupKeyboardListeners(): void {\r\n Keyboard.addListener('keyboardWillShow', async (info) => {\r\n // Set global keyboard height for fixed bottom components (composer)\r\n document.documentElement.style.setProperty('--keyboard-height', `${info.keyboardHeight}px`);\r\n \r\n // Add padding to the scroll element using Ionic's proper API\r\n // This needs to include BOTH keyboard height AND fixed bottom height\r\n if (this.ionContent) {\r\n try {\r\n const scrollElement = await this.ionContent.getScrollElement();\r\n if (scrollElement) {\r\n const fixedBottomHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--fixed-bottom-height') || '0');\r\n const totalPadding = info.keyboardHeight + fixedBottomHeight;\r\n scrollElement.style.paddingBottom = `${totalPadding}px`;\r\n scrollElement.style.transition = 'padding-bottom 0.3s ease-out';\r\n }\r\n } catch (e) {\r\n console.log('[MobileModalBase] Could not access scroll element:', e);\r\n }\r\n }\r\n }).catch((e) => console.log('[MobileModalBase] Keyboard listeners not available:', e));\r\n\r\n Keyboard.addListener('keyboardWillHide', async () => {\r\n // Reset keyboard height\r\n document.documentElement.style.setProperty('--keyboard-height', '0px');\r\n \r\n // Reset scroll element padding to just fixed bottom height (not 0!)\r\n if (this.ionContent) {\r\n try {\r\n const scrollElement = await this.ionContent.getScrollElement();\r\n if (scrollElement) {\r\n const fixedBottomHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--fixed-bottom-height') || '0');\r\n scrollElement.style.paddingBottom = `${fixedBottomHeight}px`;\r\n }\r\n } catch (e) {\r\n console.log('[MobileModalBase] Could not access scroll element:', e);\r\n }\r\n }\r\n }).catch((e) => console.log('[MobileModalBase] Keyboard listeners not available:', e));\r\n }\r\n\r\n /**\r\n * Set up ResizeObserver to track fixed bottom height and apply as CSS variable\r\n * This allows dynamic bottom padding that adjusts to content\r\n * @protected\r\n */\r\n protected async setupFixedBottomObserver(): Promise<void> {\r\n // Determine platform-specific offset\r\n const isNative = Capacitor.isNativePlatform();\r\n const offset = isNative ? -24 : -12;\r\n \r\n // Small delay to ensure DOM is ready\r\n setTimeout(async () => {\r\n const fixedBottom = document.querySelector('.modal-fixed-bottom');\r\n console.log('[MobileModalBase] Fixed bottom element:', fixedBottom, 'Platform:', isNative ? 'Native' : 'Web', 'Offset:', offset);\r\n \r\n if (fixedBottom) {\r\n this.fixedBottomObserver = new ResizeObserver(async (entries) => {\r\n for (const entry of entries) {\r\n // Use getBoundingClientRect to get full border-box height (includes padding)\r\n const height = (entry.target as HTMLElement).getBoundingClientRect().height;\r\n // Add platform-specific offset\r\n const totalHeight = height + offset;\r\n console.log('[MobileModalBase] ResizeObserver - height:', height, 'totalHeight:', totalHeight);\r\n document.documentElement.style.setProperty('--fixed-bottom-height', `${totalHeight}px`);\r\n \r\n // Also update scroll element padding\r\n if (this.ionContent) {\r\n try {\r\n const scrollElement = await this.ionContent.getScrollElement();\r\n if (scrollElement) {\r\n scrollElement.style.paddingBottom = `${totalHeight}px`;\r\n }\r\n } catch (e) {\r\n console.log('[MobileModalBase] Could not update scroll element padding:', e);\r\n }\r\n }\r\n }\r\n });\r\n \r\n this.fixedBottomObserver.observe(fixedBottom);\r\n \r\n // Set initial height immediately (with platform-specific offset)\r\n const initialHeight = fixedBottom.getBoundingClientRect().height;\r\n const initialTotal = initialHeight + offset;\r\n console.log('[MobileModalBase] Initial height:', initialHeight, 'initialTotal:', initialTotal);\r\n document.documentElement.style.setProperty('--fixed-bottom-height', `${initialTotal}px`);\r\n \r\n // Set initial scroll element padding\r\n if (this.ionContent) {\r\n try {\r\n const scrollElement = await this.ionContent.getScrollElement();\r\n if (scrollElement) {\r\n scrollElement.style.paddingBottom = `${initialTotal}px`;\r\n }\r\n } catch (e) {\r\n console.log('[MobileModalBase] Could not set initial scroll element padding:', e);\r\n }\r\n }\r\n }\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Clean up keyboard event listeners\r\n * @protected\r\n */\r\n protected cleanupKeyboardListeners(): void {\r\n Keyboard.removeAllListeners().catch((e) => console.log('[MobileModalBase] Keyboard cleanup not available:', e));\r\n }\r\n}\r\n","import { Component, ContentChild, ElementRef, CUSTOM_ELEMENTS_SCHEMA, AfterContentInit, ChangeDetectorRef, input, HostBinding, ViewChild } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { IonContent } from '@ionic/angular/standalone';\r\nimport { DsIconButtonComponent, DsIconComponent } from '@propbinder/design-system';\r\nimport { MobileModalBase } from '../shared/mobile-modal-base';\r\n\r\n/**\r\n * DsMobileModalBaseComponent\r\n * \r\n * Base modal component providing consistent layout and behavior for all modals.\r\n * \r\n * **Features:**\r\n * - Optional header with auto-detection of content\r\n * - Flexible header with slots for leading content (avatar, icon)\r\n * - Title and metadata inputs or custom header slot\r\n * - Default loading and error state templates (with override capability)\r\n * - Fixed bottom component support (e.g., message composer)\r\n * - Automatic keyboard handling\r\n * - Safe area support\r\n * \r\n * **Slot Structure:**\r\n * - `[header-leading]` - Left side of header (avatar, icon)\r\n * - `[header-main]` - Custom header content (replaces title/meta)\r\n * - `[loading-state]` - Custom loading template\r\n * - `[error-state]` - Custom error template\r\n * - `[footer]` or `[fixed-bottom]` - Fixed bottom component (slides with keyboard)\r\n * - Default slot - Main modal content\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple title modal -->\r\n * <ds-mobile-modal-base \r\n * headerTitle=\"Settings\"\r\n * closeButtonLabel=\"Close\">\r\n * <div class=\"content\">...</div>\r\n * </ds-mobile-modal-base>\r\n * \r\n * <!-- Avatar header modal -->\r\n * <ds-mobile-modal-base\r\n * headerTitle=\"John Doe\"\r\n * headerMeta=\"Tenant · 2h ago\"\r\n * [hasFixedBottom]=\"true\"\r\n * [enableKeyboardHandling]=\"true\">\r\n * \r\n * <ds-avatar header-leading [initials]=\"'JD'\" size=\"md\" />\r\n * \r\n * <div class=\"content\">...</div>\r\n * \r\n * <div fixed-bottom class=\"composer\">...</div>\r\n * </ds-mobile-modal-base>\r\n * \r\n * <!-- Headerless modal (close button positioned absolutely) -->\r\n * <ds-mobile-modal-base [showHeader]=\"false\">\r\n * <div class=\"full-width-content\">...</div>\r\n * </ds-mobile-modal-base>\r\n * \r\n * <!-- Modal with footer actions (slides with keyboard) -->\r\n * <ds-mobile-modal-base\r\n * headerTitle=\"Create Inquiry\"\r\n * [hasFixedBottom]=\"true\"\r\n * [enableKeyboardHandling]=\"true\">\r\n * \r\n * <div class=\"content\">\r\n * <input type=\"text\" placeholder=\"Type something...\" />\r\n * </div>\r\n * \r\n * <div footer class=\"action-bar\">\r\n * <button>Cancel</button>\r\n * <button>Submit</button>\r\n * </div>\r\n * </ds-mobile-modal-base>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-modal-base',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n IonContent,\r\n DsIconButtonComponent,\r\n DsIconComponent\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n styleUrls: ['./ds-mobile-modal-base.css'],\r\n template: `\r\n <ion-content [fullscreen]=\"true\" [scrollY]=\"true\" class=\"modal-base-content\">\r\n <div class=\"modal-wrapper\" [class.headerless]=\"!shouldShowHeader()\">\r\n <!-- Header (conditional) -->\r\n @if (shouldShowHeader()) {\r\n <div class=\"modal-header\">\r\n <div class=\"header-content\">\r\n <!-- Leading slot (avatar, icon) - always rendered, CSS handles empty state -->\r\n <div class=\"header-leading\">\r\n <ng-content select=\"[header-leading]\"></ng-content>\r\n </div>\r\n \r\n <!-- Main (title + meta or custom) -->\r\n <div class=\"header-main\">\r\n @if (headerTitle()) {\r\n <div class=\"modal-title\">{{ headerTitle() }}</div>\r\n }\r\n @if (headerMeta()) {\r\n <div class=\"modal-meta\">{{ headerMeta() }}</div>\r\n }\r\n <ng-content select=\"[header-main]\"></ng-content>\r\n </div>\r\n \r\n <!-- Close button (in header) -->\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 [attr.aria-label]=\"closeButtonLabel()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Absolute close button (when header is hidden) -->\r\n @if (!shouldShowHeader()) {\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-absolute\"\r\n [attr.aria-label]=\"closeButtonLabel()\"\r\n />\r\n }\r\n\r\n <!-- Content Container -->\r\n <div class=\"modal-content-container\">\r\n <!-- Custom Loading State Slot - always present -->\r\n <div class=\"custom-loading-slot\" [class.state-hidden]=\"!(loading() && hasCustomLoadingState)\">\r\n <ng-content select=\"[loading-state]\"></ng-content>\r\n </div>\r\n \r\n <!-- Default Loading State -->\r\n @if (loading() && !hasCustomLoadingState) {\r\n <div class=\"modal-loading-state\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">Loading...</p>\r\n </div>\r\n }\r\n \r\n <!-- Custom Error State Slot - always present -->\r\n <div class=\"custom-error-slot\" [class.state-hidden]=\"!(error() && !loading() && hasCustomErrorState)\">\r\n <ng-content select=\"[error-state]\"></ng-content>\r\n </div>\r\n \r\n <!-- Default Error State -->\r\n @if (error() && !loading() && !hasCustomErrorState) {\r\n <div class=\"modal-error-state\">\r\n <ds-icon name=\"remixErrorWarningLine\" size=\"48px\" [style.color]=\"'var(--color-destructive-base)'\" />\r\n <h3 class=\"error-state-title\">Error</h3>\r\n <p class=\"error-state-description\">{{ error() }}</p>\r\n </div>\r\n }\r\n \r\n <!-- Main content - always rendered but hidden when loading/error -->\r\n <div class=\"modal-main-content\" [class.content-hidden]=\"loading() || !!error()\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n </div>\r\n </ion-content>\r\n\r\n <!-- Fixed Bottom Component / Footer (slides with keyboard) -->\r\n <div class=\"modal-fixed-bottom\" [class.bottom-hidden]=\"!hasFixedBottom() || loading() || error()\">\r\n <ng-content select=\"[fixed-bottom]\"></ng-content>\r\n <ng-content select=\"[footer]\"></ng-content>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileModalBaseComponent extends MobileModalBase implements AfterContentInit {\r\n /**\r\n * Reference to ion-content for keyboard handling\r\n */\r\n @ViewChild(IonContent, { read: IonContent }) override ionContent?: IonContent = undefined;\r\n \r\n /**\r\n * Control header visibility\r\n * - true: Always show header\r\n * - false: Never show header (close button becomes absolute)\r\n * - 'auto' (default): Auto-detect based on header content\r\n */\r\n showHeader = input<boolean | 'auto'>('auto');\r\n \r\n /**\r\n * Detect if custom loading state is provided\r\n */\r\n @ContentChild('[loading-state]', { read: ElementRef }) customLoadingState?: ElementRef;\r\n \r\n /**\r\n * Detect if custom error state is provided\r\n */\r\n @ContentChild('[error-state]', { read: ElementRef }) customErrorState?: ElementRef;\r\n \r\n /**\r\n * Detect if header leading content is provided\r\n */\r\n @ContentChild('[header-leading]', { read: ElementRef }) headerLeading?: ElementRef;\r\n \r\n /**\r\n * Detect if header main content is provided\r\n */\r\n @ContentChild('[header-main]', { read: ElementRef }) headerMain?: ElementRef;\r\n \r\n /**\r\n * Flag to track if content has been initialized\r\n */\r\n hasCustomLoadingState = false;\r\n hasCustomErrorState = false;\r\n \r\n constructor(private cdr: ChangeDetectorRef) {\r\n super();\r\n }\r\n \r\n ngAfterContentInit(): void {\r\n // Check for content after content has been initialized\r\n this.hasCustomLoadingState = !!this.customLoadingState;\r\n this.hasCustomErrorState = !!this.customErrorState;\r\n \r\n // Trigger change detection to update the view\r\n this.cdr.detectChanges();\r\n }\r\n \r\n /**\r\n * Determine if header should be shown based on showHeader input and content detection\r\n */\r\n shouldShowHeader(): boolean {\r\n const showHeaderValue = this.showHeader();\r\n \r\n // Explicit override\r\n if (showHeaderValue === true) return true;\r\n if (showHeaderValue === false) return false;\r\n \r\n // Auto-detect: show header if there's any header content\r\n return !!(\r\n this.headerTitle() || \r\n this.headerMeta() || \r\n this.hasContentInSlot(this.headerLeading) ||\r\n this.hasContentInSlot(this.headerMain)\r\n );\r\n }\r\n \r\n /**\r\n * Check if a content child slot has actual content\r\n */\r\n private hasContentInSlot(slot?: ElementRef): boolean {\r\n if (!slot) return false;\r\n const element = slot.nativeElement;\r\n return element && (\r\n element.childNodes.length > 0 || \r\n element.textContent?.trim().length > 0\r\n );\r\n }\r\n}\r\n","import { Component, signal, computed, CUSTOM_ELEMENTS_SCHEMA, Input, ViewChild, ElementRef, OnInit, AfterViewInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { Keyboard } from '@capacitor/keyboard';\r\nimport { DsIconComponent, DsIconButtonComponent } 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\nimport { DsMobileModalBaseComponent } from '../modal-base/ds-mobile-modal-base';\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 DsIconComponent,\r\n DsIconButtonComponent,\r\n DsAvatarComponent,\r\n PostTextComponent,\r\n PostMediaComponent,\r\n ActionLikeComponent,\r\n ActionCommentComponent,\r\n DsMobileCommentComponent,\r\n DsMobileModalBaseComponent,\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-common.css',\r\n './ds-mobile-post-detail-modal.css'\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ds-mobile-modal-base\r\n [loading]=\"loading\"\r\n [error]=\"error\"\r\n [headerTitle]=\"post().authorName\"\r\n [headerMeta]=\"post().authorRole + ' · ' + post().timestamp\"\r\n [hasFixedBottom]=\"true\"\r\n [enableKeyboardHandling]=\"true\"\r\n closeButtonLabel=\"Luk opslag\">\r\n \r\n <!-- Header Avatar -->\r\n <ds-avatar \r\n header-leading\r\n [initials]=\"post().avatarInitials || ''\"\r\n [type]=\"post().avatarType || 'initials'\"\r\n [src]=\"post().avatarSrc || ''\"\r\n size=\"md\"\r\n />\r\n \r\n <!-- Post Content (main content slot) -->\r\n <div class=\"post-detail-container\">\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 </div>\r\n </div>\r\n \r\n <!-- Fixed comment composer -->\r\n <div fixed-bottom>\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 </ds-mobile-modal-base>\r\n `\r\n})\r\nexport class DsMobilePostDetailModalComponent implements OnInit, AfterViewInit {\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 // State management inputs (passed to modal base)\r\n @Input() loading: boolean = false;\r\n @Input() error: string | undefined;\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 // 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(\r\n private lightbox: DsMobileLightboxService,\r\n private bottomSheet: DsMobileBottomSheetService\r\n ) {}\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\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 /**\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 // Note: close() method is inherited from MobileModalBase\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, Type } from '@angular/core';\r\nimport { ModalController, ModalOptions as IonicModalOptions } from '@ionic/angular/standalone';\r\n\r\n/**\r\n * BaseModalService\r\n *\r\n * Abstract base class for all modal services in the application.\r\n * Enforces consistent modal configuration and presentation across all modals.\r\n *\r\n * **Features:**\r\n * - Standardized modal presentation (stacked effect with gap at top)\r\n * - Consistent backdrop and dismissal behavior\r\n * - Automatic safe area handling\r\n * - Native iOS-style animations\r\n *\r\n * **Why use this:**\r\n * - Ensures all modals have the same look and feel\r\n * - Prevents inconsistencies in modal configuration\r\n * - Single source of truth for modal settings\r\n * - Makes it impossible to forget critical configuration\r\n *\r\n * @example\r\n * ```typescript\r\n * @Injectable({ providedIn: 'root' })\r\n * export class MyModalService extends BaseModalService {\r\n * async open(data: MyData) {\r\n * const modal = await this.createModal(\r\n * MyModalComponent,\r\n * { data }\r\n * );\r\n * await modal.present();\r\n * }\r\n * }\r\n * ```\r\n */\r\n@Injectable()\r\nexport abstract class BaseModalService {\r\n constructor(protected modalController: ModalController) {}\r\n\r\n /**\r\n * Create a modal with standardized configuration\r\n *\r\n * This method enforces consistent modal behavior across the app:\r\n * - Uses 'ds-modal-base' CSS class for consistent styling\r\n * - iOS mode for native feel\r\n * - presentingElement for stacked modal effect\r\n * - Standard backdrop and dismissal settings\r\n *\r\n * @param component The component to display in the modal\r\n * @param componentProps Props to pass to the component\r\n * @param customOptions Optional overrides for specific modal needs\r\n * @returns Promise resolving to the created modal\r\n *\r\n * @example\r\n * ```typescript\r\n * const modal = await this.createModal(\r\n * PostDetailComponent,\r\n * { postId: '123', loading: false }\r\n * );\r\n * await modal.present();\r\n * ```\r\n */\r\n protected async createModal<T>(\r\n component: Type<T>,\r\n componentProps?: Record<string, any>,\r\n customOptions?: Partial<IonicModalOptions>\r\n ): Promise<HTMLIonModalElement> {\r\n return await this.modalController.create({\r\n component,\r\n componentProps,\r\n // Standard configuration for all modals\r\n cssClass: 'ds-modal-base',\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 // Allow service-specific overrides if needed\r\n ...customOptions,\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 * @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","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobilePostDetailModalComponent, PostDetailData } from './ds-mobile-post-detail-modal';\r\nimport { BaseModalService } from '../../services/base-modal.service';\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 extends BaseModalService {\r\n constructor(modalController: ModalController) {\r\n super(modalController);\r\n }\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.createModal(\r\n DsMobilePostDetailModalComponent,\r\n {\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 {\r\n keyboardClose: true, // Keep keyboard close behavior for this modal\r\n }\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 * 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 { 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 } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\n/**\r\n * DsMobileSystemMessageBannerComponent\r\n * \r\n * Full-width centered banner component for displaying system messages in chat conversations.\r\n * Uses the same text styling as message bubbles for consistency.\r\n * \r\n * Features:\r\n * - Full-width centered layout\r\n * - Subtle background with theming support\r\n * - Same typography as message bubbles\r\n * - Optional icon support\r\n * \r\n * Common use cases:\r\n * - Inquiry status updates (\"Your inquiry has been assigned to...\")\r\n * - System notifications (\"This inquiry is marked as resolved\")\r\n * - Auto-replies (\"We aim to respond within 24 hours...\")\r\n * - Time/date separators\r\n * \r\n * @example\r\n * ```html\r\n * <!-- Simple system message -->\r\n * <ds-mobile-system-message-banner\r\n * [message]=\"'Ricki Meihlen har overtaget din henvendelse og vil kontakte dig snart.'\">\r\n * </ds-mobile-system-message-banner>\r\n * \r\n * <!-- With icon -->\r\n * <ds-mobile-system-message-banner\r\n * [message]=\"'Vi bestræber os på at svare inden for 24 timer på hverdage.'\"\r\n * [iconName]=\"'remixInformationLine'\">\r\n * </ds-mobile-system-message-banner>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-system-message-banner',\r\n standalone: true,\r\n imports: [CommonModule],\r\n styles: [`\r\n :host {\r\n display: block;\r\n width: 100%;\r\n padding: 12px 0;\r\n }\r\n \r\n .system-message-container {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n width: 100%;\r\n padding: 0 16px;\r\n }\r\n \r\n .system-message-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n padding: 8px 16px;\r\n background: var(--color-background-neutral-secondary, #f5f5f5);\r\n border-radius: 16px;\r\n max-width: 85%;\r\n text-align: center;\r\n }\r\n \r\n .system-message-icon {\r\n flex-shrink: 0;\r\n width: 16px;\r\n height: 16px;\r\n color: var(--color-text-tertiary, #a0a0a0);\r\n }\r\n \r\n .system-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 color: var(--color-text-secondary, #666666);\r\n margin: 0;\r\n }\r\n `],\r\n template: `\r\n <div class=\"system-message-container\">\r\n <div class=\"system-message-content\">\r\n @if (iconName()) {\r\n <span class=\"system-message-icon\">\r\n <!-- Icon slot - you can add ds-icon component here if needed -->\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z\"/>\r\n </svg>\r\n </span>\r\n }\r\n <p class=\"system-message-text\">{{ message() }}</p>\r\n </div>\r\n </div>\r\n `\r\n})\r\nexport class DsMobileSystemMessageBannerComponent {\r\n /**\r\n * System message text to display\r\n */\r\n message = input.required<string>();\r\n \r\n /**\r\n * Optional icon name (currently using inline SVG for info icon)\r\n * Can be extended to support full icon library integration\r\n */\r\n iconName = input<string>('');\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 CUSTOM_ELEMENTS_SCHEMA,\r\n computed\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsMobileMessageComposerComponent } from '../message-composer';\r\nimport { DsMobileMessageBubbleComponent, ChatAttachment } from '../message-bubble';\r\nimport { DsAvatarWithBadgeComponent } from '../avatar-with-badge';\r\nimport { DsMobileModalBaseComponent } from '../modal-base/ds-mobile-modal-base';\r\nimport { DsMobileCardInlineFileComponent } from '../card-inline-file';\r\nimport { type AttachmentData } from '../attachment-preview';\r\nimport { DsMobileLightboxService, LightboxAuthor, LightboxImage } from '../lightbox';\r\nimport { DsMobileSystemMessageBannerComponent } from '../system-message-banner';\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: Date;\r\n avatarInitials?: string;\r\n avatarType?: 'initials' | 'photo' | 'icon';\r\n avatarSrc?: string;\r\n isOwnMessage: boolean;\r\n attachments?: ChatAttachment[];\r\n fileAttachments?: AttachmentData[];\r\n}\r\n\r\n/**\r\n * Message group interface for grouped timestamp display\r\n */\r\ninterface MessageGroup {\r\n timestamp: Date;\r\n displayTimestamp: string;\r\n messages: ChatMessage[];\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: 'u-123',\r\n * name: 'Ricki Meihlen',\r\n * role: 'Inquiry assignee',\r\n * avatarInitials: 'RM',\r\n * avatarType: 'initials'\r\n * },\r\n * currentUserId: 'u-456',\r\n * currentUserInitials: 'SD',\r\n * currentUserAvatarType: 'initials',\r\n * autoFocus: true,\r\n * messages: [\r\n * {\r\n * id: 'm-1',\r\n * content: 'We have received your case. Please see the attached photo.',\r\n * senderId: 'u-123',\r\n * senderName: 'Ricki Meihlen',\r\n * senderRole: 'Case worker',\r\n * timestamp: '12:34',\r\n * isOwnMessage: false,\r\n * avatarInitials: 'RM',\r\n * avatarType: 'initials',\r\n * attachments: [\r\n * {\r\n * id: 'a-1',\r\n * type: 'image',\r\n * url: 'https://example.com/photo.jpg',\r\n * name: 'photo.jpg',\r\n * thumbnail: 'https://example.com/photo_thumb.jpg'\r\n * },\r\n * {\r\n * id: 'a-2',\r\n * type: 'pdf',\r\n * url: 'https://example.com/report.pdf',\r\n * name: 'report.pdf'\r\n * }\r\n * ]\r\n * },\r\n * {\r\n * id: 'm-2',\r\n * content: 'Thanks — I will take a look.',\r\n * senderId: 'u-456',\r\n * senderName: 'You',\r\n * timestamp: '12:36',\r\n * isOwnMessage: true,\r\n * avatarInitials: 'SD',\r\n * avatarType: 'initials'\r\n * }\r\n * ]\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 DsAvatarWithBadgeComponent,\r\n DsMobileMessageComposerComponent,\r\n DsMobileMessageBubbleComponent,\r\n DsMobileModalBaseComponent,\r\n DsMobileCardInlineFileComponent,\r\n DsMobileSystemMessageBannerComponent\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-common.css',\r\n './ds-mobile-chat-modal.css'\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ds-mobile-modal-base\r\n [loading]=\"loading\"\r\n [error]=\"error\"\r\n [headerTitle]=\"participant().name\"\r\n [headerMeta]=\"participant().role || ''\"\r\n [hasFixedBottom]=\"true\"\r\n [enableKeyboardHandling]=\"true\"\r\n closeButtonLabel=\"Luk chat\">\r\n\r\n <!-- Header Avatar -->\r\n <ds-avatar-with-badge\r\n header-leading\r\n [initials]=\"participant().avatarInitials || ''\"\r\n [type]=\"participant().avatarType || 'initials'\"\r\n [src]=\"participant().avatarSrc || ''\"\r\n size=\"md\"\r\n />\r\n\r\n <!-- Messages Container (main content slot) -->\r\n <div class=\"chat-messages-container\">\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\">Ingen beskeder endnu</h3>\r\n <p class=\"empty-state-description\">Start samtalen ved at sende en besked</p>\r\n </div>\r\n } @else {\r\n @for (group of messageGroups(); track group.timestamp) {\r\n <!-- Timestamp Header -->\r\n <div class=\"timestamp-header\">\r\n <span class=\"timestamp-text\">{{ group.displayTimestamp }}</span>\r\n </div>\r\n \r\n <!-- System message example (shown after first timestamp) -->\r\n @if ($first) {\r\n <ds-mobile-system-message-banner\r\n [message]=\"participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'\">\r\n </ds-mobile-system-message-banner>\r\n }\r\n \r\n @for (message of group.messages; track message.id) {\r\n <!-- Only show bubble if has content -->\r\n @if (message.content.trim()) {\r\n <ds-mobile-message-bubble\r\n [content]=\"message.content\"\r\n [isOwnMessage]=\"message.isOwnMessage\"\r\n [timestamp]=\"formatMessageTimestamp(message.timestamp)\"\r\n [showTimestamp]=\"selectedMessageId() === message.id\"\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 (messageClick)=\"handleMessageClick(message.id)\"\r\n (attachmentClick)=\"handleAttachmentClick($event)\"\r\n (longPress)=\"handleMessageLongPress(message)\">\r\n </ds-mobile-message-bubble>\r\n }\r\n \r\n <!-- File attachments displayed below message bubble -->\r\n @if (message.fileAttachments && message.fileAttachments.length > 0) {\r\n <div class=\"message-file-attachments\" [class.own-message]=\"message.isOwnMessage\">\r\n @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {\r\n <!-- Show inline image preview for image attachments -->\r\n @if (fileAttachment.type === 'image') {\r\n <div class=\"message-image-attachment\" (click)=\"handleImageClick(fileAttachment, message)\">\r\n <img \r\n [src]=\"fileAttachment.src\" \r\n [alt]=\"fileAttachment.name || 'Image'\" \r\n class=\"inline-image\">\r\n </div>\r\n } @else {\r\n <!-- Show file card for non-image attachments -->\r\n <ds-mobile-card-inline-file\r\n [fileName]=\"fileAttachment.name || 'Unknown file'\"\r\n [fileSize]=\"fileAttachment.size || ''\"\r\n [variant]=\"getFileVariant(fileAttachment.type)\"\r\n [layout]=\"'compact'\"\r\n (fileClick)=\"handleFileAttachmentClick(fileAttachment)\">\r\n </ds-mobile-card-inline-file>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Fixed message composer -->\r\n <div fixed-bottom>\r\n <ds-mobile-message-composer\r\n [avatarInitials]=\"currentUserInitials()\"\r\n [avatarType]=\"currentUserAvatarType()\"\r\n [avatarSrc]=\"currentUserAvatarSrc()\"\r\n [placeholder]=\"'Skriv en besked...'\"\r\n [autoFocus]=\"autoFocus()\"\r\n [showAttachmentButton]=\"true\"\r\n (messageSent)=\"handleMessageSent($event)\"\r\n (attachmentClicked)=\"handleComposerAttachmentClick()\">\r\n </ds-mobile-message-composer>\r\n </div>\r\n </ds-mobile-modal-base>\r\n `\r\n})\r\nexport class DsMobileChatModalComponent implements OnInit, AfterViewInit {\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 /**\r\n * Selected message ID for showing timestamp\r\n */\r\n selectedMessageId = signal<string | null>(null);\r\n \r\n /**\r\n * Timeout for auto-hiding timestamp\r\n */\r\n private timestampTimeout?: ReturnType<typeof setTimeout>;\r\n \r\n /**\r\n * Computed signal for grouped messages with timestamp headers\r\n */\r\n messageGroups = computed(() => {\r\n return this.groupMessagesByTime(this.messages(), 5);\r\n });\r\n \r\n constructor(private lightboxService: DsMobileLightboxService) {}\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 }, 500);\r\n }\r\n }\r\n \r\n /**\r\n * Scroll to bottom of messages\r\n */\r\n private async scrollToBottom(): Promise<void> {\r\n const ionContent = document.querySelector('ds-mobile-chat-modal ion-content');\r\n if (ionContent) {\r\n await (ionContent as any).scrollToBottom(300);\r\n }\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; attachments?: AttachmentData[] }): 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(),\r\n isOwnMessage: true,\r\n avatarInitials: this.currentUserInitials(),\r\n avatarType: this.currentUserAvatarType(),\r\n avatarSrc: this.currentUserAvatarSrc(),\r\n fileAttachments: event.attachments || []\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, event.attachments);\r\n }\r\n\r\n /**\r\n * Handle attachment click\r\n */\r\n handleAttachmentClick(attachment: ChatAttachment): void {\r\n if (attachment.type !== 'image') {\r\n if (attachment.url) {\r\n window.open(attachment.url, '_blank', 'noopener,noreferrer');\r\n }\r\n return;\r\n }\r\n\r\n const msgs = this.messages();\r\n\r\n const allImages: Array<{ msg: ChatMessage; att: ChatAttachment }> = [];\r\n for (const m of msgs) {\r\n for (const att of m.attachments ?? []) {\r\n if (att.type === 'image') {\r\n allImages.push({ msg: m, att });\r\n }\r\n }\r\n }\r\n\r\n const initialIndex = Math.max(\r\n 0,\r\n allImages.findIndex((x) => x.att.id === attachment.id)\r\n );\r\n\r\n const images: LightboxImage[] = allImages.map((x) => ({\r\n type: 'image',\r\n src: x.att.url,\r\n title: x.att.name,\r\n alt: x.att.name,\r\n thumbnail: x.att.thumbnail,\r\n }));\r\n\r\n const ownerMessage = allImages[initialIndex]?.msg;\r\n\r\n const author: LightboxAuthor | undefined = ownerMessage\r\n ? {\r\n name: ownerMessage.senderName,\r\n role: ownerMessage.senderRole,\r\n timestamp: this.formatMessageTimestamp(ownerMessage.timestamp),\r\n avatarInitials: ownerMessage.avatarInitials,\r\n avatarSrc: ownerMessage.avatarSrc,\r\n avatarType: ownerMessage.avatarType === 'photo' || ownerMessage.avatarType === 'initials' ? ownerMessage.avatarType : undefined,\r\n }\r\n : undefined;\r\n\r\n this.lightboxService.openImages({\r\n images,\r\n author,\r\n initialIndex,\r\n enableZoom: true,\r\n enableSwipe: true,\r\n showControls: true,\r\n showInfo: true,\r\n animation: 'fade',\r\n });\r\n }\r\n\r\n /**\r\n * Handle composer attachment button click\r\n */\r\n handleComposerAttachmentClick(): void {\r\n console.log('[ChatModal] Composer attachment button clicked');\r\n // In a real app, you would open a file picker or show attachment options\r\n }\r\n \r\n /**\r\n * Get file variant for card-inline-file component\r\n */\r\n getFileVariant(type: string): 'pdf' | 'doc' {\r\n return type === 'pdf' ? 'pdf' : 'doc';\r\n }\r\n \r\n /**\r\n * Handle file attachment click\r\n */\r\n handleFileAttachmentClick(fileAttachment: AttachmentData): void {\r\n console.log('[ChatModal] File attachment clicked:', fileAttachment);\r\n // In a real app, you would open the file viewer\r\n }\r\n \r\n /**\r\n * Handle image attachment click - opens lightbox\r\n */\r\n async handleImageClick(attachment: AttachmentData, message: ChatMessage): Promise<void> {\r\n await this.lightboxService.openImages({\r\n images: [{\r\n type: 'image',\r\n src: attachment.src,\r\n title: attachment.name || 'Image',\r\n alt: attachment.name || 'Chat image'\r\n }],\r\n author: {\r\n name: message.senderName,\r\n role: message.senderRole,\r\n avatarInitials: message.avatarInitials,\r\n avatarType: message.avatarType === 'initials' ? 'initials' : 'photo',\r\n avatarSrc: message.avatarSrc,\r\n timestamp: this.formatMessageTimestamp(message.timestamp)\r\n },\r\n initialIndex: 0,\r\n enableZoom: true,\r\n showControls: false,\r\n enableSwipe: false,\r\n showInfo: false,\r\n showActions: false\r\n });\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 * Handle message click to show/hide timestamp\r\n */\r\n handleMessageClick(messageId: string): void {\r\n // Clear existing timeout\r\n if (this.timestampTimeout) {\r\n clearTimeout(this.timestampTimeout);\r\n }\r\n \r\n // Toggle timestamp - if clicking same message, hide it; otherwise show new one\r\n this.selectedMessageId.update(current => \r\n current === messageId ? null : messageId\r\n );\r\n \r\n // Auto-hide after 3 seconds if showing\r\n if (this.selectedMessageId() === messageId) {\r\n this.timestampTimeout = setTimeout(() => {\r\n this.selectedMessageId.set(null);\r\n }, 3000);\r\n }\r\n }\r\n \r\n /**\r\n * Format message timestamp for display (EU 24-hour format, Danish)\r\n */\r\n formatMessageTimestamp(date: Date): string {\r\n return date.toLocaleTimeString('da-DK', { \r\n hour: '2-digit', \r\n minute: '2-digit',\r\n hour12: false \r\n });\r\n }\r\n \r\n /**\r\n * Group messages by time threshold\r\n * Messages within the threshold and on the same day are grouped together\r\n */\r\n private groupMessagesByTime(messages: ChatMessage[], thresholdMinutes: number): MessageGroup[] {\r\n const groups: MessageGroup[] = [];\r\n let currentGroup: MessageGroup | null = null;\r\n \r\n messages.forEach((message) => {\r\n const messageDate = message.timestamp;\r\n \r\n // Start a new group if:\r\n // 1. It's the first message\r\n // 2. More than threshold minutes have passed since last message\r\n // 3. Date changed (new day)\r\n if (!currentGroup || this.shouldStartNewGroup(currentGroup.timestamp, messageDate, thresholdMinutes)) {\r\n currentGroup = {\r\n timestamp: messageDate,\r\n displayTimestamp: this.formatGroupTimestamp(messageDate),\r\n messages: []\r\n };\r\n groups.push(currentGroup);\r\n }\r\n \r\n currentGroup.messages.push(message);\r\n });\r\n \r\n return groups;\r\n }\r\n \r\n /**\r\n * Determine if a new message group should be started\r\n */\r\n private shouldStartNewGroup(lastTime: Date, currentTime: Date, thresholdMinutes: number): boolean {\r\n const diffMinutes = (currentTime.getTime() - lastTime.getTime()) / (1000 * 60);\r\n \r\n // New group if different day\r\n if (lastTime.toDateString() !== currentTime.toDateString()) {\r\n return true;\r\n }\r\n \r\n // New group if threshold exceeded\r\n return diffMinutes > thresholdMinutes;\r\n }\r\n \r\n /**\r\n * Format group timestamp header with smart date display\r\n * Uses 24-hour EU time format with Danish locale\r\n */\r\n private formatGroupTimestamp(date: Date): string {\r\n const now = new Date();\r\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\r\n const yesterday = new Date(today);\r\n yesterday.setDate(yesterday.getDate() - 1);\r\n \r\n const messageDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());\r\n \r\n // Format time in 24-hour EU format\r\n const timeStr = date.toLocaleTimeString('da-DK', { \r\n hour: '2-digit', \r\n minute: '2-digit',\r\n hour12: false \r\n });\r\n \r\n // Today: \"14:34\"\r\n if (messageDate.getTime() === today.getTime()) {\r\n return timeStr;\r\n }\r\n \r\n // Yesterday: \"I går, 14:34\"\r\n if (messageDate.getTime() === yesterday.getTime()) {\r\n return `I går, ${timeStr}`;\r\n }\r\n \r\n // This week: \"Mandag, 14:34\"\r\n const daysAgo = Math.floor((today.getTime() - messageDate.getTime()) / (1000 * 60 * 60 * 24));\r\n if (daysAgo < 7) {\r\n return date.toLocaleDateString('da-DK', { weekday: 'long' }) + `, ${timeStr}`;\r\n }\r\n \r\n // Older: \"15. jan, 14:34\" or \"20. dec. 2024, 14:34\" if different year\r\n const dateFormat: Intl.DateTimeFormatOptions = { \r\n month: 'short', \r\n day: 'numeric' \r\n };\r\n \r\n if (date.getFullYear() !== now.getFullYear()) {\r\n dateFormat.year = 'numeric';\r\n }\r\n \r\n return date.toLocaleDateString('da-DK', dateFormat) + `, ${timeStr}`;\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\nimport { BaseModalService } from '../../services/base-modal.service';\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 extends BaseModalService {\r\n constructor(modalController: ModalController) {\r\n super(modalController);\r\n }\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.createModal(\r\n DsMobileChatModalComponent,\r\n {\r\n chatData: chatData,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n {\r\n keyboardClose: true, // Keep keyboard close behavior for this modal\r\n }\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\r\n\r\n\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 CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { Camera, CameraResultType, CameraSource } from '@capacitor/camera';\r\nimport { \r\n DsButtonComponent,\r\n DsTextareaComponent,\r\n DsIconButtonComponent\r\n} from '@propbinder/design-system';\r\nimport { DsMobileModalBaseComponent } from '../modal-base/ds-mobile-modal-base';\r\nimport { DsMobileAttachmentPreviewComponent, type AttachmentData, type AttachmentFileType } from '../attachment-preview';\r\n\r\n/**\r\n * Photo interface for inquiry (deprecated - use AttachmentData)\r\n * @deprecated Use AttachmentData from attachment-preview component instead\r\n */\r\nexport interface InquiryPhoto {\r\n id: string;\r\n src: string;\r\n alt?: string;\r\n}\r\n\r\n/**\r\n * New inquiry form data\r\n */\r\nexport interface NewInquiryData {\r\n title: string;\r\n description: string;\r\n attachments: AttachmentData[];\r\n category?: string;\r\n}\r\n\r\n/**\r\n * DsMobileNewInquiryModalComponent\r\n * \r\n * Modal component for creating new inquiries.\r\n * Uses ds-mobile-modal-base for consistent layout and behavior.\r\n * \r\n * Features:\r\n * - Title and description fields\r\n * - Photo upload with preview\r\n * - Submit button at bottom\r\n * - Form validation\r\n * - Camera/photo picker integration\r\n * \r\n * This component is typically not used directly - use DsMobileNewInquiryModalService instead.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Don't instantiate directly - use the service:\r\n * constructor(private inquiryModal: DsMobileNewInquiryModalService) {}\r\n * \r\n * createInquiry() {\r\n * this.inquiryModal.open({\r\n * onSubmit: (data) => console.log('Inquiry created:', data)\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-new-inquiry-modal',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n DsButtonComponent,\r\n DsTextareaComponent,\r\n DsIconButtonComponent,\r\n DsMobileModalBaseComponent,\r\n DsMobileAttachmentPreviewComponent\r\n ],\r\n styleUrls: [\r\n '../shared/mobile-common.css',\r\n './ds-mobile-new-inquiry-modal.css'\r\n ],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ds-mobile-modal-base\r\n [loading]=\"loading\"\r\n [error]=\"error\"\r\n [showHeader]=\"false\"\r\n [hasFixedBottom]=\"true\"\r\n [enableKeyboardHandling]=\"true\"\r\n closeButtonLabel=\"Close\">\r\n\r\n <!-- Form Content -->\r\n <div class=\"inquiry-form\">\r\n <!-- Title Field (Large Ghost Textarea) -->\r\n <ds-textarea\r\n #titleInput\r\n [(ngModel)]=\"title\"\r\n [ghost]=\"true\"\r\n [required]=\"true\"\r\n [rows]=\"1\"\r\n placeholder=\"Name your inquiry\"\r\n class=\"inquiry-title-input ghost-input-clean\"\r\n (valueChange)=\"handleTitleChange($event)\"\r\n />\r\n\r\n <!-- Description Field (Ghost Textarea) -->\r\n <ds-textarea\r\n [(ngModel)]=\"description\"\r\n [ghost]=\"true\"\r\n [rows]=\"1\"\r\n placeholder=\"Tell us what this inquiry is about...\"\r\n class=\"ghost-input-clean\"\r\n (valueChange)=\"validateForm()\"\r\n />\r\n </div>\r\n\r\n <!-- Fixed Bottom Container (Slides with keyboard) -->\r\n <div footer class=\"fixed-bottom-container\">\r\n <!-- Attachment Previews (if any) -->\r\n @if (attachments().length > 0) {\r\n <div class=\"attachment-previews-section\">\r\n <div class=\"image-previews\">\r\n @for (attachment of attachments(); track attachment.id) {\r\n <ds-mobile-attachment-preview\r\n [attachment]=\"attachment\"\r\n (remove)=\"removeAttachment($event)\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Submit Actions Container -->\r\n <div class=\"submit-container\">\r\n <div class=\"submit-content\">\r\n <!-- Upload Actions (Left) -->\r\n <div class=\"upload-actions\">\r\n <ds-icon-button\r\n icon=\"remixImageLine\"\r\n variant=\"secondary\"\r\n size=\"md\"\r\n (clicked)=\"addPhoto()\"\r\n [disabled]=\"attachments().length >= 6\"\r\n aria-label=\"Add photo\">\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 [disabled]=\"attachments().length >= 6\"\r\n aria-label=\"Add attachment\">\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\r\n <!-- Submit Button (Right) -->\r\n <ds-button\r\n variant=\"primary\"\r\n size=\"lg\"\r\n [disabled]=\"!isFormValid() || isSubmitting()\"\r\n (clicked)=\"handleSubmit()\">\r\n Submit\r\n </ds-button>\r\n </div>\r\n </div>\r\n </div>\r\n </ds-mobile-modal-base>\r\n `\r\n})\r\nexport class DsMobileNewInquiryModalComponent implements OnInit, AfterViewInit {\r\n @ViewChild('titleInput', { read: ElementRef }) titleInputRef?: ElementRef<HTMLElement>;\r\n @ViewChild('titleInput') titleInput?: DsTextareaComponent;\r\n @ViewChild('fileInput') fileInput?: ElementRef<HTMLInputElement>;\r\n\r\n /**\r\n * Loading state for the modal\r\n */\r\n @Input() loading: boolean = false;\r\n\r\n /**\r\n * Error message to display\r\n */\r\n @Input() error?: string;\r\n\r\n /**\r\n * Callback function when form is submitted\r\n */\r\n @Input() onSubmit?: (data: NewInquiryData) => void | Promise<void>;\r\n\r\n /**\r\n * Form title field\r\n */\r\n title = '';\r\n\r\n /**\r\n * Form description field\r\n */\r\n description = '';\r\n\r\n /**\r\n * Attachments array (replaces photos)\r\n */\r\n attachments = signal<AttachmentData[]>([]);\r\n\r\n /**\r\n * Form validation state\r\n */\r\n isFormValid = signal<boolean>(false);\r\n\r\n /**\r\n * Submitting state\r\n */\r\n isSubmitting = signal<boolean>(false);\r\n\r\n ngOnInit(): void {\r\n console.log('[NewInquiryModal] Component initialized');\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n // Setup auto-resize for title textarea\r\n setTimeout(() => {\r\n this.autoResizeTitleTextarea();\r\n \r\n // Focus the title textarea after view initialization to trigger keyboard on iOS\r\n if (this.titleInputRef) {\r\n const textareaElement = this.titleInputRef.nativeElement.querySelector('textarea');\r\n if (textareaElement) {\r\n textareaElement.focus();\r\n }\r\n }\r\n }, 300);\r\n }\r\n\r\n /**\r\n * Auto-resize the title textarea based on content\r\n */\r\n private autoResizeTitleTextarea(): void {\r\n if (!this.titleInputRef) return;\r\n \r\n // Access the native textarea element\r\n const textareaElement = this.titleInputRef.nativeElement.querySelector('textarea');\r\n if (textareaElement) {\r\n textareaElement.style.height = 'auto';\r\n textareaElement.style.height = textareaElement.scrollHeight + 'px';\r\n }\r\n }\r\n\r\n /**\r\n * Handle title change with auto-resize\r\n */\r\n handleTitleChange(value: string): void {\r\n this.validateForm();\r\n this.autoResizeTitleTextarea();\r\n }\r\n\r\n /**\r\n * Validate form fields\r\n */\r\n validateForm(): void {\r\n const isValid = this.title.trim().length > 0 && this.description.trim().length > 0;\r\n this.isFormValid.set(isValid);\r\n }\r\n\r\n /**\r\n * Add a new photo from camera/library\r\n */\r\n async addPhoto(): Promise<void> {\r\n if (this.attachments().length >= 6) {\r\n return;\r\n }\r\n\r\n try {\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\r\n });\r\n\r\n if (image.webPath) {\r\n const newAttachment: AttachmentData = {\r\n id: `photo-${Date.now()}`,\r\n src: image.webPath,\r\n type: 'image',\r\n name: `Photo ${this.attachments().length + 1}`\r\n };\r\n\r\n this.attachments.update(attachments => [...attachments, newAttachment]);\r\n }\r\n } catch (error) {\r\n console.error('[NewInquiryModal] Error adding photo:', error);\r\n // User cancelled or error occurred - just ignore\r\n }\r\n }\r\n\r\n /**\r\n * Remove an attachment\r\n */\r\n removeAttachment(attachmentId: string): void {\r\n this.attachments.update(attachments => attachments.filter(a => a.id !== attachmentId));\r\n }\r\n\r\n /**\r\n * Handle attachment button click\r\n */\r\n handleAddAttachment(): void {\r\n if (this.attachments().length >= 6) {\r\n return;\r\n }\r\n\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 /**\r\n * Detect file type from file name or mime type\r\n */\r\n private detectFileType(file: File): AttachmentFileType {\r\n const fileName = file.name.toLowerCase();\r\n const mimeType = file.type.toLowerCase();\r\n \r\n // Check if it's an image\r\n if (mimeType.startsWith('image/')) {\r\n return 'image';\r\n }\r\n \r\n // Check file extension\r\n if (fileName.endsWith('.pdf')) {\r\n return 'pdf';\r\n } else if (fileName.endsWith('.doc')) {\r\n return 'doc';\r\n } else if (fileName.endsWith('.docx')) {\r\n return 'docx';\r\n } else if (fileName.endsWith('.xls')) {\r\n return 'xls';\r\n } else if (fileName.endsWith('.xlsx')) {\r\n return 'xlsx';\r\n }\r\n \r\n return 'other';\r\n }\r\n\r\n /**\r\n * Format file size for display\r\n */\r\n private formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 B';\r\n const k = 1024;\r\n const sizes = ['B', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];\r\n }\r\n\r\n /**\r\n * Handle file selection from file input\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 return;\r\n }\r\n \r\n // Process each selected file (up to the limit)\r\n const remainingSlots = 6 - this.attachments().length;\r\n const filesToProcess = Array.from(files).slice(0, remainingSlots);\r\n \r\n filesToProcess.forEach(file => {\r\n const fileType = this.detectFileType(file);\r\n \r\n // Create a data URL for preview\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 const newAttachment: AttachmentData = {\r\n id: `file-${Date.now()}-${Math.random()}`,\r\n src: result,\r\n type: fileType,\r\n name: file.name,\r\n size: this.formatFileSize(file.size)\r\n };\r\n this.attachments.update(attachments => [...attachments, newAttachment]);\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 * Handle form submission\r\n */\r\n async handleSubmit(): Promise<void> {\r\n if (!this.isFormValid() || this.isSubmitting()) {\r\n return;\r\n }\r\n\r\n this.isSubmitting.set(true);\r\n\r\n try {\r\n const inquiryData: NewInquiryData = {\r\n title: this.title.trim(),\r\n description: this.description.trim(),\r\n attachments: this.attachments()\r\n };\r\n\r\n console.log('[NewInquiryModal] Submitting inquiry:', inquiryData);\r\n\r\n if (this.onSubmit) {\r\n await this.onSubmit(inquiryData);\r\n }\r\n\r\n // Success - modal will be closed by the service\r\n } catch (error) {\r\n console.error('[NewInquiryModal] Error submitting inquiry:', error);\r\n this.error = 'Failed to create inquiry. Please try again.';\r\n } finally {\r\n this.isSubmitting.set(false);\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ModalController } from '@ionic/angular/standalone';\r\nimport { DsMobileNewInquiryModalComponent, NewInquiryData } from './ds-mobile-new-inquiry-modal';\r\nimport { BaseModalService } from '../../services/base-modal.service';\r\n\r\n/**\r\n * Options for opening the new inquiry modal\r\n */\r\nexport interface NewInquiryModalOptions {\r\n /** Callback function when inquiry is submitted */\r\n onSubmit?: (data: NewInquiryData) => void | Promise<void>;\r\n /** Initial loading state */\r\n loading?: boolean;\r\n /** Initial error message */\r\n error?: string;\r\n}\r\n\r\n/**\r\n * DsMobileNewInquiryModalService\r\n * \r\n * Service for displaying the new inquiry creation modal.\r\n * Built on Ionic's modal system with native gestures and animations.\r\n * \r\n * Features:\r\n * - Full-screen modal with form\r\n * - Title and description inputs\r\n * - Photo upload with camera/gallery\r\n * - Form validation\r\n * - Submit handling\r\n * - Loading and error states\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor(private inquiryModal: DsMobileNewInquiryModalService) {}\r\n * \r\n * async createNewInquiry() {\r\n * await this.inquiryModal.open({\r\n * onSubmit: async (data) => {\r\n * console.log('Creating inquiry:', data);\r\n * // Call your API to create the inquiry\r\n * await this.apiService.createInquiry(data);\r\n * // Close the modal\r\n * await this.inquiryModal.close();\r\n * }\r\n * });\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DsMobileNewInquiryModalService extends BaseModalService {\r\n constructor(modalController: ModalController) {\r\n super(modalController);\r\n }\r\n\r\n /**\r\n * Open the new inquiry modal\r\n * \r\n * @param options Modal options including onSubmit callback\r\n * @returns Promise that resolves when the modal is presented\r\n */\r\n async open(options?: NewInquiryModalOptions): Promise<void> {\r\n console.log('[NewInquiryModal] Opening modal with options:', options);\r\n \r\n const modal = await this.createModal(\r\n DsMobileNewInquiryModalComponent,\r\n {\r\n onSubmit: options?.onSubmit,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n {\r\n keyboardClose: false, // Don't close on keyboard hide for this modal\r\n }\r\n );\r\n\r\n console.log('[NewInquiryModal] Modal created, presenting...');\r\n await modal.present();\r\n console.log('[NewInquiryModal] Modal presented');\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\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 OnInit,\r\n CUSTOM_ELEMENTS_SCHEMA\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\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\nimport { DsMobileModalBaseComponent } from '../modal-base/ds-mobile-modal-base';\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 DsMobileHandbookFolderMiniComponent,\r\n DsMobileCardInlineFileComponent,\r\n DsMobileCardInlineContactComponent,\r\n DsMobileSwiperComponent,\r\n DsMobileModalBaseComponent\r\n ],\r\n styleUrls: ['./ds-mobile-handbook-detail-modal.css'],\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n template: `\r\n <ds-mobile-modal-base\r\n [loading]=\"loading\"\r\n [error]=\"error\"\r\n [headerTitle]=\"handbook().title\"\r\n [headerMeta]=\"handbook().itemCount + ' emner'\"\r\n closeButtonLabel=\"Luk\">\r\n\r\n <!-- Header Folder Icon -->\r\n <ds-mobile-handbook-folder-mini\r\n header-leading\r\n [variant]=\"handbook().variant\"\r\n [iconName]=\"handbook().iconName\">\r\n </ds-mobile-handbook-folder-mini>\r\n\r\n <!-- Content (main content slot) -->\r\n <div class=\"handbook-detail-container\">\r\n @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 </ds-mobile-modal-base>\r\n `\r\n})\r\nexport class DsMobileHandbookDetailModalComponent implements OnInit {\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 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 * 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\nimport { BaseModalService } from '../../services/base-modal.service';\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 extends BaseModalService {\r\n constructor(modalController: ModalController) {\r\n super(modalController);\r\n }\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.createModal(\r\n DsMobileHandbookDetailModalComponent,\r\n {\r\n handbookData: handbookData,\r\n loading: options?.loading ?? false,\r\n error: options?.error\r\n },\r\n {\r\n keyboardClose: true, // Keep keyboard close behavior for this modal\r\n }\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","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","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 * DsMobileFabComponent\r\n * \r\n * Floating Action Button component for mobile interfaces.\r\n * A prominent circular button that floats above the content.\r\n * \r\n * Features:\r\n * - Configurable positioning (bottom-right, bottom-left, bottom-center)\r\n * - Uses design system theming variables\r\n * - Handles iOS safe areas\r\n * - Accessible with ARIA labels\r\n * - Smooth entrance animation\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-fab\r\n * icon=\"remixAddLine\"\r\n * [position]=\"'bottom-right'\"\r\n * (fabClick)=\"handleAddClick()\"\r\n * ariaLabel=\"Add new inquiry\">\r\n * </ds-mobile-fab>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-fab',\r\n standalone: true,\r\n imports: [CommonModule, DsIconButtonComponent],\r\n host: {\r\n '[class.fab-bottom-right]': 'position() === \"bottom-right\"',\r\n '[class.fab-bottom-left]': 'position() === \"bottom-left\"',\r\n '[class.fab-bottom-center]': 'position() === \"bottom-center\"'\r\n },\r\n template: `\r\n <div class=\"fab-container\">\r\n <ds-icon-button\r\n [icon]=\"icon()\"\r\n variant=\"primary\"\r\n [size]=\"size()\"\r\n [ariaLabel]=\"ariaLabel()\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"handleClick()\"\r\n class=\"fab-button\">\r\n </ds-icon-button>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n position: fixed;\r\n z-index: 1000;\r\n pointer-events: none;\r\n }\r\n\r\n .fab-container {\r\n position: relative;\r\n pointer-events: none;\r\n animation: fabEnter 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;\r\n }\r\n\r\n @keyframes fabEnter {\r\n from {\r\n opacity: 0;\r\n transform: scale(0.8);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: scale(1);\r\n }\r\n }\r\n\r\n /* Position variants - now applied to :host */\r\n \r\n /* DEFAULT: Fixed 88px from bottom */\r\n :host(.fab-bottom-right) {\r\n bottom: 88px;\r\n right: 20px;\r\n }\r\n\r\n :host(.fab-bottom-left) {\r\n bottom: 88px;\r\n left: 20px;\r\n }\r\n\r\n :host(.fab-bottom-center) {\r\n bottom: 88px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n }\r\n\r\n /* CAPACITOR APPS ONLY: Use env(safe-area-inset-bottom) */\r\n /* This targets ONLY native apps, not web browsers */\r\n :host-context(body.plt-capacitor):not(.plt-desktop).fab-bottom-right,\r\n :host-context(body.plt-cordova):not(.plt-desktop).fab-bottom-right {\r\n bottom: calc(64px + env(safe-area-inset-bottom)) !important;\r\n }\r\n\r\n :host-context(body.plt-capacitor):not(.plt-desktop).fab-bottom-left,\r\n :host-context(body.plt-cordova):not(.plt-desktop).fab-bottom-left {\r\n bottom: calc(64px + env(safe-area-inset-bottom)) !important;\r\n }\r\n\r\n :host-context(body.plt-capacitor):not(.plt-desktop).fab-bottom-center,\r\n :host-context(body.plt-cordova):not(.plt-desktop).fab-bottom-center {\r\n bottom: calc(64px + env(safe-area-inset-bottom)) !important;\r\n }\r\n\r\n /* Horizontal safe area support (all platforms) */\r\n @supports (padding-right: env(safe-area-inset-right)) {\r\n :host(.fab-bottom-right) {\r\n right: calc(20px + env(safe-area-inset-right));\r\n }\r\n }\r\n\r\n @supports (padding-left: env(safe-area-inset-left)) {\r\n :host(.fab-bottom-left) {\r\n left: calc(20px + env(safe-area-inset-left));\r\n }\r\n }\r\n\r\n /* DESKTOP: Larger spacing for desktop screens */\r\n @media (min-width: 768px) {\r\n :host-context(.plt-desktop).fab-bottom-right {\r\n bottom: 40px;\r\n right: 40px;\r\n }\r\n\r\n :host-context(.plt-desktop).fab-bottom-left {\r\n bottom: 40px;\r\n left: 40px;\r\n }\r\n\r\n :host-context(.plt-desktop).fab-bottom-center {\r\n bottom: 40px;\r\n }\r\n \r\n @supports (padding-right: env(safe-area-inset-right)) {\r\n :host-context(.plt-desktop).fab-bottom-right {\r\n right: calc(40px + env(safe-area-inset-right));\r\n }\r\n }\r\n\r\n @supports (padding-left: env(safe-area-inset-left)) {\r\n :host-context(.plt-desktop).fab-bottom-left {\r\n left: calc(40px + env(safe-area-inset-left));\r\n }\r\n }\r\n }\r\n\r\n /* FAB Button Styling */\r\n .fab-button {\r\n pointer-events: auto;\r\n display: block;\r\n }\r\n\r\n /* Override icon button to be circular and use brand colors */\r\n .fab-button::ng-deep button {\r\n width: 56px !important;\r\n height: 56px !important;\r\n min-width: 56px !important;\r\n min-height: 56px !important;\r\n border-radius: 50% !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 /* Use whitelabel theming variables */\r\n background: var(--color-background-brand) !important;\r\n color: var(--color-primary-content) !important;\r\n border: none !important;\r\n \r\n /* Elevation shadow for prominence */\r\n box-shadow: \r\n 0 3px 5px -1px rgba(0, 0, 0, 0.2),\r\n 0 6px 10px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 18px 0 rgba(0, 0, 0, 0.12);\r\n \r\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\r\n }\r\n\r\n /* Hover state */\r\n .fab-button::ng-deep button:hover:not(:disabled) {\r\n background: var(--color-brand-base-hover, var(--color-background-brand)) !important;\r\n box-shadow: \r\n 0 5px 7px -2px rgba(0, 0, 0, 0.2),\r\n 0 8px 14px 0 rgba(0, 0, 0, 0.14),\r\n 0 2px 22px 0 rgba(0, 0, 0, 0.12);\r\n transform: scale(1.05);\r\n }\r\n\r\n /* Active state */\r\n .fab-button::ng-deep button:active:not(:disabled) {\r\n box-shadow: \r\n 0 2px 4px -1px rgba(0, 0, 0, 0.2),\r\n 0 4px 8px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 14px 0 rgba(0, 0, 0, 0.12);\r\n transform: scale(0.95);\r\n }\r\n\r\n /* Disabled state */\r\n .fab-button::ng-deep button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n box-shadow: \r\n 0 2px 4px -1px rgba(0, 0, 0, 0.1),\r\n 0 4px 8px 0 rgba(0, 0, 0, 0.08),\r\n 0 1px 14px 0 rgba(0, 0, 0, 0.06);\r\n }\r\n\r\n /* Icon styling */\r\n .fab-button::ng-deep button .btn__icon,\r\n .fab-button::ng-deep button .btn__icon svg {\r\n color: var(--color-primary-content) !important;\r\n fill: var(--color-primary-content) !important;\r\n }\r\n\r\n /* Ensure icon is centered and sized properly */\r\n .fab-button::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 .fab-button::ng-deep button .btn__icon svg {\r\n width: 24px !important;\r\n height: 24px !important;\r\n }\r\n `]\r\n})\r\nexport class DsMobileFabComponent {\r\n /**\r\n * Icon name from the design system icon library\r\n * @default 'remixAddLine'\r\n */\r\n icon = input<string>('remixAddLine');\r\n\r\n /**\r\n * Position of the FAB on the screen\r\n * @default 'bottom-right'\r\n */\r\n position = input<'bottom-right' | 'bottom-left' | 'bottom-center'>('bottom-right');\r\n\r\n /**\r\n * Size of the FAB button\r\n * Note: FAB is always 56px circular, but this affects the icon size\r\n * @default 'md'\r\n */\r\n size = input<'sm' | 'md' | 'lg'>('md');\r\n\r\n /**\r\n * ARIA label for accessibility\r\n * @required - Always provide a descriptive label\r\n */\r\n ariaLabel = input.required<string>();\r\n\r\n /**\r\n * Whether the FAB is disabled\r\n * @default false\r\n */\r\n disabled = input<boolean>(false);\r\n\r\n /**\r\n * Emitted when the FAB is clicked\r\n */\r\n fabClick = output<void>();\r\n\r\n /**\r\n * Handle button click\r\n */\r\n handleClick(): void {\r\n if (!this.disabled()) {\r\n this.fabClick.emit();\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 Attachment Preview Component\r\nexport * from './attachment-preview';\r\n\r\n// Mobile Modal Service\r\nexport * from './modal';\r\n\r\n// Mobile Modal Base Component\r\nexport * from './modal-base';\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 New Inquiry Modal\r\nexport * from './new-inquiry-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// FAB Component\r\nexport * from './fab';\r\n\r\n// Mobile Avatar Component\r\nexport * from './avatar-with-badge';\r\n\r\n// Shared directives\r\nexport * from './shared';","import { Injectable, signal, computed } from '@angular/core';\r\nimport { Post, Comment } from '../models/post.model';\r\n\r\n/**\r\n * PostsService\r\n * \r\n * Centralized service for managing community posts.\r\n * Provides a single source of truth for post data, including comments.\r\n * \r\n * Features:\r\n * - CRUD operations for posts\r\n * - Infinite scroll pagination\r\n * - Post search/filter (future)\r\n * - Comment management (future)\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class PostsService {\r\n // Private signal for internal state management\r\n private postsState = signal<Post[]>(this.getInitialPosts());\r\n \r\n // Public computed signal (read-only)\r\n posts = computed(() => this.postsState());\r\n \r\n // Pagination state for infinite scroll\r\n private currentPage = signal(0);\r\n private hasMore = signal(true);\r\n \r\n constructor() {}\r\n \r\n /**\r\n * Get a post by ID\r\n */\r\n getPostById(id: string): Post | undefined {\r\n return this.postsState().find(post => post.id === id);\r\n }\r\n \r\n /**\r\n * Add a new post (e.g., from post creator)\r\n * Adds to the beginning of the list\r\n */\r\n addPost(post: Post): void {\r\n this.postsState.update(posts => [post, ...posts]);\r\n }\r\n \r\n /**\r\n * Update an existing post\r\n */\r\n updatePost(id: string, updates: Partial<Post>): void {\r\n this.postsState.update(posts =>\r\n posts.map(post => post.id === id ? { ...post, ...updates } : post)\r\n );\r\n }\r\n \r\n /**\r\n * Delete a post by ID\r\n */\r\n deletePost(id: string): void {\r\n this.postsState.update(posts => posts.filter(post => post.id !== id));\r\n }\r\n \r\n /**\r\n * Load more posts for infinite scroll\r\n * Returns true if more posts were loaded, false if no more posts\r\n */\r\n async loadMorePosts(): Promise<boolean> {\r\n const page = this.currentPage();\r\n const itemsPerPage = 2;\r\n const additionalPosts = this.getAdditionalPosts();\r\n const startIndex = page * itemsPerPage;\r\n const endIndex = startIndex + itemsPerPage;\r\n \r\n // Simulate API delay\r\n await new Promise(resolve => setTimeout(resolve, 1000));\r\n \r\n // Get next batch\r\n const newPosts = additionalPosts.slice(startIndex, endIndex);\r\n \r\n if (newPosts.length > 0) {\r\n // Append to existing posts\r\n this.postsState.update(posts => [...posts, ...newPosts]);\r\n this.currentPage.update(p => p + 1);\r\n \r\n // Check if there are more posts\r\n if (endIndex >= additionalPosts.length) {\r\n this.hasMore.set(false);\r\n }\r\n \r\n return true;\r\n }\r\n \r\n this.hasMore.set(false);\r\n return false;\r\n }\r\n \r\n /**\r\n * Check if there are more posts to load\r\n */\r\n hasMorePosts(): boolean {\r\n return this.hasMore();\r\n }\r\n \r\n /**\r\n * Reset pagination (e.g., on pull-to-refresh)\r\n */\r\n resetPagination(): void {\r\n this.currentPage.set(0);\r\n this.hasMore.set(true);\r\n }\r\n \r\n /**\r\n * Get initial posts (shown on page load)\r\n */\r\n private getInitialPosts(): Post[] {\r\n return [\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',\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 comments: []\r\n },\r\n {\r\n id: 'post-1',\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 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 {\r\n id: 'post-2',\r\n authorName: 'Sophie Andersen',\r\n authorRole: 'Lejer',\r\n timestamp: '4t siden',\r\n avatarInitials: 'SA',\r\n avatarType: 'initials',\r\n content: '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! 🏡✨',\r\n hasInlinePhotos: true,\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 {\r\n id: 'post-3',\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 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 {\r\n id: 'post-3.5',\r\n authorName: 'Karen Nielsen',\r\n authorRole: 'Ejendomsadministrator',\r\n timestamp: '2d siden',\r\n avatarInitials: 'KN',\r\n avatarType: 'initials',\r\n showBadge: true,\r\n content: '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! 🏢✨',\r\n hasInlinePhotos: true,\r\n inlinePhotoCount: 6,\r\n isLiked: false,\r\n likeCount: 234,\r\n commentCount: 89,\r\n comments: []\r\n },\r\n {\r\n id: 'post-4',\r\n authorName: 'Karen Nielsen',\r\n authorRole: 'Ejendomsadministrator',\r\n timestamp: '2d siden',\r\n avatarInitials: 'KN',\r\n avatarType: 'initials',\r\n showBadge: true,\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 {\r\n id: 'post-5',\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 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 \r\n /**\r\n * Get additional posts for infinite scroll\r\n */\r\n private getAdditionalPosts(): Post[] {\r\n return [\r\n {\r\n id: 'post-6',\r\n authorName: 'Peter Christensen',\r\n authorRole: 'Lejer',\r\n timestamp: '4d siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face',\r\n content: 'Nogen der ved, hvornår de nye cykelstativer bliver installeret? 🚲',\r\n isLiked: false,\r\n likeCount: 15,\r\n commentCount: 23,\r\n comments: []\r\n },\r\n {\r\n id: 'post-7',\r\n authorName: 'Maria Schmidt',\r\n authorRole: 'Lejer',\r\n timestamp: '5d siden',\r\n avatarInitials: 'MS',\r\n avatarType: 'initials',\r\n content: 'Tak til vores fantastiske vicevært for at holde bygningen så pæn og ren! 🌟',\r\n isLiked: true,\r\n likeCount: 78,\r\n commentCount: 12,\r\n comments: []\r\n },\r\n {\r\n id: 'post-8',\r\n authorName: 'Jens Nielsen',\r\n authorRole: 'Lejer',\r\n timestamp: '6d siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?w=100&h=100&fit=crop&crop=face',\r\n content: 'Jeg har fundet en nøgle i gården. Hvis den er din, så kontakt mig! 🔑',\r\n isLiked: false,\r\n likeCount: 8,\r\n commentCount: 3,\r\n comments: []\r\n },\r\n {\r\n id: 'post-9',\r\n authorName: 'Anna Larsen',\r\n authorRole: 'Lejer',\r\n timestamp: '1u siden',\r\n avatarInitials: 'AL',\r\n avatarType: 'initials',\r\n content: 'Glædelig sommer til alle! ☀️ Håber I alle får en vidunderlig ferie!',\r\n isLiked: true,\r\n likeCount: 134,\r\n commentCount: 45,\r\n comments: []\r\n },\r\n {\r\n id: 'post-10',\r\n authorName: 'Michael Andersen',\r\n authorRole: 'Lejer',\r\n timestamp: '1u siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=100&h=100&fit=crop&crop=face',\r\n content: 'Er der nogen der kan anbefale en god pizzarestaurant i området? 🍕',\r\n isLiked: false,\r\n likeCount: 32,\r\n commentCount: 67,\r\n comments: []\r\n },\r\n {\r\n id: 'post-11',\r\n authorName: 'Camilla Jensen',\r\n authorRole: 'Lejer',\r\n timestamp: '2u siden',\r\n avatarInitials: 'CJ',\r\n avatarType: 'initials',\r\n content: 'Hej alle! Jeg overvejer at starte en bogklub. Er der nogen interesserede? 📚',\r\n isLiked: false,\r\n likeCount: 42,\r\n commentCount: 28,\r\n comments: []\r\n },\r\n {\r\n id: 'post-12',\r\n authorName: 'Henrik Madsen',\r\n authorRole: 'Lejer',\r\n timestamp: '2u siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1568602471122-7832951cc4c5?w=100&h=100&fit=crop&crop=face',\r\n content: 'Vores fælles have ser fantastisk ud i år! Stor ros til haveudvalget! 🌻🌸',\r\n isLiked: true,\r\n likeCount: 95,\r\n commentCount: 18,\r\n comments: []\r\n },\r\n {\r\n id: 'post-13',\r\n authorName: 'Louise Berg',\r\n authorRole: 'Lejer',\r\n timestamp: '3u siden',\r\n avatarInitials: 'LB',\r\n avatarType: 'initials',\r\n content: 'Påmindelse: Generalforsamling næste mandag kl. 19. Håber at se jer alle! 📋',\r\n isLiked: false,\r\n likeCount: 56,\r\n commentCount: 34,\r\n comments: []\r\n },\r\n {\r\n id: 'post-14',\r\n authorName: 'Martin Olsen',\r\n authorRole: 'Lejer',\r\n timestamp: '3u siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1566492031773-4f4e44671857?w=100&h=100&fit=crop&crop=face',\r\n content: 'Har nogen set min kat? Hun har været væk siden i går aftes. Hun hedder Luna og er grå. 🐱',\r\n isLiked: false,\r\n likeCount: 67,\r\n commentCount: 45,\r\n comments: []\r\n },\r\n {\r\n id: 'post-15',\r\n authorName: 'Sarah Thomsen',\r\n authorRole: 'Lejer',\r\n timestamp: '4u siden',\r\n avatarInitials: 'ST',\r\n avatarType: 'initials',\r\n content: 'Super godt initiativ med de nye genbrugsstationer! Gør det meget nemmere at sortere affald 💚♻️',\r\n isLiked: true,\r\n likeCount: 123,\r\n commentCount: 21,\r\n comments: []\r\n },\r\n {\r\n id: 'post-16',\r\n authorName: 'Nikolaj Hansen',\r\n authorRole: 'Lejer',\r\n timestamp: '5u siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?w=100&h=100&fit=crop&crop=face',\r\n content: 'Leder efter en pålídelig babysitter i bygningen. Kender I nogen? Tak! 👶',\r\n isLiked: false,\r\n likeCount: 12,\r\n commentCount: 9,\r\n comments: []\r\n },\r\n {\r\n id: 'post-17',\r\n authorName: 'Isabella Larsen',\r\n authorRole: 'Lejer',\r\n timestamp: '6u siden',\r\n avatarInitials: 'IL',\r\n avatarType: 'initials',\r\n content: 'Vi holder en lille julemarked i gården på lørdag! Kom og køb håndlavede ting og nyd varm kakao! 🎄☕',\r\n isLiked: true,\r\n likeCount: 187,\r\n commentCount: 56,\r\n comments: []\r\n },\r\n {\r\n id: 'post-18',\r\n authorName: 'Frederik Nielsen',\r\n authorRole: 'Lejer',\r\n timestamp: '7u siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1599566150163-29194dcaad36?w=100&h=100&fit=crop&crop=face',\r\n content: 'Er der nogen der vil være med til at starte en løbeklub? Tænker 2-3 gange om ugen. 🏃♂️',\r\n isLiked: false,\r\n likeCount: 38,\r\n commentCount: 41,\r\n comments: []\r\n },\r\n {\r\n id: 'post-19',\r\n authorName: 'Sofie Petersen',\r\n authorRole: 'Lejer',\r\n timestamp: '1d siden',\r\n avatarInitials: 'SP',\r\n avatarType: 'initials',\r\n content: 'Fantastisk sammenkomst i går aftes! Tusind tak til alle der kom. Vi skal gøre det igen snart! 🎉',\r\n isLiked: true,\r\n likeCount: 156,\r\n commentCount: 72,\r\n comments: []\r\n },\r\n {\r\n id: 'post-20',\r\n authorName: 'Christian Møller',\r\n authorRole: 'Lejer',\r\n timestamp: '1d siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1552058544-f2b08422138a?w=100&h=100&fit=crop&crop=face',\r\n content: 'Nogen der har brug for hjælp med at flytte møbler? Jeg har en stor bil og kan hjælpe i weekenden! 🚐',\r\n isLiked: false,\r\n likeCount: 29,\r\n commentCount: 15,\r\n comments: []\r\n },\r\n {\r\n id: 'post-21',\r\n authorName: 'Laura Andersen',\r\n authorRole: 'Lejer',\r\n timestamp: '2d siden',\r\n avatarInitials: 'LA',\r\n avatarType: 'initials',\r\n content: 'Jeg giver klavertimer hvis nogen er interesserede! Alle niveauer velkomne 🎹🎵',\r\n isLiked: false,\r\n likeCount: 44,\r\n commentCount: 22,\r\n comments: []\r\n },\r\n {\r\n id: 'post-22',\r\n authorName: 'Rasmus Schmidt',\r\n authorRole: 'Lejer',\r\n timestamp: '2d 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 content: 'Vi har fået ny belysning i trappeopgangen! Så meget lysere nu om aftenen 💡',\r\n isLiked: true,\r\n likeCount: 89,\r\n commentCount: 13,\r\n comments: []\r\n },\r\n {\r\n id: 'post-23',\r\n authorName: 'Mette Hansen',\r\n authorRole: 'Lejer',\r\n timestamp: '3d siden',\r\n avatarInitials: 'MH',\r\n avatarType: 'initials',\r\n content: 'Nogen der vil dele en Costco-medlemskab? Vi kan tage på indkøb sammen! 🛒',\r\n isLiked: false,\r\n likeCount: 18,\r\n commentCount: 31,\r\n comments: []\r\n },\r\n {\r\n id: 'post-24',\r\n authorName: 'Jonas Berg',\r\n authorRole: 'Lejer',\r\n timestamp: '3d siden',\r\n avatarType: 'photo',\r\n avatarSrc: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face',\r\n content: 'Har plantet nye blomster ved indgangen. Håber I kan lide dem! 🌷🌺',\r\n isLiked: true,\r\n likeCount: 142,\r\n commentCount: 38,\r\n comments: []\r\n },\r\n {\r\n id: 'post-25',\r\n authorName: 'Caroline Jensen',\r\n authorRole: 'Lejer',\r\n timestamp: '4d siden',\r\n avatarInitials: 'CJ',\r\n avatarType: 'initials',\r\n content: 'Leder efter en tennismakker. Er der nogen der spiller? 🎾',\r\n isLiked: false,\r\n likeCount: 21,\r\n commentCount: 17,\r\n comments: []\r\n }\r\n ];\r\n }\r\n}\r\n","import { Component, computed } from '@angular/core';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { IonInfiniteScroll, IonInfiniteScrollContent } from '@ionic/angular/standalone';\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\nimport { PostsService } from '../services/posts.service';\r\nimport { Post } from '../models/post.model';\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 IonInfiniteScroll,\r\n IonInfiniteScrollContent\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 /* Infinite Scroll Spinner Styling */\r\n ion-infinite-scroll {\r\n --color: var(--color-primary-surface);\r\n }\r\n \r\n ion-infinite-scroll-content {\r\n --color: var(--color-primary-surface);\r\n }\r\n \r\n /* Target the actual spinner element */\r\n ion-infinite-scroll-content::part(spinner) {\r\n color: var(--color-primary-surface);\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 role=\"feed\">\r\n <div class=\"post-feed\">\r\n <!-- Pinned Posts Section -->\r\n <div class=\"pinned-posts-section\" role=\"article\">\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('post-4')\"\r\n (commentClick)=\"openPost('post-4', true)\"\r\n (longPress)=\"handlePostLongPress('post-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 <!-- All Posts Loop -->\r\n @for (post of allPosts(); track post.id) {\r\n @if (post.hasInlinePhotos && post.id === 'post-2') {\r\n <!-- Post 2: With multiple images (grid layout) -->\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 [avatarInitials]=\"post.avatarInitials || ''\"\r\n [avatarType]=\"post.avatarType\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost(post.id)\"\r\n (commentClick)=\"openPost(post.id, true)\"\r\n (longPress)=\"handlePostLongPress(post.id, post.authorRole === 'Dig')\">\r\n \r\n <post-content>\r\n <post-text>{{ post.content }}</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]=\"post.isLiked\" [count]=\"post.likeCount\" />\r\n <action-comment [count]=\"post.commentCount\" (commentClick)=\"openPost(post.id, true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n } @else if (post.hasInlinePhotos && post.id === 'post-3.5') {\r\n <!-- Post 3.5: Property Manager showcase with 6+ photos -->\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 [avatarInitials]=\"post.avatarInitials || ''\"\r\n [avatarType]=\"post.avatarType\"\r\n [showBadge]=\"post.showBadge || false\"\r\n [clickable]=\"true\"\r\n (postClick)=\"openPost(post.id)\"\r\n (commentClick)=\"openPost(post.id, true)\"\r\n (longPress)=\"handlePostLongPress(post.id, false)\">\r\n \r\n <post-content>\r\n <post-text>{{ post.content }}</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]=\"post.likeCount\" />\r\n <action-comment [count]=\"post.commentCount\" (commentClick)=\"openPost(post.id, true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n } @else {\r\n <!-- Regular Post -->\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)=\"openPost(post.id)\"\r\n (commentClick)=\"openPost(post.id, true)\"\r\n (longPress)=\"handlePostLongPress(post.id, 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)=\"openPost(post.id, true)\" />\r\n </post-actions>\r\n </ds-mobile-interactive-list-item-post>\r\n }\r\n }\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 \r\n <!-- Infinite Scroll -->\r\n @if (hasAnyPosts()) {\r\n <ion-infinite-scroll \r\n threshold=\"100px\"\r\n [disabled]=\"!hasMorePosts()\"\r\n (ionInfinite)=\"onInfiniteScroll($event)\">\r\n <ion-infinite-scroll-content\r\n loadingSpinner=\"crescent\">\r\n </ion-infinite-scroll-content>\r\n </ion-infinite-scroll>\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 // Get posts from service (using computed for safe initialization)\r\n allPosts = computed(() => this.postsService.posts());\r\n \r\n // Computed to check if there are any posts to display\r\n hasAnyPosts = computed(() => {\r\n return this.allPosts().length > 0;\r\n });\r\n \r\n // Computed to check if there are more posts to load\r\n hasMorePosts = computed(() => {\r\n return this.postsService.hasMorePosts();\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 private postsService: PostsService\r\n ) {}\r\n \r\n /**\r\n * Handle infinite scroll event\r\n * Loads more posts when user scrolls to bottom\r\n */\r\n async onInfiniteScroll(event: any): Promise<void> {\r\n console.log('[Community] Infinite scroll triggered');\r\n \r\n const hasMore = await this.postsService.loadMorePosts();\r\n \r\n if (hasMore) {\r\n console.log('[Community] Loaded more posts');\r\n } else {\r\n console.log('[Community] No more posts to load');\r\n }\r\n \r\n // Complete the infinite scroll\r\n event.target.complete();\r\n }\r\n \r\n handleRefresh(event: any): void {\r\n console.log('Pull-to-refresh triggered');\r\n \r\n // Reset infinite scroll state\r\n this.postsService.resetPagination();\r\n \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 * Gets post data from service and opens modal\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 const post = this.postsService.getPostById(postId);\r\n \r\n if (post) {\r\n // Convert Post model to modal format (add postId and focusComment)\r\n // Filter out 'icon' avatarType if present, as modal only supports 'photo' | 'initials'\r\n const postData = {\r\n ...post,\r\n postId: post.id,\r\n avatarType: post.avatarType === 'icon' ? undefined : post.avatarType,\r\n focusComment\r\n };\r\n \r\n await this.postModal.open(postData, {\r\n currentUserName: 'Lars Mikkelsen', // Current user name\r\n currentUserInitials: this.userService.avatarInitials()\r\n });\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: Post = {\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 comments: []\r\n };\r\n \r\n // Add to the beginning of the posts array via service\r\n this.postsService.addPost(newPost);\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(postId: string, isOwnPost: boolean): Promise<void> {\r\n console.log('[Community] Post long pressed:', postId, '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:', postId);\r\n \r\n // Get post from service\r\n const post = this.postsService.getPostById(postId);\r\n if (!post) {\r\n console.error('Post not found:', postId);\r\n return;\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: post.content\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 via service\r\n this.postsService.updatePost(postId, {\r\n content: editResult.data.content,\r\n timestamp: 'Lige nu'\r\n });\r\n }\r\n break;\r\n \r\n case 'delete':\r\n console.log('Delete post:', postId);\r\n if (confirm('Er du sikker på, at du vil slette dette opslag?')) {\r\n this.postsService.deletePost(postId);\r\n }\r\n break;\r\n \r\n case 'like':\r\n console.log('Like post:', postId);\r\n // Toggle like - in a real app, this would call an API\r\n const likePost = this.postsService.getPostById(postId);\r\n if (likePost) {\r\n this.postsService.updatePost(postId, {\r\n isLiked: !likePost.isLiked,\r\n likeCount: likePost.isLiked ? likePost.likeCount - 1 : likePost.likeCount + 1\r\n });\r\n }\r\n break;\r\n \r\n case 'reply':\r\n console.log('Reply to post:', postId);\r\n // Open the post detail modal with comment input focused\r\n await this.openPost(postId, true);\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 { 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 { DsMobileFabComponent } from '../components/fab';\r\nimport { DsMobileNewInquiryModalService, NewInquiryData } from '../components/new-inquiry-modal';\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 DsMobileFabComponent\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 <!-- FAB for creating new inquiry -->\r\n <ds-mobile-fab\r\n icon=\"remixAddLine\"\r\n position=\"bottom-right\"\r\n ariaLabel=\"Create new inquiry\"\r\n (fabClick)=\"createNewInquiry()\">\r\n </ds-mobile-fab>\r\n `\r\n})\r\nexport class MobileInquiriesPageComponent {\r\n constructor(\r\n public userService: UserService,\r\n private navCtrl: NavController,\r\n private newInquiryModal: DsMobileNewInquiryModalService\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 async createNewInquiry(): Promise<void> {\r\n console.log('Opening new inquiry modal...');\r\n \r\n await this.newInquiryModal.open({\r\n onSubmit: async (data: NewInquiryData) => {\r\n console.log('New inquiry submitted:', data);\r\n \r\n // In a real app, call your API to create the inquiry\r\n // await this.inquiryService.createInquiry(data);\r\n \r\n // Add the new inquiry to the list (mock for now)\r\n const newInquiry: Inquiry = {\r\n id: `inquiry-${Date.now()}`,\r\n title: data.title,\r\n description: data.description,\r\n status: 'open',\r\n timestamp: 'Just now',\r\n category: 'other'\r\n };\r\n \r\n this.inquiries.update(inquiries => [newInquiry, ...inquiries]);\r\n \r\n // Close the modal\r\n await this.newInquiryModal.close();\r\n }\r\n });\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 * DsMobileCardInlineBannerComponent\r\n * \r\n * Specialized interactive component for displaying notification banners.\r\n * Used to show unread message notifications above inquiry details.\r\n * \r\n * Features:\r\n * - Neutral background matching file/contact cards\r\n * - Avatar icon with message symbol\r\n * - Title and timestamp\r\n * - Unread count badge\r\n * - Chevron for navigation indication\r\n * \r\n * @example\r\n * ```html\r\n * <ds-mobile-card-inline-banner\r\n * [title]=\"'New messages'\"\r\n * [timestamp]=\"'2 min ago'\"\r\n * [unreadCount]=\"3\"\r\n * (bannerClick)=\"navigateToMessages()\">\r\n * </ds-mobile-card-inline-banner>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'ds-mobile-card-inline-banner',\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 /* Badge for unread count - matching tab badge styling */\r\n .unread-badge {\r\n min-width: 24px;\r\n height: 16px;\r\n padding: 0 6px;\r\n border-radius: 10px;\r\n background: var(--color-background-neutral-tertiary, #e5e5e5);\r\n color: var(--color-text-primary, #1a1a1a);\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 margin-right: 8px;\r\n }\r\n `],\r\n template: `\r\n <ds-mobile-card-inline\r\n [variant]=\"layout()\"\r\n (cardClick)=\"handleBannerClick()\">\r\n \r\n <div content-leading class=\"item-avatar\">\r\n <ds-avatar\r\n type=\"icon\"\r\n [iconName]=\"'remixNotificationLine'\"\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\">{{ title() }}</div>\r\n \r\n @if (timestamp()) {\r\n <div class=\"item-meta\">\r\n <span>{{ timestamp() }}</span>\r\n </div>\r\n }\r\n </div>\r\n \r\n <div content-trailing class=\"item-trailing\">\r\n @if (unreadCount() && unreadCount()! > 0) {\r\n <span class=\"unread-badge\">{{ unreadCount() }}</span>\r\n }\r\n <ds-icon name=\"remixArrowRightSLine\" size=\"20px\" />\r\n </div>\r\n </ds-mobile-card-inline>\r\n `\r\n})\r\nexport class DsMobileCardInlineBannerComponent {\r\n /**\r\n * Banner title (e.g., \"New messages\", \"Unread messages\")\r\n */\r\n title = input.required<string>();\r\n \r\n /**\r\n * Timestamp text (e.g., \"2 min ago\", \"Just now\")\r\n */\r\n timestamp = input<string>('');\r\n \r\n /**\r\n * Number of unread items (optional, shows badge if > 0)\r\n */\r\n unreadCount = input<number>(0);\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 banner is clicked\r\n */\r\n bannerClick = output<void>();\r\n \r\n handleBannerClick(): void {\r\n this.bannerClick.emit();\r\n }\r\n}\r\n","import { Component, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { DsIconComponent, DsBadgeComponent } from '@propbinder/design-system';\r\nimport { DsMobilePageDetailsComponent } from '../components/page-details';\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 } from '../components/chat-modal';\r\nimport { DsAvatarWithBadgeComponent } from '../components/avatar-with-badge';\r\nimport { DsMobileCardInlineBannerComponent } from '../components/card-inline-banner';\r\nimport { UserService } from '../services/user.service';\r\nimport { type InlineTabItem } from '../components/inline-tabs';\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 DsIconComponent,\r\n DsAvatarWithBadgeComponent,\r\n DsMobilePageDetailsComponent,\r\n DsMobileInteractiveListItemMessageComponent,\r\n DsMobileListItemComponent,\r\n DsBadgeComponent,\r\n DsMobileCardInlineBannerComponent\r\n ],\r\n host: {\r\n class: 'ion-page'\r\n },\r\n styleUrls: [\r\n './inquiry-detail.example.css'\r\n ],\r\n template: `\r\n <ds-mobile-page-details\r\n [title]=\"inquiryTitle\"\r\n [tabs]=\"tabItems\"\r\n [activeTab]=\"activeTab()\"\r\n (tabChange)=\"setActiveTab($event)\"\r\n (back)=\"goBack()\"\r\n (refresh)=\"handleRefresh($event)\">\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 <!-- Unread Messages Banner -->\r\n @if (hasUnreadMessages()) {\r\n <div class=\"banner-container\">\r\n <ds-mobile-card-inline-banner\r\n [title]=\"'Du har ulæste beskeder'\"\r\n [timestamp]=\"'2 min siden'\"\r\n [unreadCount]=\"3\"\r\n (bannerClick)=\"navigateToMessagesTab()\">\r\n </ds-mobile-card-inline-banner>\r\n </div>\r\n }\r\n \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 <!-- Creation Date -->\r\n <ds-mobile-list-item [leadingSize]=\"'32px'\" [showDivider]=\"true\" [align]=\"'center'\">\r\n <ds-icon content-leading name=\"remixTimeLine\" size=\"20px\" color=\"tertiary\" />\r\n <div content-main>\r\n <div class=\"detail-value\">22. feb 2025</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 <!-- 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 </ds-mobile-page-details>\r\n `\r\n})\r\nexport class MobileInquiryDetailPageComponent {\r\n inquiryTitle = 'Tørretumbler virker ikke';\r\n activeTab = signal<string>('details');\r\n \r\n tabItems: InlineTabItem[] = [\r\n { id: 'details', label: 'Detaljer' },\r\n { id: 'messages', label: 'Beskeder', badge: 0 }\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.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 lightbox: DsMobileLightboxService,\r\n private chatModal: DsMobileChatModalService\r\n ) {\r\n // Trigger initial badge update\r\n this.unreadMessagesCount();\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 // Navigation is handled by ds-mobile-page-details component\r\n // This is just for any custom logic if needed\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 * Check if there are unread messages\r\n */\r\n hasUnreadMessages(): boolean {\r\n return this.messageThreads.some(m => m.unread);\r\n }\r\n \r\n /**\r\n * Navigate to messages tab when banner is clicked\r\n */\r\n navigateToMessagesTab(): void {\r\n this.setActiveTab('messages');\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 // Day 1 - Yesterday morning (9:15 AM)\r\n {\r\n id: '1',\r\n content: 'Good morning! I wanted to follow up on your inquiry regarding the maintenance schedule.',\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: new Date(Date.now() - 86400000 - 32700000), // Yesterday 9:15 AM\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n {\r\n id: '2',\r\n content: 'We have reviewed your case and identified the root cause of the issue.',\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: new Date(Date.now() - 86400000 - 32520000), // Yesterday 9:18 AM (grouped with previous)\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n {\r\n id: '3',\r\n content: 'Thanks for looking into this! What did you find?',\r\n senderId: 'current-user',\r\n senderName: 'You',\r\n timestamp: new Date(Date.now() - 86400000 - 32100000), // Yesterday 9:25 AM (new group - 7 min gap)\r\n isOwnMessage: true,\r\n avatarInitials: this.userService.avatarInitials(),\r\n avatarType: 'initials',\r\n },\r\n {\r\n id: '4',\r\n content: 'Can you also send me the maintenance report?',\r\n senderId: 'current-user',\r\n senderName: 'You',\r\n timestamp: new Date(Date.now() - 86400000 - 31980000), // Yesterday 9:27 AM (grouped with previous)\r\n isOwnMessage: true,\r\n avatarInitials: this.userService.avatarInitials(),\r\n avatarType: 'initials',\r\n },\r\n \r\n // Day 1 - Yesterday afternoon (2:30 PM - large time gap)\r\n {\r\n id: '5',\r\n content: messageThread.message,\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: new Date(Date.now() - 86400000 - 13800000), // Yesterday 2:30 PM (new group - 5 hour gap)\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n {\r\n id: '6',\r\n content: 'I\\'ve attached the detailed report to your inquiry dashboard. Please review it when you have a moment.',\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: new Date(Date.now() - 86400000 - 13620000), // Yesterday 2:33 PM (grouped with previous)\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n \r\n // Day 2 - Today morning (10:45 AM - new day)\r\n {\r\n id: '7',\r\n content: 'Perfect! I\\'ve reviewed the report and everything looks good.',\r\n senderId: 'current-user',\r\n senderName: 'You',\r\n timestamp: new Date(Date.now() - 7500000), // Today 10:45 AM (new group - new day)\r\n isOwnMessage: true,\r\n avatarInitials: this.userService.avatarInitials(),\r\n avatarType: 'initials',\r\n },\r\n {\r\n id: '8',\r\n content: 'When can we schedule the maintenance work?',\r\n senderId: 'current-user',\r\n senderName: 'You',\r\n timestamp: new Date(Date.now() - 7320000), // Today 10:48 AM (grouped with previous)\r\n isOwnMessage: true,\r\n avatarInitials: this.userService.avatarInitials(),\r\n avatarType: 'initials',\r\n },\r\n \r\n // Day 2 - Today (just now - 2 minutes ago)\r\n {\r\n id: '9',\r\n content: 'Great to hear! I can schedule it for next Tuesday at 9:00 AM. Does that work for you?',\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: new Date(Date.now() - 120000), // 2 minutes ago (new group - several hours gap)\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\r\n avatarType: 'initials',\r\n },\r\n {\r\n id: '10',\r\n content: 'I\\'ll send you a calendar invitation with all the details.',\r\n senderId: messageId,\r\n senderName: messageThread.senderName,\r\n senderRole: messageThread.role,\r\n timestamp: new Date(Date.now() - 60000), // 1 minute ago (grouped with previous)\r\n isOwnMessage: false,\r\n avatarInitials: messageThread.senderInitials,\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, signal } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { DsTextInputComponent } from '../components/text-input';\r\nimport { DsButtonComponent } from '@propbinder/design-system';\r\n\r\n/**\r\n * SignInPageComponent\r\n * \r\n * Sign-in page with email authentication.\r\n * Features logomark, decorative city background, and form validation.\r\n */\r\n@Component({\r\n selector: 'app-sign-in',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule, DsTextInputComponent, DsButtonComponent],\r\n template: `\r\n <div class=\"tw-relative tw-min-h-screen tw-flex tw-justify-center tw-overflow-hidden\" style=\"background: linear-gradient(180deg, #D6C7FF 0%, #8A9BFF 100%);\">\r\n <!-- City background decoration -->\r\n <div class=\"tw-absolute tw-bottom-0 tw-left-0 tw-right-0 tw-w-full tw-h-[35%] tw-z-0 tw-pointer-events-none tw-overflow-hidden md:tw-h-[50%] md:tw-min-h-[400px]\" aria-hidden=\"true\">\r\n <img src=\"/Assets/city.svg\" alt=\"\" class=\"tw-w-full tw-h-full tw-object-cover tw-object-top\" />\r\n </div>\r\n\r\n <!-- Main content -->\r\n <div class=\"tw-relative tw-z-[1] tw-w-full tw-pt-12 tw-max-w-[440px] tw-flex tw-flex-col tw-items-center lg:tw-max-w-[480px] lg:tw-pt-24\">\r\n <!-- Logo -->\r\n <div class=\"tw-flex tw-justify-center tw-items-center\">\r\n <img src=\"/Assets/logomark.svg\" alt=\"Propbinder\" class=\"tw-w-16 tw-h-16 tw-block\" />\r\n </div>\r\n\r\n <!-- Sign in form -->\r\n <div class=\"tw-w-full tw-py-10 tw-px-6 md:tw-px-8 md:tw-py-12 lg:tw-p-12 tw-relative tw-min-h-[400px] tw-box-border\">\r\n <!-- Form view -->\r\n <div class=\"tw-transition-all tw-duration-300 tw-ease-out tw-absolute tw-inset-y-10 tw-inset-x-6 md:tw-inset-y-12 md:tw-inset-x-8 lg:tw-inset-12 tw-box-border\" \r\n [class.tw-opacity-100]=\"!emailSent()\"\r\n [class.tw-translate-y-0]=\"!emailSent()\"\r\n [class.tw-z-10]=\"!emailSent()\"\r\n [class.tw-opacity-0]=\"emailSent()\"\r\n [class.-tw-translate-y-5]=\"emailSent()\"\r\n [class.tw-pointer-events-none]=\"emailSent()\"\r\n [class.tw-z-0]=\"emailSent()\">\r\n <div class=\"tw-w-full tw-h-full tw-flex tw-flex-col\">\r\n <h1 class=\"tw-text-2xl lg:tw-text-3xl tw-font-semibold tw-text-center tw-mt-0 tw-mb-2 tw-text-default-primary\">Welcome home</h1>\r\n\r\n <p class=\"body-base-regular tw-m-0 tw-mb-8 tw-text-center tw-text-default-primary\">\r\n Enter your email to continue\r\n </p>\r\n\r\n <form class=\"tw-flex tw-flex-col tw-gap-4\" (ngSubmit)=\"handleSubmit()\">\r\n <ds-text-input\r\n id=\"email-input\"\r\n type=\"email\"\r\n placeholder=\"Enter your email\"\r\n [(ngModel)]=\"email\"\r\n name=\"email\"\r\n [required]=\"true\"\r\n [hasError]=\"emailError()\"\r\n [errorMessage]=\"emailError() ? 'Please enter a valid email address' : ''\"\r\n [autoClearError]=\"true\"\r\n autocomplete=\"email\"\r\n inputmode=\"email\"\r\n (errorCleared)=\"emailError.set(false)\">\r\n </ds-text-input>\r\n\r\n <ds-button\r\n type=\"submit\"\r\n variant=\"primary\"\r\n size=\"lg\"\r\n [loading]=\"isSubmitting()\"\r\n class=\"tw-w-full\">\r\n Continue\r\n </ds-button>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <!-- Email sent confirmation view -->\r\n <div class=\"tw-transition-all tw-duration-300 tw-ease-out tw-flex tw-flex-col tw-items-center tw-absolute tw-inset-y-10 tw-inset-x-6 md:tw-inset-y-12 md:tw-inset-x-8 lg:tw-inset-12 tw-box-border tw-overflow-hidden\"\r\n [class.tw-opacity-0]=\"!emailSent()\"\r\n [class.tw-translate-y-5]=\"!emailSent()\"\r\n [class.tw-pointer-events-none]=\"!emailSent()\"\r\n [class.tw-z-0]=\"!emailSent()\"\r\n [class.tw-opacity-100]=\"emailSent()\"\r\n [class.tw-translate-y-0]=\"emailSent()\"\r\n [class.tw-pointer-events-auto]=\"emailSent()\"\r\n [class.tw-z-10]=\"emailSent()\">\r\n <div class=\"tw-w-full tw-flex tw-flex-col tw-items-center\">\r\n <h1 class=\"tw-text-lg tw-font-semibold lg:tw-text-xl tw-text-center tw-mt-0 tw-mb-4 tw-text-default-primary\">Check your email</h1>\r\n\r\n <p class=\"body-base-regular tw-m-0 tw-mb-8 tw-text-center tw-text-default-primary tw-max-w-[272px]\">\r\n We've sent you a temporary login to <span class=\"body-base-semiBold\">{{ email }}</span>\r\n </p>\r\n\r\n <a\r\n href=\"#\"\r\n (click)=\"handleBackToLogin(); $event.preventDefault()\"\r\n class=\"back-link\">\r\n Back to login\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n /* Button styling override for full width */\r\n ds-button {\r\n width: 100%;\r\n }\r\n\r\n ds-button::ng-deep button {\r\n width: 100%;\r\n }\r\n\r\n /* Link styling */\r\n .back-link {\r\n display: block;\r\n width: 100%;\r\n text-align: center;\r\n font-family: 'Brockmann', system-ui, -apple-system, sans-serif;\r\n font-size: var(--font-size-base);\r\n font-weight: 600;\r\n color: var(--text-color-default-primary);\r\n text-decoration: none;\r\n cursor: pointer;\r\n transition: opacity 0.2s ease;\r\n }\r\n\r\n .back-link:hover {\r\n opacity: 0.8;\r\n }\r\n `]\r\n})\r\nexport class SignInPageComponent {\r\n email = '';\r\n emailError = signal<boolean>(false);\r\n isSubmitting = signal<boolean>(false);\r\n emailSent = signal<boolean>(false);\r\n\r\n handleSubmit(): void {\r\n // Basic email validation\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n \r\n // Always validate on submit\r\n if (!this.email || !emailRegex.test(this.email)) {\r\n this.emailError.set(true);\r\n return;\r\n }\r\n\r\n // Only proceed if email is valid\r\n this.emailError.set(false);\r\n this.isSubmitting.set(true);\r\n \r\n // Simulate API call\r\n setTimeout(() => {\r\n console.log('Sign in with email:', this.email);\r\n this.isSubmitting.set(false);\r\n this.emailSent.set(true);\r\n // TODO: Implement actual sign-in logic and navigation\r\n }, 1500);\r\n }\r\n\r\n handleBackToLogin(): void {\r\n this.emailSent.set(false);\r\n this.email = '';\r\n this.emailError.set(false);\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","/**\r\n * Post and Comment Models\r\n * Unified data structures for community posts\r\n */\r\n\r\nexport interface Comment {\r\n authorName: string;\r\n authorRole: string;\r\n timestamp: string;\r\n avatarInitials: string;\r\n avatarSrc?: string;\r\n avatarType?: 'photo' | 'initials' | 'icon';\r\n content: string;\r\n likeCount: number;\r\n isLiked?: boolean;\r\n isOwnComment: boolean;\r\n}\r\n\r\nexport interface Post {\r\n id: string;\r\n authorName: string;\r\n authorRole: string;\r\n timestamp: string;\r\n avatarType: 'photo' | 'initials' | 'icon';\r\n avatarSrc?: string;\r\n avatarInitials?: string;\r\n avatarIconName?: string;\r\n content: string;\r\n imageSrc?: string;\r\n imageAlt?: string;\r\n isLiked: boolean;\r\n likeCount: number;\r\n commentCount: number;\r\n comments?: Comment[];\r\n isPinned?: boolean;\r\n showBadge?: boolean;\r\n hasInlinePhotos?: boolean;\r\n inlinePhotos?: string[];\r\n inlinePhotoCount?: number;\r\n}\r\n","/**\r\n * Models Barrel File\r\n * \r\n * Export all application models for easy importing\r\n */\r\n\r\nexport * from './post.model';","/* 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';\nexport * from './models';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.DsMobileLongPressDirective","i2","i1","i1.DsMobileLightboxService","DsMobileCommentActionsBottomSheetComponent","i2.DsMobileBottomSheetService","i3","i1.DsMobileHandbookDetailModalService","DsMobilePostActionsBottomSheetComponent","i3.DsMobileLightboxService","i4.DsMobilePostDetailModalService","i5.UserService","i6.PostsService","i1.UserService","i2.UserService","i3.DsMobileNewInquiryModalService","i2.DsMobileLightboxService","i3.DsMobileChatModalService"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,cAAc,GAAqB;AACvC,IAAA,OAAO,EAAE,uCAAuC;AAChD,IAAA,WAAW,EAAE,uCAAuC;AACpD,IAAA,OAAO,EAAE,YAAY;IACrB,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,SAAS;IACzB,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;AAC3B,IAAA,gBAAgB,EAAE,YAAY;AAC9B,IAAA,cAAc,EAAE;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAIU,iBAAiB,CAAA;AACpB,IAAA,OAAO,GAAG,MAAM,CAAmB,cAAc,mDAAC;;AAGjD,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,mDAAC;AAChD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW,uDAAC;AACxD,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,mDAAC;AAChD,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,UAAU,IAAI,EAAE,sDAAC;AAC5D,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,cAAc,0DAAC;AAC9D,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,cAAc,0DAAC;AAC9D,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,gBAAgB,4DAAC;AAClE,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,gBAAgB,4DAAC;AAClE,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,gBAAgB,4DAAC;AAClE,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,cAAc,0DAAC;;AAG9D,IAAA,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;AAE3C,IAAA,WAAA,GAAA;;AAEE,QAAA,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;;QAGhC,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE;AAC7B,YAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AAC1B,QAAA,CAAC,CAAC;IACJ;AAEA;;;AAGG;AACH,IAAA,UAAU,CAAC,MAAiC,EAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,KAAK;AAC9B,YAAA,GAAG,OAAO;AACV,YAAA,GAAG;AACJ,SAAA,CAAC,CAAC;IACL;AAEA;;;;;AAKG;IACH,MAAM,WAAW,CAAC,cAAuB,EAAA;AACvC,QAAA,IAAI;;;;;AAMF,YAAA,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,cAAc,CAAC;;AAGtE,YAAA,IAAI,cAAc,KAAK,aAAa,EAAE;gBACpC,IAAI,CAAC,UAAU,CAAC;AACd,oBAAA,OAAO,EAAE,6BAA6B;AACtC,oBAAA,WAAW,EAAE,6BAA6B;AAC1C,oBAAA,OAAO,EAAE,aAAa;oBACtB,cAAc,EAAE,SAAS;oBACzB,cAAc,EAAE,SAAS;oBACzB,gBAAgB,EAAE,SAAS;oBAC3B,gBAAgB,EAAE,SAAS;AAC3B,oBAAA,gBAAgB,EAAE,aAAa;AAC/B,oBAAA,cAAc,EAAE;AACjB,iBAAA,CAAC;YACJ;;QAGF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC;;QAE3D;IACF;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,OAAkC,EAAA;AAC7C,QAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;IAC1B;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,MAKZ,EAAA;QACC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,KAAK;AAC9B,YAAA,GAAG,OAAO;AACV,YAAA,GAAG;AACJ,SAAA,CAAC,CAAC;IACL;AAEA;;AAEG;IACH,cAAc,GAAA;AACZ,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAClC;AAEA;;AAEG;AACK,IAAA,QAAQ,CAAC,GAAW,EAAA;QAC1B,MAAM,MAAM,GAAG,2CAA2C,CAAC,IAAI,CAAC,GAAG,CAAC;QACpE,OAAO,MAAM,GAAG;YACd,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC1B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC1B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;SAC1B,GAAG,IAAI;IACV;AAEA;;;;AAIG;AACK,IAAA,WAAW,CAAC,MAAwB,EAAA;AAC1C,QAAA,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;YACnC,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,MAAM;AACrF,YAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe;AACrC,YAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI;YAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC;;YAGhD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,0BAA0B,EAAE,cAAc,CAAC;YAClE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,cAAc,CAAC;YAC5D,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,cAAc,CAAC;YACjE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,0BAA0B,EAAE,cAAc,CAAC;YAClE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,cAAc,CAAC;YAC5D,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,cAAc,CAAC;YACjE,IAAI,MAAM,EAAE;gBACT,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,0BAA0B,EAAE,cAAc,CAAC;gBACpF,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,cAAc,CAAC;gBAC9E,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,cAAc,CAAC;YACtF;;YAGA,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,cAAc,CAAC;YACjE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,cAAc,CAAC;YACjE,IAAI,MAAM,EAAE;gBACT,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,cAAc,CAAC;YACtF;;;YAIA,QAAQ,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,SAAS,IAAG;gBAC7D,SAAyB,CAAC,KAAK,CAAC,WAAW,CAAC,kBAAkB,EAAE,cAAc,CAAC;AAClF,YAAA,CAAC,CAAC;;YAGF,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,gBAAgB,CAAC;YACnE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,EAAE,gBAAgB,CAAC;YACrE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,gBAAgB,CAAC;YACnE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,EAAE,gBAAgB,CAAC;YACrE,IAAI,MAAM,EAAE;gBACT,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,gBAAgB,CAAC;gBACrF,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,EAAE,gBAAgB,CAAC;YAC1F;;YAGA,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,gBAAgB,CAAC;YAClE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,EAAE,gBAAgB,CAAC;YACrE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,gBAAgB,CAAC;YAClE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,EAAE,gBAAgB,CAAC;YACrE,IAAI,MAAM,EAAE;gBACT,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,gBAAgB,CAAC;gBACpF,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,EAAE,gBAAgB,CAAC;YAC1F;;YAGA,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAC3C,IAAI,GAAG,EAAE;AACP,gBAAA,MAAM,QAAQ,GAAG,CAAA,EAAG,GAAG,CAAC,CAAC,CAAA,EAAA,EAAK,GAAG,CAAC,CAAC,CAAA,EAAA,EAAK,GAAG,CAAC,CAAC,EAAE;gBAC/C,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC;gBAC9D,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,+BAA+B,EAAE,QAAQ,CAAC;gBACjE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC;gBAC9D,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,+BAA+B,EAAE,QAAQ,CAAC;gBACjE,IAAI,MAAM,EAAE;oBACT,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC;oBAChF,MAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,+BAA+B,EAAE,QAAQ,CAAC;gBACtF;YACF;;YAGA,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,0BAA0B,CAAC;YACzE,IAAI,cAAc,EAAE;AAClB,gBAAA,cAAc,CAAC,YAAY,CAAC,SAAS,EAAE,gBAAgB,CAAC;YAC1D;;AAGA,YAAA,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,CAAC;AAE5C,YAAA,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;QACnH;IACF;AAEA;;;;AAIG;IACK,MAAM,qBAAqB,CAAC,KAAa,EAAA;AAC/C,QAAA,IAAI;YACF,MAAM,SAAS,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC;QAC/C;QAAE,OAAO,CAAC,EAAE;;;QAGZ;IACF;wGAvNW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cAFhB,MAAM,EAAA,CAAA;;4FAEP,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAH7B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACzDD;;;;;;;;;;;;;;;;AAgBG;MA4BU,eAAe,CAAA;AAC1B,IAAA,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAEpC,OAAO,GAAgB,MAAM;IAC7B,IAAI,GAAa,IAAI;AACrB,IAAA,YAAY;AACZ,IAAA,WAAW;AAEpB,IAAA,IAAI,OAAO,GAAA;QACT,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;QAChD,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE;AAExD,QAAA,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE;;YAE3B,OAAO,OAAO,IAAI,WAAW;QAC/B;aAAO;;YAEL,OAAO,WAAW,IAAI,OAAO;QAC/B;IACF;AAEA,IAAA,IAAI,OAAO,GAAA;QACT,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;AAC5C,QAAA,OAAO,IAAI,CAAC,OAAO,KAAK,MAAM,GAAG,GAAG,GAAG,CAAA,EAAG,GAAG,OAAO;IACtD;AAEA;;AAEG;AACH,IAAA,IAAI,eAAe,GAAA;QACjB,OAAO,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE;IACjE;wGA/BW,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,MAAA,EAAA,YAAA,EAAA,cAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAVhB,CAAA;;;;;;;;AAQT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,kHAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAtBS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAwBX,eAAe,EAAA,UAAA,EAAA,CAAA;kBA3B3B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,SAAS,cACP,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,QAAA,EAcb,CAAA;;;;;;;;AAQT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,kHAAA,CAAA,EAAA;;sBAKA;;sBACA;;sBACA;;sBACA;;;AC9CH;;;;;;;;;;;;AAYG;MAEmB,cAAc,CAAA;AAClC;;;;;;;;;;;;;;;;;;;;;AAqBG;AACH,IAAA,YAAY,GAAG,KAAK,CAAe,UAAU,wDAAC;AAE9C;;;;;AAKG;AACO,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;AACtC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE;AAE7B,QAAA,MAAM,QAAQ,GAAiC;AAC7C,YAAA,QAAQ,EAAE,OAAO;AACjB,YAAA,UAAU,EAAE,QAAQ;AACpB,YAAA,MAAM,EAAE,QAAQ;AAChB,YAAA,MAAM,EAAE;SACT;AAED,QAAA,OAAO,QAAQ,CAAC,CAAC,CAAC;AACpB,IAAA,CAAC,yDAAC;wGA1CkB,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAd,cAAc,EAAA,YAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAAd,cAAc,EAAA,UAAA,EAAA,CAAA;kBADnC;;;ACdD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;MAKU,0BAA0B,CAAA;AACrC;;;AAGG;IACM,iBAAiB,GAAG,GAAG;AAEhC;;;AAGG;IACM,aAAa,GAAG,EAAE;AAE3B;;;AAGG;IACM,gBAAgB,GAAG,qDAAqD;AAEjF;;;AAGG;AACM,IAAA,WAAW,GAAgB,WAAW,CAAC,MAAM;AAEtD;;;AAGG;IACM,aAAa,GAAG,IAAI;AAE7B;;AAEG;AACO,IAAA,SAAS,GAAG,IAAI,YAAY,EAAQ;AAE9C;;AAEG;AACO,IAAA,cAAc,GAAG,IAAI,YAAY,EAAQ;AAEnD;;AAEG;AACO,IAAA,eAAe,GAAG,IAAI,YAAY,EAAQ;IAE5C,cAAc,GAAQ,IAAI;IAC1B,kBAAkB,GAAG,KAAK;IAC1B,WAAW,GAAG,CAAC;IACf,WAAW,GAAG,CAAC;AAEvB;;AAEG;AAEH,IAAA,gBAAgB,CAAC,KAAiB,EAAA;;;AAGhC,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB;QAC1C,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC;AAC7D,QAAA,MAAM,WAAW,GAAI,KAAK,CAAC,aAA6B;;AAGxD,QAAA,IAAI,eAAe,IAAI,eAAe,KAAK,WAAW,EAAE;YACtD;QACF;AAEA,QAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QAC/B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;QAC3C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;;AAG3C,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE;;AAG1B,QAAA,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,YAAW;AAC1C,YAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;;AAGrB,YAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACtB,gBAAA,MAAM,IAAI,CAAC,cAAc,EAAE;YAC7B;AACF,QAAA,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC;IAC5B;AAEA;;AAEG;AAEH,IAAA,cAAc,CAAC,KAAiB,EAAA;AAC9B,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;AAE1B,YAAA,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;AAC5B,gBAAA,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE;YAC7B;QACF;;AAGA,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,KAAK,CAAC,cAAc,EAAE;YACtB,KAAK,CAAC,eAAe,EAAE;AACvB,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QACjC;IACF;AAEA;;AAEG;AAEH,IAAA,eAAe,CAAC,KAAiB,EAAA;QAC/B,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE;QAE1B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;;AAGzD,QAAA,IAAI,MAAM,GAAG,IAAI,CAAC,aAAa,IAAI,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE;AAC9D,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;AAC1B,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;AAC/B,YAAA,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE;QAC7B;IACF;AAEA;;AAEG;AAEH,IAAA,iBAAiB,CAAC,KAAY,EAAA;QAC5B,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA;;AAEG;AACK,IAAA,MAAM,cAAc,GAAA;AAC1B,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QACnD;AAAE,QAAA,MAAM;;AAEN,YAAA,IAAI,SAAS,IAAI,SAAS,EAAE;;AAE1B,gBAAA,MAAM,YAAY,GAAG;AACnB,oBAAA,CAAC,WAAW,CAAC,KAAK,GAAG,EAAE;AACvB,oBAAA,CAAC,WAAW,CAAC,MAAM,GAAG,EAAE;AACxB,oBAAA,CAAC,WAAW,CAAC,KAAK,GAAG;iBACtB;AACD,gBAAA,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YACzD;QACF;IACF;AAEA;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;QAC5B;IACF;wGArKW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA1B,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,WAAA,EAAA,aAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,YAAA,EAAA,0BAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,WAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,2BAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAA1B,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAJtC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,qBAAqB;AAC/B,oBAAA,UAAU,EAAE;AACb,iBAAA;;sBAME;;sBAMA;;sBAMA;;sBAMA;;sBAMA;;sBAKA;;sBAKA;;sBAKA;;sBAUA,YAAY;uBAAC,YAAY,EAAE,CAAC,QAAQ,CAAC;;sBAmCrC,YAAY;uBAAC,UAAU,EAAE,CAAC,QAAQ,CAAC;;sBAsBnC,YAAY;uBAAC,WAAW,EAAE,CAAC,QAAQ,CAAC;;sBAoBpC,YAAY;uBAAC,aAAa,EAAE,CAAC,QAAQ,CAAC;;;AC3KzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDG;MAuPU,yBAAyB,CAAA;AAC5B,IAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;AAExC;;;AAGG;AACH,IAAA,SAAS,GAAG,MAAM,CAAU,KAAK,qDAAC;AAElC,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;;AAEtC,YAAA,MAAM,iBAAiB,GAAG,MAAM,CAAC,UAAU,IAAI,GAAG;AAElD,YAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE;gBAC3C,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B;AACD,aAAA,CAAC;AAEF,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC;;AAGrC,YAAA,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAK;AACrC,gBAAA,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,IAAI,GAAG;AAC7C,gBAAA,IAAI,YAAY,KAAK,IAAI,CAAC,SAAS,EAAE,EAAE;AACrC,oBAAA,OAAO,CAAC,GAAG,CAAC,0DAA0D,EAAE,YAAY,CAAC;AACrF,oBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC;gBAClC;AACF,YAAA,CAAC,CAAC;QACJ;IACF;AAEA;;;AAGG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,MAAM,uDAAC;AAEnC;;;;AAIG;AACH,IAAA,OAAO,GAAG,KAAK,CAAwB,SAAS,mDAAC;AAEjD;;;;;AAKG;AACH,IAAA,KAAK,GAAG,KAAK,CAA8B,KAAK,iDAAC;AAEjD;;;AAGG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,KAAK,uDAAC;AAEnC;;;AAGG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAEhC;;;AAGG;AACH,IAAA,OAAO,GAAG,KAAK,CAAU,KAAK,mDAAC;AAE/B;;;AAGG;AACH,IAAA,eAAe,GAAG,KAAK,CAAU,IAAI,2DAAC;AAEtC;;;;;AAKG;AACH,IAAA,qBAAqB,GAAG,KAAK,CAAU,IAAI,iEAAC;AAE5C;;;;AAIG;AACH,IAAA,iBAAiB,GAAG,KAAK,CAAS,KAAK,6DAAC;AAExC;;;AAGG;IACH,KAAK,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAU;AAEvB;;;AAGG;IACH,QAAQ,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,UAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAU;AAE1B;;;;AAIG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,IAAI,uDAAC;AAElC;;;AAGG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,KAAK,0DAAC;AAErC;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;;;AAIG;IACH,eAAe,GAAG,MAAM,EAAS;AAEjC;;AAEG;IACK,kBAAkB,GAAG,KAAK;AAElC;;;AAGG;IACH,iBAAiB,GAAG,QAAQ,CAAC,MAAM,IAAI,6DAAC;AAExC;;;AAGG;IACH,kBAAkB,GAAG,QAAQ,CAAC,MAAM,IAAI,8DAAC;AAEzC;;AAEG;AACH,IAAA,WAAW,CAAC,KAAY,EAAA;AACtB,QAAA,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE;AAC1C,YAAA,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;AAC/B,YAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;AACzB,YAAA,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;YACvB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,MAAM,EAAE,KAAK,CAAC;AACf,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;AAC5D,YAAA,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC;YAC7E;QACF;;;AAIA,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB;QAC1C,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,qDAAqD,CAAC;;QAGhG,IAAI,kBAAkB,IAAI,kBAAkB,KAAK,KAAK,CAAC,aAAa,EAAE;AACpE,YAAA,OAAO,CAAC,GAAG,CAAC,yDAAyD,EAAE,kBAAkB,CAAC;YAC1F;QACF;AAEA,QAAA,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;AAC5B,YAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;AAC5C,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;QACvB;aAAO;AACL,YAAA,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC;QACpE;AAEA,QAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;IACjC;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,KAAY,EAAA;AACxB,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;YAC5D;QACF;QAEA,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA;;;AAGG;IACH,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI;;QAE9B,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QACjC,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;;;AAIG;AACH,IAAA,qBAAqB,CAAC,KAAY,EAAA;AAChC,QAAA,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC;;QAGrD,KAAK,CAAC,eAAe,EAAE;QACvB,KAAK,CAAC,cAAc,EAAE;;AAGtB,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;IAClC;wGA9NW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAzB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,qBAAA,EAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,UAAA,EAAA,uBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,qBAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,WAAA,EAAA,mBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,mBAAA,EAAA,8BAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,eAAA,EAAA,WAAA,EAAA,kBAAA,EAAA,gBAAA,EAAA,uBAAA,EAAA,2BAAA,EAAA,iBAAA,EAAA,qBAAA,EAAA,oBAAA,EAAA,wBAAA,EAAA,oBAAA,EAAA,wBAAA,EAAA,WAAA,EAAA,mCAAA,EAAA,eAAA,EAAA,6CAAA,EAAA,oBAAA,EAAA,8BAAA,EAAA,sBAAA,EAAA,eAAA,EAAA,4BAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,kBAAA,EAAA,EAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAAA,0BAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlC1B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,q0FAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAjPS,YAAY,+BAAE,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAmPlC,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAtPrC,SAAS;+BACE,qBAAqB,EAAA,UAAA,EACnB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,qBAAqB,CAAC,EAAA,cAAA,EAC9B;AACd,wBAAA;AACE,4BAAA,SAAS,EAAE,0BAA0B;4BACrC,OAAO,EAAE,CAAC,WAAW;AACtB;qBACF,EAAA,IAAA,EACK;AACJ,wBAAA,qBAAqB,EAAE,8BAA8B;AACrD,wBAAA,kBAAkB,EAAE,YAAY;AAChC,wBAAA,iBAAiB,EAAE,WAAW;AAC9B,wBAAA,oBAAoB,EAAE,gBAAgB;AACtC,wBAAA,yBAAyB,EAAE,yBAAyB;AACpD,wBAAA,mBAAmB,EAAE,mBAAmB;AACxC,wBAAA,sBAAsB,EAAE,sBAAsB;AAC9C,wBAAA,sBAAsB,EAAE,sBAAsB;AAC9C,wBAAA,aAAa,EAAE,iCAAiC;AAChD,wBAAA,iBAAiB,EAAE,2CAA2C;AAC9D,wBAAA,sBAAsB,EAAE,4BAA4B;AACpD,wBAAA,wBAAwB,EAAE,eAAe;AACzC,wBAAA,8BAA8B,EAAE,qBAAqB;AACrD,wBAAA,2BAA2B,EAAE,kBAAkB;AAC/C,wBAAA,SAAS,EAAE,qBAAqB;AAChC,wBAAA,iBAAiB,EAAE,uBAAuB;AAC1C,wBAAA,iBAAiB,EAAE,uBAAuB;AAC1C,wBAAA,aAAa,EAAE;qBAChB,EAAA,QAAA,EAuLS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,q0FAAA,CAAA,EAAA;;;AC/SH;;;;;;;;;;;;;;;;;;AAkBG;MA+CU,+BAA+B,CAAA;AAC1C;;AAEG;AACH,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAU;AAEhC;;;AAGG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,KAAK,uDAAC;AAEnC;;;AAGG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAEhC;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;wGArBf,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA1ChC,CAAA;;;;;;;;;;;;;AAaT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6WAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAdS,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,SAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,mBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,aAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA2CxB,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBA9C3C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,4BAA4B,cAC1B,IAAI,EAAA,OAAA,EACP,CAAC,yBAAyB,CAAC,EAAA,QAAA,EAC1B,CAAA;;;;;;;;;;;;;AAaT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,6WAAA,CAAA,EAAA;;;AClBH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDG;MAuGU,mCAAmC,CAAA;AAgF1B,IAAA,eAAA;AA/EpB;;AAEG;AACM,IAAA,kBAAkB;AAE3B;;AAEG;IACM,YAAY,GAAY,KAAK;AAEtC;;AAEG;AACH,IAAA,YAAY,GAAG,QAAQ,CAAgB,MAAK;;AAE1C,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,OAAO,IAAI,CAAC,kBAAkB;QAChC;;AAGA,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;;YAErB,OAAO;AACL,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA;AACE,4BAAA,MAAM,EAAE,MAAM;AACd,4BAAA,KAAK,EAAE,SAAS;AAChB,4BAAA,IAAI,EAAE,eAAe;AACrB,4BAAA,WAAW,EAAE;AACd,yBAAA;AACD,wBAAA;AACE,4BAAA,MAAM,EAAE,QAAQ;AAChB,4BAAA,KAAK,EAAE,MAAM;AACb,4BAAA,IAAI,EAAE,oBAAoB;AAC1B,4BAAA,WAAW,EAAE;AACd;AACF;AACF,iBAAA;AACD,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA;AACE,4BAAA,MAAM,EAAE,MAAM;AACd,4BAAA,KAAK,EAAE,UAAU;AACjB,4BAAA,IAAI,EAAE,iBAAiB;AACvB,4BAAA,WAAW,EAAE;AACd,yBAAA;AACD,wBAAA;AACE,4BAAA,MAAM,EAAE,OAAO;AACf,4BAAA,KAAK,EAAE,MAAM;AACb,4BAAA,IAAI,EAAE,gBAAgB;AACtB,4BAAA,WAAW,EAAE;AACd;AACF;AACF;aACF;QACH;aAAO;;YAEL,OAAO;AACL,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA;AACE,4BAAA,MAAM,EAAE,MAAM;AACd,4BAAA,KAAK,EAAE,UAAU;AACjB,4BAAA,IAAI,EAAE,iBAAiB;AACvB,4BAAA,WAAW,EAAE;AACd,yBAAA;AACD,wBAAA;AACE,4BAAA,MAAM,EAAE,OAAO;AACf,4BAAA,KAAK,EAAE,MAAM;AACb,4BAAA,IAAI,EAAE,gBAAgB;AACtB,4BAAA,WAAW,EAAE;AACd;AACF;AACF;aACF;QACH;AACF,IAAA,CAAC,wDAAC;AAEF,IAAA,WAAA,CAAoB,eAAgC,EAAA;QAAhC,IAAA,CAAA,eAAe,GAAf,eAAe;IAAoB;AAEvD;;AAEG;AACH,IAAA,YAAY,CAAC,MAAc,EAAA;QACzB,IAAI,CAAC,eAAe,CAAC,OAAO,CAC1B,EAAE,MAAM,EAAkB,EAC1B,QAAQ,CACT;IACH;wGA1FW,mCAAmC,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mCAAmC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gCAAA,EAAA,MAAA,EAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlGpC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,8oCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA9BS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,+BAA+B,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,aAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAmG7D,mCAAmC,EAAA,UAAA,EAAA,CAAA;kBAtG/C,SAAS;+BACE,gCAAgC,EAAA,UAAA,EAC9B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,EAAE,+BAA+B,CAAC,EAAA,QAAA,EAC/D,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,8oCAAA,CAAA,EAAA;;sBAyEA;;sBAKA;;;ACxJH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;MAIU,0BAA0B,CAAA;AACjB,IAAA,eAAA;AAApB,IAAA,WAAA,CAAoB,eAAgC,EAAA;QAAhC,IAAA,CAAA,eAAe,GAAf,eAAe;IAAoB;AAEvD;;;;;AAKG;IACH,MAAM,MAAM,CAAC,OAA2B,EAAA;QACtC,MAAM,EACJ,SAAS,EACT,cAAc,GAAG,EAAE,EACnB,WAAW,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAC3B,iBAAiB,GAAG,GAAG,EACvB,MAAM,GAAG,IAAI,EACb,QAAQ,GAAG,EAAE,EACb,eAAe,GAAG,IAAI,EACtB,eAAe,EACf,YAAY,GAAG,KAAK,EACpB,aAAa,GAAG,IAAI,EACpB,UAAU,GAAG,KAAK,EACnB,GAAG,OAAO;;AAGX,QAAA,MAAM,UAAU,GAAG,CAAC,iBAAiB,CAAC;QACtC,IAAI,YAAY,EAAE;AAChB,YAAA,UAAU,CAAC,IAAI,CAAC,uBAAuB,CAAC;QAC1C;QACA,IAAI,UAAU,EAAE;AACd,YAAA,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC;QAChC;AACA,QAAA,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAC5C,YAAA,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC3B;AAAO,aAAA,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;AAClC,YAAA,UAAU,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;QAC9B;QAEA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;YAC9C,SAAS;YACT,cAAc;YACd,WAAW,EAAE,UAAU,GAAG,SAAS,GAAG,WAAW;YACjD,iBAAiB,EAAE,UAAU,GAAG,SAAS,GAAG,iBAAiB;YAC7D,MAAM,EAAE,UAAU,GAAG,KAAK,GAAG,MAAM;AACnC,YAAA,QAAQ,EAAE,UAAU;YACpB,eAAe;YACf,aAAa;AACb,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,UAAU,EAAE,eAAe;;AAE3B,YAAA,QAAQ,EAAE,IAAI;YACd,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,IAAI,eAAe,KAAK,SAAS,IAAI;AACnC,gBAAA,QAAQ,EAAE,CAAC,GAAG,UAAU,EAAE,kCAAkC;aAC7D;AACF,SAAA,CAAC;;AAGF,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;AACjC,YAAA,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,eAAe,CAAC,QAAQ,EAAE,CAAC;QAC3E;;AAGA,QAAA,MAAM,aAAa,GAAG,CAAC,KAAoB,KAAI;AAC7C,YAAA,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE;AAC1B,gBAAA,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;YACpC;AACF,QAAA,CAAC;;AAGD,QAAA,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,MAAK;AAChD,YAAA,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC;AACrD,QAAA,CAAC,CAAC;;AAGF,QAAA,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,MAAK;AAChD,YAAA,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC;AACxD,QAAA,CAAC,CAAC;AAEF,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;;;AAIrB,QAAA,OAAO,KAAK;IACd;AAEA;;AAEG;AACH,IAAA,MAAM,OAAO,CAAC,IAAU,EAAE,IAAa,EAAA;QACrC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;IACjD;AAEA;;AAEG;AACH,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;IACtC;wGAnGW,0BAA0B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,0BAA0B,cAFzB,MAAM,EAAA,CAAA;;4FAEP,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAHtC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACtDD;;;;;;;;;;AAUG;MAsVU,sCAAsC,CAAA;AAuBvC,IAAA,eAAA;AACA,IAAA,UAAA;AAvBkB,IAAA,aAAa;AACjB,IAAA,SAAS;;IAGjC,SAAS,GAAG,IAAI;;IAGhB,UAAU,GAAG,IAAI;;IAGjB,UAAU,GAAG,KAAK;AAClB,IAAA,MAAM;IACN,cAAc,GAAG,EAAE;IAEnB,WAAW,GAAG,EAAE;AAChB,IAAA,cAAc,GAAG,MAAM,CAAW,EAAE,0DAAC;AACrC,IAAA,QAAQ,GAAG,MAAM,CAAC,gBAAgB,oDAAC;AACnC,IAAA,WAAW,GAAG,MAAM,CAAC,cAAc,uDAAC;AACpC,IAAA,UAAU,GAAG,MAAM,CAAC,YAAY,sDAAC;AACjC,IAAA,iBAAiB,GAAG,MAAM,CAAC,QAAQ,6DAAC;IAEpC,WAAA,CACU,eAAgC,EAChC,UAAsB,EAAA;QADtB,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,UAAU,GAAV,UAAU;IACjB;AAEH;;;AAGG;IACK,sBAAsB,GAAA;AAC5B,QAAA,IAAI;AACF,YAAA,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa;YAClD,IAAI,WAAW,EAAE;gBACf,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,CAAC,YAAY,CAAC;gBACtD,IAAI,MAAM,EAAE;oBACV,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC;oBACnD,IAAI,OAAO,EAAE;wBACX,MAAM,cAAc,GAAG,OAAsB;;wBAE7C,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,WAAW,CAAC;wBACtE,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,CAAC;oBACvE;gBACF;YACF;QACF;QAAE,OAAO,CAAC,EAAE;AACV,YAAA,OAAO,CAAC,GAAG,CAAC,wCAAwC,EAAE,CAAC,CAAC;QAC1D;IACF;IAEA,QAAQ,GAAA;;QAEN,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,cAAc,EAAE;AAC1C,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,cAAc;AACtC,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC;AACrC,YAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;QACnC;IACF;IAEA,eAAe,GAAA;;QAEb,IAAI,CAAC,sBAAsB,EAAE;;QAG7B,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE;YAC1C,UAAU,CAAC,MAAK;gBACd,IAAI,CAAC,cAAc,EAAE;YACvB,CAAC,EAAE,CAAC,CAAC;QACP;;;QAIA,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE;AACxC,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa;;AAGjD,YAAA,IAAI,CAAC,UAAU,GAAG,KAAK;;YAGvB,UAAU,CAAC,MAAK;gBACd,QAAQ,CAAC,KAAK,EAAE;gBAChB,QAAQ,CAAC,KAAK,EAAE;;AAGhB,gBAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;;gBAGxE,UAAU,CAAC,MAAK;oBACd,QAAQ,CAAC,KAAK,EAAE;AAChB,oBAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;gBAC1E,CAAC,EAAE,GAAG,CAAC;YACT,CAAC,EAAE,EAAE,CAAC;QACR;IACF;AAEA;;;;AAIG;IACH,eAAe,GAAA;;QAEb,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE;YAC1C,IAAI,CAAC,cAAc,EAAE;QACvB;;QAGA,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE;AACxC,YAAA,IAAI,CAAC,UAAU,GAAG,KAAK;AACvB,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa;;YAGjD,QAAQ,CAAC,KAAK,EAAE;YAChB,QAAQ,CAAC,KAAK,EAAE;;AAGhB,YAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;;AAGxE,YAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM;AACpC,YAAA,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC;QAC5C;IACF;IAEA,WAAW,GAAA;;AAET,QAAA,IAAI,CAAC,UAAU,GAAG,KAAK;;AAEvB,QAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC1E;IAEA,WAAW,GAAA;QACT,IAAI,CAAC,cAAc,EAAE;IACvB;AAEA;;AAEG;IACK,cAAc,GAAA;AACpB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACtB,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa;;AAEjD,YAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;;AAE9B,YAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,GAAG,IAAI;QACrE;IACF;IAEA,OAAO,GAAA;AACL,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,GAAG,CAAC;IAC/E;AAEA,IAAA,MAAM,YAAY,GAAA;QAChB,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;;AAE1E,YAAA,MAAM,SAAS,GAAG,OAAO,CAAC,sBAAsB,CAAC;YACjD,IAAI,SAAS,EAAE;gBACb,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;YACpD;QACF;aAAO;YACL,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;QACpD;IACF;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE;AAErB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,YAAA,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC;QAC9D;aAAO;AACL,YAAA,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC;QAC/F;;AAGA,QAAA,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAChC;YACE,OAAO,EAAE,IAAI,CAAC,WAAW;AACzB,YAAA,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE;YAC7B,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,MAAM,EAAE,IAAI,CAAC,UAAU;YACvB,MAAM,EAAE,IAAI,CAAC;SACd,EACD,MAAM,CACP;IACH;AAEA,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;;;QAIvC,IAAI,CAAC,sBAAsB,EAAE;AAE7B,QAAA,IAAI;AACF,YAAA,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC;AAE/C,YAAA,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;AAClC,gBAAA,OAAO,EAAE,EAAE;AACX,gBAAA,YAAY,EAAE,KAAK;gBACnB,UAAU,EAAE,gBAAgB,CAAC,GAAG;AAChC,gBAAA,MAAM,EAAE,YAAY,CAAC,MAAM;AAC5B,aAAA,CAAC;AAEF,YAAA,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,KAAK,CAAC;;AAGlD,YAAA,IAAI,KAAK,CAAC,OAAO,EAAE;AACjB,gBAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,OAAQ,CAAC,CAAC;gBACjE,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,KAAK,CAAC,OAAO,CAAC;YACvD;;;YAIA,qBAAqB,CAAC,MAAK;gBACzB,IAAI,CAAC,sBAAsB,EAAE;AAC/B,YAAA,CAAC,CAAC;;YAGF,IAAI,CAAC,gBAAgB,EAAE;QAEzB;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC;;YAE9C,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE;AAC5D,gBAAA,MAAM,YAAY,GAAI,KAAa,CAAC,OAAO;gBAC3C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;oBACpC,KAAK,CAAC,CAAA,uBAAA,EAA0B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA,CAAE,CAAC;gBAC1D;YACF;QACF;IACF;AAEA;;;AAGG;IACK,gBAAgB,GAAA;QACtB,UAAU,CAAC,YAAW;AACpB,YAAA,IAAI;gBACF,MAAM,SAAS,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;gBACxD,MAAM,SAAS,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACxD;YAAE,OAAO,CAAC,EAAE;;YAEZ;QACF,CAAC,EAAE,CAAC,CAAC;IACP;AAEA,IAAA,iBAAiB,CAAC,KAAa,EAAA;AAC7B,QAAA,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,KAAK,CAAC;QAC9C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC;IAC5E;IAEA,mBAAmB,GAAA;AACjB,QAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;;AAE5C,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE;QACtC;IACF;AAEA,IAAA,gBAAgB,CAAC,KAAY,EAAA;AAC3B,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;AAC9C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;QAEzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;AAChC,YAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;YAChC;QACF;QAEA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC;;QAG5C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,IAAG;AAC/B,YAAA,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;;AAGrD,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAI;AACpB,gBAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAgB;gBACzC,IAAI,MAAM,EAAE;;AAEV,oBAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC;oBACzD,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,CAAC;gBAClD;AACF,YAAA,CAAC;AACD,YAAA,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;AAC5B,QAAA,CAAC,CAAC;;AAGF,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;wGAnSW,sCAAsC,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sCAAsC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oCAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,eAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,eAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhGvC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8FT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,miGAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA/UC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,SAAS,oGACT,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,iBAAiB,qOACjB,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAyUZ,sCAAsC,EAAA,UAAA,EAAA,CAAA;kBArVlD,SAAS;+BACE,oCAAoC,EAAA,UAAA,EAClC,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,SAAS;wBACT,UAAU;wBACV,QAAQ;wBACR,UAAU;wBACV,UAAU;wBACV,iBAAiB;wBACjB;qBACD,EAAA,QAAA,EAwOS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8FT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,miGAAA,CAAA,EAAA;;sBAGA,SAAS;uBAAC,eAAe;;sBACzB,SAAS;uBAAC,WAAW;;;ACzWxB;;AAEG;MAIU,WAAW,CAAA;;AAEd,IAAA,eAAe,GAAG,MAAM,CAAC,IAAI,2DAAC;AAC9B,IAAA,WAAW,GAAG,MAAM,CAAgC,UAAU,uDAAC;AAC/D,IAAA,UAAU,GAAG,MAAM,CAAC,EAAE,sDAAC;;AAGvB,IAAA,iBAAiB,GAAG,MAAM,CAA4B,SAAS,6DAAC;;AAG/D,IAAA,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE;AAClD,IAAA,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE;AAC1C,IAAA,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AACxC,IAAA,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE;AAE/D;;AAEG;AACH,IAAA,iBAAiB,CAAC,QAAgB,EAAA;AAChC,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC;IACpC;AAEA,IAAA,aAAa,CAAC,IAAmC,EAAA;AAC/C,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;IAC5B;AAEA,IAAA,YAAY,CAAC,GAAW,EAAA;AACtB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;IAC1B;AAEA;;;;AAIG;AACH,IAAA,mBAAmB,CAAC,KAAoB,EAAA;AACtC,QAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;IACnC;wGArCW,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAX,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAW,cAFV,MAAM,EAAA,CAAA;;4FAEP,WAAW,EAAA,UAAA,EAAA,CAAA;kBAHvB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACCD;;;;;;;;;;;;;;;AAeG;MA+EU,0BAA0B,CAAA;AACrC,IAAA,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;;IAGpC,IAAI,GAAe,UAAU;IAC7B,IAAI,GAAe,IAAI;IACvB,QAAQ,GAAW,EAAE;IACrB,GAAG,GAAW,EAAE;IAChB,QAAQ,GAAW,gBAAgB;;IAGnC,SAAS,GAAY,IAAI;IACzB,aAAa,GAAkB,cAAc;AAEtD,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAK;QAC3B,OAAO,CAAA,2BAAA,EAA8B,IAAI,CAAC,aAAa,kBAAkB,IAAI,CAAC,IAAI,CAAA,CAAE;AACtF,IAAA,CAAC,wDAAC;wGAhBS,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,GAAA,EAAA,KAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlB3B,CAAA;;;;;;;;;;;;;;;;GAgBT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ywBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzES,YAAY,+BAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA2E9B,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBA9EtC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,sBAAsB,EAAA,UAAA,EACpB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,CAAC,EAAA,aAAA,EAC3B,iBAAiB,CAAC,QAAQ,EAAA,QAAA,EAwD/B,CAAA;;;;;;;;;;;;;;;;AAgBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ywBAAA,CAAA,EAAA;;sBAMA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAGA;;sBACA;;;AC1GH;;;;;AAKG;MAgaU,4BAA4B,CAAA;AACvC,IAAA,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAErC,IAAA,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;;IAGjD,YAAY,GAAG,SAAS;;IAGxB,oBAAoB,GAAG,SAAS;IAChC,oBAAoB,GAAG,SAAS;IAChC,sBAAsB,GAAG,SAAS;IAClC,sBAAsB,GAAG,SAAS;IAElC,QAAQ,GAAA;QACN,IAAI,CAAC,uBAAuB,EAAE;QAC9B,IAAI,CAAC,kBAAkB,EAAE;IAC3B;AAEA;;AAEG;IACK,kBAAkB,GAAA;QACxB,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,CAAC,WAAW,EAAE;AAEhF,QAAA,IAAI,gBAAgB,KAAK,SAAS,EAAE;AAClC,YAAA,IAAI,CAAC,YAAY,GAAG,KAAK;QAC3B;AAAO,aAAA,IAAI,gBAAgB,KAAK,SAAS,EAAE;AACzC,YAAA,IAAI,CAAC,YAAY,GAAG,KAAK;QAC3B;AAAO,aAAA,IAAI,gBAAgB,KAAK,SAAS,EAAE;AACzC,YAAA,IAAI,CAAC,YAAY,GAAG,OAAO;QAC7B;AAAO,aAAA,IAAI,gBAAgB,KAAK,SAAS,EAAE;AACzC,YAAA,IAAI,CAAC,YAAY,GAAG,SAAS;QAC/B;aAAO;AACL,YAAA,IAAI,CAAC,YAAY,GAAG,SAAS;QAC/B;IACF;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;IAChC;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,uCAAuC;AAChD,YAAA,WAAW,EAAE,uCAAuC;AACpD,YAAA,OAAO,EAAE,YAAY;AACrB,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,YAAY;AAC9B,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,4BAA4B;AACrC,YAAA,WAAW,EAAE,4BAA4B;AACzC,YAAA,OAAO,EAAE,KAAK;AACd,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,KAAK;AACvB,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,4BAA4B;AACrC,YAAA,WAAW,EAAE,4BAA4B;AACzC,YAAA,OAAO,EAAE,KAAK;AACd,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,KAAK;AACvB,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,YAAY,GAAG,OAAO;AAC3B,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,8BAA8B;AACvC,YAAA,WAAW,EAAE,8BAA8B;AAC3C,YAAA,OAAO,EAAE,OAAO;AAChB,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,OAAO;AACzB,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,gCAAgC;AACzC,YAAA,WAAW,EAAE,oCAAoC;AACjD,YAAA,OAAO,EAAE,SAAS;AAClB,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;YAClC,cAAc,EAAE,IAAI,CAAC,oBAAoB;YACzC,cAAc,EAAE,IAAI,CAAC,oBAAoB;YACzC,gBAAgB,EAAE,IAAI,CAAC,sBAAsB;YAC7C,gBAAgB,EAAE,IAAI,CAAC;AACxB,SAAA,CAAC;IACJ;IAEQ,uBAAuB,GAAA;QAC7B,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE;QACnE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE;QACnE,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE;QACvE,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE;IACzE;wGAhJW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA5B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAvJ7B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqJT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,y3GAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzZC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,UAAU,wKACV,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,cAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC1B,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAsZZ,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBA/ZxC,SAAS;+BACE,0BAA0B,EAAA,UAAA,EACxB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,UAAU;wBACV,eAAe;wBACf,0BAA0B;wBAC1B;qBACD,EAAA,OAAA,EACQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EA6PvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqJT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,y3GAAA,CAAA,EAAA;;;ACxaH;;;;;;;;;;;;;;AAcG;MAIU,0BAA0B,CAAA;AACjB,IAAA,eAAA;AAApB,IAAA,WAAA,CAAoB,eAAgC,EAAA;QAAhC,IAAA,CAAA,eAAe,GAAf,eAAe;IAAoB;AAEvD;;;;AAIG;AACH,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,IAAI;AACF,YAAA,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC;YAE/C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;AAC9C,gBAAA,SAAS,EAAE,4BAA4B;AACvC,gBAAA,QAAQ,EAAE,0BAA0B;AACpC,gBAAA,IAAI,EAAE,KAAK;gBACX,iBAAiB,EAAE,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,IAAI,SAAS;AAC3E,gBAAA,eAAe,EAAE,IAAI;AACrB,gBAAA,YAAY,EAAE,IAAI;AAClB,gBAAA,QAAQ,EAAE,IAAI;AACd,gBAAA,aAAa,EAAE,IAAI;;gBAEnB,cAAc,EAAE,SAAS;gBACzB,cAAc,EAAE,SAAS;AAC1B,aAAA,CAAC;AAEF,YAAA,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC;AACjE,YAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AACrB,YAAA,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC;QACtD;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC;AAClE,YAAA,MAAM,KAAK;QACb;IACF;AAEA;;;;;AAKG;IACH,MAAM,KAAK,CAAC,IAAU,EAAA;QACpB,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C;AAEA;;;;AAIG;AACH,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;IACtC;wGApDW,0BAA0B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,0BAA0B,cAFzB,MAAM,EAAA,CAAA;;4FAEP,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAHtC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACAD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCG;AAkGG,MAAO,yBAA0B,SAAQ,cAAc,CAAA;AAqEvC,IAAA,UAAA;AApEG,IAAA,UAAU;;AAGzB,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC3B,IAAA,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;AACzC,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACjC,IAAA,mBAAmB,GAAG,MAAM,CAAC,0BAA0B,CAAC;;AAGhE,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC,4DAC9B;;AAGD,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAU,CAAC;AACjC,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,aAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;AAChC,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;;AAGlC,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAC7D,IAAA,cAAc,GAAG,KAAK,CAAS,GAAG,0DAAC;AACnC,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAC7B,IAAA,cAAc,GAAG,KAAK,CAAS,gBAAgB,0DAAC;;AAGhD,IAAA,WAAW,GAAG,KAAK,CAAU,IAAI,uDAAC;AAClC,IAAA,mBAAmB,GAAG,KAAK,CAAU,IAAI,+DAAC;AAC1C,IAAA,eAAe,GAAG,KAAK,CAAS,GAAG,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;AACrC,IAAA,kBAAkB,GAAG,KAAK,CAAS,GAAG,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,oBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;AAoBG;AACH,IAAA,gBAAgB,GAAG,KAAK,CAA4B,SAAS,4DAAC;;IAG9D,WAAW,GAAG,MAAM,EAAQ;AAE5B;;;AAGG;IACH,qBAAqB,GAAG,MAAM,EAAgB;IAE9C,OAAO,GAAG,MAAM,EAAO;IACvB,MAAM,GAAG,MAAM,EAAO;AAEtB,IAAA,WAAA,CAAoB,UAAsB,EAAA;AACxC,QAAA,KAAK,EAAE;QADW,IAAA,CAAA,UAAU,GAAV,UAAU;IAE9B;IAEA,eAAe,GAAA;;IAEf;AAEA;;AAEG;AACH,IAAA,MAAM,iBAAiB,GAAA;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC;;AAG5D,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;;AAGvB,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE,IAAI;AAClF,YAAA;AACE,gBAAA,OAAO,EAAE;AACP,oBAAA;AACE,wBAAA,MAAM,EAAE,SAAS;AACjB,wBAAA,KAAK,EAAE,YAAY;AACnB,wBAAA,IAAI,EAAE,gBAAgB;AACtB,wBAAA,WAAW,EAAE;AACd,qBAAA;AACD,oBAAA;AACE,wBAAA,MAAM,EAAE,UAAU;AAClB,wBAAA,KAAK,EAAE,eAAe;AACtB,wBAAA,IAAI,EAAE,oBAAoB;AAC1B,wBAAA,WAAW,EAAE;AACd;AACF;AACF,aAAA;AACD,YAAA;AACE,gBAAA,OAAO,EAAE;AACP,oBAAA;AACE,wBAAA,MAAM,EAAE,QAAQ;AAChB,wBAAA,KAAK,EAAE,QAAQ;AACf,wBAAA,IAAI,EAAE,oBAAoB;AAC1B,wBAAA,WAAW,EAAE;AACd;AACF;AACF;SACF;;QAGD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;YACxC;QACF;QAEA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;AAC9C,YAAA,SAAS,EAAE,mCAAmC;AAC9C,YAAA,cAAc,EAAE;AACd,gBAAA,kBAAkB,EAAE;AACrB,aAAA;;AAED,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;AAEF,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AAErB,QAAA,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAgB;AACxD,QAAA,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE;;YAEvB,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,iBAAiB,EAAE;AAC5C,gBAAA,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;;gBAEzC,UAAU,CAAC,YAAW;AACpB,oBAAA,IAAI;AACF,wBAAA,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE;oBACvC;oBAAE,OAAO,KAAK,EAAE;AACd,wBAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC;oBAC/D;gBACF,CAAC,EAAE,GAAG,CAAC;YACT;;YAGA,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QAC9C;IACF;AAEA;;;;;AAKG;AACH,IAAA,YAAY,CAAC,KAAU,EAAA;AACrB,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS;AACxC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,4BAA4B,CAAC;AACxF,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,oBAAoB,CAAC;;AAG1F,QAAA,IAAI,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE;AACtC,YAAA,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC1C;aAAO;AACL,YAAA,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAC7C;;QAGA,IAAI,gBAAgB,EAAE;AACpB,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE;AAC9C,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC,CAAC;;AAG1D,YAAA,MAAM,OAAO,GAAG,CAAC,GAAG,YAAY;;AAGhC,YAAA,MAAM,UAAU,GAAG,YAAY,GAAG,CAAC,EAAE;;YAGrC,gBAAgB,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE;YACnD,gBAAgB,CAAC,KAAK,CAAC,SAAS,GAAG,CAAA,WAAA,EAAc,UAAU,KAAK;QAClE;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB;AAEA;;;AAGG;IACH,MAAM,aAAa,CAAC,KAAU,EAAA;;AAE5B,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;QACrD;AAAE,QAAA,MAAM;;AAEN,YAAA,IAAI,SAAS,IAAI,SAAS,EAAE;AAC1B,gBAAA,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB;QACF;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;IAC1B;wGA7MW,yBAAyB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAzB,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,mBAAA,EAAA,EAAA,iBAAA,EAAA,qBAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,uBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,YAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EACzB,UAAU,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhFX,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,24IAAA,EAAA,oxBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3FC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,SAAS,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,UAAU,mFACV,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,YAAY,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,eAAA,EAAA,UAAA,EAAA,MAAA,EAAA,YAAA,EAAA,SAAA,EAAA,SAAA,EAAA,kBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,mBAAmB,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,aAAA,EAAA,mBAAA,EAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,iBAAiB,mIACjB,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,cAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAqFN,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAjGrC,SAAS;+BACE,qBAAqB,EAAA,UAAA,EACnB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,SAAS;wBACT,UAAU;wBACV,QAAQ;wBACR,UAAU;wBACV,YAAY;wBACZ,mBAAmB;wBACnB,iBAAiB;wBACjB;qBACD,EAAA,QAAA,EAKS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,24IAAA,EAAA,oxBAAA,CAAA,EAAA;;sBAGA,SAAS;uBAAC,UAAU;;;ACpJvB;;;;;;;;;;;;;;;;;;AAkBG;MAoFU,2BAA2B,CAAA;AACtC;;AAEG;AACH,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,+CAAmB;AAExC;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,oDAAU;AAEpC;;AAEG;IACH,SAAS,GAAG,MAAM,EAAU;AAE5B,IAAA,cAAc,CAAC,KAAa,EAAA;AAC1B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;IAC5B;wGAlBW,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA3B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlB5B,CAAA;;;;;;;;;;;;;;;;AAgBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wmCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA9ES,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAgFX,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAnFvC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,uBAAuB,cACrB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,QAAA,EA8Db,CAAA;;;;;;;;;;;;;;;;AAgBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wmCAAA,CAAA,EAAA;;;AC1GH;;;;;;;;;;;;AAYG;MACU,oBAAoB,GAAG,CAAC,CAAc,EAAE,IAAS,KAAe;IAC3E,MAAM,QAAQ,GAAG,GAAG;AACpB,IAAA,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM;IAEjD,MAAM,cAAc,GAAG,eAAe;AACnC,SAAA,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ;SAClC,MAAM,CAAC,6BAA6B,CAAC;;;;IAKxC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;AAC/C,IAAA,SAAS,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU;AACrC,IAAA,SAAS,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG;AACzB,IAAA,SAAS,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG;AAC1B,IAAA,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG;AAC3B,IAAA,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG;AAC5B,IAAA,SAAS,CAAC,KAAK,CAAC,eAAe,GAAG,MAAM;AACxC,IAAA,SAAS,CAAC,KAAK,CAAC,OAAO,GAAG,eAAe,GAAG,MAAM,GAAG,GAAG;AACxD,IAAA,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG;AAC5B,IAAA,SAAS,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM;;;;AAKtC,IAAA,MAAM,YAAY,GAAG,eAAe,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS;IACvE,IAAI,YAAY,EAAE;QAChB,MAAM,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,QAAQ;AACtE,QAAA,IAAI,eAAe,KAAK,QAAQ,EAAE;AAChC,YAAA,YAAY,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU;QAC1C;AACA,QAAA,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC;IACrC;;IAGA,MAAM,YAAY,GAAG,eAAe;AACjC,SAAA,UAAU,CAAC,IAAI,CAAC,UAAU;SAC1B,iBAAiB,CAAC,oBAAoB;AACtC,SAAA,YAAY,CAAC;QACZ,SAAS,EAAE,eAAe,GAAG,GAAG,GAAG,IAAI;AACvC,QAAA,SAAS,EAAE;KACZ;AACA,SAAA,MAAM,CAAC,WAAW,EACjB,eAAe,GAAG,kBAAkB,GAAG,kBAAkB,EACzD,eAAe,CAChB;;IAGH,MAAM,WAAW,GAAG,eAAe;AAChC,SAAA,UAAU,CAAC,IAAI,CAAC,SAAS;AACzB,SAAA,YAAY,CAAC;QACZ,SAAS,EAAE,eAAe,GAAG,IAAI,GAAG;KACrC;AACA,SAAA,MAAM,CAAC,WAAW,EACjB,eAAe,EACf,eAAe,GAAG,kBAAkB,GAAG,kBAAkB,CAC1D;;IAGH,MAAM,gBAAgB,GAAG,eAAe;SACrC,UAAU,CAAC,SAAS;SACpB,MAAM,CAAC,SAAS,EACf,eAAe,GAAG,MAAM,GAAG,GAAG,EAC9B,eAAe,GAAG,GAAG,GAAG,MAAM,CAC/B;;AAGH,IAAA,cAAc,CAAC,aAAa,CAAC,MAAK;AAChC,QAAA,IAAI,SAAS,IAAI,SAAS,CAAC,UAAU,EAAE;AACrC,YAAA,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC;QAC7C;AACF,IAAA,CAAC,CAAC;IAEF,cAAc,CAAC,YAAY,CAAC,CAAC,YAAY,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAE1E,IAAA,OAAO,cAAc;AACvB;AAEA;;;;;AAKG;MACU,oBAAoB,GAAG,CAAC,CAAc,EAAE,IAAS,KAAe;IAC3E,MAAM,QAAQ,GAAG,GAAG;IAEpB,MAAM,cAAc,GAAG,eAAe;AACnC,SAAA,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ;SAClC,MAAM,CAAC,6BAA6B,CAAC;;;IAIxC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;AAC/C,IAAA,SAAS,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU;AACrC,IAAA,SAAS,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG;AACzB,IAAA,SAAS,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG;AAC1B,IAAA,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG;AAC3B,IAAA,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG;AAC5B,IAAA,SAAS,CAAC,KAAK,CAAC,eAAe,GAAG,MAAM;AACxC,IAAA,SAAS,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AAChC,IAAA,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG;AAC5B,IAAA,SAAS,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM;;AAGtC,IAAA,MAAM,cAAc,GAAG,IAAI,CAAC,UAAyB;IACrD,IAAI,cAAc,EAAE;QAClB,MAAM,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC,QAAQ;AACxE,QAAA,IAAI,eAAe,KAAK,QAAQ,EAAE;AAChC,YAAA,cAAc,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU;QAC5C;AACA,QAAA,cAAc,CAAC,WAAW,CAAC,SAAS,CAAC;IACvC;;IAGA,MAAM,YAAY,GAAG,eAAe;AACjC,SAAA,UAAU,CAAC,IAAI,CAAC,UAAU;SAC1B,iBAAiB,CAAC,oBAAoB;AACtC,SAAA,YAAY,CAAC;AACZ,QAAA,SAAS,EAAE,GAAG;AACd,QAAA,SAAS,EAAE;KACZ;AACA,SAAA,MAAM,CAAC,WAAW,EAAE,kBAAkB,EAAE,eAAe,CAAC;;IAG3D,MAAM,WAAW,GAAG,eAAe;AAChC,SAAA,UAAU,CAAC,IAAI,CAAC,SAAS;AACzB,SAAA,YAAY,CAAC;AACZ,QAAA,SAAS,EAAE,IAAI;KAChB;AACA,SAAA,MAAM,CAAC,WAAW,EAAE,eAAe,EAAE,kBAAkB,CAAC;;IAG3D,MAAM,gBAAgB,GAAG,eAAe;SACrC,UAAU,CAAC,SAAS;AACpB,SAAA,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC;;AAGjC,IAAA,cAAc,CAAC,aAAa,CAAC,MAAK;AAChC,QAAA,IAAI,SAAS,IAAI,SAAS,CAAC,UAAU,EAAE;AACrC,YAAA,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC;QAC7C;AACF,IAAA,CAAC,CAAC;IAEF,cAAc,CAAC,YAAY,CAAC,CAAC,YAAY,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAE1E,IAAA,OAAO,cAAc;AACvB;;AClJA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCG;AAgFG,MAAO,4BAA6B,SAAQ,cAAc,CAAA;AAiCpD,IAAA,OAAA;AACA,IAAA,UAAA;AAjCa,IAAA,UAAU;;AAGzB,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;;AAGnC,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC,4DAC9B;;AAGD,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAU;AAChC,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;;AAG9B,IAAA,IAAI,GAAG,KAAK,CAA8B,SAAS,gDAAC;AACpD,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;;AAG7B,IAAA,WAAW,GAAG,KAAK,CAAU,IAAI,uDAAC;AAClC,IAAA,eAAe,GAAG,KAAK,CAAS,GAAG,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;AACrC,IAAA,kBAAkB,GAAG,KAAK,CAAS,GAAG,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,oBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;;IAGxC,IAAI,GAAG,MAAM,EAAQ;IACrB,SAAS,GAAG,MAAM,EAAU;IAC5B,OAAO,GAAG,MAAM,EAAO;IACvB,MAAM,GAAG,MAAM,EAAO;IAEtB,WAAA,CACU,OAAsB,EACtB,UAAsB,EAAA;AAE9B,QAAA,KAAK,EAAE;QAHC,IAAA,CAAA,OAAO,GAAP,OAAO;QACP,IAAA,CAAA,UAAU,GAAV,UAAU;IAGpB;IAEA,eAAe,GAAA;;IAEf;AAEA;;;;;AAKG;IACH,UAAU,GAAA;;AAER,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;;AAGhB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;YACpB,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC7C;aAAO;YACL,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;QACxD;IACF;AAEA;;AAEG;AACH,IAAA,eAAe,CAAC,KAAa,EAAA;AAC3B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;IAC5B;AAEA;;;;;AAKG;AACH,IAAA,YAAY,CAAC,KAAU,EAAA;AACrB,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS;AACxC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE;AACxC,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE;AAC9C,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,4BAA4B,CAAC;AACxF,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,oBAAoB,CAAC;;AAG1F,QAAA,IAAI,SAAS,GAAG,SAAS,EAAE;AACzB,YAAA,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC1C;aAAO;AACL,YAAA,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAC7C;;QAGA,IAAI,gBAAgB,EAAE;AACpB,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC,CAAC;;AAG1D,YAAA,MAAM,OAAO,GAAG,CAAC,GAAG,YAAY;;AAGhC,YAAA,MAAM,UAAU,GAAG,YAAY,GAAG,CAAC,EAAE;;YAGrC,gBAAgB,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE;YACnD,gBAAgB,CAAC,KAAK,CAAC,SAAS,GAAG,CAAA,WAAA,EAAc,UAAU,KAAK;QAClE;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB;AAEA;;;AAGG;IACH,MAAM,aAAa,CAAC,KAAU,EAAA;;AAE5B,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;QACrD;AAAE,QAAA,MAAM;;AAEN,YAAA,IAAI,SAAS,IAAI,SAAS,EAAE;AAC1B,gBAAA,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB;QACF;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;IAC1B;wGA1HW,4BAA4B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,aAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA5B,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,SAAA,EAAA,WAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,YAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAC5B,UAAU,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA9DX,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,24IAAA,EAAA,mxBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzEC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,SAAS,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,UAAU,mFACV,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,YAAY,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,eAAA,EAAA,UAAA,EAAA,MAAA,EAAA,YAAA,EAAA,SAAA,EAAA,SAAA,EAAA,kBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,mBAAmB,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,aAAA,EAAA,mBAAA,EAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,eAAe,sGACf,2BAA2B,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAmElB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBA/ExC,SAAS;+BACE,wBAAwB,EAAA,UAAA,EACtB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,SAAS;wBACT,UAAU;wBACV,QAAQ;wBACR,UAAU;wBACV,YAAY;wBACZ,mBAAmB;wBACnB,eAAe;wBACf;qBACD,EAAA,QAAA,EAKS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,24IAAA,EAAA,mxBAAA,CAAA,EAAA;;sBAGA,SAAS;uBAAC,UAAU;;;ACjIvB;;;;;;;;;;;;;;;;;;;;AAoBG;MAyCU,wBAAwB,CAAA;AACnC;;;;;AAKG;AACH,IAAA,MAAM,GAAG,KAAK,CAAkC,SAAS,kDAAC;wGAP/C,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAxB,wBAAwB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,sBAAA,EAAA,0BAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAFzB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6UAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAnChB,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAqCX,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAxCpC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mBAAmB,cACjB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,IAAA,EACjB;AACJ,wBAAA,wBAAwB,EAAE,wBAAwB;AAClD,wBAAA,uBAAuB,EAAE,uBAAuB;AAChD,wBAAA,uBAAuB,EAAE;AAC1B,qBAAA,EAAA,QAAA,EA8BS,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,6UAAA,CAAA,EAAA;;AAY5B;;;;;;;;;;;;;;AAcG;MAiBU,+BAA+B,CAAA;wGAA/B,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EALhC,CAAA;;;AAGT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,sDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAXS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAaX,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBAhB3C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,2BAA2B,cACzB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,QAAA,EAQb,CAAA;;;AAGT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,sDAAA,CAAA,EAAA;;AAIH;;;;;AAKG;MAuBU,sBAAsB,CAAA;;AAEjC,IAAA,KAAK,GAAG,KAAK,CAA4B,MAAM,iDAAC;wGAFrC,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,kWAFvB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,iLAAA,CAAA,EAAA,CAAA;;4FAEf,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAtBlC,SAAS;+BACE,gBAAgB,EAAA,UAAA,EACd,IAAI,EAAA,IAAA,EACV;AACJ,wBAAA,gBAAgB,EAAE,oBAAoB;AACtC,wBAAA,iBAAiB,EAAE,qBAAqB;AACxC,wBAAA,gBAAgB,EAAE;AACnB,qBAAA,EAAA,QAAA,EAaS,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,iLAAA,CAAA,EAAA;;AAO5B;;;;AAIG;MAYU,mBAAmB,CAAA;wGAAnB,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,uEAFpB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,gCAAA,CAAA,EAAA,CAAA;;4FAEf,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAX/B,SAAS;+BACE,aAAa,EAAA,UAAA,EACX,IAAI,EAAA,QAAA,EAON,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,gCAAA,CAAA,EAAA;;;ACvJ5B;;;;;;;;;;;;;;;;;;;;;AAqBG;MAoBU,8BAA8B,CAAA;wGAA9B,8BAA8B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA9B,8BAA8B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAF/B,CAAA,qDAAA,CAAuD,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,8JAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAdvD,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAgBX,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBAnB1C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,0BAA0B,cACxB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,YAcb,CAAA,qDAAA,CAAuD,EAAA,MAAA,EAAA,CAAA,8JAAA,CAAA,EAAA;;AAInE;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAqBU,kCAAkC,CAAA;wGAAlC,kCAAkC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kCAAkC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,+BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EALnC,CAAA;;;AAGT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,yOAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAfS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAiBX,kCAAkC,EAAA,UAAA,EAAA,CAAA;kBApB9C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,+BAA+B,cAC7B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,QAAA,EAYb,CAAA;;;AAGT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,yOAAA,CAAA,EAAA;;AAIH;;;;;AAKG;MA6BU,iBAAiB,CAAA;wGAAjB,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,iBAAiB,qEAFlB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mZAAA,CAAA,EAAA,CAAA;;4FAEf,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBA5B7B,SAAS;+BACE,WAAW,EAAA,UAAA,EACT,IAAI,EAAA,QAAA,EAwBN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,mZAAA,CAAA,EAAA;;AAI5B;;;;;;;;;AASG;MAoCU,oBAAoB,CAAA;wGAApB,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EALrB,CAAA;;;AAGT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,odAAA,CAAA,EAAA,CAAA;;4FAEU,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAnChC,SAAS;+BACE,cAAc,EAAA,UAAA,EACZ,IAAI,EAAA,QAAA,EA4BN,CAAA;;;AAGT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,odAAA,CAAA,EAAA;;AAIH;;;;;AAKG;MAiBU,kBAAkB,CAAA;wGAAlB,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,sEAFnB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,+MAAA,CAAA,EAAA,CAAA;;4FAEf,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAhB9B,SAAS;+BACE,YAAY,EAAA,UAAA,EACV,IAAI,EAAA,QAAA,EAYN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,+MAAA,CAAA,EAAA;;AAI5B;;;;;AAKG;MAiBU,kBAAkB,CAAA;wGAAlB,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,sEAFnB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,4LAAA,CAAA,EAAA,CAAA;;4FAEf,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAhB9B,SAAS;+BACE,YAAY,EAAA,UAAA,EACV,IAAI,EAAA,QAAA,EAYN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,4LAAA,CAAA,EAAA;;;ACnN5B;;;;;;;;;;;;;;;;AAgBG;MAkQU,wBAAwB,CAAA;AACnC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAU;AAErC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAU;AAErC;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,oDAAU;AAEpC;;AAEG;AACH,IAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,kDAAU;AAElC;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;AAElC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAE7D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC;AAEjC;;AAEG;AACH,IAAA,YAAY,GAAG,KAAK,CAAU,KAAK,wDAAC;AAEpC;;AAEG;AACH,IAAA,OAAO,GAAG,KAAK,CAAU,KAAK,mDAAC;AAE/B;;AAEG;IACH,WAAW,GAAG,MAAM,EAAsC;AAE1D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,CAAC,qDAAC;AAE5B;;AAEG;AACH,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,qDAAC;AAEzB;;AAEG;AACH,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAK;AAC/B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE;;;QAG3B,OAAO,IAAI,CAAC,OAAO,CAAC,kCAAkC,EAAE,kCAAkC,CAAC;AAC7F,IAAA,CAAC,4DAAC;AAEF;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;AAE7B;;AAEG;IACH,UAAU,GAAG,MAAM,EAAQ;AAE3B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACK,cAAc,GAAQ,IAAI;IAC1B,kBAAkB,GAAG,KAAK;IAC1B,WAAW,GAAG,CAAC;IACf,WAAW,GAAG,CAAC;AACN,IAAA,mBAAmB,GAAG,GAAG,CAAC;AAC1B,IAAA,cAAc,GAAG,EAAE,CAAC;AAErC,IAAA,kBAAkB,CAAC,KAAY,EAAA;;AAE7B,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAE,KAAK,CAAC,MAAsB,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;AAClF,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAC1B;IACF;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;AAChC,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAE1B,MAAM,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC;AACvE,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;;QAGzC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;;QAGzE,IAAI,QAAQ,EAAE;AACZ,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,YAAA,UAAU,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;QAClD;;AAGA,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;QACpD;AAAE,QAAA,MAAM;;AAEN,YAAA,IAAI,SAAS,IAAI,SAAS,EAAE;AAC1B,gBAAA,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB;QACF;IACF;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;IACxB;IAEA,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,KAAiB,EAAA;AAChC,QAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QAC/B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;QAC3C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;;AAG3C,QAAA,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,YAAW;AAC1C,YAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;;AAGrB,YAAA,IAAI;AACF,gBAAA,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;YACrD;AAAE,YAAA,MAAM;;AAEN,gBAAA,IAAI,SAAS,IAAI,SAAS,EAAE;AAC1B,oBAAA,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvB;YACF;AACF,QAAA,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAC9B;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,KAAiB,EAAA;AAC9B,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;QAC5B;;AAGA,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,KAAK,CAAC,cAAc,EAAE;YACtB,KAAK,CAAC,eAAe,EAAE;AACvB,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QACjC;IACF;AAEA;;AAEG;AACH,IAAA,eAAe,CAAC,KAAiB,EAAA;QAC/B,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE;QAE1B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;;AAGzD,QAAA,IAAI,MAAM,GAAG,IAAI,CAAC,cAAc,IAAI,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;AAChE,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;AAC1B,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QACjC;IACF;AAEA;;AAEG;AACH,IAAA,iBAAiB,CAAC,KAAY,EAAA;QAC5B,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA;;;AAGG;AACH,IAAA,qBAAqB,CAAC,KAAY,EAAA;AAChC,QAAA,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC;QACpD,KAAK,CAAC,eAAe,EAAE;QACvB,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGA5NW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,wBAAwB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,eAAA,EAAA,WAAA,EAAA,aAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,UAAA,EAAA,YAAA,EAAA,SAAA,EAAA,WAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,4BAAA,EAAA,YAAA,EAAA,0BAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,WAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,2BAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArCzB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,8zFAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA5PS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,sGAAE,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA8PtE,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAjQpC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mBAAmB,EAAA,UAAA,EACjB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,CAAC,EAAA,IAAA,EAE5E;AACJ,wBAAA,mBAAmB,EAAE,aAAa;AAClC,wBAAA,SAAS,EAAE,4BAA4B;AACvC,wBAAA,cAAc,EAAE,0BAA0B;AAC1C,wBAAA,YAAY,EAAE,wBAAwB;AACtC,wBAAA,aAAa,EAAE,yBAAyB;AACxC,wBAAA,eAAe,EAAE,2BAA2B;qBAC7C,EAAA,QAAA,EAgNS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,8zFAAA,CAAA,EAAA;;;ACnRH;;;;;;;;;;;;;;;;AAgBG;MA+EU,6BAA6B,CAAA;AACxC;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;AAElC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAE7D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,gBAAgB,0DAAC;AAEhD;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,cAAc,uDAAC;AAE3C;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAS,QAAQ,sDAAC;AAEpC;;AAEG;IACH,aAAa,GAAG,MAAM,EAAQ;IAE9B,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE;IAC3B;wGAtCW,6BAA6B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA7B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,6BAA6B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,yBAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,eAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArB9B,CAAA;;;;;;;;;;;;;;;;;;;GAmBT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,gxBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzES,YAAY,+BAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA2E9B,6BAA6B,EAAA,UAAA,EAAA,CAAA;kBA9EzC,SAAS;+BACE,yBAAyB,EAAA,UAAA,EACvB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,CAAC,EAAA,IAAA,EACpC;AACJ,wBAAA,SAAS,EAAE;qBACZ,EAAA,QAAA,EAmDS,CAAA;;;;;;;;;;;;;;;;;;;AAmBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,gxBAAA,CAAA,EAAA;;;AC7EH;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;MAgDU,kCAAkC,CAAA;AAC7C;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAkB;AAE7C;;AAEG;IACH,MAAM,GAAG,MAAM,EAAU;AAEzB;;AAEG;IACH,gBAAgB,GAAA;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE;;AAGjD,QAAA,MAAM,QAAQ,GAA2B;AACvC,YAAA,KAAK,EAAE,KAAK;AACZ,YAAA,KAAK,EAAE,KAAK;AACZ,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,KAAK,EAAE,KAAK;AACZ,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE;SACV;AAED,QAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI;IAC/B;AAEA;;AAEG;IACH,WAAW,GAAA;QACT,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI;AAEnC,QAAA,MAAM,OAAO,GAAuC;AAClD,YAAA,OAAO,EAAE,gBAAgB;AACzB,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,MAAM,EAAE,mBAAmB;AAC3B,YAAA,KAAK,EAAE,oBAAoB;AAC3B,YAAA,MAAM,EAAE,oBAAoB;AAC5B,YAAA,OAAO,EAAE;SACV;AAED,QAAA,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,qBAAqB;IAC/C;AAEA;;AAEG;IACH,YAAY,GAAA;AACV,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;IACxC;wGAtDW,kCAAkC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kCAAkC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA1CnC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,s9DAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA1CS,YAAY,+BAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA4C9B,kCAAkC,EAAA,UAAA,EAAA,CAAA;kBA/C9C,SAAS;+BACE,8BAA8B,EAAA,UAAA,EAC5B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,CAAC,EAAA,QAAA,EAEhC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,s9DAAA,CAAA,EAAA;;;ACrEH;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MAycU,gCAAgC,CAAA;AAC3C;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;AAElC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAE7D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,oBAAoB,uDAAC;AAEjD;;AAEG;AACH,IAAA,eAAe,GAAG,KAAK,CAAS,cAAc,2DAAC;AAE/C;;AAEG;AACH,IAAA,qBAAqB,GAAG,KAAK,CAAS,gBAAgB,iEAAC;AAEvD;;AAEG;AACH,IAAA,oBAAoB,GAAG,KAAK,CAAU,KAAK,gEAAC;AAE5C;;AAEG;AACH,IAAA,iBAAiB,GAAG,KAAK,CAAS,iBAAiB,6DAAC;AAEpD;;AAEG;AACH,IAAA,kBAAkB,GAAG,KAAK,CAAS,aAAa,8DAAC;AAEjD;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAU,KAAK,0DAAC;AAEtC;;AAEG;AACH,IAAA,YAAY,GAAG,KAAK,CAA0D,EAAE,wDAAC;AAEjF;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC;AAEjC;;AAEG;AACwB,IAAA,YAAY;AAEvC;;AAEG;AACqB,IAAA,SAAS;AAEjC;;AAEG;AACH,IAAA,WAAW,GAAG,MAAM,CAAC,EAAE,uDAAC;AAExB;;AAEG;AACH,IAAA,WAAW,GAAG,MAAM,CAAmB,EAAE,uDAAC;AAE1C;;AAEG;AACH,IAAA,cAAc,GAAG,MAAM,CAA4E,IAAI,0DAAC;AAExG;;AAEG;AACH,IAAA,UAAU,GAAG,MAAM,CAAiD,IAAI,sDAAC;AAEzE;;AAEG;AACH,IAAA,eAAe,GAAG,MAAM,CAAC,KAAK,2DAAC;AAE/B;;AAEG;AACH,IAAA,YAAY,GAAG,MAAM,CAAC,EAAE,wDAAC;AAEzB;;AAEG;AACH,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;AAC5B,QAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;AAAE,YAAA,OAAO,EAAE;QAErC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE;AAC/C,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AAEjC,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,KAAK;QACxB,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,IACtB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CACxC;AACH,IAAA,CAAC,yDAAC;AAEF;;AAEG;IACH,WAAW,GAAG,MAAM,EAMhB;AAEJ;;AAEG;IACH,aAAa,GAAG,MAAM,EAAQ;AAE9B;;AAEG;IACH,cAAc,GAAG,MAAM,EAAQ;AAE/B;;AAEG;IACH,eAAe,GAAG,MAAM,EAAwB;AAEhD;;AAEG;IACH,iBAAiB,GAAG,MAAM,EAAQ;IAElC,eAAe,GAAA;;AAEb,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;YACpB,UAAU,CAAC,MAAK;AACd,gBAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;gBACxC,IAAI,CAAC,YAAY,EAAE;YACrB,CAAC,EAAE,GAAG,CAAC;QACT;;QAGA,IAAI,CAAC,sBAAsB,EAAE;IAC/B;IAEA,WAAW,GAAA;;QAET,IAAI,CAAC,wBAAwB,EAAE;IACjC;AAEA;;AAEG;IACK,sBAAsB,GAAA;QAC5B,QAAQ,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC,IAAI,KAAI;AAChD,YAAA,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA,EAAA,CAAI,CAAC;AAC7F,QAAA,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,CAAC,CAAC,CAAC;AAElE,QAAA,QAAQ,CAAC,WAAW,CAAC,kBAAkB,EAAE,MAAK;YAC5C,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,KAAK,CAAC;AACxE,QAAA,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,CAAC,CAAC,CAAC;IACpE;AAEA;;AAEG;IACK,wBAAwB,GAAA;AAC9B,QAAA,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;IAC7F;AAEA;;AAEG;IACH,YAAY,GAAA;AACV,QAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC1E;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,KAAoB,EAAA;;QAEhC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;YAC3C,KAAK,CAAC,cAAc,EAAE;YACtB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,GAAG,CAAC;YACxF,IAAI,UAAU,EAAE;gBACd,IAAI,CAAC,WAAW,EAAE;YACpB;QACF;;IAEF;AAEA;;AAEG;AACH,IAAA,WAAW,CAAC,KAAY,EAAA;AACtB,QAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,MAA6B;AACpD,QAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK;AAC3B,QAAA,MAAM,cAAc,GAAG,QAAQ,CAAC,cAAc,IAAI,CAAC;;AAGnD,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;;AAG1B,QAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;QAC9B,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,YAAY,GAAG,IAAI;;AAGpD,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE;;YAEzB,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,cAAc,CAAC;YAC1D,MAAM,WAAW,GAAG,gBAAgB,CAAC,WAAW,CAAC,GAAG,CAAC;AAErD,YAAA,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE;;gBAEtB,MAAM,WAAW,GAAG,gBAAgB,CAAC,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC;gBAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAE1C,IAAI,CAAC,QAAQ,EAAE;;AAEb,oBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,oBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC;gBACpC;qBAAO;AACL,oBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;gBACjC;YACF;iBAAO;AACL,gBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;YACjC;QACF;IACF;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,QAAgB,EAAA;;AAE5B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;AAG1D,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE;AACtC,QAAA,MAAM,kBAAkB,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACjF,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC;;AAGxC,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;;QAG/B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;;QAGvC,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;QAC1C,CAAC,EAAE,CAAC,CAAC;IACP;AAEA;;AAEG;IACH,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7B,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;AACxB,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE;IAC3B;AAEA;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE;IAC5B;AAEA;;AAEG;IACH,QAAQ,CAAC,UAAkB,EAAE,OAAe,EAAA;QAC1C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;;QAE5C,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;YACxC,IAAI,CAAC,YAAY,EAAE;QACrB,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;AAEG;AACH,IAAA,OAAO,CAAC,UAAkB,EAAE,eAAuB,EAAE,SAAiB,EAAA;;AAEpE,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;;QAGzB,IAAI,aAAa,GAAG,eAAe;QACnC,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,mCAAmC,CAAC;QAC/E,IAAI,YAAY,EAAE;AAChB,YAAA,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACnE;;AAGA,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;;AAGnE,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC;;QAGnC,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE;AACpC,gBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa;gBAChD,QAAQ,CAAC,KAAK,EAAE;;AAGhB,gBAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;gBAC9B,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,YAAY,GAAG,IAAI;gBAEpD,IAAI,CAAC,YAAY,EAAE;YACrB;QACF,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;AACxB,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;;AAGxB,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE;YACpC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;QACvD;IACF;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;QACxC,IAAI,CAAC,YAAY,EAAE;IACrB;AAEA;;AAEG;IACH,qBAAqB,GAAA;;AAEnB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE;QACtC;AACA,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE;IAC/B;AAEA;;AAEG;AACK,IAAA,cAAc,CAAC,IAAU,EAAA;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;;AAGxC,QAAA,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AACjC,YAAA,OAAO,OAAO;QAChB;;AAGA,QAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AAC7B,YAAA,OAAO,KAAK;QACd;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;AACrC,YAAA,OAAO,MAAM;QACf;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;AACrC,YAAA,OAAO,MAAM;QACf;AAEA,QAAA,OAAO,OAAO;IAChB;AAEA;;AAEG;AACK,IAAA,cAAc,CAAC,KAAa,EAAA;QAClC,IAAI,KAAK,KAAK,CAAC;AAAE,YAAA,OAAO,KAAK;QAC7B,MAAM,CAAC,GAAG,IAAI;QACd,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC;IACxE;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,KAAY,EAAA;AAC3B,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;AAC9C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;QAEzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;YAChC;QACF;;QAGA,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM;AACpD,QAAA,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC;AAEjE,QAAA,cAAc,CAAC,OAAO,CAAC,IAAI,IAAG;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;;AAG1C,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAI;AACpB,gBAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAgB;gBACzC,IAAI,MAAM,EAAE;AACV,oBAAA,MAAM,aAAa,GAAmB;wBACpC,EAAE,EAAE,CAAA,KAAA,EAAQ,IAAI,CAAC,GAAG,EAAE,CAAA,CAAA,EAAI,IAAI,CAAC,MAAM,EAAE,CAAA,CAAE;AACzC,wBAAA,GAAG,EAAE,MAAM;AACX,wBAAA,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI;qBACpC;AACD,oBAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC;gBACzE;AACF,YAAA,CAAC;AACD,YAAA,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;AAC5B,QAAA,CAAC,CAAC;;AAGF,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,YAAoB,EAAA;QACnC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IACjC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAC/C;IACH;AAEA;;AAEG;IACH,WAAW,GAAA;QACT,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;QACtC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,GAAG,CAAC;;AAGpD,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc;YAAE;QAE9B,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE;QACtC,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE;;AAGnC,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACpB,YAAA,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,UAAU;kBAC/B,CAAA,CAAA,EAAI,IAAI,CAAC,UAAU,EAAG,CAAC,UAAU,CAAA,CAAA,EAAI,IAAI,CAAA;AAC3C,kBAAE,IAAI;YACR,OAAO;AACP,YAAA,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,UAAU;YACtC,MAAM;AACN,YAAA,WAAW,EAAE,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG;AACzD,SAAA,CAAC;;QAGF,IAAI,CAAC,KAAK,EAAE;;AAGZ,QAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,IAAI,EAAE;;AAGvC,QAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC1E;wGAzeW,gCAAgC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gCAAgC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,qBAAA,EAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,UAAA,EAAA,uBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,oBAAA,EAAA,EAAA,iBAAA,EAAA,sBAAA,EAAA,UAAA,EAAA,sBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,aAAA,EAAA,eAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,cAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,cAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/HjC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6HT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,muJAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAlcC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,iBAAiB,mIACjB,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACrB,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,kCAAkC,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA+bzB,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAxc5C,SAAS;+BACE,4BAA4B,EAAA,UAAA,EAC1B,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,iBAAiB;wBACjB,qBAAqB;wBACrB,eAAe;wBACf;qBACD,EAAA,QAAA,EA+TS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6HT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,muJAAA,CAAA,EAAA;;sBAkEA,SAAS;uBAAC,cAAc;;sBAKxB,SAAS;uBAAC,WAAW;;;AC3iBxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCG;MAsTU,8BAA8B,CAAA;AACzC;;AAEG;AACH,IAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,kDAAU;AAElC;;AAEG;AACH,IAAA,YAAY,GAAG,KAAK,CAAU,KAAK,wDAAC;AAEpC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAS,EAAE,sDAAC;AAE9B;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,oDAAU;AAEpC;;AAEG;AACH,IAAA,aAAa,GAAG,KAAK,CAAU,KAAK,yDAAC;AAErC;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;AAElC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAE7D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAA+B,SAAS,uDAAC;AAE5D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC;AAEjC;;AAEG;IACH,eAAe,GAAG,MAAM,EAAkB;AAE1C;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;AAE7B;;AAEG;IACK,cAAc,GAAQ,IAAI;IAC1B,kBAAkB,GAAG,KAAK;IAC1B,WAAW,GAAG,CAAC;IACf,WAAW,GAAG,CAAC;AACN,IAAA,mBAAmB,GAAG,GAAG,CAAC;AAC1B,IAAA,cAAc,GAAG,EAAE,CAAC;IAC7B,cAAc,GAAG,CAAC;AAE1B;;AAEG;AACH,IAAA,qBAAqB,CAAC,UAA0B,EAAA;AAC9C,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC;IACvC;AAEA;;AAEG;AACH,IAAA,WAAW,CAAC,KAAiB,EAAA;AAC3B,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;;;AAIvB,QAAA,IAAK,KAAa,CAAC,kBAAkB,EAAE,gBAAgB,EAAE;YACvD;QACF;;AAGA,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,KAAiB,EAAA;AAChC,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;AAEvB,QAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;AAC/B,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE;QAChC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;QAC3C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;;AAG3C,QAAA,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,MAAK;AACpC,YAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;AACvB,QAAA,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAC9B;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,KAAiB,EAAA;QAC9B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,cAAc;AAEtD,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;QAC5B;;AAGA,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,KAAK,CAAC,cAAc,EAAE;YACtB,KAAK,CAAC,eAAe,EAAE;AACvB,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;YAC/B;QACF;;QAGA,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,aAAa,GAAG,IAAI,CAAC,mBAAmB,EAAE;;YAEhE,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AACrC,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;AAEzD,YAAA,IAAI,MAAM,IAAI,IAAI,CAAC,cAAc,IAAI,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE;AAClE,gBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;gBACxB,KAAK,CAAC,cAAc,EAAE;YACxB;QACF;IACF;AAEA;;AAEG;AACH,IAAA,eAAe,CAAC,KAAiB,EAAA;QAC/B,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE;QAE1B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;;AAGzD,QAAA,IAAI,MAAM,GAAG,IAAI,CAAC,cAAc,IAAI,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE;AAChE,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AACjC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;AAC1B,YAAA,IAAI,CAAC,kBAAkB,GAAG,KAAK;QACjC;IACF;AAEA;;AAEG;AACH,IAAA,iBAAiB,CAAC,KAAY,EAAA;AAC5B,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;QACvB,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGAnLW,8BAA8B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA9B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,8BAA8B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,WAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,YAAA,EAAA,0BAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,WAAA,EAAA,yBAAA,EAAA,aAAA,EAAA,2BAAA,EAAA,EAAA,UAAA,EAAA,EAAA,sBAAA,EAAA,gBAAA,EAAA,uBAAA,EAAA,4CAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA9C/B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,07HAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAhTS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAkT/C,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBArT1C,SAAS;+BACE,0BAA0B,EAAA,UAAA,EACxB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,EAAE,eAAe,CAAC,EAAA,IAAA,EACrD;AACJ,wBAAA,wBAAwB,EAAE,gBAAgB;AAC1C,wBAAA,yBAAyB,EAAE,4CAA4C;AACvE,wBAAA,cAAc,EAAE,0BAA0B;AAC1C,wBAAA,YAAY,EAAE,wBAAwB;AACtC,wBAAA,aAAa,EAAE,yBAAyB;AACxC,wBAAA,eAAe,EAAE;qBAClB,EAAA,QAAA,EA4PS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,07HAAA,CAAA,EAAA;;;ACtWH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;MAgFU,+BAA+B,CAAA;AAC1C;;;AAGG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,MAAM,uDAAC;AAEnC;;AAEG;IACH,iBAAiB,GAAG,QAAQ,CAAC,MAAM,IAAI,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,mBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;AAEzC;;AAEG;IACH,kBAAkB,GAAG,QAAQ,CAAC,MAAM,IAAI,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,oBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC,CAAC;wGAf/B,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,sBAAA,EAAA,eAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAnBhC,CAAA;;;;;;;;;;;;;;;;;AAiBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ssBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA1ES,YAAY,EAAA,CAAA,EAAA,CAAA;;4FA4EX,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBA/E3C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,4BAA4B,cAC1B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,IAAA,EACjB;AACJ,wBAAA,wBAAwB,EAAE;qBAC3B,EAAA,QAAA,EAsDS,CAAA;;;;;;;;;;;;;;;;;AAiBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ssBAAA,CAAA,EAAA;;;AC1GH;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;MAqGU,wCAAwC,CAAA;AACnD;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAU;AAErC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAU;AAErC;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,oDAAU;AAEpC;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;AAElC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAE7D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,gBAAgB,0DAAC;AAEhD;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC;AAEjC;;;;AAIG;AACH,IAAA,OAAO,GAAG,KAAK,CAAwB,SAAS,mDAAC;AAEjD;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC;AAEjC;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;AAE7B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;IAE1B,eAAe,GAAA;AACb,QAAA,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC;AACnF,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;IAEA,kBAAkB,GAAA;AAChB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;IAEA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA,IAAA,qBAAqB,CAAC,KAAY,EAAA;;AAEhC,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGApFW,wCAAwC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,wCAAwC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sCAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAvCzC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,0wBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA/FS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,SAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,mBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,aAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAiGlE,wCAAwC,EAAA,UAAA,EAAA,CAAA;kBApGpD,SAAS;+BACE,sCAAsC,EAAA,UAAA,EACpC,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,CAAC,EAAA,QAAA,EA0DpE,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,0wBAAA,CAAA,EAAA;;AAyFH;;;;;;;;;AASG;MAmBU,oBAAoB,CAAA;wGAApB,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAPrB,CAAA;;;;;AAKT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wEAAA,CAAA,EAAA,CAAA;;4FAEU,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAlBhC,SAAS;+BACE,cAAc,EAAA,UAAA,EACZ,IAAI,EAAA,QAAA,EASN,CAAA;;;;;AAKT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wEAAA,CAAA,EAAA;;AAIH;;;;AAIG;MAmBU,iBAAiB,CAAA;wGAAjB,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,iBAAiB,qEAFlB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,gOAAA,CAAA,EAAA,CAAA;;4FAEf,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAlB7B,SAAS;+BACE,WAAW,EAAA,UAAA,EACT,IAAI,EAAA,QAAA,EAcN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,gOAAA,CAAA,EAAA;;AAI5B;;;;AAIG;MAyBU,kBAAkB,CAAA;wGAAlB,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,sEAFnB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,kKAAA,CAAA,EAAA,CAAA;;4FAEf,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAxB9B,SAAS;+BACE,YAAY,EAAA,UAAA,EACV,IAAI,EAAA,QAAA,EAoBN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,kKAAA,CAAA,EAAA;;AAI5B;;;;AAIG;MAaU,wBAAwB,CAAA;wGAAxB,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,wBAAwB,4EAFzB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,qDAAA,CAAA,EAAA,CAAA;;4FAEf,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAZpC,SAAS;+BACE,kBAAkB,EAAA,UAAA,EAChB,IAAI,EAAA,QAAA,EAQN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,qDAAA,CAAA,EAAA;;AAI5B;;;;;;;;;AASG;MAcU,oBAAoB,CAAA;wGAApB,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,wEAFrB,CAAA,cAAA,CAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mEAAA,CAAA,EAAA,CAAA;;4FAEf,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAbhC,SAAS;+BACE,cAAc,EAAA,UAAA,EACZ,IAAI,EAAA,QAAA,EASN,CAAA,cAAA,CAAgB,EAAA,MAAA,EAAA,CAAA,mEAAA,CAAA,EAAA;;AAI5B;;;;AAIG;MAiFU,mBAAmB,CAAA;AAC9B;;;AAGG;AACH,IAAA,MAAM,GAAG,KAAK,CAAU,KAAK,kDAAC;AAE9B;;;AAGG;AACH,IAAA,KAAK,GAAG,KAAK,CAAS,CAAC,iDAAC;AAExB;;AAEG;IACH,SAAS,GAAG,MAAM,EAAsC;AAExD;;AAEG;AACH,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,qDAAC;IAEzB,MAAM,WAAW,CAAC,KAAY,EAAA;QAC5B,KAAK,CAAC,eAAe,EAAE;;AAGvB,QAAA,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE;AAChC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;;QAG1B,MAAM,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC;AAChE,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;;QAGrC,IAAI,SAAS,EAAE;AACb,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,YAAA,UAAU,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;QAClD;;AAGA,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;QACpD;AAAE,QAAA,MAAM;;AAEN,YAAA,IAAI,SAAS,IAAI,SAAS,EAAE;AAC1B,gBAAA,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB;QACF;;AAGA,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAC7D;wGApDW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,MAAA,EAAA,cAAA,EAAA,KAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,qBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,cAAA,EAAA,UAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjBpB,CAAA;;;;;;;;;;;;;;;GAeT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ovBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3ES,YAAY,+BAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA6E5B,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAhF/B,SAAS;+BACE,aAAa,EAAA,UAAA,EACX,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,CAAC,EAAA,IAAA,EAClC;AACJ,wBAAA,gBAAgB,EAAE,UAAU;AAC5B,wBAAA,SAAS,EAAE;qBACZ,EAAA,QAAA,EAwDS,CAAA;;;;;;;;;;;;;;;AAeT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ovBAAA,CAAA,EAAA;;AAyDH;;;;AAIG;MA2CU,sBAAsB,CAAA;AACjC;;AAEG;AACH,IAAA,KAAK,GAAG,KAAK,CAAS,CAAC,iDAAC;AAExB;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;AAE7B,IAAA,WAAW,CAAC,KAAY,EAAA;QACtB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;wGAdW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,qBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAPvB,CAAA;;;;;GAKT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,4aAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArCS,YAAY,+BAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAuC5B,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBA1ClC,SAAS;+BACE,gBAAgB,EAAA,UAAA,EACd,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,CAAC,EAAA,IAAA,EAClC;AACJ,wBAAA,SAAS,EAAE;qBACZ,EAAA,QAAA,EA6BS,CAAA;;;;;AAKT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,4aAAA,CAAA,EAAA;;;ACrhBH;;;;;;AAMG;MA2FU,0BAA0B,CAAA;AACrC;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAS,cAAc,oDAAC;AAExC;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAS,EAAE,oDAAC;AAE5B;;AAEG;IACH,QAAQ,GAAG,MAAM,EAAQ;AAEzB,IAAA,WAAW,CAAC,KAAY,EAAA;QACtB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;IACtB;wGAnBW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,qBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArB3B,CAAA;;;;;;;;;;;;;;;;;;;AAmBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,o6BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArFS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAuF/C,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBA1FtC,SAAS;+BACE,qBAAqB,EAAA,UAAA,EACnB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,EAAE,eAAe,CAAC,EAAA,IAAA,EACrD;AACJ,wBAAA,SAAS,EAAE;qBACZ,EAAA,QAAA,EA+DS,CAAA;;;;;;;;;;;;;;;;;;;AAmBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,o6BAAA,CAAA,EAAA;;;ACpGH;;ACOA;;;;;;;;;;;;;;;;;;;AAmBG;MAuLU,2CAA2C,CAAA;AACtD;;AAEG;AACH,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAU;AAEhC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,uDAAC;AAE/B;;AAEG;AACH,IAAA,MAAM,GAAG,KAAK,CAAoB,MAAM,kDAAC;AAEzC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,uDAAC;AAE/B;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,oDAAU;AAEpC;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAS,eAAe,oDAAC;AAEzC;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,WAAW,qDAAC;AAEtC;;;;AAIG;AACH,IAAA,OAAO,GAAG,KAAK,CAAwB,SAAS,mDAAC;AAEjD;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,IAAI,qDAAC;AAEhC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,IAAI,uDAAC;AAElC;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;AAE7B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,mBAAmB,GAAA;AACjB,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AACtB,YAAA,OAAO,IAAI,CAAC,WAAW,EAAE;QAC3B;AACA,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,QAAQ;IACrD;IAEA,kBAAkB,GAAA;AAChB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;IAEA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA,IAAA,qBAAqB,CAAC,KAAY,EAAA;;AAEhC,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGApFW,2CAA2C,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA3C,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,2CAA2C,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,yCAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtD5C,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,2lCAAA,EAAA,gsEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAjLS,YAAY,+BAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,yBAAyB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,mIAAE,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,SAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,mBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,aAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAmLrG,2CAA2C,EAAA,UAAA,EAAA,CAAA;kBAtLvD,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,yCAAyC,EAAA,UAAA,EACvC,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,yBAAyB,CAAC,EAAA,QAAA,EA6HvG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,2lCAAA,EAAA,gsEAAA,CAAA,EAAA;;;AC1MH;;;;;;;;;;;;;;;;;;;;AAoBG;MAyIU,2CAA2C,CAAA;AACtD;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAU;AAErC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAU;AAErC;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH,IAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,kDAAU;AAElC;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAS,EAAE,0DAAC;AAElC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAgC,UAAU,sDAAC;AAE7D;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH,IAAA,MAAM,GAAG,KAAK,CAAU,KAAK,kDAAC;AAE9B;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,IAAI,qDAAC;AAEhC;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;AAE7B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;IAE1B,kBAAkB,GAAA;AAChB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;IAEA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGA9DW,2CAA2C,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA3C,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,2CAA2C,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,yCAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAxC5C,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,k4CAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAnIS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,SAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,mBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,aAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAqIlE,2CAA2C,EAAA,UAAA,EAAA,CAAA;kBAxIvD,SAAS;+BACE,yCAAyC,EAAA,UAAA,EACvC,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,CAAC,EAAA,QAAA,EA6FpE,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,k4CAAA,CAAA,EAAA;;;AC3JH;;;;;;;;;;;;;;;;;;AAkBG;MAoHU,gCAAgC,CAAA;AAC3C;;AAEG;AACH,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,+CAAU;AAE/B;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAC,QAAQ,mDAAU;AAEnC;;AAEG;AACH,IAAA,aAAa,GAAG,KAAK,CAAS,EAAE,yDAAC;AAEjC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,uDAAC;AAE/B;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,IAAI,qDAAC;AAEhC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,IAAI,uDAAC;AAElC;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;IAE7B,kBAAkB,GAAA;AAChB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAC1B;IACF;wGAxCW,gCAAgC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gCAAgC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,6BAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,sBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlCjC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wkCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA9GS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAgH/C,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAnH5C,SAAS;+BACE,6BAA6B,EAAA,UAAA,EAC3B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,EAAE,iBAAiB,CAAC,EAAA,IAAA,EACrD;AACJ,wBAAA,mBAAmB,EAAE,aAAa;AAClC,wBAAA,SAAS,EAAE;qBACZ,EAAA,QAAA,EA0ES,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wkCAAA,CAAA,EAAA;;;ACjHH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDG;MAkEU,uBAAuB,CAAA;AAoDxB,IAAA,UAAA;;IAlDD,IAAI,GAAgB,EAAE;;IAGtB,UAAU,GAAkC,UAAU;IACtD,cAAc,GAAW,GAAG;IAC5B,SAAS,GAAW,EAAE;IACtB,cAAc,GAAW,gBAAgB;AAElD;;;;;;;;;;;;;;;AAeG;AACM,IAAA,gBAAgB;;AAGf,IAAA,WAAW,GAAG,IAAI,YAAY,EAAQ;AAEhD;;;AAGG;AACO,IAAA,qBAAqB,GAAG,IAAI,YAAY,EAAgB;;AAGlE,IAAA,SAAS,GAAG,MAAM,CAAS,EAAE,qDAAC;AAC9B,IAAA,SAAS,GAAG,MAAM,CAAU,KAAK,qDAAC;AAE1B,IAAA,gBAAgB;AAChB,IAAA,uBAAuB;AACvB,IAAA,cAAc;AACd,IAAA,UAAU;AACV,IAAA,kBAAkB;AAElB,IAAA,MAAM;AACN,IAAA,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;AACzC,IAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AAEzC,IAAA,WAAA,CACU,UAAsB,EAAA;QAAtB,IAAA,CAAA,UAAU,GAAV,UAAU;;AAGlB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS;;;QAI7D,IAAI,CAAC,wBAAwB,EAAE;;QAG/B,UAAU,CAAC,MAAK;AACd,YAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE;AAChD,gBAAA,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;gBAC3B,WAAW,EAAE,MAAM,CAAC,UAAU;AAC9B,gBAAA,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO;gBACpC,SAAS,EAAE,SAAS,CAAC;AACtB,aAAA,CAAC;QACJ,CAAC,EAAE,GAAG,CAAC;;;QAIP,MAAM,CAAC,MAAK;;YAEV,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AACnF,YAAA,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE;;gBAEjC,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACxC;AACF,QAAA,CAAC,CAAC;IACJ;IAEA,QAAQ,GAAA;;AAGN,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,YAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;iBACnC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,YAAY,aAAa,CAAC;AACpD,iBAAA,SAAS,CAAC,CAAC,KAAU,KAAI;gBACxB,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,GAAG;;AAEhD,gBAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,KAAK,CAAC,CAAC;gBACxD,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;;AAGjD,gBAAA,IAAI,IAAI,CAAC,IAAI,IAAI,WAAW,EAAE;AAC5B,oBAAA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,KAAK,WAAW,CAAC;oBACpE,IAAI,WAAW,EAAE;wBACf,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC;oBACvC;gBACF;AACF,YAAA,CAAC,CAAC;QACN;IACF;IAEA,eAAe,GAAA;;QAEb,IAAI,CAAC,qBAAqB,EAAE;;QAG5B,IAAI,CAAC,yBAAyB,EAAE;;QAGhC,IAAI,CAAC,uBAAuB,EAAE;;QAG9B,IAAI,CAAC,UAAU,EAAE;;QAGjB,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,oBAAoB,EAAE;;YAE3B,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC;YACxC,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC;QAC1C,CAAC,EAAE,CAAC,CAAC;IACP;IAEQ,UAAU,GAAA;;;AAGhB,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;AACjD,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,GAAG,QAAQ;QACzD,MAAM,eAAe,GAAG,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC;AAExD,QAAA,IAAI,eAAe,KAAK,aAAa,EAAE;YACrC,OAAO,CAAC,GAAG,CAAC,wDAAwD,EAAE,eAAe,EAAE,IAAI,EAAE,aAAa,CAAC;AAC3G,YAAA,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC;AAC9C,YAAA,WAAmB,CAAC,IAAI,GAAG,aAAa;QAC3C;;AAGA,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC;QACzE,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC;;YAE5E,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC;YACvC;QACF;AAEA,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,GAAG,QAAQ;QACrD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;AAC/C,QAAA,MAAM,mBAAmB,GAAI,MAAc,CAAC,IAAI;;AAGhD,QAAA,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE;AAC7C,YAAA,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;YAC3B,WAAW,EAAE,MAAM,CAAC,UAAU;YAC9B,SAAS;AACT,YAAA,oBAAoB,EAAE,WAAW;AACjC,YAAA,mBAAmB,EAAE,mBAAmB;AACxC,YAAA,aAAa,EAAE,MAAM;AACrB,YAAA,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO;YAC3C,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK;AACjD,SAAA,CAAC;;QAGF,IAAI,WAAW,KAAK,SAAS,IAAI,mBAAmB,KAAK,SAAS,EAAE;YAClE,OAAO,CAAC,GAAG,CAAC,mDAAmD,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC;;AAG9F,YAAA,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC;AACrC,YAAA,MAAc,CAAC,IAAI,GAAG,SAAS;;YAGhC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAChD,IAAI,aAAa,EAAE;AACjB,gBAAA,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC;;AAEnE,gBAAA,aAAqB,CAAC,WAAW,IAAI;YACxC;;YAGA,KAAK,MAAM,CAAC,YAAY;;YAGxB,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;AAC9C,YAAA,MAAM,kBAAkB,GAAI,MAAc,CAAC,IAAI;YAC/C,OAAO,CAAC,GAAG,CAAC,+DAA+D,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,CAAC;;YAG9H,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC;YACrD,MAAM,mBAAmB,GAAG,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI;YACvG,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;AACnD,YAAA,MAAM,oBAAoB,GAAG,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,IAAI;AAEhG,YAAA,OAAO,CAAC,GAAG,CAAC,kDAAkD,EAAE;AAC9D,gBAAA,MAAM,EAAE;oBACN,QAAQ,EAAE,aAAa,CAAC,QAAQ;oBAChC,GAAG,EAAE,aAAa,CAAC,GAAG;oBACtB,MAAM,EAAE,aAAa,CAAC,MAAM;oBAC5B,KAAK,EAAE,aAAa,CAAC,KAAK;oBAC1B,OAAO,EAAE,aAAa,CAAC,OAAO;oBAC9B,MAAM,EAAE,aAAa,CAAC,MAAM;oBAC5B,SAAS,EAAE,aAAa,CAAC;AAC1B,iBAAA;AACD,gBAAA,MAAM,EAAE,mBAAmB,GAAG;oBAC5B,OAAO,EAAE,mBAAmB,CAAC,OAAO;oBACpC,aAAa,EAAE,mBAAmB,CAAC,aAAa;oBAChD,gBAAgB,EAAE,mBAAmB,CAAC;iBACvC,GAAG,IAAI;AACR,gBAAA,OAAO,EAAE,oBAAoB,GAAG;oBAC9B,OAAO,EAAE,oBAAoB,CAAC,OAAO;oBACrC,aAAa,EAAE,oBAAoB,CAAC,aAAa;oBACjD,gBAAgB,EAAE,oBAAoB,CAAC,gBAAgB;oBACvD,QAAQ,EAAE,oBAAoB,CAAC;iBAChC,GAAG,IAAI;AACR,gBAAA,UAAU,EAAE,MAAM,CAAC,qBAAqB,EAAE;gBAC1C,YAAY,EAAE,MAAM,CAAC;AACtB,aAAA,CAAC;QACJ;aAAO;AACL,YAAA,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC;;YAGrF,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC;YACrD,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;AACnD,YAAA,MAAM,oBAAoB,GAAG,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,IAAI;AAChG,YAAA,MAAM,UAAU,GAAG,MAAM,CAAC,qBAAqB,EAAE;;AAGjD,YAAA,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC,QAAQ,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,MAAM,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,aAAa,CAAC,KAAK,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,OAAO,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,WAAW,CAAC;YACxD,IAAI,oBAAoB,EAAE;gBACxB,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,oBAAoB,CAAC,OAAO,CAAC;gBAC/D,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,oBAAoB,CAAC,aAAa,CAAC;gBAC3E,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,oBAAoB,CAAC,gBAAgB,CAAC;YACnF;YACA,IAAI,gBAAgB,EAAE;gBACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;gBACtD,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,QAAQ,CAAC,MAAM,CAAC;gBACzD,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAU,EAAE,KAAK,KAAI;oBACrC,OAAO,CAAC,GAAG,CAAC,CAAA,KAAA,EAAQ,KAAK,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,CAAA,OAAA,EAAU,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA,SAAA,EAAY,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAA,CAAA,CAAG,CAAC;AACrI,gBAAA,CAAC,CAAC;YACJ;AAEA,YAAA,OAAO,CAAC,GAAG,CAAC,oFAAoF,EAAE;AAChG,gBAAA,MAAM,EAAE;oBACN,QAAQ,EAAE,aAAa,CAAC,QAAQ;oBAChC,GAAG,EAAE,aAAa,CAAC,GAAG;oBACtB,MAAM,EAAE,aAAa,CAAC,MAAM;oBAC5B,KAAK,EAAE,aAAa,CAAC,KAAK;oBAC1B,OAAO,EAAE,aAAa,CAAC,OAAO;oBAC9B,MAAM,EAAE,aAAa,CAAC,MAAM;oBAC5B,SAAS,EAAE,aAAa,CAAC,SAAS;oBAClC,SAAS,EAAE,aAAa,CAAC,SAAS;oBAClC,YAAY,EAAE,aAAa,CAAC,YAAY;oBACxC,KAAK,EAAE,aAAa,CAAC,KAAK;oBAC1B,MAAM,EAAE,aAAa,CAAC;AACvB,iBAAA;AACD,gBAAA,OAAO,EAAE,oBAAoB,GAAG;oBAC9B,OAAO,EAAE,oBAAoB,CAAC,OAAO;oBACrC,aAAa,EAAE,oBAAoB,CAAC,aAAa;oBACjD,gBAAgB,EAAE,oBAAoB,CAAC,gBAAgB;oBACvD,mBAAmB,EAAE,oBAAoB,CAAC,mBAAmB;oBAC7D,QAAQ,EAAE,oBAAoB,CAAC,QAAQ;oBACvC,UAAU,EAAE,oBAAoB,CAAC,UAAU;oBAC3C,cAAc,EAAE,oBAAoB,CAAC,cAAc;oBACnD,MAAM,EAAE,oBAAoB,CAAC,MAAM;oBACnC,SAAS,EAAE,oBAAoB,CAAC;iBACjC,GAAG,IAAI;AACR,gBAAA,UAAU,EAAE;oBACV,GAAG,EAAE,UAAU,CAAC,GAAG;oBACnB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,CAAC,EAAE,UAAU,CAAC,CAAC;oBACf,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,KAAK,EAAE,UAAU,CAAC;AACnB,iBAAA;gBACD,YAAY,EAAE,MAAM,CAAC,WAAW;gBAChC,eAAe,EAAE,UAAU,CAAC,GAAG;AAC/B,gBAAA,kBAAkB,EAAE,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC,MAAM;;AAE1D,gBAAA,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO;AAC3C,gBAAA,iBAAiB,EAAE,MAAM,CAAC,kBAAkB,EAAE,OAAO;AACrD,gBAAA,qBAAqB,EAAE,MAAM,CAAC,sBAAsB,EAAE,OAAO;;gBAE7D,eAAe,EAAE,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAU,MAAM;oBAC7F,OAAO,EAAE,KAAK,CAAC,OAAO;AACtB,oBAAA,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC;oBAChC,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACvC,iBAAA,CAAC,CAAC,GAAG;AACP,aAAA,CAAC;QACJ;IACF;IAEQ,oBAAoB,GAAA;AAC1B,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;AACjD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC;QACzE,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC;;YAEtF,UAAU,CAAC,MAAM,IAAI,CAAC,oBAAoB,EAAE,EAAE,EAAE,CAAC;YACjD;QACF;AAEA,QAAA,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC;QAEpF,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,KAAI;AAClD,YAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;AAC7B,gBAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,IAAI,QAAQ,CAAC,aAAa,KAAK,MAAM,EAAE;AACvE,oBAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAqB;AAC7C,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,GAAG,QAAQ;;oBAGxD,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,MAAM,EAAE;wBAC/C,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;AAE/C,wBAAA,OAAO,CAAC,GAAG,CAAC,sDAAsD,EAAE;4BAClE,MAAM,EAAE,MAAM,CAAC,OAAO;4BACtB,WAAW;4BACX,YAAY;AACZ,4BAAA,SAAS,EAAE,IAAI,CAAC,SAAS;AAC1B,yBAAA,CAAC;;AAGF,wBAAA,IAAI,WAAW,KAAK,YAAY,EAAE;AAChC,4BAAA,OAAO,CAAC,GAAG,CAAC,6CAA6C,EAAE,YAAY,CAAC;;4BAExE,qBAAqB,CAAC,MAAK;AACzB,gCAAA,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC;AACxC,gCAAA,MAAc,CAAC,IAAI,GAAG,YAAY;AACrC,4BAAA,CAAC,CAAC;wBACJ;oBACF;gBACF;AACF,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;;AAGF,QAAA,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE;AAC5B,YAAA,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,CAAC,MAAM;AACzB,SAAA,CAAC;AAEF,QAAA,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE;AACvB,YAAA,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,CAAC,MAAM;AACzB,SAAA,CAAC;;AAGF,QAAA,IAAI,CAAC,uBAAuB,GAAG,QAAQ;IACzC;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE;QACpC;AACA,QAAA,IAAI,IAAI,CAAC,uBAAuB,EAAE;AAChC,YAAA,IAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE;QAC3C;AACA,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,sBAAsB,CAAC;QAC5E;AACA,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;AAC3B,YAAA,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE;QACvC;IACF;IAEQ,wBAAwB,GAAA;;QAE9B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC;QACzD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAE3C,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;QACpE,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,sBAAsB,CAAC;IACzE;AAEQ,IAAA,sBAAsB,GAAG,CAAC,CAAsB,KAAU;AAChE,QAAA,OAAO,CAAC,GAAG,CAAC,6CAA6C,EAAE;YACzD,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,WAAW,EAAE,MAAM,CAAC,UAAU;AAC9B,YAAA,iBAAiB,EAAE,IAAI,CAAC,SAAS;AAClC,SAAA,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;;QAE7B,IAAI,CAAC,UAAU,EAAE;AACnB,IAAA,CAAC;IAEO,yBAAyB,GAAA;AAC/B,QAAA,MAAM,MAAM,GAAG;AACb,YAAA,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,CAAC,OAAO,CAAC;AAC1B,YAAA,OAAO,EAAE,IAAI;AACb,YAAA,SAAS,EAAE;SACZ;QAED,IAAI,CAAC,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,KAAI;AACzD,YAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;AAC7B,gBAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,IAAI,QAAQ,CAAC,aAAa,KAAK,OAAO,EAAE;AACxE,oBAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAqB;AAC7C,oBAAA,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,IAAI,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;AACvE,wBAAA,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC;oBACjC;gBACF;AACF,YAAA,CAAC,CAAC;;YAEF,IAAI,CAAC,qBAAqB,EAAE;AAC9B,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,MAAM,CAAC;IACtE;IAEQ,qBAAqB,GAAA;AAC3B,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;AACnF,QAAA,UAAU,CAAC,OAAO,CAAC,CAAC,MAAmB,KAAI;AACzC,YAAA,IAAI,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;AAChC,gBAAA,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC;YACjC;;YAEA,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,QAAQ,CAAC;AAC/D,YAAA,IAAI,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE;AACvC,gBAAA,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC;YACvC;AACF,QAAA,CAAC,CAAC;IACJ;IAEQ,uBAAuB,GAAA;;AAE7B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC;QACjE,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC;YACzE;QACF;;QAGA,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,CAAC,KAAU,KAAI;AAC1D,YAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,GAAG;YAClC,IAAI,QAAQ,EAAE;AACZ,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC9B;iBAAO;;gBAEL,UAAU,CAAC,MAAM,IAAI,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;YACpD;AACF,QAAA,CAAC,CAAC;;AAGF,QAAA,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAU,KAAI;YACrE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC;YACrD,IAAI,MAAM,EAAE;gBACV,UAAU,CAAC,MAAM,IAAI,CAAC,sBAAsB,EAAE,EAAE,EAAE,CAAC;YACrD;AACF,QAAA,CAAC,CAAC;;QAGF,IAAI,CAAC,sBAAsB,EAAE;;AAG7B,QAAA,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAK;YACzC,IAAI,CAAC,sBAAsB,EAAE;AAC/B,QAAA,CAAC,CAAC;QAEF,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE;AAC9C,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,eAAe,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC;AACpC,YAAA,OAAO,EAAE,IAAI;AACb,YAAA,SAAS,EAAE;AACZ,SAAA,CAAC;;AAGF,QAAA,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE;AACxB,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,eAAe,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC;AACpC,YAAA,OAAO,EAAE;AACV,SAAA,CAAC;;QAGF,WAAW,CAAC,MAAK;YACf,IAAI,CAAC,sBAAsB,EAAE;QAC/B,CAAC,EAAE,GAAG,CAAC;IACT;IAEQ,sBAAsB,GAAA;;AAE5B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC;QACjE,IAAI,OAAO,EAAE;;YAEX,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,mBAAmB,CAAC;YAC9D,IAAI,WAAW,EAAE;gBACf,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC;gBAChD,IAAI,QAAQ,EAAE;AACZ,oBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAC5B;gBACF;YACF;;YAGA,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,0BAA0B,CAAC;YACpE,IAAI,UAAU,EAAE;gBACd,MAAM,QAAQ,GAAG,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC;gBAC/C,IAAI,QAAQ,EAAE;AACZ,oBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAC5B;gBACF;YACF;QACF;;AAGA,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;AACnF,QAAA,UAAU,CAAC,OAAO,CAAC,CAAC,MAAW,KAAI;;AAEjC,YAAA,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE;gBAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;gBAC3C,IAAI,QAAQ,EAAE;AACZ,oBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAC9B;YACF;AACF,QAAA,CAAC,CAAC;IACJ;IAEA,YAAY,CAAC,KAAa,EAAE,GAAc,EAAA;QACxC,OAAO,GAAG,CAAC,EAAE;IACf;AAEA,IAAA,WAAW,CAAC,QAAgB,EAAA;AAC1B,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE;;AAEtC,QAAA,IAAI,aAAa,KAAK,QAAQ,EAAE;AAC9B,YAAA,OAAO,IAAI;QACb;;AAGA,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;AACnF,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC1C,YAAA,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAQ;AACnC,YAAA,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE;AACvE,gBAAA,OAAO,IAAI;YACb;QACF;AAEA,QAAA,OAAO,KAAK;IACd;AAEA;;AAEG;AACH,IAAA,MAAM,iBAAiB,GAAA;;AAErB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;;AAGvB,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE;;QAG9E,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;YACxC;QACF;;QAGA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;AAC9C,YAAA,SAAS,EAAE,mCAAmC;AAC9C,YAAA,cAAc,EAAE;AACd,gBAAA,kBAAkB,EAAE;AACrB,aAAA;;AAED,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;AAEF,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AAErB,QAAA,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAgB;AACxD,QAAA,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE;;YAEvB,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QAC9C;IACF;wGAvkBW,uBAAuB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,UAAA,EAAA,YAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,SAAA,EAAA,WAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,uBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApDxB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,snOAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,cAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,IAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,SAAS,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,aAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,YAAY,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,cAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAuDN,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAjEnC,SAAS;+BACE,mBAAmB,EAAA,UAAA,EACjB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,SAAS;wBACT,YAAY;wBACZ,QAAQ;wBACR,eAAe;wBACf,iBAAiB;wBACjB;qBACD,EAAA,QAAA,EAES,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,snOAAA,CAAA,EAAA;;sBAIA;;sBAGA;;sBACA;;sBACA;;sBACA;;sBAkBA;;sBAGA;;sBAMA;;;AC3KH;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MA4BU,qBAAqB,CAAA;;IAEvB,IAAI,GAAgB,EAAE;;IAGtB,UAAU,GAAkC,UAAU;IACtD,cAAc,GAAW,GAAG;IAC5B,SAAS,GAAW,EAAE;IACtB,cAAc,GAAW,gBAAgB;;AAGxC,IAAA,WAAW,GAAG,IAAI,YAAY,EAAQ;AAEhD,IAAA,WAAA,GAAA,EAAe;IAEf,QAAQ,GAAA;AACN,QAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAClD;IAEA,YAAY,CAAC,KAAa,EAAE,GAAc,EAAA;QACxC,OAAO,GAAG,CAAC,EAAE;IACf;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;IACzB;wGAzBW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,UAAA,EAAA,YAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,SAAA,EAAA,WAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjBtB,CAAA;;;;;;;;;;;;;;;AAeT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wOAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArBC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,cAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,IAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACP,MAAM,kFACN,uBAAuB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,uBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAoBd,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBA3BjC,SAAS;+BACE,gBAAgB,EAAA,UAAA,EACd,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,OAAO;wBACP,MAAM;wBACN;qBACD,EAAA,QAAA,EAES,CAAA;;;;;;;;;;;;;;;AAeT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wOAAA,CAAA,EAAA;;sBAIA;;sBAGA;;sBACA;;sBACA;;sBACA;;sBAGA;;;ACnEH;;;;;AAKG;MA8KU,+BAA+B,CAAA;AAC1C;;AAEG;IACH,MAAM,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,QAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAkB;AAEhC;;AAEG;IACH,UAAU,GAAG,MAAM,EAAQ;AAE3B;;AAEG;IACH,UAAU,GAAG,MAAM,EAAQ;wGAdhB,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAxKhC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,+uDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArDS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA0KrD,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBA7K3C,SAAS;+BACE,2BAA2B,EAAA,UAAA,EACzB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,EAAA,QAAA,EAEvD,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,+uDAAA,CAAA,EAAA;;;AChEH;;;;;AAKG;MAwPU,+BAA+B,CAAA;AAC1C;;AAEG;AACH,IAAA,cAAc,GAAG,KAAK,CAAU,KAAK,0DAAC;AAEtC;;AAEG;AACH,IAAA,YAAY,GAAG,KAAK,CAAS,CAAC,wDAAC;AAE/B;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,CAAC,uDAAC;AAE9B;;;AAGG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,KAAK,uDAAC;AAEnC;;AAEG;AACH,IAAA,OAAO,GAAG,KAAK,CAAU,KAAK,mDAAC;AAE/B;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,CAAC,qDAAC;AAE5B;;AAEG;AACH,IAAA,YAAY,GAAG,KAAK,CAAS,CAAC,wDAAC;AAE/B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;wGAvDlB,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,SAAA,EAAA,WAAA,EAAA,SAAA,EAAA,WAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAnPhC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mzGAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA5DS,YAAY,+BAAE,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAoPlC,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBAvP3C,SAAS;+BACE,2BAA2B,EAAA,UAAA,EACzB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,qBAAqB,CAAC,EAAA,QAAA,EACpC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,mzGAAA,CAAA,EAAA;;;AC/CH;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;MAmEU,8BAA8B,CAAA;AAoC/B,IAAA,WAAA;;AAlCV,IAAA,MAAM;AACN,IAAA,MAAM;IACN,YAAY,GAAW,CAAC;IACxB,UAAU,GAAY,IAAI;IAC1B,YAAY,GAAY,IAAI;IAC5B,WAAW,GAAY,IAAI;IAC3B,QAAQ,GAAY,IAAI;IACxB,WAAW,GAAY,KAAK;IAC5B,SAAS,GAA8B,MAAM;AAC7C,IAAA,gBAAgB;;AAGoC,IAAA,eAAe;;AAGnE,IAAA,YAAY,GAAG,MAAM,CAAC,CAAC,wDAAC;AACxB,IAAA,KAAK,GAAG,MAAM,CAAC,CAAC,iDAAC;AACjB,IAAA,QAAQ,GAAG,MAAM,CAAC,KAAK,oDAAC;AACxB,IAAA,SAAS,GAAG,MAAM,CAAC,IAAI,qDAAC;AACxB,IAAA,QAAQ,GAAG,MAAM,CAAC,KAAK,oDAAC;;AAGxB,IAAA,OAAO,GAAG,MAAM,CAAC,KAAK,mDAAC;AACvB,IAAA,SAAS,GAAG,MAAM,CAAC,CAAC,qDAAC;AACrB,IAAA,YAAY,GAAG,MAAM,CAAC,CAAC,wDAAC;;AAGxB,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,wDAAC;;AAGvD,IAAA,MAAM;AACN,IAAA,QAAQ,GAAyD,IAAI,GAAG,EAAE;AAElF,IAAA,WAAA,CACU,WAA8B,EAAA;QAA9B,IAAA,CAAA,WAAW,GAAX,WAAW;IAClB;IAEH,QAAQ,GAAA;;AAEN,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE;YACnC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;QAC1C;;QAGA,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACnD,IAAI,UAAU,EAAE;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,KAAK,CAAC;YAC7C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,IAAI,CAAC,CAAC;QACrD;IACF;IAEA,eAAe,GAAA;QACb,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,gBAAgB,EAAE;YACvB,IAAI,CAAC,sBAAsB,EAAE;QAC/B,CAAC,EAAE,GAAG,CAAC;IACT;IAEA,WAAW,GAAA;;AAET,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,YAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACrB,YAAA,IAAI,CAAC,MAAM,GAAG,SAAS;QACzB;IACF;AACA;;AAEG;IACK,gBAAgB,GAAA;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;AACzB,YAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC;YACtD;QACF;AAEA,QAAA,MAAM,aAAa,GAAkB;YACnC,YAAY,EAAE,IAAI,CAAC,YAAY;AAC/B,YAAA,KAAK,EAAE,GAAG;AACV,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,aAAa,EAAE,CAAC;AAChB,YAAA,YAAY,EAAE,CAAC;AACf,YAAA,UAAU,EAAE,CAAC;AACb,YAAA,eAAe,EAAE,GAAG;AACpB,YAAA,SAAS,EAAE,EAAE;AACb,YAAA,EAAE,EAAE;AACF,gBAAA,WAAW,EAAE,CAAC,MAAM,KAAI;oBACtB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;oBACzC,IAAI,CAAC,kBAAkB,EAAE;;oBAGzB,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;oBACtD,MAAM,GAAG,GAAG,YAAY,EAAE,aAAa,CAAC,KAAK,CAAC;AAC9C,oBAAA,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,aAAa,KAAK,CAAC,EAAE;;AAEpD,wBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;oBACzB;gBACF,CAAC;gBACD,0BAA0B,EAAE,MAAK;;AAE/B,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;oBACjE,MAAM,GAAG,GAAG,YAAY,EAAE,aAAa,CAAC,KAAK,CAAC;AAC9C,oBAAA,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,aAAa,KAAK,CAAC,EAAE;AACtD,wBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;oBACxB;gBACF;AACD;SACF;AAED,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC;;QAG3E,UAAU,CAAC,MAAK;AACd,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,YAAY,EAAE,aAAa,CAAC,KAAK,CAAC;AAC9C,YAAA,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,aAAa,KAAK,CAAC,EAAE;AACtD,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;YACvB;QACF,CAAC,EAAE,CAAC,CAAC;IACP;AAEA;;AAEG;IACK,sBAAsB,GAAA;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE;AAEtB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,gBAAgB,CAAC,uBAAuB,CAAC;QAE3F,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;AAC9B,YAAA,IAAI,CAAC,sBAAsB,CAAC,KAAoB,EAAE,KAAK,CAAC;AAC1D,QAAA,CAAC,CAAC;IACJ;AAEA;;AAEG;IACK,sBAAsB,CAAC,SAAsB,EAAE,KAAa,EAAA;QAClE,IAAI,eAAe,GAAG,CAAC;QACvB,IAAI,YAAY,GAAG,CAAC;QACpB,IAAI,YAAY,GAAG,CAAC;QACpB,IAAI,OAAO,GAAG,CAAC;;QAGf,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAiB,KAAI;AACxD,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;AACtB,YAAA,MAAM,gBAAgB,GAAG,GAAG,GAAG,OAAO;YAEtC,IAAI,gBAAgB,GAAG,GAAG,IAAI,gBAAgB,GAAG,CAAC,EAAE;gBAClD,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC;YACnC;YAEA,OAAO,GAAG,GAAG;AACf,QAAA,CAAC,CAAC;;AAGF,QAAA,MAAM,gBAAgB,GAAG,CAAC,OAAkB,KAAI;AAC9C,YAAA,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;AAClD,YAAA,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;AAClD,YAAA,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACrC,QAAA,CAAC;QAED,SAAS,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC,KAAiB,KAAI;YAC7D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC9B,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,eAAe,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;gBACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACrE,gBAAA,YAAY,GAAG,QAAQ,CAAC,KAAK;;AAG7B,gBAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,oBAAA,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,KAAK;gBACpC;YACF;AACF,QAAA,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAEtB,SAAS,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,KAAiB,KAAI;YAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC9B,KAAK,CAAC,cAAc,EAAE;gBAEtB,MAAM,eAAe,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;AACvD,gBAAA,MAAM,UAAU,GAAG,eAAe,GAAG,eAAe;AAEpD,gBAAA,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;gBAElE,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC;gBAC1C,IAAI,GAAG,EAAE;oBACP,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,CAAA,MAAA,EAAS,YAAY,GAAG;gBAChD;AAEA,gBAAA,IAAI,YAAY,GAAG,CAAC,EAAE;AACpB,oBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBACzB;qBAAO;AACL,oBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;gBAC1B;YACF;AACF,QAAA,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAEtB,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,KAAiB,KAAI;YAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;;gBAE5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;;gBAG7D,IAAI,IAAI,CAAC,MAAM,IAAI,YAAY,IAAI,CAAC,EAAE;AACpC,oBAAA,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,IAAI;gBACnC;YACF;AACF,QAAA,CAAC,CAAC;IACJ;AAEA;;AAEG;IACK,UAAU,CAAC,SAAsB,EAAE,KAAa,EAAA;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;QACrE,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC;AAE1C,QAAA,IAAI,CAAC,GAAG;YAAE;AAEV,QAAA,IAAI,QAAQ,CAAC,KAAK,GAAG,CAAC,EAAE;;AAEtB,YAAA,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,UAAU;YAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClD,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AACxB,YAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,gBAAA,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,IAAI;YACnC;QACF;aAAO;;AAEL,YAAA,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,UAAU;YAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClD,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;AACvB,YAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,gBAAA,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,KAAK;YACpC;QACF;IACF;AAEA;;AAEG;IACK,kBAAkB,GAAA;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACnD,IAAI,UAAU,EAAE;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,KAAK,CAAC;YAC7C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,IAAI,CAAC,CAAC;QACrD;IACF;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAI,CAAC,gBAAgB,EAAE;QACzB;IACF;AAEA;;AAEG;AACH,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC;AAC9C,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE;AAEtC,QAAA,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;AACpB,YAAA,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC;YAC5C;QACF;AAEA,QAAA,IAAI;;AAEF,YAAA,IAAI,SAAS,CAAC,KAAK,EAAE;gBACnB,MAAM,SAAS,CAAC,KAAK,CAAC;AACpB,oBAAA,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,cAAc;AACzC,oBAAA,IAAI,EAAE,UAAU,CAAC,WAAW,IAAI,EAAE;oBAClC,GAAG,EAAE,UAAU,CAAC,GAAG;AACpB,iBAAA,CAAC;AACF,gBAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;YACpD;iBAAO;;gBAEL,MAAM,KAAK,CAAC,KAAK,CAAC;AAChB,oBAAA,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,cAAc;oBACzC,GAAG,EAAE,UAAU,CAAC,GAAG;AACnB,oBAAA,WAAW,EAAE,aAAa;AAC3B,iBAAA,CAAC;AACF,gBAAA,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC;YAC1D;QACF;QAAE,OAAO,KAAU,EAAE;;AAEnB,YAAA,IAAI,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,IAAI,KAAK,gBAAgB,EAAE;AAC1E,gBAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;gBACjD;YACF;AACA,YAAA,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC;QAClD;IACF;AAEA;;AAEG;IACH,YAAY,GAAA;AACV,QAAA,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC;AAC7C,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC;AAEpC,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC;QAC3C;aAAO;YACL,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACxD;IACF;AAEA;;AAEG;IACH,OAAO,GAAA;AACL,QAAA,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC;AAC9C,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAI,CAAC,gBAAgB,EAAE;QACzB;IACF;AAEA;;AAEG;IACH,SAAS,GAAA;AACP,QAAA,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;AAC/D,YAAA,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;QACzB;IACF;AAEA;;AAEG;IACH,aAAa,GAAA;QACX,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE;AAC1C,YAAA,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;QACzB;IACF;AAEA;;AAEG;AACH,IAAA,WAAW,CAAC,KAAa,EAAA;AACvB,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,EAAE;AACjC,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,KAAa,EAAA;AACxB,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,EAAE;AACjC,YAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,KAAK,CAAA,eAAA,CAAiB,CAAC;AACzD,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QACzB;IACF;wGA3WW,8BAA8B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA9B,8BAA8B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,iBAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAcH,UAAU,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtEtC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,03UAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,+BAA+B,iIAC/B,+BAA+B,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,CAAA,gBAAA,EAAA,cAAA,EAAA,aAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,cAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,WAAA,EAAA,WAAA,EAAA,cAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA2DtB,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBAlE1C,SAAS;+BACE,0BAA0B,EAAA,UAAA,EACxB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,UAAU;wBACV,+BAA+B;wBAC/B;qBACD,EAAA,OAAA,EACQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,03UAAA,CAAA,EAAA;;sBAiBA,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,iBAAiB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;;ACjHpD;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;MAuFU,4BAA4B,CAAA;;AAEvC,IAAA,GAAG;AACH,IAAA,MAAM;AACN,IAAA,gBAAgB;;IAGhB,SAAS,GAAG,KAAK;IACjB,QAAQ,GAAG,KAAK;IAChB,YAAY,GAAG,EAAE;AACjB,IAAA,cAAc;AAEd,IAAA,WAAA,GAAA,EAAe;IAEf,QAAQ,GAAA;QACN,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,IAAI,CAAC,GAAG,CAAC;;;IAIhE;AAEA;;AAEG;AACH,IAAA,MAAM,qBAAqB,GAAA;AACzB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;AAClB,YAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC;AACtD,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,YAAA,IAAI,CAAC,YAAY,GAAG,sBAAsB;YAC1C;QACF;AAEA,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI;AACrB,QAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;AACrB,QAAA,IAAI,CAAC,YAAY,GAAG,EAAE;AAEtB,QAAA,IAAI;YACF,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;;AAGxD,YAAA,IAAI,MAAc;YAElB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;;AAE7E,gBAAA,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG;YACvB;iBAAO;;;;AAIL,gBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG;gBACrF,MAAM,GAAG,CAAA,EAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE;YACnD;AAEA,YAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,MAAM,CAAC;;YAGzD,MAAM,OAAO,CAAC,IAAI,CAAC;AACjB,gBAAA,GAAG,EAAE,MAAM;AACX,gBAAA,iBAAiB,EAAE;AACpB,aAAA,CAAC;AAEF,YAAA,IAAI,CAAC,SAAS,GAAG,KAAK;;YAGtB,UAAU,CAAC,MAAK;gBACd,IAAI,CAAC,KAAK,EAAE;YACd,CAAC,EAAE,GAAG,CAAC;QACT;QAAE,OAAO,KAAU,EAAE;AACnB,YAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC;AACzD,YAAA,IAAI,CAAC,SAAS,GAAG,KAAK;AACtB,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;YACpB,IAAI,CAAC,YAAY,GAAG,KAAK,EAAE,OAAO,IAAI,oBAAoB;QAC5D;IACF;AAEA;;AAEG;AACK,IAAA,MAAM,kBAAkB,GAAA;AAC9B,QAAA,IAAI;YACF,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;;YAGjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC1C,YAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAChB,MAAM,IAAI,KAAK,CAAC,CAAA,wBAAA,EAA2B,QAAQ,CAAC,UAAU,CAAA,CAAE,CAAC;YACnE;AAEA,YAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;YAClC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;;AAGhD,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC;AACxB,kBAAE,CAAA,EAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA,IAAA;kBAC7C,cAAc;;AAGlB,YAAA,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC;AACxC,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE,SAAS,CAAC;AACtB,aAAA,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,MAAM,CAAC,GAAG,CAAC;AAC7D,YAAA,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,GAAG;;YAGhC,MAAM,OAAO,CAAC,IAAI,CAAC;gBACjB,GAAG,EAAE,MAAM,CAAC,GAAG;AACf,gBAAA,iBAAiB,EAAE;AACpB,aAAA,CAAC;AAEF,YAAA,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC;QACvD;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,+CAA+C,EAAE,KAAK,CAAC;AACrE,YAAA,MAAM,KAAK;QACb;IACF;AAEA;;AAEG;AACK,IAAA,MAAM,YAAY,GAAA;AACxB,QAAA,IAAI;;AAEF,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG;YACrF,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,GAAG,SAAS;YAExD,MAAM,OAAO,CAAC,IAAI,CAAC;AACjB,gBAAA,GAAG,EAAE,OAAO;AACZ,gBAAA,iBAAiB,EAAE;AACpB,aAAA,CAAC;AAEF,YAAA,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC;QAC7D;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC;AAC/D,YAAA,MAAM,KAAK;QACb;IACF;AAEA;;AAEG;AACK,IAAA,YAAY,CAAC,IAAU,EAAA;QAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;AACrC,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,YAAA,MAAM,CAAC,SAAS,GAAG,MAAK;AACtB,gBAAA,MAAM,YAAY,GAAG,MAAM,CAAC,MAAgB;;gBAE5C,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC7C,OAAO,CAAC,UAAU,CAAC;AACrB,YAAA,CAAC;AACD,YAAA,MAAM,CAAC,OAAO,GAAG,MAAM;AACvB,YAAA,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;AAC5B,QAAA,CAAC,CAAC;IACJ;AAEA;;;;AAIG;IACH,eAAe,GAAA;AACb,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE;;AAElB,YAAA,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAA,EAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAA,IAAA,CAAM;QACnF;;AAGA,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;AAChB,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,kBAAkB;AACpE,YAAA,OAAO,QAAQ;QACjB;AAEA,QAAA,OAAO,kBAAkB;IAC3B;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,KAAa,EAAA;QAC1B,IAAI,KAAK,KAAK,CAAC;AAAE,YAAA,OAAO,SAAS;QAEjC,MAAM,CAAC,GAAG,IAAI;QACd,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEnD,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC;IAC1E;AAEA;;AAEG;AACH,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;AAElD,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG;YAAE;AAEpB,QAAA,IAAI;YACF,MAAM,KAAK,CAAC,KAAK,CAAC;AAChB,gBAAA,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,cAAc;AACvC,gBAAA,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE;AAChC,gBAAA,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG;AACjB,gBAAA,WAAW,EAAE;AACd,aAAA,CAAC;AAEF,YAAA,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC;QACvD;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC;QAC3D;IACF;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAI,CAAC,gBAAgB,EAAE;QACzB;IACF;AAEA;;AAEG;IACH,YAAY,GAAA;AACV,QAAA,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;;IAE5C;AAEA;;;AAGG;IACH,OAAO,GAAA;AACL,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;AAClD,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAI,CAAC,gBAAgB,EAAE;;QAEzB;IACF;wGA/OW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA5B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,wBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAzE7B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6hOAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA/EC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,aAAA,EAAA,cAAA,EAAA,WAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,+BAA+B,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,CAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC/B,+BAA+B,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,CAAA,gBAAA,EAAA,cAAA,EAAA,aAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,cAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,WAAA,EAAA,WAAA,EAAA,cAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA4EtB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBAtFxC,SAAS;+BACE,wBAAwB,EAAA,UAAA,EACtB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,UAAU;wBACV,UAAU;wBACV,iBAAiB;wBACjB,iBAAiB;wBACjB,+BAA+B;wBAC/B;qBACD,EAAA,OAAA,EACQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsET,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,6hOAAA,CAAA,EAAA;;;ACrBH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDG;MAIU,uBAAuB,CAAA;AAIxB,IAAA,MAAA;AACA,IAAA,QAAA;IAJF,eAAe,GAA6B,IAAI;IAExD,WAAA,CACU,MAAsB,EACtB,QAA6B,EAAA;QAD7B,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,QAAQ,GAAR,QAAQ;IACf;AAEH;;;;;AAKG;IACH,MAAM,IAAI,CAAC,OAAwB,EAAA;AACjC,QAAA,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;IACjC;AAEA;;;;;AAKG;IACH,MAAM,UAAU,CAAC,OAA6B,EAAA;AAC5C,QAAA,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,OAAO,CAAC;;AAG/D,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,KAAK,EAAE;QACd;;AAGA,QAAA,MAAM,YAAY,GAAG,eAAe,CAAC,8BAA8B,EAAE;YACnE,mBAAmB,EAAE,IAAI,CAAC;AAC3B,SAAA,CAAC;;QAGF,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;QAC7C,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;QAC7C,YAAY,CAAC,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC;QAC9D,YAAY,CAAC,QAAQ,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,KAAK,KAAK;QAC/D,YAAY,CAAC,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,KAAK,KAAK;QACnE,YAAY,CAAC,QAAQ,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,KAAK,KAAK;QACjE,YAAY,CAAC,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,KAAK;QAC3D,YAAY,CAAC,QAAQ,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,KAAK;QAChE,YAAY,CAAC,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM;;AAG7D,QAAA,YAAY,CAAC,QAAQ,CAAC,gBAAgB,GAAG,MAAK;YAC5C,IAAI,CAAC,KAAK,EAAE;AACd,QAAA,CAAC;;QAGD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC;;QAG7C,MAAM,OAAO,GAAI,YAAY,CAAC,QAAgB,CAAC,SAAS,CAAC,CAAC,CAAgB;AAC1E,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;;AAGlC,QAAA,IAAI,CAAC,eAAe,GAAG,YAAY;AAEnC,QAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;;AAGjD,QAAA,OAAO,MAAM,IAAI,CAAC,KAAK,EAAE;IAC3B;AAEA;;;;;AAKG;IACH,MAAM,OAAO,CAAC,OAA2B,EAAA;AACvC,QAAA,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,OAAO,CAAC;;AAG5D,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,KAAK,EAAE;QACd;;AAGA,QAAA,MAAM,YAAY,GAAG,eAAe,CAAC,4BAA4B,EAAE;YACjE,mBAAmB,EAAE,IAAI,CAAC;AAC3B,SAAA,CAAC;;QAGF,YAAY,CAAC,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG;QACvC,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;;AAG7C,QAAA,YAAY,CAAC,QAAQ,CAAC,gBAAgB,GAAG,MAAK;YAC5C,IAAI,CAAC,KAAK,EAAE;AACd,QAAA,CAAC;;QAGD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC;;QAG7C,MAAM,OAAO,GAAI,YAAY,CAAC,QAAgB,CAAC,SAAS,CAAC,CAAC,CAAgB;AAC1E,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;;AAGlC,QAAA,IAAI,CAAC,eAAe,GAAG,YAAY;AAEnC,QAAA,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC;;AAG/C,QAAA,OAAO,MAAM,IAAI,CAAC,KAAK,EAAE;IAC3B;AAEA;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;AACxB,YAAA,MAAM,OAAO,GAAI,IAAI,CAAC,eAAe,CAAC,QAAgB,CAAC,SAAS,CAAC,CAAC,CAAgB;YAClF,OAAO,CAAC,MAAM,EAAE;YAChB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;AACrD,YAAA,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;AAC9B,YAAA,IAAI,CAAC,eAAe,GAAG,IAAI;QAC7B;IACF;AAEA;;AAEG;IACH,MAAM,GAAA;AACJ,QAAA,OAAO,IAAI,CAAC,eAAe,KAAK,IAAI;IACtC;wGAnIW,uBAAuB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,cAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,uBAAuB,cAFtB,MAAM,EAAA,CAAA;;4FAEP,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAHnC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACjKD;;ACIA;;;;;;;;;;;;;;;;;;;AAmBG;MAsKU,4BAA4B,CAAA;AA6BnB,IAAA,eAAA;AA5BpB;;AAEG;IACM,MAAM,GAAa,EAAE;AAE9B;;AAEG;AACM,IAAA,MAAM;AASf;;;AAGG;IACM,UAAU,GAAW,CAAC;AAE/B;;AAEG;IACH,UAAU,GAAG,MAAM,EAA0C;AAE7D,IAAA,WAAA,CAAoB,eAAwC,EAAA;QAAxC,IAAA,CAAA,eAAe,GAAf,eAAe;IAA4B;AAE/D;;AAEG;AACH,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC;IAC9C;AAEA;;AAEG;AACH,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;IAC1D;AAEA;;AAEG;IACH,YAAY,CAAC,KAAa,EAAE,KAAa,EAAA;;QAEvC,IAAI,KAAK,EAAE;YACT,KAAK,CAAC,eAAe,EAAE;YACvB,KAAK,CAAC,cAAc,EAAE;QACxB;;AAGA,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,KAAK;AACL,YAAA,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC;AAC1B,SAAA,CAAC;;AAGF,QAAA,MAAM,cAAc,GAAoB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM;AACnE,YAAA,IAAI,EAAE,OAAO;YACb,GAAG;AACH,YAAA,GAAG,EAAE,CAAA,MAAA,EAAS,CAAC,GAAG,CAAC,CAAA;AACpB,SAAA,CAAC,CAAC;;AAGH,QAAA,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;AAC9B,YAAA,MAAM,EAAE,cAAc;AACtB,YAAA,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;AACnB,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,WAAW,EAAE;AACd,SAAA,CAAC;IACJ;wGA7EW,4BAA4B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAC,uBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA5B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjK7B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AAwBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,66DAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzBS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAkKX,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBArKxC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,wBAAwB,cACtB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,QAAA,EACb,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AAwBT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,66DAAA,CAAA,EAAA;;sBA6IA;;sBAKA;;sBAaA;;;AChLH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CG;MAIU,oBAAoB,CAAA;AACX,IAAA,eAAA;AAApB,IAAA,WAAA,CAAoB,eAAgC,EAAA;QAAhC,IAAA,CAAA,eAAe,GAAf,eAAe;IAAoB;AAEvD;;;;;;;;;;;;;;AAcG;IACH,MAAM,IAAI,CAAU,OAAwB,EAAA;AAC1C,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,OAAO,CAAC;AAE3D,QAAA,MAAM,EACJ,SAAS,EACT,cAAc,EACd,QAAQ,EACR,iBAAiB,GAAG,MAAM,EAC1B,eAAe,GAAG,IAAI,EACtB,YAAY,GAAG,IAAI,EACnB,aAAa,GAAG,IAAI,EACpB,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,QAAQ,GAAG,IAAI,EACf,IAAI,GAAG,KAAK,EACZ,oBAAoB,GAAG,IAAI,EAC5B,GAAG,OAAO;;AAGX,QAAA,MAAM,WAAW,GAAQ;YACvB,SAAS;YACT,cAAc,EAAE,cAAc,IAAI,EAAE;YACpC,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,iBAAiB,CAAC;YAC3D,IAAI;YACJ,eAAe;YACf,YAAY;YACZ,QAAQ;YACR,aAAa;YACb,iBAAiB,EAAE,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,IAAI,SAAS;AAC3E,YAAA,MAAM,EAAE,iBAAiB,KAAK,OAAO;SACtC;;AAGD,QAAA,IAAI,YAAY,KAAK,SAAS,EAAE;AAC9B,YAAA,WAAW,CAAC,UAAU,GAAG,YAAY;QACvC;;AAGA,QAAA,IAAI,iBAAiB,KAAK,OAAO,IAAI,WAAW,EAAE;AAChD,YAAA,WAAW,CAAC,WAAW,GAAG,WAAW;AACrC,YAAA,IAAI,iBAAiB,KAAK,SAAS,EAAE;AACnC,gBAAA,WAAW,CAAC,iBAAiB,GAAG,iBAAiB;YACnD;QACF;;QAGA,IAAI,oBAAoB,EAAE;AACxB,YAAA,WAAW,CAAC,UAAU,GAAG,YAAW;;AAElC,gBAAA,OAAO,IAAI;AACb,YAAA,CAAC;QACH;QAEA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC;AAE5D,QAAA,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC;AACnD,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;AAEtC,QAAA,OAAO,KAAK;IACd;AAEA;;;;;;;;;;;AAWG;AACH,IAAA,MAAM,cAAc,CAClB,SAAkB,EAClB,cAAoC,EAAA;QAEpC,OAAO,IAAI,CAAC,IAAI,CAAC;YACf,SAAS;YACT,cAAc;AACd,YAAA,iBAAiB,EAAE,YAAY;AAC/B,YAAA,eAAe,EAAE,KAAK;AACtB,YAAA,YAAY,EAAE;AACf,SAAA,CAAC;IACJ;AAEA;;;;;;;;;;;AAWG;AACH,IAAA,MAAM,QAAQ,CACZ,SAAkB,EAClB,cAAoC,EAAA;QAEpC,OAAO,IAAI,CAAC,IAAI,CAAC;YACf,SAAS;YACT,cAAc;AACd,YAAA,iBAAiB,EAAE,MAAM;AACzB,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,YAAY,EAAE;AACf,SAAA,CAAC;IACJ;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH,IAAA,MAAM,SAAS,CACb,SAAkB,EAClB,cAAoC,EACpC,OAIC,EAAA;QAED,OAAO,IAAI,CAAC,IAAI,CAAC;YACf,SAAS;YACT,cAAc;AACd,YAAA,iBAAiB,EAAE,OAAO;AAC1B,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,IAAI;AAC3C,YAAA,iBAAiB,EAAE,OAAO,EAAE,iBAAiB,IAAI,GAAG;AACpD,YAAA,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACtD,SAAA,CAAC;IACJ;AAEA;;;;;;;;;;;AAWG;AACH,IAAA,MAAM,OAAO,CAAC,IAAU,EAAE,IAAa,EAAA;QACrC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;IACjD;AAEA;;;;;;;;;;;;AAYG;AACH,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;IACtC;AAEA;;;;AAIG;AACH,IAAA,MAAM,MAAM,GAAA;QACV,MAAM,MAAM,GAA0B,EAAE;QACxC,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;QAE/C,OAAO,KAAK,EAAE;AACZ,YAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;;AAElB,YAAA,MAAM,KAAK,CAAC,OAAO,EAAE;YACrB,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;QAC7C;AAEA,QAAA,OAAO,MAAM;IACf;AAEA;;AAEG;IACK,eAAe,CACrB,WAA+B,EAC/B,iBAA0B,EAAA;AAE1B,QAAA,MAAM,OAAO,GAAa,CAAC,iBAAiB,CAAC;QAE7C,IAAI,iBAAiB,EAAE;AACrB,YAAA,OAAO,CAAC,IAAI,CAAC,YAAY,iBAAiB,CAAA,CAAE,CAAC;QAC/C;QAEA,IAAI,WAAW,EAAE;AACf,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;AAC9B,gBAAA,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC;YAC9B;iBAAO;AACL,gBAAA,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;YAC3B;QACF;AAEA,QAAA,OAAO,OAAO;IAChB;wGAnPW,oBAAoB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAApB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,oBAAoB,cAFnB,MAAM,EAAA,CAAA;;4FAEP,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAHhC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;AClFD;;;;AAIG;;ACCH;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MAEmB,eAAe,CAAA;AACzB,IAAA,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;AAEnD;;AAEG;AACoD,IAAA,UAAU;AAEjE;;AAEG;AACK,IAAA,mBAAmB;AAE3B;;;AAGG;AACH,IAAA,OAAO,GAAG,KAAK,CAAU,KAAK,mDAAC;AAE/B;;;AAGG;IACH,KAAK,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAsB;AAEnC;;;AAGG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,uDAAC;AAE/B;;;AAGG;AACH,IAAA,UAAU,GAAG,KAAK,CAAS,EAAE,sDAAC;AAE9B;;;AAGG;AACH,IAAA,gBAAgB,GAAG,KAAK,CAAS,OAAO,4DAAC;AAEzC;;;;AAIG;AACH,IAAA,sBAAsB,GAAG,KAAK,CAAU,KAAK,kEAAC;AAE9C;;;;AAIG;AACH,IAAA,cAAc,GAAG,KAAK,CAAU,KAAK,0DAAC;AAEtC;;AAEG;IACH,MAAM,GAAG,MAAM,EAAQ;IAEvB,QAAQ,GAAA;AACN,QAAA,IAAI,IAAI,CAAC,sBAAsB,EAAE,EAAE;YACjC,IAAI,CAAC,sBAAsB,EAAE;QAC/B;AAEA,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE;YACzB,IAAI,CAAC,wBAAwB,EAAE;QACjC;IACF;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,sBAAsB,EAAE,EAAE;YACjC,IAAI,CAAC,wBAAwB,EAAE;QACjC;AAEA,QAAA,IAAI,IAAI,CAAC,mBAAmB,EAAE;AAC5B,YAAA,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE;QACvC;IACF;AAEA;;;AAGG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;AAClB,QAAA,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;IAChC;AAEA;;;;AAIG;IACO,sBAAsB,GAAA;QAC9B,QAAQ,CAAC,WAAW,CAAC,kBAAkB,EAAE,OAAO,IAAI,KAAI;;AAEtD,YAAA,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA,EAAA,CAAI,CAAC;;;AAI3F,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,gBAAA,IAAI;oBACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE;oBAC9D,IAAI,aAAa,EAAE;AACjB,wBAAA,MAAM,iBAAiB,GAAG,UAAU,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC;AACjI,wBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,GAAG,iBAAiB;wBAC5D,aAAa,CAAC,KAAK,CAAC,aAAa,GAAG,CAAA,EAAG,YAAY,IAAI;AACvD,wBAAA,aAAa,CAAC,KAAK,CAAC,UAAU,GAAG,8BAA8B;oBACjE;gBACF;gBAAE,OAAO,CAAC,EAAE;AACV,oBAAA,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,CAAC,CAAC;gBACtE;YACF;AACF,QAAA,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,qDAAqD,EAAE,CAAC,CAAC,CAAC;AAEtF,QAAA,QAAQ,CAAC,WAAW,CAAC,kBAAkB,EAAE,YAAW;;YAElD,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,KAAK,CAAC;;AAGtE,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,gBAAA,IAAI;oBACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE;oBAC9D,IAAI,aAAa,EAAE;AACjB,wBAAA,MAAM,iBAAiB,GAAG,UAAU,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC;wBACjI,aAAa,CAAC,KAAK,CAAC,aAAa,GAAG,CAAA,EAAG,iBAAiB,IAAI;oBAC9D;gBACF;gBAAE,OAAO,CAAC,EAAE;AACV,oBAAA,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,CAAC,CAAC;gBACtE;YACF;AACF,QAAA,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,qDAAqD,EAAE,CAAC,CAAC,CAAC;IACxF;AAEA;;;;AAIG;AACO,IAAA,MAAM,wBAAwB,GAAA;;AAEtC,QAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,gBAAgB,EAAE;AAC7C,QAAA,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE;;QAGnC,UAAU,CAAC,YAAW;YACpB,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,qBAAqB,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC;YAEhI,IAAI,WAAW,EAAE;gBACf,IAAI,CAAC,mBAAmB,GAAG,IAAI,cAAc,CAAC,OAAO,OAAO,KAAI;AAC9D,oBAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;;wBAE3B,MAAM,MAAM,GAAI,KAAK,CAAC,MAAsB,CAAC,qBAAqB,EAAE,CAAC,MAAM;;AAE3E,wBAAA,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM;wBACnC,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,CAAC;AAC9F,wBAAA,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAA,EAAG,WAAW,CAAA,EAAA,CAAI,CAAC;;AAGvF,wBAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,4BAAA,IAAI;gCACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE;gCAC9D,IAAI,aAAa,EAAE;oCACjB,aAAa,CAAC,KAAK,CAAC,aAAa,GAAG,CAAA,EAAG,WAAW,IAAI;gCACxD;4BACF;4BAAE,OAAO,CAAC,EAAE;AACV,gCAAA,OAAO,CAAC,GAAG,CAAC,4DAA4D,EAAE,CAAC,CAAC;4BAC9E;wBACF;oBACF;AACF,gBAAA,CAAC,CAAC;AAEF,gBAAA,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC;;gBAG7C,MAAM,aAAa,GAAG,WAAW,CAAC,qBAAqB,EAAE,CAAC,MAAM;AAChE,gBAAA,MAAM,YAAY,GAAG,aAAa,GAAG,MAAM;gBAC3C,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,CAAC;AAC9F,gBAAA,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAA,EAAG,YAAY,CAAA,EAAA,CAAI,CAAC;;AAGxF,gBAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,oBAAA,IAAI;wBACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE;wBAC9D,IAAI,aAAa,EAAE;4BACjB,aAAa,CAAC,KAAK,CAAC,aAAa,GAAG,CAAA,EAAG,YAAY,IAAI;wBACzD;oBACF;oBAAE,OAAO,CAAC,EAAE;AACV,wBAAA,OAAO,CAAC,GAAG,CAAC,iEAAiE,EAAE,CAAC,CAAC;oBACnF;gBACF;YACF;QACF,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;;AAGG;IACO,wBAAwB,GAAA;QAChC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,mDAAmD,EAAE,CAAC,CAAC,CAAC;IACjH;wGA7MoB,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAf,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,sBAAA,EAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,YAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAMxB,UAAU,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAAU,UAAU,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FANrB,eAAe,EAAA,UAAA,EAAA,CAAA;kBADpC;;sBAOE,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,UAAU,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;;AC9B7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEG;AAwGG,MAAO,0BAA2B,SAAQ,eAAe,CAAA;AAwCzC,IAAA,GAAA;AAvCpB;;AAEG;IACmD,UAAU,GAAgB,SAAS;AAEzF;;;;;AAKG;AACH,IAAA,UAAU,GAAG,KAAK,CAAmB,MAAM,sDAAC;AAE5C;;AAEG;AACoD,IAAA,kBAAkB;AAEzE;;AAEG;AACkD,IAAA,gBAAgB;AAErE;;AAEG;AACqD,IAAA,aAAa;AAErE;;AAEG;AACkD,IAAA,UAAU;AAE/D;;AAEG;IACH,qBAAqB,GAAG,KAAK;IAC7B,mBAAmB,GAAG,KAAK;AAE3B,IAAA,WAAA,CAAoB,GAAsB,EAAA;AACxC,QAAA,KAAK,EAAE;QADW,IAAA,CAAA,GAAG,GAAH,GAAG;IAEvB;IAEA,kBAAkB,GAAA;;QAEhB,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB;QACtD,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB;;AAGlD,QAAA,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE;IAC1B;AAEA;;AAEG;IACH,gBAAgB,GAAA;AACd,QAAA,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE;;QAGzC,IAAI,eAAe,KAAK,IAAI;AAAE,YAAA,OAAO,IAAI;QACzC,IAAI,eAAe,KAAK,KAAK;AAAE,YAAA,OAAO,KAAK;;AAG3C,QAAA,OAAO,CAAC,EACN,IAAI,CAAC,WAAW,EAAE;YAClB,IAAI,CAAC,UAAU,EAAE;AACjB,YAAA,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC;YACzC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CACvC;IACH;AAEA;;AAEG;AACK,IAAA,gBAAgB,CAAC,IAAiB,EAAA;AACxC,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,KAAK;AACvB,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa;QAClC,OAAO,OAAO,KACZ,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;YAC7B,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CACvC;IACH;wGAlFW,0BAA0B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,oBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,iBAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAiBI,UAAU,EAAA,EAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,eAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAKZ,UAAU,EAAA,EAAA,EAAA,YAAA,EAAA,eAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAKP,UAAU,EAAA,EAAA,EAAA,YAAA,EAAA,YAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,eAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAKb,UAAU,EAAA,CAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,YAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EA5BtC,UAAU,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAAU,UAAU,EAAA,CAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhG/B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,83HAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAjGC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,qBAAqB,yPACrB,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAgGN,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAvGtC,SAAS;+BACE,sBAAsB,EAAA,UAAA,EACpB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,UAAU;wBACV,qBAAqB;wBACrB;qBACD,EAAA,OAAA,EACQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EAEvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,83HAAA,CAAA,EAAA;;sBAMA,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,UAAU,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAa1C,YAAY;AAAC,gBAAA,IAAA,EAAA,CAAA,iBAAiB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAKpD,YAAY;AAAC,gBAAA,IAAA,EAAA,CAAA,eAAe,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAKlD,YAAY;AAAC,gBAAA,IAAA,EAAA,CAAA,kBAAkB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAKrD,YAAY;AAAC,gBAAA,IAAA,EAAA,CAAA,eAAe,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;;ACtGrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;MAqKU,gCAAgC,CAAA;AAwFjC,IAAA,QAAA;AACA,IAAA,WAAA;;AAvFD,IAAA,QAAQ;;IAGR,eAAe,GAAW,EAAE;IAC5B,wBAAwB,GAAW,EAAE;;IAGrC,OAAO,GAAY,KAAK;AACxB,IAAA,KAAK;;AAGL,IAAA,eAAe;;AAGf,IAAA,mBAAmB;;AAGnB,IAAA,aAAa;;AAGb,IAAA,eAAe;;AAGG,IAAA,YAAY;;IAGvC,IAAI,GAAG,MAAM,CAAiB;AAC5B,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,UAAU,EAAE,EAAE;AACd,QAAA,UAAU,EAAE,EAAE;AACd,QAAA,SAAS,EAAE,EAAE;AACb,QAAA,OAAO,EAAE,EAAE;AACX,QAAA,QAAQ,EAAE,EAAE;AACb,KAAA,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGF,IAAA,WAAW,GAAG,MAAM,CAAC,EAAE,uDAAC;AACxB,IAAA,mBAAmB,GAAG,MAAM,CAAC,EAAE,+DAAC;AAChC,IAAA,UAAU,GAAG,MAAM,CAAiD,IAAI,sDAAC;AACzE,IAAA,cAAc,GAAG,MAAM,CAAyF,IAAI,0DAAC;;AAGrH,IAAA,eAAe,GAAG,MAAM,CAAC,KAAK,2DAAC;AAC/B,IAAA,YAAY,GAAG,MAAM,CAAC,EAAE,wDAAC;;AAGzB,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AAC7B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;QACxB,MAAM,KAAK,GAA4D,EAAE;;QAGzE,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,IAAI,CAAC,UAAU;YACrB,QAAQ,EACN,IAAI,CAAC,cAAc;AACnB,gBAAA,IAAI,CAAC;qBACF,KAAK,CAAC,GAAG;qBACT,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;qBACf,IAAI,CAAC,EAAE,CAAC;YACb,IAAI,EAAE,IAAI,CAAC,UAAU;AACtB,SAAA,CAAC;;AAGF,QAAA,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU;QACxC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,KAAI;YACjC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;AAC3C,gBAAA,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;gBACtC,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,OAAO,CAAC,UAAU;oBACxB,QAAQ,EAAE,OAAO,CAAC,cAAc;oBAChC,IAAI,EAAE,OAAO,CAAC,UAAU;AACzB,iBAAA,CAAC;YACJ;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,KAAK;AACd,IAAA,CAAC,0DAAC;;AAGF,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE;AAC/C,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI,CAAC,cAAc,EAAE;QACxC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxF,IAAA,CAAC,yDAAC;IAEF,WAAA,CACU,QAAiC,EACjC,WAAuC,EAAA;QADvC,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,WAAW,GAAX,WAAW;IAClB;IAEH,QAAQ,GAAA;;AAEN,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC9B;;AAGA,QAAA,IAAI,IAAI,CAAC,wBAAwB,EAAE;YACjC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC;QAC7D;AAAO,aAAA,IAAI,IAAI,CAAC,eAAe,EAAE;;AAE/B,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC;AACnB,iBAAA,IAAI;iBACJ,KAAK,CAAC,KAAK;iBACX,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;iBACf,IAAI,CAAC,EAAE;AACP,iBAAA,SAAS,CAAC,CAAC,EAAE,CAAC;AACd,iBAAA,WAAW,EAAE;AAChB,YAAA,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACxC;IACF;IAEA,eAAe,GAAA;;AAEb,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE;;YAE/B,UAAU,CAAC,MAAK;AACd,gBAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;;gBAExC,IAAI,CAAC,YAAY,EAAE;YACrB,CAAC,EAAE,GAAG,CAAC;QACT;IACF;AAEA;;AAEG;IACH,YAAY,GAAA;AACV,QAAA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC5E;AAEA;;AAEG;IACH,iBAAiB,GAAA;;AAEf,QAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;;QAExC,IAAI,CAAC,YAAY,EAAE;IACrB;AAEA;;AAEG;AACH,IAAA,WAAW,CAAC,KAAY,EAAA;AACtB,QAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,MAA6B;AACpD,QAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK;AAC3B,QAAA,MAAM,cAAc,GAAG,QAAQ,CAAC,cAAc,IAAI,CAAC;;AAGnD,QAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;QAC9B,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,YAAY,GAAG,IAAI;;QAGpD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,cAAc,CAAC;QAC1D,MAAM,WAAW,GAAG,gBAAgB,CAAC,WAAW,CAAC,GAAG,CAAC;AAErD,QAAA,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE;;YAEtB,MAAM,WAAW,GAAG,gBAAgB,CAAC,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC;YAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC;YAE1C,IAAI,CAAC,QAAQ,EAAE;;AAEb,gBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC;YACpC;iBAAO;AACL,gBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;YACjC;QACF;aAAO;AACL,YAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;QACjC;IACF;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,QAAgB,EAAA;;AAE5B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;AAG1D,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE;AACtC,QAAA,MAAM,kBAAkB,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACjF,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC;;AAGxC,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;;QAG/B,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;QAC1C,CAAC,EAAE,CAAC,CAAC;IACP;AAEA;;AAEG;IACH,WAAW,CAAC,UAAkB,EAAE,OAAe,EAAA;QAC7C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;;QAE5C,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE;YACxC,IAAI,CAAC,YAAY,EAAE;QACrB,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;IAC3B;AAEA;;AAEG;IACH,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7B,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1B;AAEA;;AAEG;AACH,IAAA,iBAAiB,CAAC,OAAoB,EAAA;;AAEpC,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;;AAGzB,QAAA,IAAI,aAAa,GAAG,OAAO,CAAC,OAAO;QACnC,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,mCAAmC,CAAC;QAC7E,IAAI,YAAY,EAAE;AAChB,YAAA,aAAa,GAAG,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE;;AAGA,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;YACtB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,eAAe,EAAE,OAAO,CAAC,OAAO;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;AAC7B,SAAA,CAAC;;AAGF,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC;;QAGnC,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE;AACpC,gBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa;gBAChD,QAAQ,CAAC,KAAK,EAAE;;AAGhB,gBAAA,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;gBAC9B,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,YAAY,GAAG,IAAI;gBAEpD,IAAI,CAAC,YAAY,EAAE;YACrB;QACF,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;;;AAIG;IACH,uBAAuB,CAAC,OAAoB,EAAE,EAAsC,EAAA;;AAElF,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE;QAC/B,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AAEvI,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACZ,YAAA,GAAG,WAAW;AACd,YAAA,QAAQ,EAAE,eAAe;AAC1B,SAAA,CAAC;;AAGF,QAAA,IAAI,IAAI,CAAC,mBAAmB,EAAE;YAC5B,IAAI,CAAC,mBAAmB,CAAC;gBACvB,SAAS,EAAE,OAAO,CAAC,EAAG;gBACtB,MAAM,EAAE,EAAE,CAAC,MAAM;AAClB,aAAA,CAAC;QACJ;IACF;;AAIA;;AAEG;IACH,aAAa,GAAA;QACX,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;AACtC,QAAA,IAAI,CAAC,IAAI;YAAE;AAEX,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE;AAC/B,QAAA,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM;;QAGjC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,CAAA,CAAA,EAAI,IAAI,CAAC,UAAU,EAAG,CAAC,UAAU,CAAA,CAAA,EAAI,IAAI,EAAE,GAAG,IAAI;;AAGxF,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE;AACzB,YAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,IAAI,CAAC;AAExD,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAG;YAEtC,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,OAAO,KAAI;AAC5D,gBAAA,IAAI,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,EAAE;oBACzD,OAAO;AACL,wBAAA,GAAG,OAAO;AACV,wBAAA,OAAO,EAAE,IAAI;AACb,wBAAA,SAAS,EAAE,mBAAmB;qBAC/B;gBACH;AACA,gBAAA,OAAO,OAAO;AAChB,YAAA,CAAC,CAAC;AAEF,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACZ,gBAAA,GAAG,WAAW;AACd,gBAAA,QAAQ,EAAE,eAAe;AAC1B,aAAA,CAAC;;YAGF,IAAI,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,EAAE,EAAE;gBACpC,IAAI,CAAC,aAAa,CAAC;oBACjB,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,OAAO,EAAE,SAAS;AACnB,iBAAA,CAAC;YACJ;AAEA,YAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAC/B;aAAO;AACL,YAAA,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,SAAS,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,IAAI,CAAC,eAAe,CAAC;AAExE,YAAA,MAAM,UAAU,GAAgB;AAC9B,gBAAA,UAAU,EAAE,IAAI,CAAC,eAAe,IAAI,KAAK;AACzC,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE;AAC1C,gBAAA,OAAO,EAAE,SAAS;AAClB,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,CAAC;AACZ,gBAAA,YAAY,EAAE,IAAI;aACnB;;AAGD,YAAA,MAAM,eAAe,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,UAAU,CAAC;AAErE,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACZ,gBAAA,GAAG,WAAW;AACd,gBAAA,QAAQ,EAAE,eAAe;gBACzB,YAAY,EAAE,eAAe,CAAC,MAAM;AACrC,aAAA,CAAC;;AAGF,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QAC3B;;AAGA,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;AACxB,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;AAE/B,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE;;YAEpC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;;AAErD,YAAA,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,IAAI,EAAE;QACzC;;QAGA,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAK,EAAE,CAAC,CAAC;;;AAI/B,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACnD;IACF;AAEA;;AAEG;IACH,iBAAiB,GAAA;AACf,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE;QAE5B,IAAI,CAAC,QAAQ,CAAC,QAAQ;YAAE;AAExB,QAAA,MAAM,UAAU,GAAmB;YACjC,IAAI,EAAE,QAAQ,CAAC,UAAU;YACzB,IAAI,EAAE,QAAQ,CAAC,UAAU;AACzB,YAAA,cAAc,EAAE,QAAQ,CAAC,cAAc,IAAI,EAAE;AAC7C,YAAA,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,UAAU;AAC7C,YAAA,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,EAAE;YACnC,SAAS,EAAE,QAAQ,CAAC,SAAS;SAC9B;AAED,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACjB,YAAA,MAAM,EAAE;AACN,gBAAA;AACE,oBAAA,IAAI,EAAE,OAAO;oBACb,GAAG,EAAE,QAAQ,CAAC,QAAQ;AACtB,oBAAA,GAAG,EAAE,QAAQ,CAAC,QAAQ,IAAI,YAAY;AACtC,oBAAA,KAAK,EAAE,QAAQ,CAAC,QAAQ,IAAI,EAAE;oBAC9B,WAAW,EAAE,QAAQ,CAAC,OAAO;AAC7B,oBAAA,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,KAAK;AAClC,oBAAA,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,CAAC;AAClC,oBAAA,YAAY,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC;AACzC,iBAAA;AACF,aAAA;AACD,YAAA,MAAM,EAAE,UAAU;AAClB,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,QAAQ,EAAE,IAAI;AACf,SAAA,CAAC;IACJ;AAEA;;AAEG;AACH,IAAA,MAAM,sBAAsB,CAAC,UAAkB,EAAE,OAAe,EAAE,YAAqB,EAAA;QACrF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AAC1C,YAAA,SAAS,EAAEC,mCAA0C;AACrD,YAAA,cAAc,EAAE;AACd,gBAAA,YAAY,EAAE,YAAY;AAC3B,aAAA;AACD,YAAA,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACnB,YAAA,iBAAiB,EAAE,CAAC;AACpB,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,QAAQ,EAAE,aAAa;AACxB,SAAA,CAAC;AAEF,QAAA,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;QAE1C,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE;AAC3C,YAAA,MAAM,MAAM,GAAI,MAAM,CAAC,IAA4B,CAAC,MAAM;AAC1D,YAAA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE;YAE/B,QAAQ,MAAM;AACZ,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;oBAC1C,IAAI,gBAAgB,GAAkB,IAAI;oBAC1C,IAAI,SAAS,GAAG,KAAK;;oBAErB,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,OAAO,KAAI;AAC5D,wBAAA,IAAI,OAAO,CAAC,UAAU,KAAK,UAAU,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE;AACpE,4BAAA,SAAS,GAAG,CAAC,OAAO,CAAC,OAAO;AAC5B,4BAAA,gBAAgB,GAAG,OAAO,CAAC,EAAG;4BAE9B,OAAO;AACL,gCAAA,GAAG,OAAO;AACV,gCAAA,OAAO,EAAE,SAAS;AAClB,gCAAA,SAAS,EAAE,SAAS,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,CAAC;6BAChG;wBACH;AACA,wBAAA,OAAO,OAAO;AAChB,oBAAA,CAAC,CAAC;AAEF,oBAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;;AAG5D,oBAAA,IAAI,gBAAgB,IAAI,IAAI,CAAC,mBAAmB,EAAE;wBAChD,IAAI,CAAC,mBAAmB,CAAC;AACvB,4BAAA,SAAS,EAAE,gBAAgB;AAC3B,4BAAA,MAAM,EAAE,SAAS;AAClB,yBAAA,CAAC;oBACJ;oBACA;AACF,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,UAAU,CAAC;AAC9C,oBAAA,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC;oBACrC;AACF,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;;oBAE1C,MAAM,aAAa,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,UAAU,KAAK,UAAU,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;oBAC/H,IAAI,aAAa,EAAE;AACjB,wBAAA,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC;oBACvC;oBACA;AACF,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,UAAU,CAAC;;AAE5C,oBAAA,IAAI,OAAO,CAAC,+CAA+C,CAAC,EAAE;wBAC5D,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,UAAU,KAAK,UAAU,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;AACjI,wBAAA,MAAM,0BAA0B,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,EAAE,OAAO,CAAC,UAAU,KAAK,UAAU,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;AACjJ,wBAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACZ,4BAAA,GAAG,WAAW;AACd,4BAAA,QAAQ,EAAE,0BAA0B;AACpC,4BAAA,YAAY,EAAE,0BAA0B,EAAE,MAAM,IAAI,CAAC;AACtD,yBAAA,CAAC;;wBAGF,IAAI,eAAe,EAAE,EAAE,IAAI,IAAI,CAAC,eAAe,EAAE;4BAC/C,IAAI,CAAC,eAAe,CAAC,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC;wBACzD;oBACF;oBACA;;QAEN;IACF;wGAxfW,gCAAgC,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAD,uBAAA,EAAA,EAAA,EAAA,KAAA,EAAAE,0BAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gCAAgC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,6BAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,0BAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,qBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,cAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,cAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/IjC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6IT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,mwLAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA9JC,YAAY,8BACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,qBAAqB,yPACrB,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,kBAAkB,uDAClB,mBAAmB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,EAAA,aAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,sBAAsB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACtB,wBAAwB,uUACxB,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAsJjB,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBApK5C,SAAS;+BACE,6BAA6B,EAAA,UAAA,EAC3B,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,eAAe;wBACf,qBAAqB;wBACrB,iBAAiB;wBACjB,iBAAiB;wBACjB,kBAAkB;wBAClB,mBAAmB;wBACnB,sBAAsB;wBACtB,wBAAwB;wBACxB,0BAA0B;qBAC3B,EAAA,OAAA,EAKQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6IT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,mwLAAA,CAAA,EAAA;;sBAIA;;sBAGA;;sBACA;;sBAGA;;sBACA;;sBAGA;;sBAGA;;sBAGA;;sBAGA;;sBAGA,SAAS;uBAAC,cAAc;;;ACjU3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BG;MAEmB,gBAAgB,CAAA;AACd,IAAA,eAAA;AAAtB,IAAA,WAAA,CAAsB,eAAgC,EAAA;QAAhC,IAAA,CAAA,eAAe,GAAf,eAAe;IAAoB;AAEzD;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACO,IAAA,MAAM,WAAW,CACzB,SAAkB,EAClB,cAAoC,EACpC,aAA0C,EAAA;AAE1C,QAAA,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;YACvC,SAAS;YACT,cAAc;;AAEd,YAAA,QAAQ,EAAE,eAAe;AACzB,YAAA,IAAI,EAAE,KAAK;YACX,iBAAiB,EAAE,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,IAAI,SAAS;AAC3E,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,QAAQ,EAAE,IAAI;;AAEd,YAAA,GAAG,aAAa;AACjB,SAAA,CAAC;IACJ;AAEA;;;;;AAKG;IACH,MAAM,KAAK,CAAC,IAAU,EAAA;QACpB,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C;AAEA;;;;AAIG;AACH,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;IACtC;wGA/DoB,gBAAgB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;4GAAhB,gBAAgB,EAAA,CAAA;;4FAAhB,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBADrC;;;AC9BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CG;AAIG,MAAO,8BAA+B,SAAQ,gBAAgB,CAAA;AAClE,IAAA,WAAA,CAAY,eAAgC,EAAA;QAC1C,KAAK,CAAC,eAAe,CAAC;IACxB;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,IAAI,CACR,QAAwB,EACxB,OASC,EAAA;AAED,QAAA,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,QAAQ,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,6CAA6C,EAAE,OAAO,EAAE,eAAe,CAAC;QAEpF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAClC,gCAAgC,EAChC;AACE,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK;YAClC,KAAK,EAAE,OAAO,EAAE,KAAK;YACrB,eAAe,EAAE,OAAO,EAAE,eAAe;YACzC,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;AACjD,YAAA,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,EAAE;AAC/C,YAAA,wBAAwB,EAAE,OAAO,EAAE,mBAAmB,IAAI,EAAE;SAC7D,EACD;YACE,aAAa,EAAE,IAAI;AACpB,SAAA,CACF;AAED,QAAA,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC;AAC7D,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAClD;wGA/CW,8BAA8B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAA9B,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,8BAA8B,cAF7B,MAAM,EAAA,CAAA;;4FAEP,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBAH1C,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA;;;AClDD;;;;AAIG;;ACDH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDG;MAgMU,2BAA2B,CAAA;AACtC;;;;AAIG;AACH,IAAA,OAAO,GAAG,KAAK,CAAwB,SAAS,mDAAC;AAEjD;;;AAGG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAEhC;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;AACH,IAAA,WAAW,CAAC,KAAY,EAAA;AACtB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACnB;QACF;;AAGA,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB;QAC1C,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,qDAAqD,CAAC;;QAGhG,IAAI,kBAAkB,IAAI,kBAAkB,KAAK,KAAK,CAAC,aAAa,EAAE;YACpE;QACF;AAEA,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,KAAoB,EAAA;AAChC,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACnB;QACF;QAEA,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGAjDW,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA3B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,qBAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,uBAAA,EAAA,2BAAA,EAAA,uBAAA,EAAA,2BAAA,EAAA,WAAA,EAAA,YAAA,EAAA,eAAA,EAAA,2BAAA,EAAA,oBAAA,EAAA,8BAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjB5B,CAAA;;;;;;;;;;;;;;;AAeT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wjEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA1LS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FA4LX,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBA/LvC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,uBAAuB,cACrB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,IAAA,EACjB;AACJ,wBAAA,kBAAkB,EAAE,YAAY;AAChC,wBAAA,yBAAyB,EAAE,yBAAyB;AACpD,wBAAA,yBAAyB,EAAE,yBAAyB;AACpD,wBAAA,aAAa,EAAE,UAAU;AACzB,wBAAA,iBAAiB,EAAE,yBAAyB;AAC5C,wBAAA,sBAAsB,EAAE,4BAA4B;AACpD,wBAAA,SAAS,EAAE,qBAAqB;AAChC,wBAAA,iBAAiB,EAAE,uBAAuB;AAC1C,wBAAA,iBAAiB,EAAE;qBACpB,EAAA,QAAA,EAgKS,CAAA;;;;;;;;;;;;;;;AAeT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wjEAAA,CAAA,EAAA;;;ACjPH;;;;;;;;;;;;;;;;;;AAkBG;MA+CU,+BAA+B,CAAA;AAC1C;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAS,UAAU,oDAAC;AAEpC;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAS,EAAE,oDAAC;AAE5B;;;;AAIG;AACH,IAAA,OAAO,GAAG,KAAK,CAAgB,KAAK,mDAAC;AAErC;;;;AAIG;AACH,IAAA,MAAM,GAAG,KAAK,CAAwB,SAAS,kDAAC;AAEhD;;AAEG;IACH,SAAS,GAAG,MAAM,EAAQ;AAE1B;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,KAAK,GAAG,mBAAmB,GAAG,qBAAqB;IAC/E;AAEA;;AAEG;IACH,gBAAgB,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,KAAK,GAAG,KAAK,GAAG,KAAK;IACjD;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGA9CW,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/BhC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,oLAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzCS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,sGAAE,2BAA2B,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA2C5E,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBA9C3C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,4BAA4B,EAAA,UAAA,EAC1B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,2BAA2B,CAAC,EAAA,QAAA,EAY9E,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,oLAAA,CAAA,EAAA;;;AClEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BG;MAiEU,oCAAoC,CAAA;AAC/C;;AAEG;AACH,IAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,kDAAU;AAElC;;;AAGG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAS,EAAE,oDAAC;wGAVjB,oCAAoC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oCAAoC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iCAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhBrC,CAAA;;;;;;;;;;;;;;AAcT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wpBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FA6DX,oCAAoC,EAAA,UAAA,EAAA,CAAA;kBAhEhD,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iCAAiC,cAC/B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,QAAA,EA6Cb,CAAA;;;;;;;;;;;;;;AAcT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wpBAAA,CAAA,EAAA;;;ACwCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;MA8HU,0BAA0B,CAAA;AA4CjB,IAAA,eAAA;;AA1CX,IAAA,QAAQ;AAEjB;;AAEG;IACM,OAAO,GAAY,KAAK;AAEjC;;AAEG;AACM,IAAA,KAAK;;IAGd,WAAW,GAAG,MAAM,CAAkB;AACpC,QAAA,EAAE,EAAE,EAAE;AACN,QAAA,IAAI,EAAE,EAAE;AACR,QAAA,cAAc,EAAE,EAAE;AACnB,KAAA,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,aAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;AAEF,IAAA,QAAQ,GAAG,MAAM,CAAgB,EAAE,oDAAC;AACpC,IAAA,mBAAmB,GAAG,MAAM,CAAS,EAAE,+DAAC;AACxC,IAAA,qBAAqB,GAAG,MAAM,CAAgC,UAAU,iEAAC;AACzE,IAAA,oBAAoB,GAAG,MAAM,CAAS,EAAE,gEAAC;AACzC,IAAA,SAAS,GAAG,MAAM,CAAU,KAAK,qDAAC;AAElC;;AAEG;AACH,IAAA,iBAAiB,GAAG,MAAM,CAAgB,IAAI,6DAAC;AAE/C;;AAEG;AACK,IAAA,gBAAgB;AAExB;;AAEG;AACH,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;QAC5B,OAAO,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACrD,IAAA,CAAC,yDAAC;AAEF,IAAA,WAAA,CAAoB,eAAwC,EAAA;QAAxC,IAAA,CAAA,eAAe,GAAf,eAAe;IAA4B;IAE/D,QAAQ,GAAA;;AAEN,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;AAC/C,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;AAC/C,YAAA,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,IAAI,EAAE,CAAC;AACrE,YAAA,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,IAAI,UAAU,CAAC;AACjF,YAAA,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,IAAI,EAAE,CAAC;AACvE,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,KAAK,CAAC;QACtD;IACF;IAEA,eAAe,GAAA;;QAEb,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9B,UAAU,CAAC,MAAK;gBACd,IAAI,CAAC,cAAc,EAAE;YACvB,CAAC,EAAE,GAAG,CAAC;QACT;IACF;AAEA;;AAEG;AACK,IAAA,MAAM,cAAc,GAAA;QAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,kCAAkC,CAAC;QAC7E,IAAI,UAAU,EAAE;AACd,YAAA,MAAO,UAAkB,CAAC,cAAc,CAAC,GAAG,CAAC;QAC/C;IACF;AAEA;;AAEG;AACH,IAAA,iBAAiB,CAAC,KAAiH,EAAA;AACjI,QAAA,MAAM,UAAU,GAAgB;AAC9B,YAAA,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YACzB,OAAO,EAAE,KAAK,CAAC,OAAO;AACtB,YAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa;AACrC,YAAA,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,IAAI,IAAI,EAAE;AACrB,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE;AAC1C,YAAA,UAAU,EAAE,IAAI,CAAC,qBAAqB,EAAE;AACxC,YAAA,SAAS,EAAE,IAAI,CAAC,oBAAoB,EAAE;AACtC,YAAA,eAAe,EAAE,KAAK,CAAC,WAAW,IAAI;SACvC;;QAGD,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,UAAU,CAAC;AACxD,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC;;QAGlC,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,cAAc,EAAE;QACvB,CAAC,EAAE,GAAG,CAAC;;;IAIT;AAEA;;AAEG;AACH,IAAA,qBAAqB,CAAC,UAA0B,EAAA;AAC9C,QAAA,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE;AAC/B,YAAA,IAAI,UAAU,CAAC,GAAG,EAAE;gBAClB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,qBAAqB,CAAC;YAC9D;YACA;QACF;AAEA,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;QAE5B,MAAM,SAAS,GAAqD,EAAE;AACtE,QAAA,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;YACpB,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE,EAAE;AACrC,gBAAA,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE;oBACxB,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;gBACjC;YACF;QACF;AAEA,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAC3B,CAAC,EACD,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC,CACvD;QAED,MAAM,MAAM,GAAoB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM;AACpD,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG;AACd,YAAA,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI;AACjB,YAAA,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI;AACf,YAAA,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS;AAC3B,SAAA,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,EAAE,GAAG;QAEjD,MAAM,MAAM,GAA+B;AACzC,cAAE;gBACE,IAAI,EAAE,YAAY,CAAC,UAAU;gBAC7B,IAAI,EAAE,YAAY,CAAC,UAAU;gBAC7B,SAAS,EAAE,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,SAAS,CAAC;gBAC9D,cAAc,EAAE,YAAY,CAAC,cAAc;gBAC3C,SAAS,EAAE,YAAY,CAAC,SAAS;gBACjC,UAAU,EAAE,YAAY,CAAC,UAAU,KAAK,OAAO,IAAI,YAAY,CAAC,UAAU,KAAK,UAAU,GAAG,YAAY,CAAC,UAAU,GAAG,SAAS;AAChI;cACD,SAAS;AAEb,QAAA,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;YAC9B,MAAM;YACN,MAAM;YACN,YAAY;AACZ,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,QAAQ,EAAE,IAAI;AACd,YAAA,SAAS,EAAE,MAAM;AAClB,SAAA,CAAC;IACJ;AAEA;;AAEG;IACH,6BAA6B,GAAA;AAC3B,QAAA,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC;;IAE/D;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,IAAY,EAAA;QACzB,OAAO,IAAI,KAAK,KAAK,GAAG,KAAK,GAAG,KAAK;IACvC;AAEA;;AAEG;AACH,IAAA,yBAAyB,CAAC,cAA8B,EAAA;AACtD,QAAA,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,cAAc,CAAC;;IAErE;AAEA;;AAEG;AACH,IAAA,MAAM,gBAAgB,CAAC,UAA0B,EAAE,OAAoB,EAAA;AACrE,QAAA,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;AACpC,YAAA,MAAM,EAAE,CAAC;AACP,oBAAA,IAAI,EAAE,OAAO;oBACb,GAAG,EAAE,UAAU,CAAC,GAAG;AACnB,oBAAA,KAAK,EAAE,UAAU,CAAC,IAAI,IAAI,OAAO;AACjC,oBAAA,GAAG,EAAE,UAAU,CAAC,IAAI,IAAI;iBACzB,CAAC;AACF,YAAA,MAAM,EAAE;gBACN,IAAI,EAAE,OAAO,CAAC,UAAU;gBACxB,IAAI,EAAE,OAAO,CAAC,UAAU;gBACxB,cAAc,EAAE,OAAO,CAAC,cAAc;AACtC,gBAAA,UAAU,EAAE,OAAO,CAAC,UAAU,KAAK,UAAU,GAAG,UAAU,GAAG,OAAO;gBACpE,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,SAAS;AACzD,aAAA;AACD,YAAA,YAAY,EAAE,CAAC;AACf,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,WAAW,EAAE,KAAK;AAClB,YAAA,QAAQ,EAAE,KAAK;AACf,YAAA,WAAW,EAAE;AACd,SAAA,CAAC;IACJ;AAEA;;AAEG;AACH,IAAA,sBAAsB,CAAC,OAAoB,EAAA;AACzC,QAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,OAAO,CAAC;;IAE3D;AAEA;;AAEG;AACH,IAAA,kBAAkB,CAAC,SAAiB,EAAA;;AAElC,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC;QACrC;;QAGA,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,IACnC,OAAO,KAAK,SAAS,GAAG,IAAI,GAAG,SAAS,CACzC;;AAGD,QAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE,KAAK,SAAS,EAAE;AAC1C,YAAA,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,MAAK;AACtC,gBAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC;YAClC,CAAC,EAAE,IAAI,CAAC;QACV;IACF;AAEA;;AAEG;AACH,IAAA,sBAAsB,CAAC,IAAU,EAAA;AAC/B,QAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE;AACtC,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,MAAM,EAAE,SAAS;AACjB,YAAA,MAAM,EAAE;AACT,SAAA,CAAC;IACJ;AAEA;;;AAGG;IACK,mBAAmB,CAAC,QAAuB,EAAE,gBAAwB,EAAA;QAC3E,MAAM,MAAM,GAAmB,EAAE;QACjC,IAAI,YAAY,GAAwB,IAAI;AAE5C,QAAA,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,KAAI;AAC3B,YAAA,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS;;;;;AAMrC,YAAA,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,gBAAgB,CAAC,EAAE;AACpG,gBAAA,YAAY,GAAG;AACb,oBAAA,SAAS,EAAE,WAAW;AACtB,oBAAA,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC;AACxD,oBAAA,QAAQ,EAAE;iBACX;AACD,gBAAA,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;YAC3B;AAEA,YAAA,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;AACrC,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,MAAM;IACf;AAEA;;AAEG;AACK,IAAA,mBAAmB,CAAC,QAAc,EAAE,WAAiB,EAAE,gBAAwB,EAAA;AACrF,QAAA,MAAM,WAAW,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,KAAK,IAAI,GAAG,EAAE,CAAC;;QAG9E,IAAI,QAAQ,CAAC,YAAY,EAAE,KAAK,WAAW,CAAC,YAAY,EAAE,EAAE;AAC1D,YAAA,OAAO,IAAI;QACb;;QAGA,OAAO,WAAW,GAAG,gBAAgB;IACvC;AAEA;;;AAGG;AACK,IAAA,oBAAoB,CAAC,IAAU,EAAA;AACrC,QAAA,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE;QACtB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;AACxE,QAAA,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;QACjC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAE1C,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;;AAGjF,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE;AAC/C,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,MAAM,EAAE,SAAS;AACjB,YAAA,MAAM,EAAE;AACT,SAAA,CAAC;;QAGF,IAAI,WAAW,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE;AAC7C,YAAA,OAAO,OAAO;QAChB;;QAGA,IAAI,WAAW,CAAC,OAAO,EAAE,KAAK,SAAS,CAAC,OAAO,EAAE,EAAE;YACjD,OAAO,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE;QAC5B;;AAGA,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAC7F,QAAA,IAAI,OAAO,GAAG,CAAC,EAAE;AACf,YAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,CAAA,EAAA,EAAK,OAAO,EAAE;QAC/E;;AAGA,QAAA,MAAM,UAAU,GAA+B;AAC7C,YAAA,KAAK,EAAE,OAAO;AACd,YAAA,GAAG,EAAE;SACN;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,EAAE;AAC5C,YAAA,UAAU,CAAC,IAAI,GAAG,SAAS;QAC7B;AAEA,QAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE;IACtE;wGA9VW,0BAA0B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAH,uBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA5G3B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0GT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,6lDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAvHC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC1B,gCAAgC,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,CAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,sBAAA,EAAA,mBAAA,EAAA,oBAAA,EAAA,gBAAA,EAAA,cAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,iBAAA,EAAA,mBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAChC,8BAA8B,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,cAAA,EAAA,YAAA,EAAA,WAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,aAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,iBAAA,EAAA,WAAA,EAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC9B,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC1B,+BAA+B,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC/B,oCAAoC,EAAA,QAAA,EAAA,iCAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAmH3B,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBA7HtC,SAAS;+BACE,sBAAsB,EAAA,UAAA,EACpB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,0BAA0B;wBAC1B,gCAAgC;wBAChC,8BAA8B;wBAC9B,0BAA0B;wBAC1B,+BAA+B;wBAC/B;qBACD,EAAA,OAAA,EAKQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0GT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,6lDAAA,CAAA,EAAA;;sBAIA;;sBAKA;;sBAKA;;;AC1SH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDG;AAIG,MAAO,wBAAyB,SAAQ,gBAAgB,CAAA;AAC5D,IAAA,WAAA,CAAY,eAAgC,EAAA;QAC1C,KAAK,CAAC,eAAe,CAAC;IACxB;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,IAAI,CACR,QAAuB,EACvB,OAA+C,EAAA;AAE/C,QAAA,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,QAAQ,CAAC;QAEvD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAClC,0BAA0B,EAC1B;AACE,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK;YAClC,KAAK,EAAE,OAAO,EAAE;SACjB,EACD;YACE,aAAa,EAAE,IAAI;AACpB,SAAA,CACF;AAED,QAAA,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC;AACvD,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;IAC5C;wGAjCW,wBAAwB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,wBAAwB,cAFvB,MAAM,EAAA,CAAA;;4FAEP,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAHpC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACrBD;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;MAoHU,gCAAgC,CAAA;AACI,IAAA,aAAa;AACnC,IAAA,UAAU;AACX,IAAA,SAAS;AAEjC;;AAEG;IACM,OAAO,GAAY,KAAK;AAEjC;;AAEG;AACM,IAAA,KAAK;AAEd;;AAEG;AACM,IAAA,QAAQ;AAEjB;;AAEG;IACH,KAAK,GAAG,EAAE;AAEV;;AAEG;IACH,WAAW,GAAG,EAAE;AAEhB;;AAEG;AACH,IAAA,WAAW,GAAG,MAAM,CAAmB,EAAE,uDAAC;AAE1C;;AAEG;AACH,IAAA,WAAW,GAAG,MAAM,CAAU,KAAK,uDAAC;AAEpC;;AAEG;AACH,IAAA,YAAY,GAAG,MAAM,CAAU,KAAK,wDAAC;IAErC,QAAQ,GAAA;AACN,QAAA,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC;IACxD;IAEA,eAAe,GAAA;;QAEb,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,uBAAuB,EAAE;;AAG9B,YAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACtB,gBAAA,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,CAAC;gBAClF,IAAI,eAAe,EAAE;oBACnB,eAAe,CAAC,KAAK,EAAE;gBACzB;YACF;QACF,CAAC,EAAE,GAAG,CAAC;IACT;AAEA;;AAEG;IACK,uBAAuB,GAAA;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;;AAGzB,QAAA,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU,CAAC;QAClF,IAAI,eAAe,EAAE;AACnB,YAAA,eAAe,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;YACrC,eAAe,CAAC,KAAK,CAAC,MAAM,GAAG,eAAe,CAAC,YAAY,GAAG,IAAI;QACpE;IACF;AAEA;;AAEG;AACH,IAAA,iBAAiB,CAAC,KAAa,EAAA;QAC7B,IAAI,CAAC,YAAY,EAAE;QACnB,IAAI,CAAC,uBAAuB,EAAE;IAChC;AAEA;;AAEG;IACH,YAAY,GAAA;QACV,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;AAClF,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC;IAC/B;AAEA;;AAEG;AACH,IAAA,MAAM,QAAQ,GAAA;QACZ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE;YAClC;QACF;AAEA,QAAA,IAAI;AACF,YAAA,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;AAClC,gBAAA,OAAO,EAAE,EAAE;AACX,gBAAA,YAAY,EAAE,KAAK;gBACnB,UAAU,EAAE,gBAAgB,CAAC,GAAG;AAChC,gBAAA,MAAM,EAAE,YAAY,CAAC,MAAM;AAC5B,aAAA,CAAC;AAEF,YAAA,IAAI,KAAK,CAAC,OAAO,EAAE;AACjB,gBAAA,MAAM,aAAa,GAAmB;AACpC,oBAAA,EAAE,EAAE,CAAA,MAAA,EAAS,IAAI,CAAC,GAAG,EAAE,CAAA,CAAE;oBACzB,GAAG,EAAE,KAAK,CAAC,OAAO;AAClB,oBAAA,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,CAAA,MAAA,EAAS,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA;iBAC7C;AAED,gBAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC;YACzE;QACF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC;;QAE/D;IACF;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,YAAoB,EAAA;QACnC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IACxF;AAEA;;AAEG;IACH,mBAAmB,GAAA;QACjB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE;YAClC;QACF;;AAGA,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE;QACtC;IACF;AAEA;;AAEG;AACK,IAAA,cAAc,CAAC,IAAU,EAAA;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;;AAGxC,QAAA,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AACjC,YAAA,OAAO,OAAO;QAChB;;AAGA,QAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AAC7B,YAAA,OAAO,KAAK;QACd;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;AACrC,YAAA,OAAO,MAAM;QACf;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;AACrC,YAAA,OAAO,MAAM;QACf;AAEA,QAAA,OAAO,OAAO;IAChB;AAEA;;AAEG;AACK,IAAA,cAAc,CAAC,KAAa,EAAA;QAClC,IAAI,KAAK,KAAK,CAAC;AAAE,YAAA,OAAO,KAAK;QAC7B,MAAM,CAAC,GAAG,IAAI;QACd,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC;IACxE;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,KAAY,EAAA;AAC3B,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;AAC9C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;QAEzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;YAChC;QACF;;QAGA,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM;AACpD,QAAA,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC;AAEjE,QAAA,cAAc,CAAC,OAAO,CAAC,IAAI,IAAG;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;;AAG1C,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAI;AACpB,gBAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAgB;gBACzC,IAAI,MAAM,EAAE;AACV,oBAAA,MAAM,aAAa,GAAmB;wBACpC,EAAE,EAAE,CAAA,KAAA,EAAQ,IAAI,CAAC,GAAG,EAAE,CAAA,CAAA,EAAI,IAAI,CAAC,MAAM,EAAE,CAAA,CAAE;AACzC,wBAAA,GAAG,EAAE,MAAM;AACX,wBAAA,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI;qBACpC;AACD,oBAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC;gBACzE;AACF,YAAA,CAAC;AACD,YAAA,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;AAC5B,QAAA,CAAC,CAAC;;AAGF,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;AAEA;;AAEG;AACH,IAAA,MAAM,YAAY,GAAA;QAChB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;YAC9C;QACF;AAEA,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;AAE3B,QAAA,IAAI;AACF,YAAA,MAAM,WAAW,GAAmB;AAClC,gBAAA,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;AACxB,gBAAA,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;AACpC,gBAAA,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B;AAED,YAAA,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,WAAW,CAAC;AAEjE,YAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,gBAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;YAClC;;QAGF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC;AACnE,YAAA,IAAI,CAAC,KAAK,GAAG,6CAA6C;QAC5D;gBAAU;AACR,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9B;IACF;wGAhQW,gCAAgC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAhC,gCAAgC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,6BAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,eAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,YAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EACV,UAAU,EAAA,EAAA,EAAA,YAAA,EAAA,YAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,YAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAnGjC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,y1CAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA7GC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAD,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,iBAAA,EAAA,QAAA,EAAA,wIAAA,EAAA,MAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,aAAA,EAAA,cAAA,EAAA,WAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,mBAAmB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,aAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,OAAA,EAAA,MAAA,EAAA,MAAA,EAAA,WAAA,EAAA,WAAA,EAAA,WAAA,EAAA,iBAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACrB,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC1B,kCAAkC,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAyGzB,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAnH5C,SAAS;+BACE,6BAA6B,EAAA,UAAA,EAC3B,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,iBAAiB;wBACjB,mBAAmB;wBACnB,qBAAqB;wBACrB,0BAA0B;wBAC1B;qBACD,EAAA,OAAA,EAKQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,w1EAAA,EAAA,y1CAAA,CAAA,EAAA;;sBAGA,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,YAAY,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAC5C,SAAS;uBAAC,YAAY;;sBACtB,SAAS;uBAAC,WAAW;;sBAKrB;;sBAKA;;sBAKA;;;ACxLH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;AAIG,MAAO,8BAA+B,SAAQ,gBAAgB,CAAA;AAClE,IAAA,WAAA,CAAY,eAAgC,EAAA;QAC1C,KAAK,CAAC,eAAe,CAAC;IACxB;AAEA;;;;;AAKG;IACH,MAAM,IAAI,CAAC,OAAgC,EAAA;AACzC,QAAA,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,OAAO,CAAC;QAErE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAClC,gCAAgC,EAChC;YACE,QAAQ,EAAE,OAAO,EAAE,QAAQ;AAC3B,YAAA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK;YAClC,KAAK,EAAE,OAAO,EAAE;SACjB,EACD;YACE,aAAa,EAAE,KAAK;AACrB,SAAA,CACF;AAED,QAAA,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC;AAC7D,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAClD;wGA7BW,8BAA8B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAA9B,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,8BAA8B,cAF7B,MAAM,EAAA,CAAA;;4FAEP,8BAA8B,EAAA,UAAA,EAAA,CAAA;kBAH1C,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;AC9CD;;;;;;;;;;;;;AAaG;MA+EU,mCAAmC,CAAA;AAC9C;;;AAGG;IACM,OAAO,GAAW,cAAc;AAEzC;;AAEG;IACM,QAAQ,GAAW,kBAAkB;AAE9C;;AAEG;AACH,IAAA,WAAW,CAAC,MAAyB,EAAA;AACnC,QAAA,MAAM,UAAU,GAA2B;AACzC,YAAA,SAAS,EAAE,SAAS;AACpB,YAAA,SAAS,EAAE,SAAS;AACpB,YAAA,aAAa,EAAE,aAAa;AAC5B,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,cAAc,EAAE,cAAc;AAC9B,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,eAAe,EAAE,eAAe;AAChC,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,YAAY,EAAE,YAAY;AAC1B,YAAA,MAAM,EAAE;SACT;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc;AAC5D,QAAA,OAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,EAAI,MAAM,GAAG;IAC9C;wGA/BW,mCAAmC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mCAAmC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gCAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA9BpC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6gBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzES,YAAY,+BAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA2E5B,mCAAmC,EAAA,UAAA,EAAA,CAAA;kBA9E/C,SAAS;+BACE,gCAAgC,EAAA,UAAA,EAC9B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,CAAC,EAAA,QAAA,EA6C9B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,6gBAAA,CAAA,EAAA;;sBAOA;;sBAKA;;;ACpGH;;;;;;;;;;;;;;;;;;AAkBG;MAgDU,kCAAkC,CAAA;AAC7C;;AAEG;AACH,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,+CAAU;AAE/B;;AAEG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAC,QAAQ,mDAAU;AAEnC;;AAEG;AACH,IAAA,aAAa,GAAG,KAAK,CAAS,EAAE,yDAAC;AAEjC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,uDAAC;AAE/B;;;;AAIG;AACH,IAAA,MAAM,GAAG,KAAK,CAAwB,SAAS,kDAAC;AAEhD;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAU,IAAI,qDAAC;AAEhC;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAU,IAAI,uDAAC;AAElC;;AAEG;IACH,YAAY,GAAG,MAAM,EAAQ;IAE7B,kBAAkB,GAAA;AAChB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;wGA7CW,kCAAkC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kCAAkC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAxCnC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA1CS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,mIAAE,2BAA2B,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA4C5E,kCAAkC,EAAA,UAAA,EAAA,CAAA;kBA/C9C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,+BAA+B,EAAA,UAAA,EAC7B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,2BAA2B,CAAC,EAAA,QAAA,EAI9E,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCT,EAAA,CAAA,EAAA;;;AC1DH;;;;;;;;;;;;;;;;;;;;AAoBG;MA0CU,uBAAuB,CAAA;AAClC;;AAEG;AACH,IAAA,UAAU,GAAG,KAAK,CAAS,MAAM,sDAAC;AAElC;;AAEG;AACH,IAAA,GAAG,GAAG,KAAK,CAAS,EAAE,+CAAC;AAE0B,IAAA,eAAe;IAExD,cAAc,GAAkB,IAAI;IAE5C,eAAe,GAAA;QACb,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,gBAAgB,EAAE;QACzB,CAAC,EAAE,GAAG,CAAC;IACT;IAEQ,gBAAgB,GAAA;QACtB,IAAI,CAAC,IAAI,CAAC,eAAe;YAAE;;AAG3B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,gBAAgB,CAAC,eAAe,CAAC;AACnF,QAAA,MAAM,CAAC,OAAO,CAAC,CAAC,KAAkB,KAAI;YACpC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE;AACvC,QAAA,CAAC,CAAC;QAEF,IAAI,CAAC,cAAc,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE;AACnE,YAAA,aAAa,EAAE,MAAM;AACrB,YAAA,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;AACxB,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,oBAAoB,EAAE,IAAI;AAC1B,YAAA,KAAK,EAAE,GAAG;AACV,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,eAAe,EAAE,IAAI;AACtB,SAAA,CAAC;IACJ;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;AAC7B,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;QAC5B;IACF;wGA9CW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,iBAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApCxB,CAAA;;;;;;AAMT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wUAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EARS,YAAY,EAAA,CAAA,EAAA,CAAA;;4FAsCX,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAzCnC,SAAS;+BACE,kBAAkB,EAAA,UAAA,EAChB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAAA,OAAA,EACd,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;AAMT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wUAAA,CAAA,EAAA;;sBAyCA,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,iBAAiB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;;;ACyCjD;;;;;;;;;;;;;;AAcG;MAuGU,oCAAoC,CAAA;;AAEtC,IAAA,YAAY;AAErB;;AAEG;IACM,OAAO,GAAY,KAAK;AAEjC;;AAEG;AACM,IAAA,KAAK;;IAGd,QAAQ,GAAG,MAAM,CAAqB;AACpC,QAAA,KAAK,EAAE,EAAE;AACT,QAAA,OAAO,EAAE,cAAc;AACvB,QAAA,QAAQ,EAAE,kBAAkB;AAC5B,QAAA,SAAS,EAAE,CAAC;AACZ,QAAA,KAAK,EAAE;AACR,KAAA,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,UAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;IAEF,QAAQ,GAAA;;AAEN,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;QACtC;IACF;AAEA;;;;;;;AAOG;AACH,IAAA,wBAAwB,CAAC,IAAkB,EAAA;QACzC,MAAM,YAAY,GAAmB,EAAE;AAEvC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;AACvD,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;AAC7D,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;;AAGtE,QAAA,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM;AACxF,QAAA,IAAI,gBAAgB,IAAI,CAAC,EAAE;YACzB,OAAO,CAAC,IAAI,CAAC;QACf;;AAGA,QAAA,IAAI,SAAS,IAAI,WAAW,IAAI,CAAC,cAAc,EAAE;YAC/C,OAAO,CAAC,IAAI,CAAC;QACf;;;QAKA,IAAI,SAAS,EAAE;YACb,YAAY,CAAC,IAAI,CAAC;gBAChB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,MAAM,EAAE,IAAI,CAAC;AACd,aAAA,CAAC;QACJ;;QAGA,IAAI,WAAW,EAAE;YACf,YAAY,CAAC,IAAI,CAAC;gBAChB,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,gBAAA,WAAW,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC,WAAW;gBACrD,QAAQ,EAAE,IAAI,CAAC;AAChB,aAAA,CAAC;QACJ;;QAGA,IAAI,cAAc,EAAE;YAClB,YAAY,CAAC,IAAI,CAAC;gBAChB,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,gBAAA,WAAW,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,GAAG,SAAS;gBACxE,WAAW,EAAE,IAAI,CAAC;AACnB,aAAA,CAAC;QACJ;AAEA,QAAA,OAAO,YAAY;IACrB;AAEA;;AAEG;IACH,eAAe,GAAA;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,EAAE;QACzC,MAAM,YAAY,GAAmB,EAAE;AAEvC,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,MAAM,UAAU,GAAG,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC;AACtD,YAAA,YAAY,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;QAClC;AAEA,QAAA,OAAO,YAAY;IACrB;AAEA;;AAEG;AACH,IAAA,kBAAkB,CAAC,OAAoB,EAAA;AACrC,QAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,CAAC;;IAE1C;AAEA;;AAEG;AACH,IAAA,qBAAqB,CAAC,UAA0B,EAAA;AAC9C,QAAA,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,UAAU,CAAC;;IAEhD;wGArHW,oCAAoC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oCAAoC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iCAAA,EAAA,MAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAzFrC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,s6CAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAhGC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,mCAAmC,EAAA,QAAA,EAAA,gCAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnC,+BAA+B,sJAC/B,kCAAkC,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,eAAA,EAAA,aAAA,EAAA,QAAA,EAAA,WAAA,EAAA,aAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClC,uBAAuB,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,KAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACvB,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA6FjB,oCAAoC,EAAA,UAAA,EAAA,CAAA;kBAtGhD,SAAS;+BACE,iCAAiC,EAAA,UAAA,EAC/B,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,mCAAmC;wBACnC,+BAA+B;wBAC/B,kCAAkC;wBAClC,uBAAuB;wBACvB;qBACD,EAAA,OAAA,EAEQ,CAAC,sBAAsB,CAAC,EAAA,QAAA,EACvB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,s6CAAA,CAAA,EAAA;;sBAIA;;sBAKA;;sBAKA;;;AC1PH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCG;AAIG,MAAO,kCAAmC,SAAQ,gBAAgB,CAAA;AACtE,IAAA,WAAA,CAAY,eAAgC,EAAA;QAC1C,KAAK,CAAC,eAAe,CAAC;IACxB;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,IAAI,CACR,YAAgC,EAChC,OAA+C,EAAA;AAE/C,QAAA,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,YAAY,CAAC;QAErE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAClC,oCAAoC,EACpC;AACE,YAAA,YAAY,EAAE,YAAY;AAC1B,YAAA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK;YAClC,KAAK,EAAE,OAAO,EAAE;SACjB,EACD;YACE,aAAa,EAAE,IAAI;AACpB,SAAA,CACF;AAED,QAAA,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC;AACjE,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC;IACtD;wGAjCW,kCAAkC,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAlC,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,kCAAkC,cAFjC,MAAM,EAAA,CAAA;;4FAEP,kCAAkC,EAAA,UAAA,EAAA,CAAA;kBAH9C,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACxCD;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MA8SU,+BAA+B,CAAA;AAgJhC,IAAA,aAAA;AA/IV;;;;AAIG;IACM,OAAO,GAAW,cAAc;AAEzC;;;AAGG;IACM,QAAQ,GAAW,kBAAkB;AAE9C;;;AAGG;IACM,SAAS,GAAW,CAAC;AAE9B;;AAEG;IACM,KAAK,GAAW,QAAQ;AAEjC;;;AAGG;AACM,IAAA,KAAK;AAEd;;;AAGG;IACM,OAAO,GAAY,KAAK;AAEjC;;;AAGG;AACM,IAAA,KAAK;AAEd;;AAEG;AACH,IAAA,MAAM,GAAG,MAAM,CAAC,KAAK,kDAAC;AAEtB;;AAEG;AACH,IAAA,WAAW,CAAC,MAAyB,EAAA;AACnC,QAAA,MAAM,UAAU,GAA2B;AACzC,YAAA,SAAS,EAAE,SAAS;AACpB,YAAA,SAAS,EAAE,SAAS;AACpB,YAAA,aAAa,EAAE,aAAa;AAC5B,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,cAAc,EAAE,cAAc;AAC9B,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,eAAe,EAAE,eAAe;AAChC,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,YAAY,EAAE,YAAY;AAC1B,YAAA,MAAM,EAAE;SACT;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc;AAC5D,QAAA,OAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,EAAI,MAAM,GAAG;IAC9C;AAEA;;AAEG;IAEH,IAAI,GAAA;AACF,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB;AAEA;;AAEG;IAEH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;IACxB;AAEA;;AAEG;AAEH,IAAA,YAAY,CAAC,KAAiB,EAAA;AAC5B,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB;AAEA;;AAEG;IAEH,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;IACxB;AAEA;;AAEG;IAEH,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;IACxB;AAEA;;;AAGG;AAEH,IAAA,MAAM,OAAO,GAAA;;QAEX,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,EAAE;YAC9B;QACF;AAEA,QAAA,MAAM,YAAY,GAAuB;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC;SACb;AAED,QAAA,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE;YAC1C,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC;AACb,SAAA,CAAC;IACJ;AAEA;;;AAGG;IACH,aAAa,GAAA;AACX,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7B;AAEA,IAAA,WAAA,CACU,aAAiD,EAAA;QAAjD,IAAA,CAAA,aAAa,GAAb,aAAa;IACpB;wGAjJQ,+BAA+B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAK,kCAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA/B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,KAAA,EAAA,OAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,YAAA,EAAA,QAAA,EAAA,YAAA,EAAA,SAAA,EAAA,YAAA,EAAA,sBAAA,EAAA,UAAA,EAAA,cAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,WAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAvDhC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6pKAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAxSS,YAAY,+BAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA0S5B,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBA7S3C,SAAS;+BACE,2BAA2B,EAAA,UAAA,EACzB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,CAAC,EAAA,QAAA,EAmP9B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,6pKAAA,CAAA,EAAA;;sBAQA;;sBAMA;;sBAMA;;sBAKA;;sBAMA;;sBAMA;;sBAMA;;sBA+BA,YAAY;uBAAC,YAAY;;sBAQzB,YAAY;uBAAC,YAAY;;sBAQzB,YAAY;uBAAC,YAAY,EAAE,CAAC,QAAQ,CAAC;;sBAQrC,YAAY;uBAAC,UAAU;;sBAQvB,YAAY;uBAAC,aAAa;;sBAS1B,YAAY;uBAAC,OAAO;;;ACvbvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CG;MAwIU,oBAAoB,CAAA;;AAE/B,IAAA,IAAI,GAAG,KAAK,CAA2D,MAAM,gDAAC;AAC9E,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,uDAAC;AAC/B,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAChC,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAChC,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAChC,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAChC,IAAA,YAAY,GAAG,KAAK,CAAS,EAAE,wDAAC;AAChC,IAAA,YAAY,GAAG,KAAK,CAAS,EAAE,wDAAC;AAChC,IAAA,SAAS,GAAG,KAAK,CAAsE,SAAS,qDAAC;AACjG,IAAA,cAAc,GAAG,KAAK,CAAU,IAAI,0DAAC;AACrC,IAAA,SAAS,GAAG,KAAK,CAAsC,IAAI,qDAAC;;IAG5D,WAAW,GAAG,MAAM,EAAU;IAC9B,IAAI,GAAG,MAAM,EAAc;IAC3B,KAAK,GAAG,MAAM,EAAc;IAC5B,YAAY,GAAG,MAAM,EAAQ;;AAGrB,IAAA,MAAM,GAAG,MAAM,CAAS,EAAE,kDAAC;IACnC,KAAK,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGrC,IAAA,OAAO,GAAG,CAAA,cAAA,EAAiB,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;;AAG/D,IAAA,QAAQ,GAAG,CAAC,KAAa,KAAI,EAAE,CAAC;AAChC,IAAA,SAAS,GAAG,MAAK,EAAE,CAAC;AAE5B,IAAA,OAAO,CAAC,KAAY,EAAA;AAClB,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAA0B;AAC/C,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK;AAC7B,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;AACzB,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;;QAG/B,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;YAC5C,IAAI,OAAO,EAAE;AACX,gBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;YAC1B;QACF;IACF;AAEA;;AAEG;AACK,IAAA,aAAa,CAAC,KAAa,EAAA;;AAEjC,QAAA,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE;QACxC,IAAI,eAAe,EAAE;AACnB,YAAA,OAAO,eAAe,CAAC,KAAK,CAAC;QAC/B;;AAGA,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE;QAC7B,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AACpD,QAAA,YAAY,CAAC,IAAI,GAAG,SAAS;AAC7B,QAAA,YAAY,CAAC,KAAK,GAAG,KAAK;;AAG1B,QAAA,IAAI,SAAS,KAAK,OAAO,EAAE;AACzB,YAAA,OAAO,YAAY,CAAC,QAAQ,CAAC,KAAK;QACpC;;QAGA,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;;AAGA,QAAA,OAAO,YAAY,CAAC,QAAQ,CAAC,KAAK;IACpC;IAEA,MAAM,GAAA;QACJ,IAAI,CAAC,SAAS,EAAE;IAClB;IAEA,OAAO,GAAA;;IAEP;;AAGA,IAAA,UAAU,CAAC,KAAa,EAAA;QACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;IAC9B;AAEA,IAAA,gBAAgB,CAAC,EAA2B,EAAA;AAC1C,QAAA,IAAI,CAAC,QAAQ,GAAG,EAAE;IACpB;AAEA,IAAA,iBAAiB,CAAC,EAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACrB;AAEA,IAAA,gBAAgB,CAAC,UAAmB,EAAA;;IAEpC;wGApGW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,SAAA,EAnIpB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,oBAAoB,CAAC;AACnD,gBAAA,KAAK,EAAE;AACR;SACF,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA8FS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,uoDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAlIS,YAAY,8BAAE,WAAW,EAAA,CAAA,EAAA,CAAA;;4FAoIxB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAvIhC,SAAS;+BACE,eAAe,EAAA,UAAA,EACb,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,WAAW,CAAC,EAAA,SAAA,EACzB;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,CAAC,0BAA0B,CAAC;AACnD,4BAAA,KAAK,EAAE;AACR;qBACF,EAAA,QAAA,EA8FS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,uoDAAA,CAAA,EAAA;;;AClLH;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAgNU,oBAAoB,CAAA;AAC/B;;;AAGG;AACH,IAAA,IAAI,GAAG,KAAK,CAAS,cAAc,gDAAC;AAEpC;;;AAGG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAmD,cAAc,oDAAC;AAElF;;;;AAIG;AACH,IAAA,IAAI,GAAG,KAAK,CAAqB,IAAI,gDAAC;AAEtC;;;AAGG;AACH,IAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,oDAAU;AAEpC;;;AAGG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;AAEhC;;AAEG;IACH,QAAQ,GAAG,MAAM,EAAQ;AAEzB;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;QACtB;IACF;wGA5CW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,wBAAA,EAAA,iCAAA,EAAA,uBAAA,EAAA,gCAAA,EAAA,yBAAA,EAAA,kCAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtMrB,CAAA;;;;;;;;;;;;GAYT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ypGAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAlBS,YAAY,+BAAE,qBAAqB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA4MlC,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBA/MhC,SAAS;+BACE,eAAe,EAAA,UAAA,EACb,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,qBAAqB,CAAC,EAAA,IAAA,EACxC;AACJ,wBAAA,0BAA0B,EAAE,+BAA+B;AAC3D,wBAAA,yBAAyB,EAAE,8BAA8B;AACzD,wBAAA,2BAA2B,EAAE;qBAC9B,EAAA,QAAA,EACS,CAAA;;;;;;;;;;;;AAYT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ypGAAA,CAAA,EAAA;;;AChDH;;ACGA;;;;;;;;;;;AAWG;MAIU,YAAY,CAAA;;IAEf,UAAU,GAAG,MAAM,CAAS,IAAI,CAAC,eAAe,EAAE,sDAAC;;IAG3D,KAAK,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGjC,IAAA,WAAW,GAAG,MAAM,CAAC,CAAC,uDAAC;AACvB,IAAA,OAAO,GAAG,MAAM,CAAC,IAAI,mDAAC;AAE9B,IAAA,WAAA,GAAA,EAAe;AAEf;;AAEG;AACH,IAAA,WAAW,CAAC,EAAU,EAAA;AACpB,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACvD;AAEA;;;AAGG;AACH,IAAA,OAAO,CAAC,IAAU,EAAA;AAChB,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC;IACnD;AAEA;;AAEG;IACH,UAAU,CAAC,EAAU,EAAE,OAAsB,EAAA;AAC3C,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,IAC1B,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,CACnE;IACH;AAEA;;AAEG;AACH,IAAA,UAAU,CAAC,EAAU,EAAA;QACnB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE;AAEA;;;AAGG;AACH,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE;QAC/B,MAAM,YAAY,GAAG,CAAC;AACtB,QAAA,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE;AACjD,QAAA,MAAM,UAAU,GAAG,IAAI,GAAG,YAAY;AACtC,QAAA,MAAM,QAAQ,GAAG,UAAU,GAAG,YAAY;;AAG1C,QAAA,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;;QAGvD,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC;AAE5D,QAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;;AAEvB,YAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC;AACxD,YAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;AAGnC,YAAA,IAAI,QAAQ,IAAI,eAAe,CAAC,MAAM,EAAE;AACtC,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YACzB;AAEA,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,QAAA,OAAO,KAAK;IACd;AAEA;;AAEG;IACH,YAAY,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;AAEA;;AAEG;IACH,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACvB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IACxB;AAEA;;AAEG;IACK,eAAe,GAAA;QACrB,OAAO;AACL,YAAA;AACE,gBAAA,EAAE,EAAE,aAAa;AACjB,gBAAA,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,OAAO,EAAE,+EAA+E;AACxF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,CAAC;AACZ,gBAAA,YAAY,EAAE,CAAC;AACf,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,0JAA0J;AACnK,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACR,oBAAA;AACE,wBAAA,UAAU,EAAE,cAAc;AAC1B,wBAAA,UAAU,EAAE,OAAO;AACnB,wBAAA,SAAS,EAAE,UAAU;AACrB,wBAAA,cAAc,EAAE,IAAI;AACpB,wBAAA,OAAO,EAAE,6BAA6B;AACtC,wBAAA,SAAS,EAAE,CAAC;AACZ,wBAAA,YAAY,EAAE;AACf,qBAAA;AACD,oBAAA;AACE,wBAAA,UAAU,EAAE,gBAAgB;AAC5B,wBAAA,UAAU,EAAE,KAAK;AACjB,wBAAA,SAAS,EAAE,SAAS;AACpB,wBAAA,cAAc,EAAE,IAAI;AACpB,wBAAA,OAAO,EAAE,SAAS;AAClB,wBAAA,SAAS,EAAE,CAAC;AACZ,wBAAA,YAAY,EAAE;AACf;AACF;AACF,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,iBAAiB;AAC7B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,6LAA6L;AACtM,gBAAA,eAAe,EAAE,IAAI;AACrB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACR,oBAAA;AACE,wBAAA,UAAU,EAAE,eAAe;AAC3B,wBAAA,UAAU,EAAE,OAAO;AACnB,wBAAA,SAAS,EAAE,UAAU;AACrB,wBAAA,cAAc,EAAE,IAAI;AACpB,wBAAA,OAAO,EAAE,wDAAwD;AACjE,wBAAA,SAAS,EAAE,EAAE;AACb,wBAAA,YAAY,EAAE;AACf,qBAAA;AACD,oBAAA;AACE,wBAAA,UAAU,EAAE,eAAe;AAC3B,wBAAA,UAAU,EAAE,OAAO;AACnB,wBAAA,SAAS,EAAE,UAAU;AACrB,wBAAA,cAAc,EAAE,IAAI;AACpB,wBAAA,OAAO,EAAE,0DAA0D;AACnE,wBAAA,OAAO,EAAE,IAAI;AACb,wBAAA,SAAS,EAAE,CAAC;AACZ,wBAAA,YAAY,EAAE;AACf,qBAAA;AACD,oBAAA;AACE,wBAAA,UAAU,EAAE,gBAAgB;AAC5B,wBAAA,UAAU,EAAE,KAAK;AACjB,wBAAA,SAAS,EAAE,SAAS;AACpB,wBAAA,cAAc,EAAE,IAAI;AACpB,wBAAA,OAAO,EAAE,SAAS;AAClB,wBAAA,SAAS,EAAE,CAAC;AACZ,wBAAA,YAAY,EAAE;AACf;AACF;AACF,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,kHAAkH;AAC3H,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,UAAU;AACd,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,uBAAuB;AACnC,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,SAAS,EAAE,IAAI;AACf,gBAAA,OAAO,EAAE,mMAAmM;AAC5M,gBAAA,eAAe,EAAE,IAAI;AACrB,gBAAA,gBAAgB,EAAE,CAAC;AACnB,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,uBAAuB;AACnC,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,SAAS,EAAE,IAAI;AACf,gBAAA,OAAO,EAAE,2JAA2J;AACpK,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,2IAA2I;AACpJ,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX;SACF;IACH;AAEA;;AAEG;IACK,kBAAkB,GAAA;QACxB,OAAO;AACL,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,mBAAmB;AAC/B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,oEAAoE;AAC7E,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,6EAA6E;AACtF,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,cAAc;AAC1B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,uEAAuE;AAChF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,CAAC;AACZ,gBAAA,YAAY,EAAE,CAAC;AACf,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE,aAAa;AACzB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,qEAAqE;AAC9E,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,kBAAkB;AAC9B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,oEAAoE;AAC7E,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,8EAA8E;AACvF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,2EAA2E;AACpF,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,aAAa;AACzB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,6EAA6E;AACtF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,cAAc;AAC1B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,2FAA2F;AACpG,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,eAAe;AAC3B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,iGAAiG;AAC1G,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,0EAA0E;AACnF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,CAAC;AACf,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,iBAAiB;AAC7B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,qGAAqG;AAC9G,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,kBAAkB;AAC9B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,0FAA0F;AACnG,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,kGAAkG;AAC3G,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,kBAAkB;AAC9B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,0FAA0F;AACrG,gBAAA,OAAO,EAAE,sGAAsG;AAC/G,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,gFAAgF;AACzF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,6EAA6E;AACtF,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,cAAc;AAC1B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,2EAA2E;AACpF,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,YAAY;AACxB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,6FAA6F;AACxG,gBAAA,OAAO,EAAE,oEAAoE;AAC7E,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,GAAG;AACd,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX,aAAA;AACD,YAAA;AACE,gBAAA,EAAE,EAAE,SAAS;AACb,gBAAA,UAAU,EAAE,iBAAiB;AAC7B,gBAAA,UAAU,EAAE,OAAO;AACnB,gBAAA,SAAS,EAAE,UAAU;AACrB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,UAAU,EAAE,UAAU;AACtB,gBAAA,OAAO,EAAE,2DAA2D;AACpE,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,EAAE;AACb,gBAAA,YAAY,EAAE,EAAE;AAChB,gBAAA,QAAQ,EAAE;AACX;SACF;IACH;wGA/fW,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,YAAY,cAFX,MAAM,EAAA,CAAA;;4FAEP,YAAY,EAAA,UAAA,EAAA,CAAA;kBAHxB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;MCoTY,4BAA4B,CAAA;AAe7B,IAAA,MAAA;AACA,IAAA,KAAA;AACA,IAAA,WAAA;AACA,IAAA,QAAA;AACA,IAAA,SAAA;AACD,IAAA,WAAA;AACC,IAAA,YAAA;;AAnBV,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,oDAAC;;AAGpD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;QAC1B,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,GAAG,CAAC;AACnC,IAAA,CAAC,uDAAC;;AAGF,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAK;AAC3B,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE;AACzC,IAAA,CAAC,wDAAC;AAEF,IAAA,WAAA,CACU,MAAc,EACd,KAAqB,EACrB,WAAuC,EACvC,QAAiC,EACjC,SAAyC,EAC1C,WAAwB,EACvB,YAA0B,EAAA;QAN1B,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,KAAK,GAAL,KAAK;QACL,IAAA,CAAA,WAAW,GAAX,WAAW;QACX,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,SAAS,GAAT,SAAS;QACV,IAAA,CAAA,WAAW,GAAX,WAAW;QACV,IAAA,CAAA,YAAY,GAAZ,YAAY;IACnB;AAEH;;;AAGG;IACH,MAAM,gBAAgB,CAAC,KAAU,EAAA;AAC/B,QAAA,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC;QAEpD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE;QAEvD,IAAI,OAAO,EAAE;AACX,YAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;QAC9C;aAAO;AACL,YAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;QAClD;;AAGA,QAAA,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;IACzB;AAEA,IAAA,aAAa,CAAC,KAAU,EAAA;AACtB,QAAA,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;;AAGxC,QAAA,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE;QAEnC,UAAU,CAAC,MAAK;AACd,YAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC/B,YAAA,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QACzB,CAAC,EAAE,IAAI,CAAC;IACV;AAEA;;;AAGG;AACH,IAAA,MAAM,QAAQ,CAAC,MAAc,EAAE,eAAwB,KAAK,EAAA;QAC1D,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,MAAM,EAAE,gBAAgB,EAAE,YAAY,CAAC;QAE9F,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC;QAElD,IAAI,IAAI,EAAE;;;AAGR,YAAA,MAAM,QAAQ,GAAG;AACf,gBAAA,GAAG,IAAI;gBACP,MAAM,EAAE,IAAI,CAAC,EAAE;AACf,gBAAA,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,UAAU;gBACpE;aACD;AAED,YAAA,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAClC,eAAe,EAAE,gBAAgB;AACjC,gBAAA,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc;AACrD,aAAA,CAAC;QACJ;IACF;AAEA,IAAA,MAAM,eAAe,GAAA;;;QAGnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AAC1C,YAAA,SAAS,EAAE,sCAAsC;AACjD,YAAA,cAAc,EAAE;;AAEd,gBAAA,SAAS,EAAE;AACZ,aAAA;AACD,YAAA,WAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACzB,YAAA,iBAAiB,EAAE,IAAI;AACvB,YAAA,MAAM,EAAE;AACT,SAAA,CAAC;;AAGF,QAAA,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;QAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE;YACzC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC;;AAG7C,YAAA,MAAM,OAAO,GAAS;gBACpB,EAAE,EAAE,aAAa,IAAI,CAAC,GAAG,EAAE,CAAA,CAAE;gBAC7B,UAAU,EAAE,gBAAgB;AAC5B,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,SAAS,EAAE,SAAS;AACpB,gBAAA,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,UAAU,EAAmC;AAC1E,gBAAA,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE;AACvC,gBAAA,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;AACjD,gBAAA,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;AAC5B,gBAAA,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS;gBACjG,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,kBAAkB,GAAG,SAAS;AAC9F,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,SAAS,EAAE,CAAC;AACZ,gBAAA,YAAY,EAAE,CAAC;AACf,gBAAA,QAAQ,EAAE;aACX;;AAGD,YAAA,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;QACpC;IACF;AAEA;;;AAGG;IACH,MAAM,iBAAiB,CAAC,QAAgB,EAAE,KAAa,EAAE,WAAmB,EAAE,KAAY,EAAA;AACxF,QAAA,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,QAAQ,CAAC;;QAGhE,KAAK,CAAC,eAAe,EAAE;AAEvB,QAAA,MAAM,UAAU,GAAmB;AACjC,YAAA,IAAI,EAAE,iBAAiB;AACvB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,SAAS,EAAE;SACZ;;AAGD,QAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACvB,YAAA,MAAM,EAAE;AACN,gBAAA;AACE,oBAAA,IAAI,EAAE,OAAO;AACb,oBAAA,GAAG,EAAE,QAAQ;AACb,oBAAA,GAAG,EAAE,KAAK;AACV,oBAAA,KAAK,EAAE,KAAK;AACZ,oBAAA,WAAW,EAAE,WAAW;AACxB,oBAAA,OAAO,EAAE,IAAI;AACb,oBAAA,SAAS,EAAE,GAAG;AACd,oBAAA,YAAY,EAAE;AACf;AACF,aAAA;AACD,YAAA,MAAM,EAAE,UAAU;AAClB,YAAA,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,IAAI;AACjB,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;IACJ;AAEA,IAAA,MAAM,iBAAiB,GAAA;AACrB,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;;AAGlD,QAAA,MAAM,UAAU,GAAmB;AACjC,YAAA,IAAI,EAAE,eAAe;AACrB,YAAA,IAAI,EAAE,uBAAuB;AAC7B,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,SAAS,EAAE;SACZ;;;AAID,QAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;AAC1B,YAAA,GAAG,EAAE;AACH,gBAAA,IAAI,EAAE,KAAK;gBACX,GAAG,EAAE,yBAAyB;AAC9B,gBAAA,KAAK,EAAE,aAAa;AACpB,gBAAA,WAAW,EAAE,+CAA+C;gBAC5D,QAAQ,EAAE,MAAM;AAChB,gBAAA,SAAS,EAAE;AACZ,aAAA;AACD,YAAA,MAAM,EAAE;AACT,SAAA,CAAC;IACJ;AAEA;;AAEG;AACH,IAAA,MAAM,mBAAmB,CAAC,MAAc,EAAE,SAAkB,EAAA;QAC1D,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC;QAE1E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AAC1C,YAAA,SAAS,EAAEC,mCAAuC;AAClD,YAAA,cAAc,EAAE;AACd,gBAAA,YAAY,EAAE;AACf,aAAA;AACD,YAAA,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACnB,YAAA,iBAAiB,EAAE,CAAC;AACpB,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;AAEF,QAAA,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;QAE1C,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE;AAC3C,YAAA,MAAM,MAAM,GAAI,MAAM,CAAC,IAAyB,CAAC,MAAM;YAEvD,QAAQ,MAAM;AACZ,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC;;oBAGjC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC;oBAClD,IAAI,CAAC,IAAI,EAAE;AACT,wBAAA,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,MAAM,CAAC;wBACxC;oBACF;;oBAGA,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AAC9C,wBAAA,SAAS,EAAE,sCAAsC;AACjD,wBAAA,cAAc,EAAE;AACd,4BAAA,SAAS,EAAE,IAAI;AACf,4BAAA,UAAU,EAAE,IAAI;AAChB,4BAAA,MAAM,EAAE,MAAM;4BACd,cAAc,EAAE,IAAI,CAAC;AACtB,yBAAA;AACD,wBAAA,WAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACzB,wBAAA,iBAAiB,EAAE,IAAI;AACvB,wBAAA,MAAM,EAAE,IAAI;AACZ,wBAAA,YAAY,EAAE,IAAI;AAClB,wBAAA,eAAe,EAAE;AAClB,qBAAA,CAAC;;AAGF,oBAAA,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,aAAa,EAAE;oBAClD,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,IAAI,UAAU,CAAC,IAAI,EAAE;wBACjD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,IAAI,CAAC;;AAG7C,wBAAA,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,EAAE;AACnC,4BAAA,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO;AAChC,4BAAA,SAAS,EAAE;AACZ,yBAAA,CAAC;oBACJ;oBACA;AAEF,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC;AACnC,oBAAA,IAAI,OAAO,CAAC,iDAAiD,CAAC,EAAE;AAC9D,wBAAA,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC;oBACtC;oBACA;AAEF,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC;;oBAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC;oBACtD,IAAI,QAAQ,EAAE;AACZ,wBAAA,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,EAAE;AACnC,4BAAA,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO;AAC1B,4BAAA,SAAS,EAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,SAAS,GAAG;AAC7E,yBAAA,CAAC;oBACJ;oBACA;AAEF,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC;;oBAErC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;oBACjC;;QAEN;IACF;wGArRW,4BAA4B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAN,IAAA,CAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAAAA,IAAA,CAAA,cAAA,EAAA,EAAA,EAAA,KAAA,EAAAG,0BAAA,EAAA,EAAA,EAAA,KAAA,EAAAI,uBAAA,EAAA,EAAA,EAAA,KAAA,EAAAC,8BAAA,EAAA,EAAA,EAAA,KAAA,EAAAC,WAAA,EAAA,EAAA,EAAA,KAAA,EAAAC,YAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA5B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlN7B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgNT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,20BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAnSC,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,aAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,uBAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACzB,wBAAwB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACxB,wCAAwC,EAAA,QAAA,EAAA,sCAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,YAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,SAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,cAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACxC,6BAA6B,EAAA,QAAA,EAAA,yBAAA,EAAA,MAAA,EAAA,CAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC7B,oBAAoB,EAAA,QAAA,EAAA,cAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACpB,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,kBAAkB,EAAA,QAAA,EAAA,YAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClB,wBAAwB,EAAA,QAAA,EAAA,kBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACxB,oBAAoB,EAAA,QAAA,EAAA,cAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACpB,mBAAmB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,EAAA,aAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,sBAAsB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACtB,+BAA+B,EAAA,QAAA,EAAA,4BAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC/B,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,4BAA4B,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,QAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC5B,iBAAiB,+GACjB,wBAAwB,EAAA,QAAA,EAAA,6BAAA,EAAA,MAAA,EAAA,CAAA,gBAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAsRf,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBAzSxC,SAAS;+BACE,2BAA2B,EAAA,UAAA,EACzB,IAAI,EAAA,OAAA,EACP;wBACP,yBAAyB;wBACzB,wBAAwB;wBACxB,wCAAwC;wBACxC,6BAA6B;wBAC7B,oBAAoB;wBACpB,iBAAiB;wBACjB,kBAAkB;wBAClB,wBAAwB;wBACxB,oBAAoB;wBACpB,mBAAmB;wBACnB,sBAAsB;wBACtB,+BAA+B;wBAC/B,eAAe;wBACf,4BAA4B;wBAC5B,iBAAiB;wBACjB;qBACD,EAAA,QAAA,EAmES,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgNT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,20BAAA,CAAA,EAAA;;;MC7OU,2BAA2B,CAAA;AAqMnB,IAAA,WAAA;;AAnMnB,IAAA,cAAc,GAAmB;AAC/B,QAAA;AACE,YAAA,KAAK,EAAE,IAAI;AACX,YAAA,WAAW,EAAE,yGAAyG;AACtH,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB;AACvG;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,WAAW,EAAE,yFAAyF;AACtG,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,KAAK;AAC7C;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,eAAe;AACtB,YAAA,WAAW,EAAE,4IAA4I;AACzJ,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB;AACnG;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,aAAa;AACpB,YAAA,WAAW,EAAE,mJAAmJ;AAChK,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB;AAC1G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,0BAA0B;AACjC,YAAA,WAAW,EAAE,+EAA+E;AAC5F,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE;AACtC,gBAAA,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,KAAK;AAC/C;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,eAAe;AACtB,YAAA,WAAW,EAAE,sIAAsI;AACnJ,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB;AAC7G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,yBAAyB;AAChC,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,KAAK;AAC7C;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,WAAW,EAAE,kJAAkJ;AAC/J,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,KAAK;AACjD;AACF;KACF;;AAGD,IAAA,qBAAqB,GAAmB;AACtC,QAAA;AACE,YAAA,KAAK,EAAE,6BAA6B;AACpC,YAAA,WAAW,EAAE,qHAAqH;AAClI,YAAA,MAAM,EAAE;gBACN,oCAAoC;gBACpC;AACD;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,qBAAqB;AAC5B,YAAA,WAAW,EAAE,4JAA4J;AACzK,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,iBAAiB;AAC3G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,sBAAsB;AAC7B,YAAA,WAAW,EAAE,yGAAyG;AACtH,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK;AACrC;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,aAAa;AACpB,YAAA,WAAW,EAAE,4IAA4I;AACzJ,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB;AAC1G;AACF;KACF;;AAGD,IAAA,qBAAqB,GAAmB;AACtC,QAAA;AACE,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,WAAW,EAAE,wJAAwJ;AACrK,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB;AAC3G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,oBAAoB;AAC3B,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,6BAA6B,EAAE,IAAI,EAAE,KAAK,EAAE;AACpD,gBAAA,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,KAAK;AAC1C;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,kBAAkB;AACzB,YAAA,WAAW,EAAE,sIAAsI;AACnJ,YAAA,MAAM,EAAE;gBACN,+BAA+B;gBAC/B;AACD;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,qBAAqB;AAC5B,YAAA,WAAW,EAAE,yHAAyH;AACtI,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB;AAC3G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,KAAK;AAC7C;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,iBAAiB;AACxB,YAAA,WAAW,EAAE,qGAAqG;AAClH,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,uBAAuB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB;AAC9G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,mBAAmB;AAC1B,YAAA,WAAW,EAAE,0FAA0F;AACvG,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB;AAC1G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,kCAAkC;AACzC,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,KAAK,EAAE;AAC/C,gBAAA,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,KAAK;AACzC;AACF;KACF;;AAGD,IAAA,cAAc,GAAmB;AAC/B,QAAA;AACE,YAAA,KAAK,EAAE,eAAe;AACtB,YAAA,WAAW,EAAE,2GAA2G;AACxH,YAAA,MAAM,EAAE;gBACN;AACD;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,UAAU;AACjB,YAAA,WAAW,EAAE,mKAAmK;AAChL,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB;AACzG;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,uBAAuB;AAC9B,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,KAAK,EAAE;AAC/C,gBAAA,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,KAAK;AACxC;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,iCAAiC;AACxC,YAAA,WAAW,EAAE,oIAAoI;AACjJ,YAAA,MAAM,EAAE;gBACN;AACD,aAAA;AACD,YAAA,QAAQ,EAAE;AACR,gBAAA,EAAE,IAAI,EAAE,qBAAqB,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB;AAC7G;AACF,SAAA;AACD,QAAA;AACE,YAAA,KAAK,EAAE,eAAe;AACtB,YAAA,WAAW,EAAE,kHAAkH;AAC/H,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,KAAK,EAAE;AAC1C,gBAAA,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,KAAK;AACzC;AACF;KACF;AAED,IAAA,WAAA,CAAmB,WAAwB,EAAA;QAAxB,IAAA,CAAA,WAAW,GAAX,WAAW;IAAgB;AAE9C,IAAA,aAAa,CAAC,KAAU,EAAA;AACtB,QAAA,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;QACxC,UAAU,CAAC,MAAK;AACd,YAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC/B,YAAA,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QACzB,CAAC,EAAE,IAAI,CAAC;IACV;wGA7MW,2BAA2B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAC,WAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA3B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/C5B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mNAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAtEC,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,aAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,uBAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACzB,wBAAwB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACxB,+BAA+B,sEAC/B,+BAA+B,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,EAAA,WAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAqEtB,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBA5EvC,SAAS;+BACE,0BAA0B,EAAA,UAAA,EACxB,IAAI,EAAA,OAAA,EACP;wBACP,yBAAyB;wBACzB,wBAAwB;wBACxB,+BAA+B;wBAC/B;qBACD,EAAA,QAAA,EAqBS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,mNAAA,CAAA,EAAA;;;MCsFU,uBAAuB,CAAA;AAExB,IAAA,OAAA;AACD,IAAA,WAAA;IAFT,WAAA,CACU,OAAsB,EACvB,WAAwB,EAAA;QADvB,IAAA,CAAA,OAAO,GAAP,OAAO;QACR,IAAA,CAAA,WAAW,GAAX,WAAW;AAElB,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;IACpD;AAEA,IAAA,aAAa,CAAC,KAAU,EAAA;AACtB,QAAA,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;QACxC,UAAU,CAAC,MAAK;AACd,YAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC/B,YAAA,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QACzB,CAAC,EAAE,IAAI,CAAC;IACV;IAEA,gBAAgB,GAAA;;AAEd,QAAA,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAClD;wGAnBW,uBAAuB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,aAAA,EAAA,EAAA,EAAA,KAAA,EAAAC,WAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlHxB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgHT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6SAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAhJC,eAAe,sGACf,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,aAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,uBAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACzB,8BAA8B,EAAA,QAAA,EAAA,0BAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC9B,kCAAkC,EAAA,QAAA,EAAA,+BAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClC,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,oBAAoB,yDACpB,kBAAkB,EAAA,QAAA,EAAA,YAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClB,kBAAkB,EAAA,QAAA,EAAA,YAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClB,wBAAwB,kFACxB,+BAA+B,EAAA,QAAA,EAAA,2BAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC/B,sBAAsB,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACtB,mBAAmB,EAAA,QAAA,EAAA,aAAA,EAAA,CAAA,EAAA,CAAA;;4FAuIV,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAtJnC,SAAS;+BACE,eAAe,EAAA,UAAA,EACb,IAAI,EAAA,OAAA,EACP;wBACP,eAAe;wBACf,yBAAyB;wBACzB,8BAA8B;wBAC9B,kCAAkC;wBAClC,iBAAiB;wBACjB,oBAAoB;wBACpB,kBAAkB;wBAClB,kBAAkB;wBAClB,wBAAwB;wBACxB,+BAA+B;wBAC/B,sBAAsB;wBACtB;qBACD,EAAA,QAAA,EAoBS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,6SAAA,CAAA,EAAA;;;MC9BU,4BAA4B,CAAA;AAE9B,IAAA,WAAA;AACC,IAAA,OAAA;AACA,IAAA,eAAA;AAHV,IAAA,WAAA,CACS,WAAwB,EACvB,OAAsB,EACtB,eAA+C,EAAA;QAFhD,IAAA,CAAA,WAAW,GAAX,WAAW;QACV,IAAA,CAAA,OAAO,GAAP,OAAO;QACP,IAAA,CAAA,eAAe,GAAf,eAAe;IACtB;AAEH,IAAA,YAAY,GAAG,MAAM,CAA4B,KAAK,wDAAC;AAEvD,IAAA,QAAQ,GAAoB;AAC1B,QAAA,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE;AAC5B,QAAA,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;AAC7B,QAAA,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;KAChC;IAED,SAAS,GAAG,MAAM,CAAY;AAC5B,QAAA;AACE,YAAA,EAAE,EAAE,GAAG;AACP,YAAA,KAAK,EAAE,0BAA0B;AACjC,YAAA,WAAW,EAAE,2HAA2H;AACxI,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,SAAS,EAAE,eAAe;AAC1B,YAAA,QAAQ,EAAE;AACX,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,GAAG;AACP,YAAA,KAAK,EAAE,sBAAsB;AAC7B,YAAA,WAAW,EAAE,iGAAiG;AAC9G,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,SAAS,EAAE,cAAc;AACzB,YAAA,QAAQ,EAAE;AACX,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,GAAG;AACP,YAAA,KAAK,EAAE,8BAA8B;AACrC,YAAA,WAAW,EAAE,yGAAyG;AACtH,YAAA,MAAM,EAAE,QAAQ;AAChB,YAAA,SAAS,EAAE,iBAAiB;AAC5B,YAAA,QAAQ,EAAE;AACX;AACF,KAAA,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGF,IAAA,iBAAiB,GAAG,QAAQ,CAAC,MAAK;AAChC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE;AAC5B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE;AAElC,QAAA,IAAI,MAAM,KAAK,KAAK,EAAE;AACpB,YAAA,OAAO,GAAG;QACZ;AAAO,aAAA,IAAI,MAAM,KAAK,MAAM,EAAE;AAC5B,YAAA,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAC7C;aAAO;AACL,YAAA,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC;QAC/C;AACF,IAAA,CAAC,6DAAC;AAEF,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;AAC5B,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;AAC1D,IAAA,CAAC,yDAAC;AAEF,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAK;AAC9B,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC;AAC5D,IAAA,CAAC,2DAAC;AAEF,IAAA,SAAS,CAAC,MAAiC,EAAA;AACzC,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;IAC/B;AAEA,IAAA,cAAc,CAAC,QAAgB,EAAA;AAC7B,QAAA,OAAO,eAAe;IACxB;AAEA,IAAA,iBAAiB,CAAC,SAAiB,EAAA;AACjC,QAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC;;QAE1C,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAE,CAAC,EAAE;AAC7D,YAAA,SAAS,EAAE;AACZ,SAAA,CAAC;IACJ;AAEA,IAAA,kBAAkB,CAAC,SAAiB,EAAA;AAClC,QAAA,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,SAAS,CAAC;;IAExD;AAEA,IAAA,MAAM,gBAAgB,GAAA;AACpB,QAAA,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC;AAE3C,QAAA,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;AAC9B,YAAA,QAAQ,EAAE,OAAO,IAAoB,KAAI;AACvC,gBAAA,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC;;;;AAM3C,gBAAA,MAAM,UAAU,GAAY;AAC1B,oBAAA,EAAE,EAAE,CAAA,QAAA,EAAW,IAAI,CAAC,GAAG,EAAE,CAAA,CAAE;oBAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;AAC7B,oBAAA,MAAM,EAAE,MAAM;AACd,oBAAA,SAAS,EAAE,UAAU;AACrB,oBAAA,QAAQ,EAAE;iBACX;AAED,gBAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,GAAG,SAAS,CAAC,CAAC;;AAG9D,gBAAA,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE;YACpC;AACD,SAAA,CAAC;IACJ;wGA/GW,4BAA4B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAD,WAAA,EAAA,EAAA,EAAA,KAAA,EAAAZ,EAAA,CAAA,aAAA,EAAA,EAAA,EAAA,KAAA,EAAAc,8BAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA5B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,UAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/D7B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,4hBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA/GC,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,aAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,uBAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACzB,wBAAwB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACxB,2CAA2C,oQAC3C,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,2BAA2B,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC3B,oBAAoB,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,WAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA4GX,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBArHxC,SAAS;+BACE,2BAA2B,EAAA,UAAA,EACzB,IAAI,EAAA,OAAA,EACP;wBACP,yBAAyB;wBACzB,wBAAwB;wBACxB,2CAA2C;wBAC3C,eAAe;wBACf,2BAA2B;wBAC3B;qBACD,EAAA,IAAA,EACK;AACJ,wBAAA,KAAK,EAAE;qBACR,EAAA,QAAA,EAyCS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,4hBAAA,CAAA,EAAA;;;AClIH;;;;;;;;;;;;;;;;;;;;;;AAsBG;MA0DU,iCAAiC,CAAA;AAC5C;;AAEG;AACH,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAU;AAEhC;;AAEG;AACH,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,qDAAC;AAE7B;;AAEG;AACH,IAAA,WAAW,GAAG,KAAK,CAAS,CAAC,uDAAC;AAE9B;;;;AAIG;AACH,IAAA,MAAM,GAAG,KAAK,CAAwB,SAAS,kDAAC;AAEhD;;AAEG;IACH,WAAW,GAAG,MAAM,EAAQ;IAE5B,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;IACzB;wGA9BW,iCAAiC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,iCAAiC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhClC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,yVAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EApDS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,mIAAE,2BAA2B,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAsD5E,iCAAiC,EAAA,UAAA,EAAA,CAAA;kBAzD7C,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,8BAA8B,EAAA,UAAA,EAC5B,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,2BAA2B,CAAC,EAAA,QAAA,EAsB9E,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,yVAAA,CAAA,EAAA;;;MC6EU,gCAAgC,CAAA;AAoDlC,IAAA,WAAA;AACC,IAAA,QAAA;AACA,IAAA,SAAA;IArDV,YAAY,GAAG,0BAA0B;AACzC,IAAA,SAAS,GAAG,MAAM,CAAS,SAAS,qDAAC;AAErC,IAAA,QAAQ,GAAoB;AAC1B,QAAA,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE;QACpC,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;KAC9C;AAED,IAAA,cAAc,GAAoB;AAChC,QAAA;AACE,YAAA,EAAE,EAAE,GAAG;AACP,YAAA,UAAU,EAAE,cAAc;AAC1B,YAAA,YAAY,EAAE,EAAE;AAChB,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,OAAO,EAAE,4DAA4D;AACrE,YAAA,IAAI,EAAE,eAAe;AACrB,YAAA,SAAS,EAAE,UAAU;AACrB,YAAA,MAAM,EAAE;AACT,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,GAAG;AACP,YAAA,UAAU,EAAE,cAAc;AAC1B,YAAA,YAAY,EAAE,EAAE;AAChB,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,OAAO,EAAE,4DAA4D;AACrE,YAAA,IAAI,EAAE,UAAU;AAChB,YAAA,SAAS,EAAE,UAAU;AACrB,YAAA,MAAM,EAAE;AACT;KACF;AAED,IAAA,mBAAmB,GAAG,QAAQ,CAAC,MAAK;AAClC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM;;AAExC,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC;QAChE,IAAI,WAAW,EAAE;AACf,YAAA,WAAW,CAAC,KAAK,GAAG,KAAK;QAC3B;AACA,QAAA,OAAO,KAAK;AACd,IAAA,CAAC,+DAAC;;AAGF,IAAA,MAAM,GAAoB;AACxB,QAAA,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,mCAAmC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;AAC/F,QAAA,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,uCAAuC,EAAE,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;AAC3G,QAAA,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,oCAAoC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;AAClG,QAAA,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,+BAA+B,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;AACnF,QAAA,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,oCAAoC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW;KACjG;AAED,IAAA,WAAA,CACS,WAAwB,EACvB,QAAiC,EACjC,SAAmC,EAAA;QAFpC,IAAA,CAAA,WAAW,GAAX,WAAW;QACV,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,SAAS,GAAT,SAAS;;QAGjB,IAAI,CAAC,mBAAmB,EAAE;IAC5B;AAEA,IAAA,YAAY,CAAC,KAAa,EAAA;AACxB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;IAC3B;IAEA,MAAM,GAAA;;;IAGN;AAEA,IAAA,aAAa,CAAC,KAAU,EAAA;AACtB,QAAA,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;QACxC,UAAU,CAAC,MAAK;AACd,YAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC/B,YAAA,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QACzB,CAAC,EAAE,IAAI,CAAC;IACV;AAEA;;AAEG;IACH,iBAAiB,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAChD;AAEA;;AAEG;IACH,qBAAqB,GAAA;AACnB,QAAA,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;IAC/B;IAEA,MAAM,WAAW,CAAC,SAAiB,EAAA;AACjC,QAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC;;AAG1C,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC;QACvE,IAAI,CAAC,aAAa,EAAE;AAClB,YAAA,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,SAAS,CAAC;YACrD;QACF;;;AAIA,QAAA,MAAM,QAAQ,GAAkB;AAC9B,YAAA,WAAW,EAAE;AACX,gBAAA,EAAE,EAAE,SAAS;gBACb,IAAI,EAAE,aAAa,CAAC,UAAU;gBAC9B,IAAI,EAAE,aAAa,CAAC,IAAI;gBACxB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,gBAAA,UAAU,EAAE;AACb,aAAA;AACD,YAAA,QAAQ,EAAE;;AAER,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,yFAAyF;AAClG,oBAAA,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,UAAU,EAAE,aAAa,CAAC,IAAI;AAC9B,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,oBAAA,YAAY,EAAE,KAAK;oBACnB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;AACD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,wEAAwE;AACjF,oBAAA,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,UAAU,EAAE,aAAa,CAAC,IAAI;AAC9B,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,oBAAA,YAAY,EAAE,KAAK;oBACnB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;AACD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,kDAAkD;AAC3D,oBAAA,QAAQ,EAAE,cAAc;AACxB,oBAAA,UAAU,EAAE,KAAK;AACjB,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,oBAAA,YAAY,EAAE,IAAI;AAClB,oBAAA,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;AACjD,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;AACD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,8CAA8C;AACvD,oBAAA,QAAQ,EAAE,cAAc;AACxB,oBAAA,UAAU,EAAE,KAAK;AACjB,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,oBAAA,YAAY,EAAE,IAAI;AAClB,oBAAA,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;AACjD,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;;AAGD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;oBACP,OAAO,EAAE,aAAa,CAAC,OAAO;AAC9B,oBAAA,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,UAAU,EAAE,aAAa,CAAC,IAAI;AAC9B,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,oBAAA,YAAY,EAAE,KAAK;oBACnB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;AACD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,wGAAwG;AACjH,oBAAA,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,UAAU,EAAE,aAAa,CAAC,IAAI;AAC9B,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,oBAAA,YAAY,EAAE,KAAK;oBACnB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;;AAGD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,+DAA+D;AACxE,oBAAA,QAAQ,EAAE,cAAc;AACxB,oBAAA,UAAU,EAAE,KAAK;AACjB,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;AACzC,oBAAA,YAAY,EAAE,IAAI;AAClB,oBAAA,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;AACjD,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;AACD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,4CAA4C;AACrD,oBAAA,QAAQ,EAAE,cAAc;AACxB,oBAAA,UAAU,EAAE,KAAK;AACjB,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;AACzC,oBAAA,YAAY,EAAE,IAAI;AAClB,oBAAA,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;AACjD,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;;AAGD,gBAAA;AACE,oBAAA,EAAE,EAAE,GAAG;AACP,oBAAA,OAAO,EAAE,uFAAuF;AAChG,oBAAA,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,UAAU,EAAE,aAAa,CAAC,IAAI;AAC9B,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;AACxC,oBAAA,YAAY,EAAE,KAAK;oBACnB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,oBAAA,UAAU,EAAE,UAAU;AACvB,iBAAA;AACD,gBAAA;AACE,oBAAA,EAAE,EAAE,IAAI;AACR,oBAAA,OAAO,EAAE,4DAA4D;AACrE,oBAAA,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,UAAU,EAAE,aAAa,CAAC,IAAI;AAC9B,oBAAA,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;AACvC,oBAAA,YAAY,EAAE,KAAK;oBACnB,cAAc,EAAE,aAAa,CAAC,cAAc;AAC5C,oBAAA,UAAU,EAAE,UAAU;AACvB;AACF,aAAA;AACD,YAAA,aAAa,EAAE,cAAc;AAC7B,YAAA,mBAAmB,EAAE,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;AACtD,YAAA,qBAAqB,EAAE,UAAU;AACjC,YAAA,SAAS,EAAE;SACZ;;QAGD,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;IACrC;IAEA,MAAM,iBAAiB,CAAC,KAAa,EAAA;AACnC,QAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;AACnB,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;IACJ;wGArPW,gCAAgC,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAF,WAAA,EAAA,EAAA,EAAA,KAAA,EAAAG,uBAAA,EAAA,EAAA,EAAA,KAAA,EAAAC,wBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gCAAgC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gCAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,UAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtHjC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,2pGAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAnIC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC1B,4BAA4B,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,WAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,oBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,MAAA,EAAA,WAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC5B,2CAA2C,EAAA,QAAA,EAAA,yCAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,YAAA,EAAA,WAAA,EAAA,SAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,QAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC3C,yBAAyB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,SAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,mBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,aAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,iBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACzB,gBAAgB,qIAChB,iCAAiC,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,WAAA,EAAA,aAAA,EAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FA8HxB,gCAAgC,EAAA,UAAA,EAAA,CAAA;kBAzI5C,SAAS;+BACE,gCAAgC,EAAA,UAAA,EAC9B,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,eAAe;wBACf,0BAA0B;wBAC1B,4BAA4B;wBAC5B,2CAA2C;wBAC3C,yBAAyB;wBACzB,gBAAgB;wBAChB;qBACD,EAAA,IAAA,EACK;AACJ,wBAAA,KAAK,EAAE;qBACR,EAAA,QAAA,EAIS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,2pGAAA,CAAA,EAAA;;;ACtJH;;;;;;;;AAQG;MA2BU,0BAA0B,CAAA;AAI5B,IAAA,WAAA;AACC,IAAA,MAAA;AAJF,IAAA,mBAAmB,GAAG,MAAM,CAAC,0BAA0B,CAAC;IAEhE,WAAA,CACS,WAAwB,EACvB,MAAc,EAAA;QADf,IAAA,CAAA,WAAW,GAAX,WAAW;QACV,IAAA,CAAA,MAAM,GAAN,MAAM;AAEd,QAAA,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC;IACvD;IAEA,QAAQ,GAAA;AACN,QAAA,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;;AAElD,QAAA,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC;AACxC,QAAA,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,UAAU,CAAC;;QAG1C,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,IAAI,CAAC,gBAAgB,CAAC;IAC7D;AAEA,IAAA,IAAI,GAAgB;AAClB,QAAA;AACE,YAAA,EAAE,EAAE,MAAM;AACV,YAAA,KAAK,EAAE,MAAM;AACb,YAAA,KAAK,EAAE,MAAM;AACb,YAAA,IAAI,EAAE,qBAAqB;AAC3B,YAAA,UAAU,EAAE;AACb,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,WAAW;AACf,YAAA,KAAK,EAAE,cAAc;AACrB,YAAA,KAAK,EAAE,WAAW;AAClB,YAAA,IAAI,EAAE,oBAAoB;AAC1B,YAAA,UAAU,EAAE;AACb,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,eAAe;AACnB,YAAA,KAAK,EAAE,YAAY;AACnB,YAAA,KAAK,EAAE,eAAe;AACtB,YAAA,IAAI,EAAE,oBAAoB;AAC1B,YAAA,UAAU,EAAE;AACb,SAAA;AACD,QAAA;AACE,YAAA,EAAE,EAAE,UAAU;AACd,YAAA,KAAK,EAAE,SAAS;AAChB,YAAA,KAAK,EAAE,UAAU;AACjB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,UAAU,EAAE;AACb;KACF;AAED;;;;;AAKG;AACH,IAAA,gBAAgB,GAAkB;AAChC,QAAA;AACE,YAAA,OAAO,EAAE;AACP,gBAAA;AACE,oBAAA,MAAM,EAAE,SAAS;AACjB,oBAAA,KAAK,EAAE,YAAY;AACnB,oBAAA,IAAI,EAAE,gBAAgB;AACtB,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,MAAM,EAAE,UAAU;AAClB,oBAAA,KAAK,EAAE,eAAe;AACtB,oBAAA,IAAI,EAAE,oBAAoB;AAC1B,oBAAA,WAAW,EAAE;AACd,iBAAA;AACD,gBAAA;AACE,oBAAA,MAAM,EAAE,iBAAiB;AACzB,oBAAA,KAAK,EAAE,iBAAiB;AACxB,oBAAA,IAAI,EAAE,kBAAkB;AACxB,oBAAA,WAAW,EAAE;AACd;AACF;AACF,SAAA;AACD,QAAA;AACE,YAAA,OAAO,EAAE;AACP,gBAAA;AACE,oBAAA,MAAM,EAAE,QAAQ;AAChB,oBAAA,KAAK,EAAE,QAAQ;AACf,oBAAA,IAAI,EAAE,oBAAoB;AAC1B,oBAAA,WAAW,EAAE;AACd;AACF;AACF;KACF;AAED;;;;AAIG;AACH,IAAA,mBAAmB,CAAC,MAAoB,EAAA;QACtC,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;AAEtD,QAAA,QAAQ,MAAM,CAAC,MAAM;AACnB,YAAA,KAAK,QAAQ;AACX,gBAAA,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;;gBAE7B;AACF,YAAA,KAAK,SAAS;AACZ,gBAAA,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;;gBAEjC;AACF,YAAA,KAAK,UAAU;AACb,gBAAA,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;;gBAElC;AACF,YAAA,KAAK,iBAAiB;AACpB,gBAAA,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;;gBAEzC,UAAU,CAAC,YAAW;AACpB,oBAAA,IAAI;AACF,wBAAA,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE;oBACvC;oBAAE,OAAO,KAAK,EAAE;AACd,wBAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC;oBAC/D;gBACF,CAAC,EAAE,GAAG,CAAC;gBACP;;IAEN;wGA7HW,0BAA0B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAJ,WAAA,EAAA,EAAA,EAAA,KAAA,EAAAZ,IAAA,CAAA,MAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA1B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,yBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAd3B,CAAA;;;;;;;;;;;;AAYT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArBS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,uBAAuB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,kBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,aAAA,EAAA,uBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAuB7C,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBA1BtC,SAAS;+BACE,yBAAyB,EAAA,UAAA,EACvB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,OAAO,EAAE,uBAAuB,CAAC,EAAA,QAAA,EAS/C,CAAA;;;;;;;;;;;;AAYT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,mEAAA,CAAA,EAAA;;;AC9BH;;;;;AAKG;MA4LU,uBAAuB,CAAA;AAcxB,IAAA,MAAA;AACA,IAAA,KAAA;AACD,IAAA,WAAA;AAfmB,IAAA,aAAa;IAEzC,WAAW,GAAG,EAAE;AAChB,IAAA,QAAQ,GAAG,MAAM,CAAC,gBAAgB,oDAAC;AACnC,IAAA,WAAW,GAAG,MAAM,CAAC,aAAa,uDAAC;;AAGnC,IAAA,UAAU,GAAG,MAAM,CAAC,KAAK,sDAAC;AAC1B,IAAA,MAAM,GAAG,MAAM,CAAgB,IAAI,kDAAC;AACpC,IAAA,SAAS,GAAG,MAAM,CAAC,UAAU,qDAAC;AAC9B,IAAA,iBAAiB,GAAG,MAAM,CAAC,MAAM,6DAAC;AAElC,IAAA,WAAA,CACU,MAAc,EACd,KAAqB,EACtB,WAAwB,EAAA;QAFvB,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,KAAK,GAAL,KAAK;QACN,IAAA,CAAA,WAAW,GAAX,WAAW;IACjB;IAEH,QAAQ,GAAA;;QAEN,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,IAAG;YACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,MAAM;AAC1C,YAAA,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC;AAC3B,YAAA,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;AAEjC,YAAA,IAAI,QAAQ,IAAI,MAAM,EAAE;AACtB,gBAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;AACvB,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC;AAC/B,gBAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;;gBAGlC,IAAI,OAAO,EAAE;AACX,oBAAA,IAAI,CAAC,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC;gBAChD;YACF;iBAAO;;AAEL,gBAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACrB,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;AAC9B,gBAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;AAClC,gBAAA,IAAI,CAAC,WAAW,GAAG,EAAE;YACvB;AACF,QAAA,CAAC,CAAC;IACJ;IAEA,eAAe,GAAA;;QAEb,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,KAAK,EAAE;QAC3C,CAAC,EAAE,GAAG,CAAC;IACT;IAEA,WAAW,GAAA;;IAEX;IAEA,OAAO,GAAA;QACL,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;IAC3C;IAEA,YAAY,GAAA;QACV,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;;AAEtC,YAAA,MAAM,SAAS,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAC/C,IAAI,SAAS,EAAE;gBACb,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,gCAAgC,CAAC,CAAC;YAC1D;QACF;aAAO;YACL,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,gCAAgC,CAAC,CAAC;QAC1D;IACF;IAEA,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE;AAErB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;AACrB,YAAA,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC;;;;;QAKhE;aAAO;YACL,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,WAAW,CAAC;;;;;QAKjD;;QAGA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,gCAAgC,CAAC,CAAC;IAC1D;IAEA,cAAc,GAAA;AACZ,QAAA,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;;IAE1B;IAEA,cAAc,GAAA;AACZ,QAAA,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;;IAE1B;wGAvGW,uBAAuB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAC,IAAA,CAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAAAA,IAAA,CAAA,cAAA,EAAA,EAAA,EAAA,KAAA,EAAAY,WAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,eAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,eAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EArDxB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,wgDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArLC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAR,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,iBAAiB,mIACjB,eAAe,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,aAAA,EAAA,cAAA,EAAA,WAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,4BAA4B,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,WAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,oBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,MAAA,EAAA,WAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAkLnB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBA3LnC,SAAS;+BACE,sBAAsB,EAAA,UAAA,EACpB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,iBAAiB;wBACjB,eAAe;wBACf,iBAAiB;wBACjB;qBACD,EAAA,QAAA,EA4HS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,wgDAAA,CAAA,EAAA;;sBAGA,SAAS;uBAAC,eAAe;;;MCOf,6BAA6B,CAAA;AAI9B,IAAA,QAAA;AACA,IAAA,WAAA;IAJV,YAAY,GAAG,CAAC;IAEhB,WAAA,CACU,QAAiC,EACjC,WAAuC,EAAA;QADvC,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,WAAW,GAAX,WAAW;IAClB;AAEH;;AAEG;AACH,IAAA,iBAAiB,CAAC,QAAgB,EAAE,KAAa,EAAE,WAAmB,EAAA;AACpE,QAAA,MAAM,UAAU,GAAmB;AACjC,YAAA,IAAI,EAAE,iBAAiB;AACvB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,SAAS,EAAE;SACZ;AAED,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjB,WAAW,EAAE,IAAI;AACjB,YAAA,MAAM,EAAE;AACN,gBAAA;AACE,oBAAA,IAAI,EAAE,OAAO;AACb,oBAAA,GAAG,EAAE,QAAQ;AACb,oBAAA,GAAG,EAAE,KAAK;AACV,oBAAA,KAAK,EAAE,KAAK;AACZ,oBAAA,WAAW,EAAE,WAAW;AACxB,oBAAA,OAAO,EAAE,IAAI;AACb,oBAAA,SAAS,EAAE,GAAG;AACd,oBAAA,YAAY,EAAE;AACf;AACF,aAAA;AACD,YAAA,MAAM,EAAE,UAAU;AAClB,YAAA,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;AACnB,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;IACJ;AAEA;;AAEG;AACH,IAAA,MAAM,sBAAsB,CAAC,UAAkB,EAAE,OAAe,EAAE,YAAqB,EAAA;QACrF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AAC1C,YAAA,SAAS,EAAEF,mCAA0C;AACrD,YAAA,cAAc,EAAE;AACd,gBAAA,YAAY,EAAE;AACf,aAAA;AACD,YAAA,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACnB,YAAA,iBAAiB,EAAE,CAAC;AACpB,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,QAAQ,EAAE;AACX,SAAA,CAAC;AAEF,QAAA,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;QAE1C,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE;AAC3C,YAAA,MAAM,MAAM,GAAI,MAAM,CAAC,IAA4B,CAAC,MAAM;YAE1D,QAAQ,MAAM;AACZ,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;;oBAE1C;AACF,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,UAAU,CAAC;;oBAE9C;AACF,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;;oBAE1C;AACF,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,UAAU,CAAC;;oBAE5C;;QAEN;IACF;wGAhFW,6BAA6B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAD,uBAAA,EAAA,EAAA,EAAA,KAAA,EAAAE,0BAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAA7B,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,6BAA6B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,6BAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjI9B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+HT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,6sBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA/LC,4BAA4B,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,WAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,oBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,MAAA,EAAA,WAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAC5B,wCAAwC,EAAA,QAAA,EAAA,sCAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,YAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,SAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,cAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACxC,oBAAoB,yDACpB,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,kBAAkB,EAAA,QAAA,EAAA,YAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAClB,oBAAoB,EAAA,QAAA,EAAA,cAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACpB,mBAAmB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,EAAA,aAAA,EAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,sBAAsB,yGACtB,wBAAwB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,YAAA,EAAA,WAAA,EAAA,SAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,EAAA,aAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,YAAA,EAAA,WAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAyLf,6BAA6B,EAAA,UAAA,EAAA,CAAA;kBArMzC,SAAS;+BACE,6BAA6B,EAAA,UAAA,EAC3B,IAAI,EAAA,OAAA,EACP;wBACP,4BAA4B;wBAC5B,wCAAwC;wBACxC,oBAAoB;wBACpB,iBAAiB;wBACjB,kBAAkB;wBAClB,oBAAoB;wBACpB,mBAAmB;wBACnB,sBAAsB;wBACtB;qBACD,EAAA,QAAA,EAuDS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+HT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,6sBAAA,CAAA,EAAA;;;AC7MH;;;;;AAKG;MA2HU,mBAAmB,CAAA;IAC9B,KAAK,GAAG,EAAE;AACV,IAAA,UAAU,GAAG,MAAM,CAAU,KAAK,sDAAC;AACnC,IAAA,YAAY,GAAG,MAAM,CAAU,KAAK,wDAAC;AACrC,IAAA,SAAS,GAAG,MAAM,CAAU,KAAK,qDAAC;IAElC,YAAY,GAAA;;QAEV,MAAM,UAAU,GAAG,4BAA4B;;AAG/C,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC/C,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YACzB;QACF;;AAGA,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;;QAG3B,UAAU,CAAC,MAAK;YACd,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,KAAK,CAAC;AAC9C,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5B,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;;QAE1B,CAAC,EAAE,IAAI,CAAC;IACV;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,KAAK,GAAG,EAAE;AACf,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;IAC5B;wGAjCW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtHpB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwFT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,iWAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzFS,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAH,IAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,0FAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,iBAAA,EAAA,QAAA,EAAA,wIAAA,EAAA,MAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,MAAA,EAAA,QAAA,EAAA,wDAAA,EAAA,MAAA,EAAA,CAAA,eAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,oBAAoB,kRAAE,iBAAiB,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,EAAA,aAAA,EAAA,cAAA,EAAA,WAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAuHjE,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBA1H/B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,aAAa,EAAA,UAAA,EACX,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,EAAA,QAAA,EACnE,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwFT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,iWAAA,CAAA,EAAA;;;AChGH;;;;AAIG;MAkWU,kBAAkB,CAAA;AAC7B,IAAA,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;;IAG7C,YAAY,GAAG,SAAS;;IAGxB,oBAAoB,GAAG,SAAS;IAChC,oBAAoB,GAAG,SAAS;IAChC,sBAAsB,GAAG,SAAS;IAClC,sBAAsB,GAAG,SAAS;IAElC,QAAQ,GAAA;QACN,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,uCAAuC;AAChD,YAAA,WAAW,EAAE,uCAAuC;AACpD,YAAA,OAAO,EAAE,YAAY;AACrB,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,YAAY;AAC9B,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,4BAA4B;AACrC,YAAA,WAAW,EAAE,4BAA4B;AACzC,YAAA,OAAO,EAAE,KAAK;AACd,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,KAAK;AACvB,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,4BAA4B;AACrC,YAAA,WAAW,EAAE,4BAA4B;AACzC,YAAA,OAAO,EAAE,KAAK;AACd,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,KAAK;AACvB,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,YAAY,GAAG,OAAO;AAC3B,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,8BAA8B;AACvC,YAAA,WAAW,EAAE,8BAA8B;AAC3C,YAAA,OAAO,EAAE,OAAO;AAChB,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,OAAO;AACzB,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;AAClC,YAAA,OAAO,EAAE,gCAAgC;AACzC,YAAA,WAAW,EAAE,oCAAoC;AACjD,YAAA,OAAO,EAAE,SAAS;AAClB,YAAA,UAAU,EAAE,EAAE;AACd,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,cAAc,EAAE,SAAS;AACzB,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,gBAAgB,EAAE,SAAS;AAC3B,YAAA,cAAc,EAAE;AACjB,SAAA,CAAC;QACF,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;YAClC,cAAc,EAAE,IAAI,CAAC,oBAAoB;YACzC,cAAc,EAAE,IAAI,CAAC,oBAAoB;YACzC,gBAAgB,EAAE,IAAI,CAAC,sBAAsB;YAC7C,gBAAgB,EAAE,IAAI,CAAC;AACxB,SAAA,CAAC;IACJ;IAEQ,uBAAuB,GAAA;QAC7B,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE;QACnE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE;QACnE,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE;QACvE,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE;IACzE;wGAnHW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA7InB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2IT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,koFAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3VC,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,UAAU,wKACV,SAAS,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,UAAU,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACR,SAAS,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,OAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,eAAe,gHACf,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA,EAAA,UAAA,EAAA,WAAA,EAAA,eAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAqVjB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAjW9B,SAAS;+BACE,qBAAqB,EAAA,UAAA,EACnB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,UAAU;wBACV,SAAS;wBACT,UAAU;wBACV,QAAQ;wBACR,SAAS;wBACT,eAAe;wBACf;qBACD,EAAA,QAAA,EAuMS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2IT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,koFAAA,CAAA,EAAA;;;AC5WH;;;AAGG;;ACHH;;;;AAIG;;ACJH;;ACAA;;AAEG;;;;"}
|