@propbinder/mobile-design 0.1.15 → 0.1.17
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 +1836 -1601
- package/fesm2022/propbinder-mobile-design.mjs.map +1 -1
- package/index.d.ts +357 -237
- package/package.json +1 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed, effect, Injectable, inject, Input, Component, input, Directive, EventEmitter, HostListener, Output, PLATFORM_ID, output, ViewChild,
|
|
2
|
+
import { signal, computed, effect, Injectable, inject, Input, Component, input, Directive, EventEmitter, HostListener, Output, PLATFORM_ID, output, ViewChild, model, ElementRef, CUSTOM_ELEMENTS_SCHEMA, createComponent, forwardRef, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import * as i1$2 from '@angular/common';
|
|
4
4
|
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
5
5
|
import * as i1$3 from '@angular/router';
|
|
6
6
|
import { Router, NavigationEnd } from '@angular/router';
|
|
7
7
|
import * as i1 from '@ionic/angular/standalone';
|
|
8
|
-
import { IonHeader, IonToolbar, IonTitle, IonContent, IonButtons,
|
|
8
|
+
import { IonHeader, IonToolbar, IonTitle, IonContent, IonButtons, Platform, ModalController, IonRefresher, IonRefresherContent, IonTabBar, IonTabButton, IonLabel, IonTabs, IonTab, IonSpinner, IonButton } from '@ionic/angular/standalone';
|
|
9
9
|
import { ImpactStyle, Haptics } from '@capacitor/haptics';
|
|
10
10
|
import { DsIconButtonComponent, DsIconComponent, DsButtonComponent, DsAvatarComponent, DsShapeIndicatorComponent } from '@propbinder/design-system';
|
|
11
11
|
import { StatusBar } from '@capacitor/status-bar';
|
|
12
12
|
import * as i1$1 from '@angular/forms';
|
|
13
|
-
import { FormsModule } from '@angular/forms';
|
|
13
|
+
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
14
14
|
import { Keyboard } from '@capacitor/keyboard';
|
|
15
15
|
import { Camera, CameraSource, CameraResultType } from '@capacitor/camera';
|
|
16
16
|
import { filter } from 'rxjs/operators';
|
|
@@ -1815,1111 +1815,579 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
1815
1815
|
}] } });
|
|
1816
1816
|
|
|
1817
1817
|
/**
|
|
1818
|
-
*
|
|
1819
|
-
*
|
|
1820
|
-
* Displays an avatar with a logomark badge overlay.
|
|
1821
|
-
* Useful for showing user avatars with organization branding.
|
|
1822
|
-
*
|
|
1823
|
-
* @example
|
|
1824
|
-
* ```html
|
|
1825
|
-
* <ds-avatar-with-badge
|
|
1826
|
-
* [type]="'initials'"
|
|
1827
|
-
* [initials]="'JD'"
|
|
1828
|
-
* [size]="'lg'"
|
|
1829
|
-
* [badgePosition]="'bottom-right'"
|
|
1830
|
-
* />
|
|
1831
|
-
* ```
|
|
1818
|
+
* User service for managing current user data globally
|
|
1832
1819
|
*/
|
|
1833
|
-
class
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1820
|
+
class UserService {
|
|
1821
|
+
// User avatar configuration
|
|
1822
|
+
_avatarInitials = signal('LM', ...(ngDevMode ? [{ debugName: "_avatarInitials" }] : []));
|
|
1823
|
+
_avatarType = signal('initials', ...(ngDevMode ? [{ debugName: "_avatarType" }] : []));
|
|
1824
|
+
_avatarSrc = signal('', ...(ngDevMode ? [{ debugName: "_avatarSrc" }] : []));
|
|
1825
|
+
// Profile menu items configuration
|
|
1826
|
+
_profileMenuItems = signal(undefined, ...(ngDevMode ? [{ debugName: "_profileMenuItems" }] : []));
|
|
1827
|
+
// Readonly computed values
|
|
1828
|
+
avatarInitials = this._avatarInitials.asReadonly();
|
|
1829
|
+
avatarType = this._avatarType.asReadonly();
|
|
1830
|
+
avatarSrc = this._avatarSrc.asReadonly();
|
|
1831
|
+
profileMenuItems = this._profileMenuItems.asReadonly();
|
|
1832
|
+
/**
|
|
1833
|
+
* Update avatar configuration
|
|
1834
|
+
*/
|
|
1835
|
+
setAvatarInitials(initials) {
|
|
1836
|
+
this._avatarInitials.set(initials);
|
|
1837
|
+
}
|
|
1838
|
+
setAvatarType(type) {
|
|
1839
|
+
this._avatarType.set(type);
|
|
1840
|
+
}
|
|
1841
|
+
setAvatarSrc(src) {
|
|
1842
|
+
this._avatarSrc.set(src);
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Set profile menu items globally.
|
|
1846
|
+
* This will be used by both ds-mobile-tab-bar and ds-mobile-page-main
|
|
1847
|
+
* if they don't receive profileMenuItems as an input.
|
|
1848
|
+
*/
|
|
1849
|
+
setProfileMenuItems(items) {
|
|
1850
|
+
this._profileMenuItems.set(items);
|
|
1851
|
+
}
|
|
1852
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1853
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: UserService, providedIn: 'root' });
|
|
1865
1854
|
}
|
|
1866
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
1867
|
-
type:
|
|
1868
|
-
args: [{
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
[size]="size"
|
|
1873
|
-
[initials]="initials"
|
|
1874
|
-
[src]="src"
|
|
1875
|
-
[iconName]="iconName"
|
|
1876
|
-
/>
|
|
1877
|
-
|
|
1878
|
-
@if (showBadge) {
|
|
1879
|
-
<div [class]="badgeClasses()">
|
|
1880
|
-
<img [src]="whitelabelService.logoMarkUrl()" [alt]="whitelabelService.logoAlt()" />
|
|
1881
|
-
</div>
|
|
1882
|
-
}
|
|
1883
|
-
</div>
|
|
1884
|
-
`, styles: [":host{display:inline-block;position:relative}.avatar-badge-container{position:relative;display:inline-block}.avatar-badge{position:absolute;background:var(--color-brand-secondary, #5d5fef);border-radius:8px;display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge img{width:10px;height:10px;object-fit:contain}.avatar-badge--bottom-right{bottom:-6px;right:-6px}.avatar-badge--bottom-left{bottom:-6px;left:-6px}.avatar-badge--top-right{top:-6px;right:-6px}.avatar-badge--top-left{top:-6px;left:-6px}.avatar-badge--xs{width:16px;height:16px}.avatar-badge--sm{width:18px;height:18px}.avatar-badge--md{width:20px;height:20px}.avatar-badge--lg{width:24px;height:24px}.avatar-badge--xl{width:28px;height:28px}\n"] }]
|
|
1885
|
-
}], propDecorators: { type: [{
|
|
1886
|
-
type: Input
|
|
1887
|
-
}], size: [{
|
|
1888
|
-
type: Input
|
|
1889
|
-
}], initials: [{
|
|
1890
|
-
type: Input
|
|
1891
|
-
}], src: [{
|
|
1892
|
-
type: Input
|
|
1893
|
-
}], iconName: [{
|
|
1894
|
-
type: Input
|
|
1895
|
-
}], showBadge: [{
|
|
1896
|
-
type: Input
|
|
1897
|
-
}], badgePosition: [{
|
|
1898
|
-
type: Input
|
|
1899
|
-
}] } });
|
|
1855
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: UserService, decorators: [{
|
|
1856
|
+
type: Injectable,
|
|
1857
|
+
args: [{
|
|
1858
|
+
providedIn: 'root'
|
|
1859
|
+
}]
|
|
1860
|
+
}] });
|
|
1900
1861
|
|
|
1901
1862
|
/**
|
|
1902
|
-
*
|
|
1863
|
+
* DsMobilePageMainComponent
|
|
1903
1864
|
*
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1865
|
+
* A complete mobile page layout for main/tab pages with:
|
|
1866
|
+
* - Fixed header with logomark + title + avatar
|
|
1867
|
+
* - Purple expandable header section (scrolls with content)
|
|
1868
|
+
* - White rounded content wrapper
|
|
1869
|
+
* - Pull-to-refresh support
|
|
1870
|
+
* - Auto scroll title fade-in
|
|
1871
|
+
*
|
|
1872
|
+
* @example
|
|
1873
|
+
* ```html
|
|
1874
|
+
* <!-- Simple page -->
|
|
1875
|
+
* <ds-mobile-page-main
|
|
1876
|
+
* title="Inquiries"
|
|
1877
|
+
* [avatarInitials]="'JD'">
|
|
1878
|
+
* <div class="page-content">
|
|
1879
|
+
* <!-- Your content -->
|
|
1880
|
+
* </div>
|
|
1881
|
+
* </ds-mobile-page-main>
|
|
1882
|
+
*
|
|
1883
|
+
* <!-- Page with custom header content -->
|
|
1884
|
+
* <ds-mobile-page-main
|
|
1885
|
+
* title="Home"
|
|
1886
|
+
* headerTitle="Welcome, Lars"
|
|
1887
|
+
* headerSubtitle="Your rental property at a glance."
|
|
1888
|
+
* [avatarInitials]="'L'">
|
|
1889
|
+
*
|
|
1890
|
+
* <div header-content class="property-tiles">
|
|
1891
|
+
* <!-- Custom header content like tiles -->
|
|
1892
|
+
* </div>
|
|
1893
|
+
*
|
|
1894
|
+
* <div class="page-content">
|
|
1895
|
+
* <!-- Main page content -->
|
|
1896
|
+
* </div>
|
|
1897
|
+
* </ds-mobile-page-main>
|
|
1898
|
+
* ```
|
|
1906
1899
|
*/
|
|
1907
|
-
class
|
|
1908
|
-
|
|
1900
|
+
class DsMobilePageMainComponent extends MobilePageBase {
|
|
1901
|
+
elementRef;
|
|
1902
|
+
ionContent;
|
|
1903
|
+
// Platform detection
|
|
1904
|
+
platform = inject(Platform);
|
|
1909
1905
|
modalController = inject(ModalController);
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
//
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1906
|
+
router = inject(Router);
|
|
1907
|
+
userService = inject(UserService);
|
|
1908
|
+
// Computed property to check if running on native platform
|
|
1909
|
+
isNativePlatform = computed(() => this.platform.is('ios') ||
|
|
1910
|
+
this.platform.is('android') ||
|
|
1911
|
+
this.platform.is('capacitor'), ...(ngDevMode ? [{ debugName: "isNativePlatform" }] : []));
|
|
1912
|
+
// Inputs - Title
|
|
1913
|
+
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : [])); // For fixed header title
|
|
1914
|
+
headerTitle = input('', ...(ngDevMode ? [{ debugName: "headerTitle" }] : [])); // Optional different title for expandable header
|
|
1915
|
+
headerSubtitle = input('', ...(ngDevMode ? [{ debugName: "headerSubtitle" }] : []));
|
|
1916
|
+
// Inputs - Avatar
|
|
1917
|
+
avatarType = input('initials', ...(ngDevMode ? [{ debugName: "avatarType" }] : []));
|
|
1918
|
+
avatarInitials = input('U', ...(ngDevMode ? [{ debugName: "avatarInitials" }] : []));
|
|
1919
|
+
avatarSrc = input('', ...(ngDevMode ? [{ debugName: "avatarSrc" }] : []));
|
|
1920
|
+
avatarIconName = input('remixUser3Line', ...(ngDevMode ? [{ debugName: "avatarIconName" }] : []));
|
|
1921
|
+
// Inputs - Features
|
|
1922
|
+
showRefresh = input(true, ...(ngDevMode ? [{ debugName: "showRefresh" }] : []));
|
|
1923
|
+
showCondensedHeader = input(true, ...(ngDevMode ? [{ debugName: "showCondensedHeader" }] : []));
|
|
1924
|
+
scrollThreshold = input(160, ...(ngDevMode ? [{ debugName: "scrollThreshold" }] : [])); // Pixels to scroll before title appears
|
|
1925
|
+
headerFadeDistance = input(150, ...(ngDevMode ? [{ debugName: "headerFadeDistance" }] : [])); // Distance over which header fades out
|
|
1921
1926
|
/**
|
|
1922
|
-
*
|
|
1927
|
+
* Profile menu action groups to display when avatar is clicked.
|
|
1928
|
+
* If not provided, a default menu will be used (without Whitelabel Demo).
|
|
1929
|
+
*
|
|
1930
|
+
* @example
|
|
1931
|
+
* ```typescript
|
|
1932
|
+
* profileMenuItems: ActionGroup[] = [
|
|
1933
|
+
* {
|
|
1934
|
+
* actions: [
|
|
1935
|
+
* { action: 'profile', title: 'Min profil', icon: 'remixUser3Line' },
|
|
1936
|
+
* { action: 'settings', title: 'Indstillinger', icon: 'remixSettings3Line' }
|
|
1937
|
+
* ]
|
|
1938
|
+
* },
|
|
1939
|
+
* {
|
|
1940
|
+
* actions: [
|
|
1941
|
+
* { action: 'logout', title: 'Log ud', icon: 'remixLogoutBoxLine', destructive: true }
|
|
1942
|
+
* ]
|
|
1943
|
+
* }
|
|
1944
|
+
* ];
|
|
1945
|
+
* ```
|
|
1923
1946
|
*/
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
this.currentTheme = 'cej';
|
|
1928
|
-
}
|
|
1929
|
-
else if (secondarySurface === '#660036') {
|
|
1930
|
-
this.currentTheme = 'pka';
|
|
1931
|
-
}
|
|
1932
|
-
else if (secondarySurface === '#262424') {
|
|
1933
|
-
this.currentTheme = 'clave';
|
|
1934
|
-
}
|
|
1935
|
-
else {
|
|
1936
|
-
this.currentTheme = 'default';
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1947
|
+
profileMenuItems = input(undefined, ...(ngDevMode ? [{ debugName: "profileMenuItems" }] : []));
|
|
1948
|
+
// Outputs
|
|
1949
|
+
avatarClick = output();
|
|
1939
1950
|
/**
|
|
1940
|
-
*
|
|
1951
|
+
* Emitted when a profile menu action is selected.
|
|
1952
|
+
* Parent component should handle the action logic (navigation, logout, etc.).
|
|
1941
1953
|
*/
|
|
1942
|
-
|
|
1943
|
-
|
|
1954
|
+
profileActionSelected = output();
|
|
1955
|
+
refresh = output();
|
|
1956
|
+
scroll = output();
|
|
1957
|
+
constructor(elementRef) {
|
|
1958
|
+
super();
|
|
1959
|
+
this.elementRef = elementRef;
|
|
1944
1960
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
this.whitelabelService.updateConfig({
|
|
1948
|
-
logoUrl: '/Assets/logos/propbinder-logomark.svg',
|
|
1949
|
-
logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',
|
|
1950
|
-
logoAlt: 'Propbinder',
|
|
1951
|
-
logoHeight: 28,
|
|
1952
|
-
primarySurface: '#6B5FF5',
|
|
1953
|
-
primaryContent: '#FFFFFF',
|
|
1954
|
-
secondarySurface: '#221a4c',
|
|
1955
|
-
secondaryContent: '#FFFFFF',
|
|
1956
|
-
organizationName: 'Propbinder',
|
|
1957
|
-
organizationId: 'default'
|
|
1958
|
-
});
|
|
1959
|
-
this.updateCustomColorInputs();
|
|
1961
|
+
ngAfterViewInit() {
|
|
1962
|
+
// Initial setup if needed
|
|
1960
1963
|
}
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
1964
|
+
/**
|
|
1965
|
+
* Handle avatar click - opens profile actions bottom sheet
|
|
1966
|
+
*/
|
|
1967
|
+
async handleAvatarClick() {
|
|
1968
|
+
console.log('Avatar clicked - opening profile bottom sheet');
|
|
1969
|
+
// Emit the event for any parent listeners
|
|
1970
|
+
this.avatarClick.emit();
|
|
1971
|
+
// Use input if provided, otherwise fall back to service, otherwise use default menu
|
|
1972
|
+
const menuItems = this.profileMenuItems() || this.userService.profileMenuItems() || [
|
|
1973
|
+
{
|
|
1974
|
+
actions: [
|
|
1975
|
+
{
|
|
1976
|
+
action: 'profile',
|
|
1977
|
+
title: 'Min profil',
|
|
1978
|
+
icon: 'remixUser3Line',
|
|
1979
|
+
destructive: false
|
|
1980
|
+
},
|
|
1981
|
+
{
|
|
1982
|
+
action: 'settings',
|
|
1983
|
+
title: 'Indstillinger',
|
|
1984
|
+
icon: 'remixSettings3Line',
|
|
1985
|
+
destructive: false
|
|
1986
|
+
}
|
|
1987
|
+
]
|
|
1988
|
+
},
|
|
1989
|
+
{
|
|
1990
|
+
actions: [
|
|
1991
|
+
{
|
|
1992
|
+
action: 'logout',
|
|
1993
|
+
title: 'Log ud',
|
|
1994
|
+
icon: 'remixLogoutBoxLine',
|
|
1995
|
+
destructive: true
|
|
1996
|
+
}
|
|
1997
|
+
]
|
|
1998
|
+
}
|
|
1999
|
+
];
|
|
2000
|
+
// If no menu items configured, just emit and return
|
|
2001
|
+
if (!menuItems || menuItems.length === 0) {
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
const sheet = await this.modalController.create({
|
|
2005
|
+
component: DsMobileActionsBottomSheetComponent,
|
|
2006
|
+
componentProps: {
|
|
2007
|
+
customActionGroups: menuItems
|
|
2008
|
+
},
|
|
2009
|
+
// Auto-height: no breakpoints, no handle
|
|
2010
|
+
cssClass: 'ds-bottom-sheet auto-height'
|
|
2006
2011
|
});
|
|
2007
|
-
|
|
2012
|
+
await sheet.present();
|
|
2013
|
+
const result = await sheet.onWillDismiss();
|
|
2014
|
+
if (result.data?.action) {
|
|
2015
|
+
// Emit the selected action to parent
|
|
2016
|
+
this.profileActionSelected.emit(result.data);
|
|
2017
|
+
}
|
|
2008
2018
|
}
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2019
|
+
/**
|
|
2020
|
+
* Handle scroll events
|
|
2021
|
+
* - Shows title in fixed header when scrolled past threshold
|
|
2022
|
+
* - Fades out expandable header content based on scroll position
|
|
2023
|
+
* - Emits scroll event for custom handling
|
|
2024
|
+
*/
|
|
2025
|
+
handleScroll(event) {
|
|
2026
|
+
const scrollTop = event.detail.scrollTop;
|
|
2027
|
+
const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');
|
|
2028
|
+
const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');
|
|
2029
|
+
// Show title in fixed header when scrolled past threshold
|
|
2030
|
+
if (scrollTop > this.scrollThreshold()) {
|
|
2031
|
+
header?.classList.add('header-scrolled');
|
|
2032
|
+
}
|
|
2033
|
+
else {
|
|
2034
|
+
header?.classList.remove('header-scrolled');
|
|
2035
|
+
}
|
|
2036
|
+
// Fade out header-expandable content based on scroll
|
|
2037
|
+
if (headerExpandable) {
|
|
2038
|
+
const fadeDistance = this.headerFadeDistance();
|
|
2039
|
+
const fadeProgress = Math.min(scrollTop / fadeDistance, 1);
|
|
2040
|
+
// Calculate opacity (1 to 0)
|
|
2041
|
+
const opacity = 1 - fadeProgress;
|
|
2042
|
+
// Calculate transform (0px to -20px upward)
|
|
2043
|
+
const translateY = fadeProgress * -20;
|
|
2044
|
+
// Apply styles
|
|
2045
|
+
headerExpandable.style.opacity = opacity.toString();
|
|
2046
|
+
headerExpandable.style.transform = `translateY(${translateY}px)`;
|
|
2047
|
+
}
|
|
2048
|
+
this.scroll.emit(event);
|
|
2016
2049
|
}
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2050
|
+
/**
|
|
2051
|
+
* Handle pull-to-refresh
|
|
2052
|
+
* Emits refresh event - parent should call event.target.complete()
|
|
2053
|
+
*/
|
|
2054
|
+
async handleRefresh(event) {
|
|
2055
|
+
// Haptic feedback for pull-to-refresh
|
|
2056
|
+
try {
|
|
2057
|
+
await Haptics.impact({ style: ImpactStyle.Medium });
|
|
2058
|
+
}
|
|
2059
|
+
catch {
|
|
2060
|
+
// Fallback to Web Vibration API if Capacitor Haptics is not available
|
|
2061
|
+
if ('vibrate' in navigator) {
|
|
2062
|
+
navigator.vibrate(50);
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
this.refresh.emit(event);
|
|
2022
2066
|
}
|
|
2023
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
2024
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2025
|
-
<!-- Fixed
|
|
2026
|
-
<
|
|
2027
|
-
<
|
|
2028
|
-
<
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
variant="secondary"
|
|
2032
|
-
size="lg"
|
|
2033
|
-
(click)="close()"
|
|
2034
|
-
class="close-button"
|
|
2035
|
-
aria-label="Close">
|
|
2036
|
-
</ds-icon-button>
|
|
2037
|
-
</div>
|
|
2038
|
-
</div>
|
|
2039
|
-
|
|
2040
|
-
<!-- Scrollable Content -->
|
|
2041
|
-
<ion-content [scrollY]="true" class="modal-content">
|
|
2042
|
-
<div class="demo-container">
|
|
2043
|
-
<!-- Theme Selection -->
|
|
2044
|
-
<div class="demo-section">
|
|
2045
|
-
<h2>Theme</h2>
|
|
2046
|
-
<div class="theme-buttons">
|
|
2047
|
-
<button class="theme-btn" (click)="applyDefaultTheme()" [class.active]="currentTheme === 'default'">
|
|
2048
|
-
Propbinder
|
|
2049
|
-
</button>
|
|
2050
|
-
<button class="theme-btn" (click)="applyCejTheme()" [class.active]="currentTheme === 'cej'">
|
|
2051
|
-
CEJ
|
|
2052
|
-
</button>
|
|
2053
|
-
<button class="theme-btn" (click)="applyPkaTheme()" [class.active]="currentTheme === 'pka'">
|
|
2054
|
-
PKA
|
|
2055
|
-
</button>
|
|
2056
|
-
<button class="theme-btn" (click)="applyClaveTheme()" [class.active]="currentTheme === 'clave'">
|
|
2057
|
-
Clave
|
|
2058
|
-
</button>
|
|
2059
|
-
</div>
|
|
2060
|
-
</div>
|
|
2067
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsMobilePageMainComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2068
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: DsMobilePageMainComponent, isStandalone: true, selector: "ds-mobile-page-main", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, headerTitle: { classPropertyName: "headerTitle", publicName: "headerTitle", isSignal: true, isRequired: false, transformFunction: null }, headerSubtitle: { classPropertyName: "headerSubtitle", publicName: "headerSubtitle", isSignal: true, isRequired: false, transformFunction: null }, avatarType: { classPropertyName: "avatarType", publicName: "avatarType", isSignal: true, isRequired: false, transformFunction: null }, avatarInitials: { classPropertyName: "avatarInitials", publicName: "avatarInitials", isSignal: true, isRequired: false, transformFunction: null }, avatarSrc: { classPropertyName: "avatarSrc", publicName: "avatarSrc", isSignal: true, isRequired: false, transformFunction: null }, avatarIconName: { classPropertyName: "avatarIconName", publicName: "avatarIconName", isSignal: true, isRequired: false, transformFunction: null }, showRefresh: { classPropertyName: "showRefresh", publicName: "showRefresh", isSignal: true, isRequired: false, transformFunction: null }, showCondensedHeader: { classPropertyName: "showCondensedHeader", publicName: "showCondensedHeader", isSignal: true, isRequired: false, transformFunction: null }, scrollThreshold: { classPropertyName: "scrollThreshold", publicName: "scrollThreshold", isSignal: true, isRequired: false, transformFunction: null }, headerFadeDistance: { classPropertyName: "headerFadeDistance", publicName: "headerFadeDistance", isSignal: true, isRequired: false, transformFunction: null }, profileMenuItems: { classPropertyName: "profileMenuItems", publicName: "profileMenuItems", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { avatarClick: "avatarClick", profileActionSelected: "profileActionSelected", refresh: "refresh", scroll: "scroll" }, viewQueries: [{ propertyName: "ionContent", first: true, predicate: IonContent, descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
2069
|
+
<!-- Fixed header at top -->
|
|
2070
|
+
<ion-header>
|
|
2071
|
+
<ion-toolbar>
|
|
2072
|
+
<div class="header-home">
|
|
2073
|
+
<!-- Whitelabel Logomark -->
|
|
2074
|
+
<ds-logo variant="mark" size="lg" />
|
|
2061
2075
|
|
|
2062
|
-
<!--
|
|
2063
|
-
<
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2076
|
+
<!-- Title - fades in on scroll -->
|
|
2077
|
+
<ion-title class="header-home__title">{{ title() }}</ion-title>
|
|
2078
|
+
|
|
2079
|
+
<!-- Avatar -->
|
|
2080
|
+
<div class="header-home__actions">
|
|
2081
|
+
<ds-avatar
|
|
2082
|
+
[size]="'md'"
|
|
2083
|
+
[type]="avatarType()"
|
|
2084
|
+
[initials]="avatarInitials()"
|
|
2085
|
+
[src]="avatarSrc()"
|
|
2086
|
+
[iconName]="avatarIconName()"
|
|
2087
|
+
(click)="handleAvatarClick()"
|
|
2088
|
+
style="cursor: pointer;"
|
|
2089
|
+
/>
|
|
2090
|
+
</div>
|
|
2091
|
+
</div>
|
|
2092
|
+
</ion-toolbar>
|
|
2093
|
+
</ion-header>
|
|
2094
|
+
|
|
2095
|
+
<!-- Content with expandable header -->
|
|
2096
|
+
<ion-content [scrollEvents]="true" (ionScroll)="handleScroll($event)">
|
|
2097
|
+
<!-- Condensed header for Ionic scroll effects -->
|
|
2098
|
+
@if (showCondensedHeader()) {
|
|
2099
|
+
<ion-header collapse="condense">
|
|
2100
|
+
<ion-toolbar>
|
|
2101
|
+
<ion-title size="large">{{ title() }}</ion-title>
|
|
2102
|
+
</ion-toolbar>
|
|
2103
|
+
</ion-header>
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
2107
|
+
@if (showRefresh() && isNativePlatform()) {
|
|
2108
|
+
<ion-refresher
|
|
2109
|
+
slot="fixed"
|
|
2110
|
+
(ionRefresh)="handleRefresh($event)"
|
|
2111
|
+
[pullFactor]="0.4"
|
|
2112
|
+
[pullMin]="80"
|
|
2113
|
+
[pullMax]="240"
|
|
2114
|
+
closeDuration="600ms">
|
|
2115
|
+
<ion-refresher-content
|
|
2116
|
+
pullingIcon="remixArrowDownS"
|
|
2117
|
+
refreshingSpinner="lines">
|
|
2118
|
+
</ion-refresher-content>
|
|
2119
|
+
</ion-refresher>
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
<!-- Expandable header section (purple background) -->
|
|
2123
|
+
<div class="header-expandable">
|
|
2124
|
+
<div class="header-expandable-inner">
|
|
2125
|
+
<div class="header-expandable__text">
|
|
2126
|
+
<h1 class="header-expandable__title">{{ headerTitle() || title() }}</h1>
|
|
2127
|
+
@if (headerSubtitle()) {
|
|
2128
|
+
<p class="header-expandable__subtitle">{{ headerSubtitle() }}</p>
|
|
2129
|
+
}
|
|
2084
2130
|
</div>
|
|
2085
2131
|
|
|
2086
|
-
<!--
|
|
2087
|
-
<
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
<div class="swatch-label">Primary Content</div>
|
|
2097
|
-
<div class="swatch-value">{{ whitelabelService.primaryContent() }}</div>
|
|
2098
|
-
</div>
|
|
2099
|
-
<div class="swatch swatch--secondary-surface">
|
|
2100
|
-
<div class="swatch-label">Secondary Surface</div>
|
|
2101
|
-
<div class="swatch-value">{{ whitelabelService.secondarySurface() }}</div>
|
|
2102
|
-
</div>
|
|
2103
|
-
<div class="swatch swatch--secondary-content">
|
|
2104
|
-
<div class="swatch-label">Secondary Content</div>
|
|
2105
|
-
<div class="swatch-value">{{ whitelabelService.secondaryContent() }}</div>
|
|
2106
|
-
</div>
|
|
2107
|
-
</div>
|
|
2108
|
-
|
|
2109
|
-
<div class="color-inputs">
|
|
2110
|
-
<div class="color-group-label">Primary</div>
|
|
2111
|
-
<div class="color-row">
|
|
2112
|
-
<label>Surface</label>
|
|
2113
|
-
<input
|
|
2114
|
-
type="color"
|
|
2115
|
-
[(ngModel)]="customPrimarySurface"
|
|
2116
|
-
(change)="applyCustomColors()"
|
|
2117
|
-
/>
|
|
2118
|
-
<input
|
|
2119
|
-
type="text"
|
|
2120
|
-
[(ngModel)]="customPrimarySurface"
|
|
2121
|
-
(change)="applyCustomColors()"
|
|
2122
|
-
/>
|
|
2123
|
-
</div>
|
|
2124
|
-
<div class="color-row">
|
|
2125
|
-
<label>Content</label>
|
|
2126
|
-
<input
|
|
2127
|
-
type="color"
|
|
2128
|
-
[(ngModel)]="customPrimaryContent"
|
|
2129
|
-
(change)="applyCustomColors()"
|
|
2130
|
-
/>
|
|
2131
|
-
<input
|
|
2132
|
-
type="text"
|
|
2133
|
-
[(ngModel)]="customPrimaryContent"
|
|
2134
|
-
(change)="applyCustomColors()"
|
|
2135
|
-
/>
|
|
2136
|
-
</div>
|
|
2137
|
-
|
|
2138
|
-
<div class="color-group-label">Secondary</div>
|
|
2139
|
-
<div class="color-row">
|
|
2140
|
-
<label>Surface</label>
|
|
2141
|
-
<input
|
|
2142
|
-
type="color"
|
|
2143
|
-
[(ngModel)]="customSecondarySurface"
|
|
2144
|
-
(change)="applyCustomColors()"
|
|
2145
|
-
/>
|
|
2146
|
-
<input
|
|
2147
|
-
type="text"
|
|
2148
|
-
[(ngModel)]="customSecondarySurface"
|
|
2149
|
-
(change)="applyCustomColors()"
|
|
2150
|
-
/>
|
|
2151
|
-
</div>
|
|
2152
|
-
<div class="color-row">
|
|
2153
|
-
<label>Content</label>
|
|
2154
|
-
<input
|
|
2155
|
-
type="color"
|
|
2156
|
-
[(ngModel)]="customSecondaryContent"
|
|
2157
|
-
(change)="applyCustomColors()"
|
|
2158
|
-
/>
|
|
2159
|
-
<input
|
|
2160
|
-
type="text"
|
|
2161
|
-
[(ngModel)]="customSecondaryContent"
|
|
2162
|
-
(change)="applyCustomColors()"
|
|
2163
|
-
/>
|
|
2164
|
-
</div>
|
|
2165
|
-
</div>
|
|
2166
|
-
</div>
|
|
2167
|
-
</div>
|
|
2132
|
+
<!-- Slot for custom header content (e.g., property tiles) -->
|
|
2133
|
+
<ng-content select="[header-content]"></ng-content>
|
|
2134
|
+
</div>
|
|
2135
|
+
</div>
|
|
2136
|
+
|
|
2137
|
+
<!-- Content wrapper -->
|
|
2138
|
+
<div class="content-wrapper">
|
|
2139
|
+
<div class="content-inner">
|
|
2140
|
+
<!-- Main page content -->
|
|
2141
|
+
<ng-content></ng-content>
|
|
2168
2142
|
</div>
|
|
2143
|
+
</div>
|
|
2169
2144
|
</ion-content>
|
|
2170
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100
|
|
2145
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;align-items:center;height:100%}:host ion-header{background:var(--color-brand-secondary);box-shadow:none;height:72px;min-height:72px;margin-top:var(--app-header-top-offset)}ion-header ion-toolbar{--background: var(--color-brand-secondary);--border-width: 0;--box-shadow: none;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 72px;height:72px;min-height:72px;padding:0}@media (min-width: 768px){ion-header{display:none;height:auto}}.header-home{display:flex;align-items:center;justify-content:space-between;padding:0 20px;background:var(--color-brand-secondary);height:72px}.header-home__title{position:absolute;left:50%;transform:translate(-50%) translateY(-100%);font-size:var(--font-size-base);font-weight:600;color:#fff;opacity:0;transition:transform .6s ease,opacity .6s ease;margin:0;padding:0;--color: white}.header-scrolled .header-home__title{opacity:1;transform:translate(-50%) translateY(0)}.header-home__actions{display:flex;align-items:center;gap:8px}.header-home__actions ds-avatar{cursor:pointer;-webkit-tap-highlight-color:transparent}.logomark{height:28px;width:auto;flex-shrink:0}@media (min-width: 768px){.header-home{padding:16px 24px}.logomark{height:32px}.header-home__title{display:none}}ion-content{--background: var(--color-brand-secondary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;border-radius:24px;overflow:hidden}ion-content::part(scroll){display:flex;flex-direction:column}.plt-ios ion-content{--background: var(--color-background-neutral-primary)}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;display:flex;flex-direction:column}ion-header[collapse=condense]{display:none}@media (min-width: 768px){ion-header[collapse=condense]{display:none}}ion-refresher{z-index:0}ion-refresher-content{--color: white}.header-expandable{background:var(--color-brand-secondary);padding:32px 20px 24px;color:var(--header-content-color, white);position:sticky;top:0;z-index:5;transition:opacity .1s ease-out,transform .1s ease-out}.header-expandable-inner{display:flex;flex-direction:column;gap:20px;max-width:640px;margin:0 auto}.header-expandable__text{margin-bottom:0}.header-expandable__title{font-size:var(--font-size-2xl);font-weight:600;color:var(--header-content-color, white);margin:0}.header-expandable__subtitle{font-size:var(--font-size-sm);font-weight:400;color:var(--header-content-color, white);opacity:.85;margin:0}@media (min-width: 768px){.header-expandable{padding:48px var(--content-padding-md)}.header-expandable__title{font-size:var(--font-size-3xl)}.header-expandable__subtitle{font-size:var(--font-size-base)}}@media (min-width: 992px){.header-expandable{padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.header-expandable{padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.header-expandable{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.header-expandable{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}.content-wrapper{position:relative;z-index:20;padding:0;flex:1;display:flex;flex-direction:column}@media (min-width: 768px){.content-wrapper{width:100%}}.content-inner{background:var(--color-background-neutral-primary);border-radius:24px 24px 0 0;transform:translateZ(0);will-change:transform;isolation:isolate;box-shadow:0 200vh 0 0 var(--color-background-neutral-primary);flex:1;padding:24px 20px 32px;padding-bottom:calc(var(--mobile-content-spacing) + var(--mobile-tab-bar-height) + env(safe-area-inset-bottom,0px))}@media (min-width: 768px){.content-inner{border-radius:16px 16px 0 0;padding:32px var(--content-padding-md)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}}@media (min-width: 992px){.content-inner{padding:32px var(--content-padding-lg)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2))}}@media (min-width: 1440px){.content-inner{padding:32px var(--content-padding-xl)!important;max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2))}}@media (min-width: 1768px){.content-inner{padding:32px var(--content-padding-2xl)!important}}@media (min-width: 1920px){.content-inner{padding:32px var(--content-padding-3xl)!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsLogoComponent, selector: "ds-logo", inputs: ["variant", "size", "customHeight", "customWidth"] }] });
|
|
2171
2146
|
}
|
|
2172
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
2147
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsMobilePageMainComponent, decorators: [{
|
|
2173
2148
|
type: Component,
|
|
2174
|
-
args: [{ selector: 'ds-
|
|
2149
|
+
args: [{ selector: 'ds-mobile-page-main', standalone: true, imports: [
|
|
2175
2150
|
CommonModule,
|
|
2176
|
-
|
|
2151
|
+
IonHeader,
|
|
2152
|
+
IonToolbar,
|
|
2153
|
+
IonTitle,
|
|
2177
2154
|
IonContent,
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
<
|
|
2187
|
-
|
|
2188
|
-
variant="
|
|
2189
|
-
size="lg"
|
|
2190
|
-
(click)="close()"
|
|
2191
|
-
class="close-button"
|
|
2192
|
-
aria-label="Close">
|
|
2193
|
-
</ds-icon-button>
|
|
2194
|
-
</div>
|
|
2195
|
-
</div>
|
|
2196
|
-
|
|
2197
|
-
<!-- Scrollable Content -->
|
|
2198
|
-
<ion-content [scrollY]="true" class="modal-content">
|
|
2199
|
-
<div class="demo-container">
|
|
2200
|
-
<!-- Theme Selection -->
|
|
2201
|
-
<div class="demo-section">
|
|
2202
|
-
<h2>Theme</h2>
|
|
2203
|
-
<div class="theme-buttons">
|
|
2204
|
-
<button class="theme-btn" (click)="applyDefaultTheme()" [class.active]="currentTheme === 'default'">
|
|
2205
|
-
Propbinder
|
|
2206
|
-
</button>
|
|
2207
|
-
<button class="theme-btn" (click)="applyCejTheme()" [class.active]="currentTheme === 'cej'">
|
|
2208
|
-
CEJ
|
|
2209
|
-
</button>
|
|
2210
|
-
<button class="theme-btn" (click)="applyPkaTheme()" [class.active]="currentTheme === 'pka'">
|
|
2211
|
-
PKA
|
|
2212
|
-
</button>
|
|
2213
|
-
<button class="theme-btn" (click)="applyClaveTheme()" [class.active]="currentTheme === 'clave'">
|
|
2214
|
-
Clave
|
|
2215
|
-
</button>
|
|
2216
|
-
</div>
|
|
2217
|
-
</div>
|
|
2155
|
+
IonRefresher,
|
|
2156
|
+
IonRefresherContent,
|
|
2157
|
+
DsAvatarComponent,
|
|
2158
|
+
DsLogoComponent
|
|
2159
|
+
], template: `
|
|
2160
|
+
<!-- Fixed header at top -->
|
|
2161
|
+
<ion-header>
|
|
2162
|
+
<ion-toolbar>
|
|
2163
|
+
<div class="header-home">
|
|
2164
|
+
<!-- Whitelabel Logomark -->
|
|
2165
|
+
<ds-logo variant="mark" size="lg" />
|
|
2218
2166
|
|
|
2219
|
-
<!--
|
|
2220
|
-
<
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2167
|
+
<!-- Title - fades in on scroll -->
|
|
2168
|
+
<ion-title class="header-home__title">{{ title() }}</ion-title>
|
|
2169
|
+
|
|
2170
|
+
<!-- Avatar -->
|
|
2171
|
+
<div class="header-home__actions">
|
|
2172
|
+
<ds-avatar
|
|
2173
|
+
[size]="'md'"
|
|
2174
|
+
[type]="avatarType()"
|
|
2175
|
+
[initials]="avatarInitials()"
|
|
2176
|
+
[src]="avatarSrc()"
|
|
2177
|
+
[iconName]="avatarIconName()"
|
|
2178
|
+
(click)="handleAvatarClick()"
|
|
2179
|
+
style="cursor: pointer;"
|
|
2180
|
+
/>
|
|
2181
|
+
</div>
|
|
2182
|
+
</div>
|
|
2183
|
+
</ion-toolbar>
|
|
2184
|
+
</ion-header>
|
|
2185
|
+
|
|
2186
|
+
<!-- Content with expandable header -->
|
|
2187
|
+
<ion-content [scrollEvents]="true" (ionScroll)="handleScroll($event)">
|
|
2188
|
+
<!-- Condensed header for Ionic scroll effects -->
|
|
2189
|
+
@if (showCondensedHeader()) {
|
|
2190
|
+
<ion-header collapse="condense">
|
|
2191
|
+
<ion-toolbar>
|
|
2192
|
+
<ion-title size="large">{{ title() }}</ion-title>
|
|
2193
|
+
</ion-toolbar>
|
|
2194
|
+
</ion-header>
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
2198
|
+
@if (showRefresh() && isNativePlatform()) {
|
|
2199
|
+
<ion-refresher
|
|
2200
|
+
slot="fixed"
|
|
2201
|
+
(ionRefresh)="handleRefresh($event)"
|
|
2202
|
+
[pullFactor]="0.4"
|
|
2203
|
+
[pullMin]="80"
|
|
2204
|
+
[pullMax]="240"
|
|
2205
|
+
closeDuration="600ms">
|
|
2206
|
+
<ion-refresher-content
|
|
2207
|
+
pullingIcon="remixArrowDownS"
|
|
2208
|
+
refreshingSpinner="lines">
|
|
2209
|
+
</ion-refresher-content>
|
|
2210
|
+
</ion-refresher>
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
<!-- Expandable header section (purple background) -->
|
|
2214
|
+
<div class="header-expandable">
|
|
2215
|
+
<div class="header-expandable-inner">
|
|
2216
|
+
<div class="header-expandable__text">
|
|
2217
|
+
<h1 class="header-expandable__title">{{ headerTitle() || title() }}</h1>
|
|
2218
|
+
@if (headerSubtitle()) {
|
|
2219
|
+
<p class="header-expandable__subtitle">{{ headerSubtitle() }}</p>
|
|
2220
|
+
}
|
|
2241
2221
|
</div>
|
|
2242
2222
|
|
|
2243
|
-
<!--
|
|
2244
|
-
<
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
<div class="swatch-label">Primary Content</div>
|
|
2254
|
-
<div class="swatch-value">{{ whitelabelService.primaryContent() }}</div>
|
|
2255
|
-
</div>
|
|
2256
|
-
<div class="swatch swatch--secondary-surface">
|
|
2257
|
-
<div class="swatch-label">Secondary Surface</div>
|
|
2258
|
-
<div class="swatch-value">{{ whitelabelService.secondarySurface() }}</div>
|
|
2259
|
-
</div>
|
|
2260
|
-
<div class="swatch swatch--secondary-content">
|
|
2261
|
-
<div class="swatch-label">Secondary Content</div>
|
|
2262
|
-
<div class="swatch-value">{{ whitelabelService.secondaryContent() }}</div>
|
|
2263
|
-
</div>
|
|
2264
|
-
</div>
|
|
2265
|
-
|
|
2266
|
-
<div class="color-inputs">
|
|
2267
|
-
<div class="color-group-label">Primary</div>
|
|
2268
|
-
<div class="color-row">
|
|
2269
|
-
<label>Surface</label>
|
|
2270
|
-
<input
|
|
2271
|
-
type="color"
|
|
2272
|
-
[(ngModel)]="customPrimarySurface"
|
|
2273
|
-
(change)="applyCustomColors()"
|
|
2274
|
-
/>
|
|
2275
|
-
<input
|
|
2276
|
-
type="text"
|
|
2277
|
-
[(ngModel)]="customPrimarySurface"
|
|
2278
|
-
(change)="applyCustomColors()"
|
|
2279
|
-
/>
|
|
2280
|
-
</div>
|
|
2281
|
-
<div class="color-row">
|
|
2282
|
-
<label>Content</label>
|
|
2283
|
-
<input
|
|
2284
|
-
type="color"
|
|
2285
|
-
[(ngModel)]="customPrimaryContent"
|
|
2286
|
-
(change)="applyCustomColors()"
|
|
2287
|
-
/>
|
|
2288
|
-
<input
|
|
2289
|
-
type="text"
|
|
2290
|
-
[(ngModel)]="customPrimaryContent"
|
|
2291
|
-
(change)="applyCustomColors()"
|
|
2292
|
-
/>
|
|
2293
|
-
</div>
|
|
2294
|
-
|
|
2295
|
-
<div class="color-group-label">Secondary</div>
|
|
2296
|
-
<div class="color-row">
|
|
2297
|
-
<label>Surface</label>
|
|
2298
|
-
<input
|
|
2299
|
-
type="color"
|
|
2300
|
-
[(ngModel)]="customSecondarySurface"
|
|
2301
|
-
(change)="applyCustomColors()"
|
|
2302
|
-
/>
|
|
2303
|
-
<input
|
|
2304
|
-
type="text"
|
|
2305
|
-
[(ngModel)]="customSecondarySurface"
|
|
2306
|
-
(change)="applyCustomColors()"
|
|
2307
|
-
/>
|
|
2308
|
-
</div>
|
|
2309
|
-
<div class="color-row">
|
|
2310
|
-
<label>Content</label>
|
|
2311
|
-
<input
|
|
2312
|
-
type="color"
|
|
2313
|
-
[(ngModel)]="customSecondaryContent"
|
|
2314
|
-
(change)="applyCustomColors()"
|
|
2315
|
-
/>
|
|
2316
|
-
<input
|
|
2317
|
-
type="text"
|
|
2318
|
-
[(ngModel)]="customSecondaryContent"
|
|
2319
|
-
(change)="applyCustomColors()"
|
|
2320
|
-
/>
|
|
2321
|
-
</div>
|
|
2322
|
-
</div>
|
|
2323
|
-
</div>
|
|
2324
|
-
</div>
|
|
2223
|
+
<!-- Slot for custom header content (e.g., property tiles) -->
|
|
2224
|
+
<ng-content select="[header-content]"></ng-content>
|
|
2225
|
+
</div>
|
|
2226
|
+
</div>
|
|
2227
|
+
|
|
2228
|
+
<!-- Content wrapper -->
|
|
2229
|
+
<div class="content-wrapper">
|
|
2230
|
+
<div class="content-inner">
|
|
2231
|
+
<!-- Main page content -->
|
|
2232
|
+
<ng-content></ng-content>
|
|
2325
2233
|
</div>
|
|
2234
|
+
</div>
|
|
2326
2235
|
</ion-content>
|
|
2327
|
-
`, styles: [":host{display:flex;flex-direction:column;height:100
|
|
2328
|
-
}] }
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
*
|
|
2333
|
-
* Service for displaying the whitelabel demo in a full-screen modal.
|
|
2334
|
-
* Built on Ionic's modal system with native gestures and animations.
|
|
2335
|
-
*
|
|
2336
|
-
* @example
|
|
2337
|
-
* ```typescript
|
|
2338
|
-
* constructor(private whitelabelModal: WhitelabelDemoModalService) {}
|
|
2339
|
-
*
|
|
2340
|
-
* async openDemo() {
|
|
2341
|
-
* await this.whitelabelModal.open();
|
|
2342
|
-
* }
|
|
2343
|
-
* ```
|
|
2344
|
-
*/
|
|
2345
|
-
class WhitelabelDemoModalService {
|
|
2346
|
-
modalController;
|
|
2347
|
-
constructor(modalController) {
|
|
2348
|
-
this.modalController = modalController;
|
|
2349
|
-
}
|
|
2350
|
-
/**
|
|
2351
|
-
* Open the whitelabel demo modal
|
|
2352
|
-
*
|
|
2353
|
-
* @returns Promise that resolves when the modal is presented
|
|
2354
|
-
*/
|
|
2355
|
-
async open() {
|
|
2356
|
-
try {
|
|
2357
|
-
console.log('[WhitelabelDemoModal] Opening...');
|
|
2358
|
-
const modal = await this.modalController.create({
|
|
2359
|
-
component: WhitelabelDemoModalComponent,
|
|
2360
|
-
cssClass: 'ds-whitelabel-demo-modal',
|
|
2361
|
-
mode: 'ios',
|
|
2362
|
-
presentingElement: document.querySelector('ion-router-outlet') || undefined,
|
|
2363
|
-
backdropDismiss: true,
|
|
2364
|
-
showBackdrop: true,
|
|
2365
|
-
animated: true,
|
|
2366
|
-
keyboardClose: true
|
|
2367
|
-
});
|
|
2368
|
-
console.log('[WhitelabelDemoModal] Modal created, presenting...');
|
|
2369
|
-
await modal.present();
|
|
2370
|
-
console.log('[WhitelabelDemoModal] Modal presented');
|
|
2371
|
-
}
|
|
2372
|
-
catch (error) {
|
|
2373
|
-
console.error('[WhitelabelDemoModal] Error opening modal:', error);
|
|
2374
|
-
throw error;
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
/**
|
|
2378
|
-
* Close the currently open whitelabel demo modal
|
|
2379
|
-
*
|
|
2380
|
-
* @param data Optional data to pass back when dismissing
|
|
2381
|
-
* @returns Promise that resolves when the modal is dismissed
|
|
2382
|
-
*/
|
|
2383
|
-
async close(data) {
|
|
2384
|
-
return this.modalController.dismiss(data);
|
|
2385
|
-
}
|
|
2386
|
-
/**
|
|
2387
|
-
* Get the top-most modal if one exists
|
|
2388
|
-
*
|
|
2389
|
-
* @returns Promise that resolves to the modal element or undefined
|
|
2390
|
-
*/
|
|
2391
|
-
async getTop() {
|
|
2392
|
-
return this.modalController.getTop();
|
|
2393
|
-
}
|
|
2394
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2395
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalService, providedIn: 'root' });
|
|
2396
|
-
}
|
|
2397
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalService, decorators: [{
|
|
2398
|
-
type: Injectable,
|
|
2399
|
-
args: [{
|
|
2400
|
-
providedIn: 'root'
|
|
2401
|
-
}]
|
|
2402
|
-
}], ctorParameters: () => [{ type: i1.ModalController }] });
|
|
2236
|
+
`, styles: [":host{display:flex;flex-direction:column;align-items:center;height:100%}:host ion-header{background:var(--color-brand-secondary);box-shadow:none;height:72px;min-height:72px;margin-top:var(--app-header-top-offset)}ion-header ion-toolbar{--background: var(--color-brand-secondary);--border-width: 0;--box-shadow: none;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 72px;height:72px;min-height:72px;padding:0}@media (min-width: 768px){ion-header{display:none;height:auto}}.header-home{display:flex;align-items:center;justify-content:space-between;padding:0 20px;background:var(--color-brand-secondary);height:72px}.header-home__title{position:absolute;left:50%;transform:translate(-50%) translateY(-100%);font-size:var(--font-size-base);font-weight:600;color:#fff;opacity:0;transition:transform .6s ease,opacity .6s ease;margin:0;padding:0;--color: white}.header-scrolled .header-home__title{opacity:1;transform:translate(-50%) translateY(0)}.header-home__actions{display:flex;align-items:center;gap:8px}.header-home__actions ds-avatar{cursor:pointer;-webkit-tap-highlight-color:transparent}.logomark{height:28px;width:auto;flex-shrink:0}@media (min-width: 768px){.header-home{padding:16px 24px}.logomark{height:32px}.header-home__title{display:none}}ion-content{--background: var(--color-brand-secondary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;border-radius:24px;overflow:hidden}ion-content::part(scroll){display:flex;flex-direction:column}.plt-ios ion-content{--background: var(--color-background-neutral-primary)}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;display:flex;flex-direction:column}ion-header[collapse=condense]{display:none}@media (min-width: 768px){ion-header[collapse=condense]{display:none}}ion-refresher{z-index:0}ion-refresher-content{--color: white}.header-expandable{background:var(--color-brand-secondary);padding:32px 20px 24px;color:var(--header-content-color, white);position:sticky;top:0;z-index:5;transition:opacity .1s ease-out,transform .1s ease-out}.header-expandable-inner{display:flex;flex-direction:column;gap:20px;max-width:640px;margin:0 auto}.header-expandable__text{margin-bottom:0}.header-expandable__title{font-size:var(--font-size-2xl);font-weight:600;color:var(--header-content-color, white);margin:0}.header-expandable__subtitle{font-size:var(--font-size-sm);font-weight:400;color:var(--header-content-color, white);opacity:.85;margin:0}@media (min-width: 768px){.header-expandable{padding:48px var(--content-padding-md)}.header-expandable__title{font-size:var(--font-size-3xl)}.header-expandable__subtitle{font-size:var(--font-size-base)}}@media (min-width: 992px){.header-expandable{padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.header-expandable{padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.header-expandable{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.header-expandable{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}.content-wrapper{position:relative;z-index:20;padding:0;flex:1;display:flex;flex-direction:column}@media (min-width: 768px){.content-wrapper{width:100%}}.content-inner{background:var(--color-background-neutral-primary);border-radius:24px 24px 0 0;transform:translateZ(0);will-change:transform;isolation:isolate;box-shadow:0 200vh 0 0 var(--color-background-neutral-primary);flex:1;padding:24px 20px 32px;padding-bottom:calc(var(--mobile-content-spacing) + var(--mobile-tab-bar-height) + env(safe-area-inset-bottom,0px))}@media (min-width: 768px){.content-inner{border-radius:16px 16px 0 0;padding:32px var(--content-padding-md)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}}@media (min-width: 992px){.content-inner{padding:32px var(--content-padding-lg)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2))}}@media (min-width: 1440px){.content-inner{padding:32px var(--content-padding-xl)!important;max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2))}}@media (min-width: 1768px){.content-inner{padding:32px var(--content-padding-2xl)!important}}@media (min-width: 1920px){.content-inner{padding:32px var(--content-padding-3xl)!important}}\n"] }]
|
|
2237
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { ionContent: [{
|
|
2238
|
+
type: ViewChild,
|
|
2239
|
+
args: [IonContent]
|
|
2240
|
+
}], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], headerTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerTitle", required: false }] }], headerSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerSubtitle", required: false }] }], avatarType: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarType", required: false }] }], avatarInitials: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarInitials", required: false }] }], avatarSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarSrc", required: false }] }], avatarIconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarIconName", required: false }] }], showRefresh: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRefresh", required: false }] }], showCondensedHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCondensedHeader", required: false }] }], scrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollThreshold", required: false }] }], headerFadeDistance: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerFadeDistance", required: false }] }], profileMenuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "profileMenuItems", required: false }] }], avatarClick: [{ type: i0.Output, args: ["avatarClick"] }], profileActionSelected: [{ type: i0.Output, args: ["profileActionSelected"] }], refresh: [{ type: i0.Output, args: ["refresh"] }], scroll: [{ type: i0.Output, args: ["scroll"] }] } });
|
|
2403
2241
|
|
|
2404
2242
|
/**
|
|
2405
|
-
*
|
|
2243
|
+
* DsMobilePageDetailsComponent
|
|
2406
2244
|
*
|
|
2407
|
-
* A
|
|
2408
|
-
* -
|
|
2409
|
-
* -
|
|
2410
|
-
* -
|
|
2411
|
-
* - Pull-to-refresh support
|
|
2412
|
-
* - Auto scroll title fade-in
|
|
2245
|
+
* A mobile page layout for detail/drill-down pages with:
|
|
2246
|
+
* - Back button header (mobile + desktop variants)
|
|
2247
|
+
* - White background content area
|
|
2248
|
+
* - Responsive padding
|
|
2413
2249
|
*
|
|
2414
2250
|
* @example
|
|
2415
2251
|
* ```html
|
|
2416
|
-
* <!-- Simple page -->
|
|
2417
|
-
* <ds-mobile-page-
|
|
2418
|
-
* title="
|
|
2419
|
-
*
|
|
2252
|
+
* <!-- Simple detail page -->
|
|
2253
|
+
* <ds-mobile-page-details
|
|
2254
|
+
* title="Property Details"
|
|
2255
|
+
* (back)="goBack()">
|
|
2420
2256
|
* <div class="page-content">
|
|
2421
2257
|
* <!-- Your content -->
|
|
2422
2258
|
* </div>
|
|
2423
|
-
* </ds-mobile-page-
|
|
2424
|
-
*
|
|
2425
|
-
* <!-- Page with custom header content -->
|
|
2426
|
-
* <ds-mobile-page-main
|
|
2427
|
-
* title="Home"
|
|
2428
|
-
* headerTitle="Welcome, Lars"
|
|
2429
|
-
* headerSubtitle="Your rental property at a glance."
|
|
2430
|
-
* [avatarInitials]="'L'">
|
|
2431
|
-
*
|
|
2432
|
-
* <div header-content class="property-tiles">
|
|
2433
|
-
* <!-- Custom header content like tiles -->
|
|
2434
|
-
* </div>
|
|
2259
|
+
* </ds-mobile-page-details>
|
|
2435
2260
|
*
|
|
2261
|
+
* <!-- With default back route -->
|
|
2262
|
+
* <ds-mobile-page-details
|
|
2263
|
+
* title="Invoice Details"
|
|
2264
|
+
* backRoute="/invoices">
|
|
2436
2265
|
* <div class="page-content">
|
|
2437
|
-
* <!--
|
|
2266
|
+
* <!-- Your content -->
|
|
2438
2267
|
* </div>
|
|
2439
|
-
* </ds-mobile-page-
|
|
2268
|
+
* </ds-mobile-page-details>
|
|
2440
2269
|
* ```
|
|
2441
2270
|
*/
|
|
2442
|
-
class
|
|
2271
|
+
class DsMobilePageDetailsComponent extends MobilePageBase {
|
|
2272
|
+
navCtrl;
|
|
2443
2273
|
elementRef;
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
modalController = inject(ModalController);
|
|
2448
|
-
router = inject(Router);
|
|
2449
|
-
whitelabelDemoModal = inject(WhitelabelDemoModalService);
|
|
2450
|
-
// Computed property to check if running on native platform
|
|
2451
|
-
isNativePlatform = computed(() => this.platform.is('ios') ||
|
|
2452
|
-
this.platform.is('android') ||
|
|
2453
|
-
this.platform.is('capacitor'), ...(ngDevMode ? [{ debugName: "isNativePlatform" }] : []));
|
|
2454
|
-
// Inputs - Title
|
|
2455
|
-
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : [])); // For fixed header title
|
|
2456
|
-
headerTitle = input('', ...(ngDevMode ? [{ debugName: "headerTitle" }] : [])); // Optional different title for expandable header
|
|
2457
|
-
headerSubtitle = input('', ...(ngDevMode ? [{ debugName: "headerSubtitle" }] : []));
|
|
2458
|
-
// Inputs - Avatar
|
|
2459
|
-
avatarType = input('initials', ...(ngDevMode ? [{ debugName: "avatarType" }] : []));
|
|
2460
|
-
avatarInitials = input('U', ...(ngDevMode ? [{ debugName: "avatarInitials" }] : []));
|
|
2461
|
-
avatarSrc = input('', ...(ngDevMode ? [{ debugName: "avatarSrc" }] : []));
|
|
2462
|
-
avatarIconName = input('remixUser3Line', ...(ngDevMode ? [{ debugName: "avatarIconName" }] : []));
|
|
2463
|
-
// Inputs - Features
|
|
2464
|
-
showRefresh = input(true, ...(ngDevMode ? [{ debugName: "showRefresh" }] : []));
|
|
2465
|
-
showCondensedHeader = input(true, ...(ngDevMode ? [{ debugName: "showCondensedHeader" }] : []));
|
|
2466
|
-
scrollThreshold = input(160, ...(ngDevMode ? [{ debugName: "scrollThreshold" }] : [])); // Pixels to scroll before title appears
|
|
2467
|
-
headerFadeDistance = input(150, ...(ngDevMode ? [{ debugName: "headerFadeDistance" }] : [])); // Distance over which header fades out
|
|
2274
|
+
// Inputs
|
|
2275
|
+
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
2276
|
+
backRoute = input('', ...(ngDevMode ? [{ debugName: "backRoute" }] : [])); // Optional default back route
|
|
2468
2277
|
// Outputs
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
scroll = output();
|
|
2472
|
-
constructor(elementRef) {
|
|
2278
|
+
back = output();
|
|
2279
|
+
constructor(navCtrl, elementRef) {
|
|
2473
2280
|
super();
|
|
2281
|
+
this.navCtrl = navCtrl;
|
|
2474
2282
|
this.elementRef = elementRef;
|
|
2475
2283
|
}
|
|
2476
|
-
ngAfterViewInit() {
|
|
2477
|
-
// Initial setup if needed
|
|
2478
|
-
}
|
|
2479
2284
|
/**
|
|
2480
|
-
* Handle
|
|
2285
|
+
* Handle back navigation
|
|
2286
|
+
*
|
|
2287
|
+
* By default, navigates using the provided backRoute or browser back.
|
|
2288
|
+
* Parent components can listen to the (back) event to override this behavior.
|
|
2289
|
+
*
|
|
2290
|
+
* @example
|
|
2291
|
+
* ```html
|
|
2292
|
+
* <!-- Default behavior: uses backRoute or browser back -->
|
|
2293
|
+
* <ds-mobile-page-details
|
|
2294
|
+
* title="Details"
|
|
2295
|
+
* backRoute="/home">
|
|
2296
|
+
* </ds-mobile-page-details>
|
|
2297
|
+
*
|
|
2298
|
+
* <!-- Custom behavior: parent handles navigation -->
|
|
2299
|
+
* <ds-mobile-page-details
|
|
2300
|
+
* title="Details"
|
|
2301
|
+
* (back)="customBackHandler()">
|
|
2302
|
+
* </ds-mobile-page-details>
|
|
2303
|
+
* ```
|
|
2481
2304
|
*/
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
{
|
|
2491
|
-
actions: [
|
|
2492
|
-
{
|
|
2493
|
-
action: 'profile',
|
|
2494
|
-
title: 'Min profil',
|
|
2495
|
-
icon: 'remixUser3Line',
|
|
2496
|
-
destructive: false
|
|
2497
|
-
},
|
|
2498
|
-
{
|
|
2499
|
-
action: 'settings',
|
|
2500
|
-
title: 'Indstillinger',
|
|
2501
|
-
icon: 'remixSettings3Line',
|
|
2502
|
-
destructive: false
|
|
2503
|
-
},
|
|
2504
|
-
{
|
|
2505
|
-
action: 'whitelabel-demo',
|
|
2506
|
-
title: 'Whitelabel Demo',
|
|
2507
|
-
icon: 'remixPaletteLine',
|
|
2508
|
-
destructive: false
|
|
2509
|
-
}
|
|
2510
|
-
]
|
|
2511
|
-
},
|
|
2512
|
-
{
|
|
2513
|
-
actions: [
|
|
2514
|
-
{
|
|
2515
|
-
action: 'logout',
|
|
2516
|
-
title: 'Log ud',
|
|
2517
|
-
icon: 'remixLogoutBoxLine',
|
|
2518
|
-
destructive: true
|
|
2519
|
-
}
|
|
2520
|
-
]
|
|
2521
|
-
}
|
|
2522
|
-
]
|
|
2523
|
-
},
|
|
2524
|
-
// Auto-height: no breakpoints, no handle
|
|
2525
|
-
cssClass: 'ds-bottom-sheet auto-height'
|
|
2526
|
-
});
|
|
2527
|
-
await sheet.present();
|
|
2528
|
-
const result = await sheet.onWillDismiss();
|
|
2529
|
-
if (result.data?.action) {
|
|
2530
|
-
console.log('Profile action selected:', result.data.action);
|
|
2531
|
-
switch (result.data.action) {
|
|
2532
|
-
case 'logout':
|
|
2533
|
-
console.log('Logging out...');
|
|
2534
|
-
// TODO: Implement logout logic
|
|
2535
|
-
break;
|
|
2536
|
-
case 'profile':
|
|
2537
|
-
console.log('Opening profile...');
|
|
2538
|
-
// TODO: Navigate to profile page
|
|
2539
|
-
break;
|
|
2540
|
-
case 'settings':
|
|
2541
|
-
console.log('Opening settings...');
|
|
2542
|
-
// TODO: Navigate to settings page
|
|
2543
|
-
break;
|
|
2544
|
-
case 'whitelabel-demo':
|
|
2545
|
-
console.log('Whitelabel demo selected');
|
|
2546
|
-
await this.whitelabelDemoModal.open();
|
|
2547
|
-
break;
|
|
2548
|
-
}
|
|
2549
|
-
}
|
|
2550
|
-
}
|
|
2551
|
-
/**
|
|
2552
|
-
* Handle scroll events
|
|
2553
|
-
* - Shows title in fixed header when scrolled past threshold
|
|
2554
|
-
* - Fades out expandable header content based on scroll position
|
|
2555
|
-
* - Emits scroll event for custom handling
|
|
2556
|
-
*/
|
|
2557
|
-
handleScroll(event) {
|
|
2558
|
-
const scrollTop = event.detail.scrollTop;
|
|
2559
|
-
const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');
|
|
2560
|
-
const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');
|
|
2561
|
-
// Show title in fixed header when scrolled past threshold
|
|
2562
|
-
if (scrollTop > this.scrollThreshold()) {
|
|
2563
|
-
header?.classList.add('header-scrolled');
|
|
2305
|
+
handleBack() {
|
|
2306
|
+
// Add class to trigger reverse animation
|
|
2307
|
+
this.elementRef.nativeElement.classList.add('navigating-back');
|
|
2308
|
+
// Emit event for parent to optionally handle
|
|
2309
|
+
this.back.emit();
|
|
2310
|
+
// Default behavior: navigate using backRoute or browser back
|
|
2311
|
+
if (this.backRoute()) {
|
|
2312
|
+
this.navCtrl.navigateBack(this.backRoute());
|
|
2564
2313
|
}
|
|
2565
2314
|
else {
|
|
2566
|
-
|
|
2567
|
-
}
|
|
2568
|
-
// Fade out header-expandable content based on scroll
|
|
2569
|
-
if (headerExpandable) {
|
|
2570
|
-
const fadeDistance = this.headerFadeDistance();
|
|
2571
|
-
const fadeProgress = Math.min(scrollTop / fadeDistance, 1);
|
|
2572
|
-
// Calculate opacity (1 to 0)
|
|
2573
|
-
const opacity = 1 - fadeProgress;
|
|
2574
|
-
// Calculate transform (0px to -20px upward)
|
|
2575
|
-
const translateY = fadeProgress * -20;
|
|
2576
|
-
// Apply styles
|
|
2577
|
-
headerExpandable.style.opacity = opacity.toString();
|
|
2578
|
-
headerExpandable.style.transform = `translateY(${translateY}px)`;
|
|
2579
|
-
}
|
|
2580
|
-
this.scroll.emit(event);
|
|
2581
|
-
}
|
|
2582
|
-
/**
|
|
2583
|
-
* Handle pull-to-refresh
|
|
2584
|
-
* Emits refresh event - parent should call event.target.complete()
|
|
2585
|
-
*/
|
|
2586
|
-
async handleRefresh(event) {
|
|
2587
|
-
// Haptic feedback for pull-to-refresh
|
|
2588
|
-
try {
|
|
2589
|
-
await Haptics.impact({ style: ImpactStyle.Medium });
|
|
2590
|
-
}
|
|
2591
|
-
catch {
|
|
2592
|
-
// Fallback to Web Vibration API if Capacitor Haptics is not available
|
|
2593
|
-
if ('vibrate' in navigator) {
|
|
2594
|
-
navigator.vibrate(50);
|
|
2595
|
-
}
|
|
2315
|
+
this.navCtrl.back();
|
|
2596
2316
|
}
|
|
2597
|
-
this.refresh.emit(event);
|
|
2598
2317
|
}
|
|
2599
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
2600
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
2601
|
-
<!--
|
|
2318
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsMobilePageDetailsComponent, deps: [{ token: i1.NavController }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2319
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.14", type: DsMobilePageDetailsComponent, isStandalone: true, selector: "ds-mobile-page-details", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, backRoute: { classPropertyName: "backRoute", publicName: "backRoute", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { back: "back" }, usesInheritance: true, ngImport: i0, template: `
|
|
2320
|
+
<!-- Mobile header - hidden on desktop -->
|
|
2602
2321
|
<ion-header>
|
|
2603
2322
|
<ion-toolbar>
|
|
2604
|
-
<div class="header-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
<ion-title class="header-home__title">{{ title() }}</ion-title>
|
|
2610
|
-
|
|
2611
|
-
<!-- Avatar -->
|
|
2612
|
-
<div class="header-home__actions">
|
|
2613
|
-
<ds-avatar
|
|
2614
|
-
[size]="'md'"
|
|
2615
|
-
[type]="avatarType()"
|
|
2616
|
-
[initials]="avatarInitials()"
|
|
2617
|
-
[src]="avatarSrc()"
|
|
2618
|
-
[iconName]="avatarIconName()"
|
|
2619
|
-
(click)="handleAvatarClick()"
|
|
2620
|
-
style="cursor: pointer;"
|
|
2621
|
-
/>
|
|
2622
|
-
</div>
|
|
2323
|
+
<div class="header-back">
|
|
2324
|
+
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2325
|
+
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2326
|
+
</button>
|
|
2327
|
+
<h1 class="header-title">{{ title() }}</h1>
|
|
2623
2328
|
</div>
|
|
2624
2329
|
</ion-toolbar>
|
|
2625
2330
|
</ion-header>
|
|
2626
2331
|
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
</ion-toolbar>
|
|
2635
|
-
</ion-header>
|
|
2636
|
-
}
|
|
2637
|
-
|
|
2638
|
-
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
2639
|
-
@if (showRefresh() && isNativePlatform()) {
|
|
2640
|
-
<ion-refresher
|
|
2641
|
-
slot="fixed"
|
|
2642
|
-
(ionRefresh)="handleRefresh($event)"
|
|
2643
|
-
[pullFactor]="0.4"
|
|
2644
|
-
[pullMin]="80"
|
|
2645
|
-
[pullMax]="240"
|
|
2646
|
-
closeDuration="600ms">
|
|
2647
|
-
<ion-refresher-content
|
|
2648
|
-
pullingIcon="remixArrowDownS"
|
|
2649
|
-
refreshingSpinner="lines">
|
|
2650
|
-
</ion-refresher-content>
|
|
2651
|
-
</ion-refresher>
|
|
2652
|
-
}
|
|
2653
|
-
|
|
2654
|
-
<!-- Expandable header section (purple background) -->
|
|
2655
|
-
<div class="header-expandable">
|
|
2656
|
-
<div class="header-expandable-inner">
|
|
2657
|
-
<div class="header-expandable__text">
|
|
2658
|
-
<h1 class="header-expandable__title">{{ headerTitle() || title() }}</h1>
|
|
2659
|
-
@if (headerSubtitle()) {
|
|
2660
|
-
<p class="header-expandable__subtitle">{{ headerSubtitle() }}</p>
|
|
2661
|
-
}
|
|
2662
|
-
</div>
|
|
2663
|
-
|
|
2664
|
-
<!-- Slot for custom header content (e.g., property tiles) -->
|
|
2665
|
-
<ng-content select="[header-content]"></ng-content>
|
|
2666
|
-
</div>
|
|
2332
|
+
<ion-content>
|
|
2333
|
+
<!-- Desktop header above content -->
|
|
2334
|
+
<div class="desktop-header">
|
|
2335
|
+
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2336
|
+
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2337
|
+
</button>
|
|
2338
|
+
<h1>{{ title() }}</h1>
|
|
2667
2339
|
</div>
|
|
2668
2340
|
|
|
2669
|
-
<!-- Content
|
|
2670
|
-
<div class="content
|
|
2671
|
-
<
|
|
2672
|
-
<!-- Main page content -->
|
|
2673
|
-
<ng-content></ng-content>
|
|
2674
|
-
</div>
|
|
2341
|
+
<!-- Content area -->
|
|
2342
|
+
<div class="detail-content">
|
|
2343
|
+
<ng-content></ng-content>
|
|
2675
2344
|
</div>
|
|
2676
2345
|
</ion-content>
|
|
2677
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;
|
|
2346
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%}ion-header{background:var(--color-brand-secondary);box-shadow:none;height:64px}ion-header ion-toolbar{--background: var(--color-brand-secondary);--border-width: 0;--box-shadow: none;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 64px;height:100%;min-height:64px;padding:0}ion-header ion-toolbar::part(native){height:100%;min-height:64px;padding:0}@media (min-width: 768px){ion-header{display:none}}.header-back{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:var(--color-brand-secondary);position:relative;height:100%;min-height:64px}.header-back .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;transition:opacity var(--transition-duration-fast) var(--ease-smooth);z-index:10}.header-back .back-button:hover{opacity:.8}.header-back .back-button:active{opacity:.6}.header-back .header-title{position:absolute;left:50%;transform:translate(-50%);font-size:var(--font-size-base);font-weight:600;color:#fff;margin:0}.desktop-header{display:none}@media (min-width: 768px){.desktop-header{display:flex;align-items:center;gap:16px;padding:32px var(--content-padding-md) 24px var(--content-padding-md);max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}.desktop-header .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-color-default-primary);transition:opacity var(--transition-duration-fast) var(--ease-smooth)}.desktop-header .back-button:hover{opacity:.8}.desktop-header .back-button:active{opacity:.6}.desktop-header h1{font-size:var(--font-size-2xl);font-weight:600;margin:0;color:var(--text-color-default-primary)}}@media (min-width: 992px){.desktop-header{max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.desktop-header{max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2));padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.desktop-header{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.desktop-header{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}ion-content{--background: var(--color-background-neutral-primary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;overflow:hidden}@media (max-width: 767px){ion-content{border-radius:24px 24px 36px 36px;animation:bottomRadiusOut .6s ease .3s forwards}:host(.navigating-back) ion-content{border-radius:24px 24px 0 0;animation:bottomRadiusIn .8s cubic-bezier(.36,.66,.04,1) forwards!important}}@keyframes bottomRadiusOut{0%{border-radius:24px 24px 36px 36px}to{border-radius:24px 24px 0 0}}@keyframes bottomRadiusIn{0%{border-radius:24px 24px 0 0}to{border-radius:24px 24px 36px 36px}}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0;animation:none}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;overscroll-behavior-y:none}.detail-content{padding:24px 20px 32px}@media (min-width: 768px){.detail-content{padding:32px var(--content-padding-md)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}}@media (min-width: 992px){.detail-content{padding:32px var(--content-padding-lg)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2))}}@media (min-width: 1440px){.detail-content{padding:32px var(--content-padding-xl)!important;max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2))}}@media (min-width: 1768px){.detail-content{padding:32px var(--content-padding-2xl)!important}}@media (min-width: 1920px){.detail-content{padding:32px var(--content-padding-3xl)!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
|
|
2678
2347
|
}
|
|
2679
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
2348
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsMobilePageDetailsComponent, decorators: [{
|
|
2680
2349
|
type: Component,
|
|
2681
|
-
args: [{ selector: 'ds-mobile-page-
|
|
2350
|
+
args: [{ selector: 'ds-mobile-page-details', standalone: true, imports: [
|
|
2682
2351
|
CommonModule,
|
|
2683
2352
|
IonHeader,
|
|
2684
2353
|
IonToolbar,
|
|
2685
|
-
IonTitle,
|
|
2686
2354
|
IonContent,
|
|
2687
|
-
|
|
2688
|
-
IonRefresherContent,
|
|
2689
|
-
DsAvatarComponent,
|
|
2690
|
-
DsLogoComponent
|
|
2355
|
+
DsIconComponent
|
|
2691
2356
|
], template: `
|
|
2692
|
-
<!--
|
|
2357
|
+
<!-- Mobile header - hidden on desktop -->
|
|
2693
2358
|
<ion-header>
|
|
2694
2359
|
<ion-toolbar>
|
|
2695
|
-
<div class="header-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
<ion-title class="header-home__title">{{ title() }}</ion-title>
|
|
2701
|
-
|
|
2702
|
-
<!-- Avatar -->
|
|
2703
|
-
<div class="header-home__actions">
|
|
2704
|
-
<ds-avatar
|
|
2705
|
-
[size]="'md'"
|
|
2706
|
-
[type]="avatarType()"
|
|
2707
|
-
[initials]="avatarInitials()"
|
|
2708
|
-
[src]="avatarSrc()"
|
|
2709
|
-
[iconName]="avatarIconName()"
|
|
2710
|
-
(click)="handleAvatarClick()"
|
|
2711
|
-
style="cursor: pointer;"
|
|
2712
|
-
/>
|
|
2713
|
-
</div>
|
|
2360
|
+
<div class="header-back">
|
|
2361
|
+
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2362
|
+
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2363
|
+
</button>
|
|
2364
|
+
<h1 class="header-title">{{ title() }}</h1>
|
|
2714
2365
|
</div>
|
|
2715
2366
|
</ion-toolbar>
|
|
2716
2367
|
</ion-header>
|
|
2717
2368
|
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
</ion-toolbar>
|
|
2726
|
-
</ion-header>
|
|
2727
|
-
}
|
|
2728
|
-
|
|
2729
|
-
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
2730
|
-
@if (showRefresh() && isNativePlatform()) {
|
|
2731
|
-
<ion-refresher
|
|
2732
|
-
slot="fixed"
|
|
2733
|
-
(ionRefresh)="handleRefresh($event)"
|
|
2734
|
-
[pullFactor]="0.4"
|
|
2735
|
-
[pullMin]="80"
|
|
2736
|
-
[pullMax]="240"
|
|
2737
|
-
closeDuration="600ms">
|
|
2738
|
-
<ion-refresher-content
|
|
2739
|
-
pullingIcon="remixArrowDownS"
|
|
2740
|
-
refreshingSpinner="lines">
|
|
2741
|
-
</ion-refresher-content>
|
|
2742
|
-
</ion-refresher>
|
|
2743
|
-
}
|
|
2744
|
-
|
|
2745
|
-
<!-- Expandable header section (purple background) -->
|
|
2746
|
-
<div class="header-expandable">
|
|
2747
|
-
<div class="header-expandable-inner">
|
|
2748
|
-
<div class="header-expandable__text">
|
|
2749
|
-
<h1 class="header-expandable__title">{{ headerTitle() || title() }}</h1>
|
|
2750
|
-
@if (headerSubtitle()) {
|
|
2751
|
-
<p class="header-expandable__subtitle">{{ headerSubtitle() }}</p>
|
|
2752
|
-
}
|
|
2753
|
-
</div>
|
|
2754
|
-
|
|
2755
|
-
<!-- Slot for custom header content (e.g., property tiles) -->
|
|
2756
|
-
<ng-content select="[header-content]"></ng-content>
|
|
2757
|
-
</div>
|
|
2369
|
+
<ion-content>
|
|
2370
|
+
<!-- Desktop header above content -->
|
|
2371
|
+
<div class="desktop-header">
|
|
2372
|
+
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2373
|
+
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2374
|
+
</button>
|
|
2375
|
+
<h1>{{ title() }}</h1>
|
|
2758
2376
|
</div>
|
|
2759
2377
|
|
|
2760
|
-
<!-- Content
|
|
2761
|
-
<div class="content
|
|
2762
|
-
<
|
|
2763
|
-
<!-- Main page content -->
|
|
2764
|
-
<ng-content></ng-content>
|
|
2765
|
-
</div>
|
|
2378
|
+
<!-- Content area -->
|
|
2379
|
+
<div class="detail-content">
|
|
2380
|
+
<ng-content></ng-content>
|
|
2766
2381
|
</div>
|
|
2767
2382
|
</ion-content>
|
|
2768
|
-
`, styles: [":host{display:flex;flex-direction:column;
|
|
2769
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: {
|
|
2770
|
-
type: ViewChild,
|
|
2771
|
-
args: [IonContent]
|
|
2772
|
-
}], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], headerTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerTitle", required: false }] }], headerSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerSubtitle", required: false }] }], avatarType: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarType", required: false }] }], avatarInitials: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarInitials", required: false }] }], avatarSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarSrc", required: false }] }], avatarIconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarIconName", required: false }] }], showRefresh: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRefresh", required: false }] }], showCondensedHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCondensedHeader", required: false }] }], scrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollThreshold", required: false }] }], headerFadeDistance: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerFadeDistance", required: false }] }], avatarClick: [{ type: i0.Output, args: ["avatarClick"] }], refresh: [{ type: i0.Output, args: ["refresh"] }], scroll: [{ type: i0.Output, args: ["scroll"] }] } });
|
|
2383
|
+
`, styles: [":host{display:flex;flex-direction:column;height:100%}ion-header{background:var(--color-brand-secondary);box-shadow:none;height:64px}ion-header ion-toolbar{--background: var(--color-brand-secondary);--border-width: 0;--box-shadow: none;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 64px;height:100%;min-height:64px;padding:0}ion-header ion-toolbar::part(native){height:100%;min-height:64px;padding:0}@media (min-width: 768px){ion-header{display:none}}.header-back{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:var(--color-brand-secondary);position:relative;height:100%;min-height:64px}.header-back .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;transition:opacity var(--transition-duration-fast) var(--ease-smooth);z-index:10}.header-back .back-button:hover{opacity:.8}.header-back .back-button:active{opacity:.6}.header-back .header-title{position:absolute;left:50%;transform:translate(-50%);font-size:var(--font-size-base);font-weight:600;color:#fff;margin:0}.desktop-header{display:none}@media (min-width: 768px){.desktop-header{display:flex;align-items:center;gap:16px;padding:32px var(--content-padding-md) 24px var(--content-padding-md);max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}.desktop-header .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-color-default-primary);transition:opacity var(--transition-duration-fast) var(--ease-smooth)}.desktop-header .back-button:hover{opacity:.8}.desktop-header .back-button:active{opacity:.6}.desktop-header h1{font-size:var(--font-size-2xl);font-weight:600;margin:0;color:var(--text-color-default-primary)}}@media (min-width: 992px){.desktop-header{max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.desktop-header{max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2));padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.desktop-header{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.desktop-header{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}ion-content{--background: var(--color-background-neutral-primary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;overflow:hidden}@media (max-width: 767px){ion-content{border-radius:24px 24px 36px 36px;animation:bottomRadiusOut .6s ease .3s forwards}:host(.navigating-back) ion-content{border-radius:24px 24px 0 0;animation:bottomRadiusIn .8s cubic-bezier(.36,.66,.04,1) forwards!important}}@keyframes bottomRadiusOut{0%{border-radius:24px 24px 36px 36px}to{border-radius:24px 24px 0 0}}@keyframes bottomRadiusIn{0%{border-radius:24px 24px 0 0}to{border-radius:24px 24px 36px 36px}}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0;animation:none}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;overscroll-behavior-y:none}.detail-content{padding:24px 20px 32px}@media (min-width: 768px){.detail-content{padding:32px var(--content-padding-md)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}}@media (min-width: 992px){.detail-content{padding:32px var(--content-padding-lg)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2))}}@media (min-width: 1440px){.detail-content{padding:32px var(--content-padding-xl)!important;max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2))}}@media (min-width: 1768px){.detail-content{padding:32px var(--content-padding-2xl)!important}}@media (min-width: 1920px){.detail-content{padding:32px var(--content-padding-3xl)!important}}\n"] }]
|
|
2384
|
+
}], ctorParameters: () => [{ type: i1.NavController }, { type: i0.ElementRef }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], backRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "backRoute", required: false }] }], back: [{ type: i0.Output, args: ["back"] }] } });
|
|
2773
2385
|
|
|
2774
2386
|
/**
|
|
2775
|
-
*
|
|
2387
|
+
* DsMobileContentComponent
|
|
2776
2388
|
*
|
|
2777
|
-
*
|
|
2778
|
-
*
|
|
2779
|
-
* - White background content area
|
|
2780
|
-
* - Responsive padding
|
|
2781
|
-
*
|
|
2782
|
-
* @example
|
|
2783
|
-
* ```html
|
|
2784
|
-
* <!-- Simple detail page -->
|
|
2785
|
-
* <ds-mobile-page-details
|
|
2786
|
-
* title="Property Details"
|
|
2787
|
-
* (back)="goBack()">
|
|
2788
|
-
* <div class="page-content">
|
|
2789
|
-
* <!-- Your content -->
|
|
2790
|
-
* </div>
|
|
2791
|
-
* </ds-mobile-page-details>
|
|
2792
|
-
*
|
|
2793
|
-
* <!-- With default back route -->
|
|
2794
|
-
* <ds-mobile-page-details
|
|
2795
|
-
* title="Invoice Details"
|
|
2796
|
-
* backRoute="/invoices">
|
|
2797
|
-
* <div class="page-content">
|
|
2798
|
-
* <!-- Your content -->
|
|
2799
|
-
* </div>
|
|
2800
|
-
* </ds-mobile-page-details>
|
|
2801
|
-
* ```
|
|
2802
|
-
*/
|
|
2803
|
-
class DsMobilePageDetailsComponent extends MobilePageBase {
|
|
2804
|
-
navCtrl;
|
|
2805
|
-
elementRef;
|
|
2806
|
-
// Inputs
|
|
2807
|
-
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
2808
|
-
backRoute = input('', ...(ngDevMode ? [{ debugName: "backRoute" }] : [])); // Optional default back route
|
|
2809
|
-
// Outputs
|
|
2810
|
-
back = output();
|
|
2811
|
-
constructor(navCtrl, elementRef) {
|
|
2812
|
-
super();
|
|
2813
|
-
this.navCtrl = navCtrl;
|
|
2814
|
-
this.elementRef = elementRef;
|
|
2815
|
-
}
|
|
2816
|
-
/**
|
|
2817
|
-
* Handle back navigation
|
|
2818
|
-
*
|
|
2819
|
-
* By default, navigates using the provided backRoute or browser back.
|
|
2820
|
-
* Parent components can listen to the (back) event to override this behavior.
|
|
2821
|
-
*
|
|
2822
|
-
* @example
|
|
2823
|
-
* ```html
|
|
2824
|
-
* <!-- Default behavior: uses backRoute or browser back -->
|
|
2825
|
-
* <ds-mobile-page-details
|
|
2826
|
-
* title="Details"
|
|
2827
|
-
* backRoute="/home">
|
|
2828
|
-
* </ds-mobile-page-details>
|
|
2829
|
-
*
|
|
2830
|
-
* <!-- Custom behavior: parent handles navigation -->
|
|
2831
|
-
* <ds-mobile-page-details
|
|
2832
|
-
* title="Details"
|
|
2833
|
-
* (back)="customBackHandler()">
|
|
2834
|
-
* </ds-mobile-page-details>
|
|
2835
|
-
* ```
|
|
2836
|
-
*/
|
|
2837
|
-
handleBack() {
|
|
2838
|
-
// Add class to trigger reverse animation
|
|
2839
|
-
this.elementRef.nativeElement.classList.add('navigating-back');
|
|
2840
|
-
// Emit event for parent to optionally handle
|
|
2841
|
-
this.back.emit();
|
|
2842
|
-
// Default behavior: navigate using backRoute or browser back
|
|
2843
|
-
if (this.backRoute()) {
|
|
2844
|
-
this.navCtrl.navigateBack(this.backRoute());
|
|
2845
|
-
}
|
|
2846
|
-
else {
|
|
2847
|
-
this.navCtrl.back();
|
|
2848
|
-
}
|
|
2849
|
-
}
|
|
2850
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsMobilePageDetailsComponent, deps: [{ token: i1.NavController }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2851
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.14", type: DsMobilePageDetailsComponent, isStandalone: true, selector: "ds-mobile-page-details", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, backRoute: { classPropertyName: "backRoute", publicName: "backRoute", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { back: "back" }, usesInheritance: true, ngImport: i0, template: `
|
|
2852
|
-
<!-- Mobile header - hidden on desktop -->
|
|
2853
|
-
<ion-header>
|
|
2854
|
-
<ion-toolbar>
|
|
2855
|
-
<div class="header-back">
|
|
2856
|
-
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2857
|
-
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2858
|
-
</button>
|
|
2859
|
-
<h1 class="header-title">{{ title() }}</h1>
|
|
2860
|
-
</div>
|
|
2861
|
-
</ion-toolbar>
|
|
2862
|
-
</ion-header>
|
|
2863
|
-
|
|
2864
|
-
<ion-content>
|
|
2865
|
-
<!-- Desktop header above content -->
|
|
2866
|
-
<div class="desktop-header">
|
|
2867
|
-
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2868
|
-
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2869
|
-
</button>
|
|
2870
|
-
<h1>{{ title() }}</h1>
|
|
2871
|
-
</div>
|
|
2872
|
-
|
|
2873
|
-
<!-- Content area -->
|
|
2874
|
-
<div class="detail-content">
|
|
2875
|
-
<ng-content></ng-content>
|
|
2876
|
-
</div>
|
|
2877
|
-
</ion-content>
|
|
2878
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%}ion-header{background:var(--color-brand-secondary);box-shadow:none;height:64px}ion-header ion-toolbar{--background: var(--color-brand-secondary);--border-width: 0;--box-shadow: none;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 64px;height:100%;min-height:64px;padding:0}ion-header ion-toolbar::part(native){height:100%;min-height:64px;padding:0}@media (min-width: 768px){ion-header{display:none}}.header-back{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:var(--color-brand-secondary);position:relative;height:100%;min-height:64px}.header-back .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;transition:opacity var(--transition-duration-fast) var(--ease-smooth);z-index:10}.header-back .back-button:hover{opacity:.8}.header-back .back-button:active{opacity:.6}.header-back .header-title{position:absolute;left:50%;transform:translate(-50%);font-size:var(--font-size-base);font-weight:600;color:#fff;margin:0}.desktop-header{display:none}@media (min-width: 768px){.desktop-header{display:flex;align-items:center;gap:16px;padding:32px var(--content-padding-md) 24px var(--content-padding-md);max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}.desktop-header .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-color-default-primary);transition:opacity var(--transition-duration-fast) var(--ease-smooth)}.desktop-header .back-button:hover{opacity:.8}.desktop-header .back-button:active{opacity:.6}.desktop-header h1{font-size:var(--font-size-2xl);font-weight:600;margin:0;color:var(--text-color-default-primary)}}@media (min-width: 992px){.desktop-header{max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.desktop-header{max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2));padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.desktop-header{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.desktop-header{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}ion-content{--background: var(--color-background-neutral-primary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;overflow:hidden}@media (max-width: 767px){ion-content{border-radius:24px 24px 36px 36px;animation:bottomRadiusOut .6s ease .3s forwards}:host(.navigating-back) ion-content{border-radius:24px 24px 0 0;animation:bottomRadiusIn .8s cubic-bezier(.36,.66,.04,1) forwards!important}}@keyframes bottomRadiusOut{0%{border-radius:24px 24px 36px 36px}to{border-radius:24px 24px 0 0}}@keyframes bottomRadiusIn{0%{border-radius:24px 24px 0 0}to{border-radius:24px 24px 36px 36px}}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0;animation:none}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;overscroll-behavior-y:none}.detail-content{padding:24px 20px 32px}@media (min-width: 768px){.detail-content{padding:32px var(--content-padding-md)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}}@media (min-width: 992px){.detail-content{padding:32px var(--content-padding-lg)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2))}}@media (min-width: 1440px){.detail-content{padding:32px var(--content-padding-xl)!important;max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2))}}@media (min-width: 1768px){.detail-content{padding:32px var(--content-padding-2xl)!important}}@media (min-width: 1920px){.detail-content{padding:32px var(--content-padding-3xl)!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
|
|
2879
|
-
}
|
|
2880
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsMobilePageDetailsComponent, decorators: [{
|
|
2881
|
-
type: Component,
|
|
2882
|
-
args: [{ selector: 'ds-mobile-page-details', standalone: true, imports: [
|
|
2883
|
-
CommonModule,
|
|
2884
|
-
IonHeader,
|
|
2885
|
-
IonToolbar,
|
|
2886
|
-
IonContent,
|
|
2887
|
-
DsIconComponent
|
|
2888
|
-
], template: `
|
|
2889
|
-
<!-- Mobile header - hidden on desktop -->
|
|
2890
|
-
<ion-header>
|
|
2891
|
-
<ion-toolbar>
|
|
2892
|
-
<div class="header-back">
|
|
2893
|
-
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2894
|
-
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2895
|
-
</button>
|
|
2896
|
-
<h1 class="header-title">{{ title() }}</h1>
|
|
2897
|
-
</div>
|
|
2898
|
-
</ion-toolbar>
|
|
2899
|
-
</ion-header>
|
|
2900
|
-
|
|
2901
|
-
<ion-content>
|
|
2902
|
-
<!-- Desktop header above content -->
|
|
2903
|
-
<div class="desktop-header">
|
|
2904
|
-
<button class="back-button" (click)="handleBack()" [attr.aria-label]="'Go back'">
|
|
2905
|
-
<ds-icon name="remixArrowLeftLine" size="24px" />
|
|
2906
|
-
</button>
|
|
2907
|
-
<h1>{{ title() }}</h1>
|
|
2908
|
-
</div>
|
|
2909
|
-
|
|
2910
|
-
<!-- Content area -->
|
|
2911
|
-
<div class="detail-content">
|
|
2912
|
-
<ng-content></ng-content>
|
|
2913
|
-
</div>
|
|
2914
|
-
</ion-content>
|
|
2915
|
-
`, styles: [":host{display:flex;flex-direction:column;height:100%}ion-header{background:var(--color-brand-secondary);box-shadow:none;height:64px}ion-header ion-toolbar{--background: var(--color-brand-secondary);--border-width: 0;--box-shadow: none;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 64px;height:100%;min-height:64px;padding:0}ion-header ion-toolbar::part(native){height:100%;min-height:64px;padding:0}@media (min-width: 768px){ion-header{display:none}}.header-back{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:var(--color-brand-secondary);position:relative;height:100%;min-height:64px}.header-back .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;transition:opacity var(--transition-duration-fast) var(--ease-smooth);z-index:10}.header-back .back-button:hover{opacity:.8}.header-back .back-button:active{opacity:.6}.header-back .header-title{position:absolute;left:50%;transform:translate(-50%);font-size:var(--font-size-base);font-weight:600;color:#fff;margin:0}.desktop-header{display:none}@media (min-width: 768px){.desktop-header{display:flex;align-items:center;gap:16px;padding:32px var(--content-padding-md) 24px var(--content-padding-md);max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}.desktop-header .back-button{background:none;border:none;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-color-default-primary);transition:opacity var(--transition-duration-fast) var(--ease-smooth)}.desktop-header .back-button:hover{opacity:.8}.desktop-header .back-button:active{opacity:.6}.desktop-header h1{font-size:var(--font-size-2xl);font-weight:600;margin:0;color:var(--text-color-default-primary)}}@media (min-width: 992px){.desktop-header{max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.desktop-header{max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2));padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.desktop-header{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.desktop-header{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}ion-content{--background: var(--color-background-neutral-primary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;overflow:hidden}@media (max-width: 767px){ion-content{border-radius:24px 24px 36px 36px;animation:bottomRadiusOut .6s ease .3s forwards}:host(.navigating-back) ion-content{border-radius:24px 24px 0 0;animation:bottomRadiusIn .8s cubic-bezier(.36,.66,.04,1) forwards!important}}@keyframes bottomRadiusOut{0%{border-radius:24px 24px 36px 36px}to{border-radius:24px 24px 0 0}}@keyframes bottomRadiusIn{0%{border-radius:24px 24px 0 0}to{border-radius:24px 24px 36px 36px}}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0;animation:none}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;overscroll-behavior-y:none}.detail-content{padding:24px 20px 32px}@media (min-width: 768px){.detail-content{padding:32px var(--content-padding-md)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2));margin:0 auto;width:100%}}@media (min-width: 992px){.detail-content{padding:32px var(--content-padding-lg)!important;max-width:calc(var(--content-max-width-md) + (var(--content-padding-md) * 2))}}@media (min-width: 1440px){.detail-content{padding:32px var(--content-padding-xl)!important;max-width:calc(var(--content-max-width-lg) + (var(--content-padding-lg) * 2))}}@media (min-width: 1768px){.detail-content{padding:32px var(--content-padding-2xl)!important}}@media (min-width: 1920px){.detail-content{padding:32px var(--content-padding-3xl)!important}}\n"] }]
|
|
2916
|
-
}], ctorParameters: () => [{ type: i1.NavController }, { type: i0.ElementRef }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], backRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "backRoute", required: false }] }], back: [{ type: i0.Output, args: ["back"] }] } });
|
|
2917
|
-
|
|
2918
|
-
/**
|
|
2919
|
-
* DsMobileContentComponent
|
|
2920
|
-
*
|
|
2921
|
-
* Main content container for mobile pages with flexible layout options.
|
|
2922
|
-
* Provides consistent spacing and layout patterns.
|
|
2389
|
+
* Main content container for mobile pages with flexible layout options.
|
|
2390
|
+
* Provides consistent spacing and layout patterns.
|
|
2923
2391
|
*
|
|
2924
2392
|
* @example
|
|
2925
2393
|
* ```html
|
|
@@ -4720,6 +4188,7 @@ class DsMobileTabBarComponent {
|
|
|
4720
4188
|
routerSubscription;
|
|
4721
4189
|
router;
|
|
4722
4190
|
modalController = inject(ModalController);
|
|
4191
|
+
userService = inject(UserService);
|
|
4723
4192
|
constructor(elementRef) {
|
|
4724
4193
|
this.elementRef = elementRef;
|
|
4725
4194
|
// Inject Router optionally
|
|
@@ -5168,15 +4637,17 @@ class DsMobileTabBarComponent {
|
|
|
5168
4637
|
async handleAvatarClick() {
|
|
5169
4638
|
// Emit the basic click event (for backwards compatibility)
|
|
5170
4639
|
this.avatarClick.emit();
|
|
4640
|
+
// Use input if provided, otherwise fall back to service
|
|
4641
|
+
const menuItems = this.profileMenuItems || this.userService.profileMenuItems();
|
|
5171
4642
|
// If no menu items configured, just emit and return
|
|
5172
|
-
if (!
|
|
4643
|
+
if (!menuItems || menuItems.length === 0) {
|
|
5173
4644
|
return;
|
|
5174
4645
|
}
|
|
5175
4646
|
// Open the bottom sheet with configured menu items
|
|
5176
4647
|
const sheet = await this.modalController.create({
|
|
5177
4648
|
component: DsMobileActionsBottomSheetComponent,
|
|
5178
4649
|
componentProps: {
|
|
5179
|
-
customActionGroups:
|
|
4650
|
+
customActionGroups: menuItems
|
|
5180
4651
|
},
|
|
5181
4652
|
// Auto-height: no breakpoints, no handle
|
|
5182
4653
|
cssClass: 'ds-bottom-sheet auto-height'
|
|
@@ -9565,41 +9036,214 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
9565
9036
|
args: ['click']
|
|
9566
9037
|
}] } });
|
|
9567
9038
|
|
|
9568
|
-
// Mobile Page Components
|
|
9569
|
-
|
|
9570
9039
|
/**
|
|
9571
|
-
*
|
|
9040
|
+
* DsTextInputComponent
|
|
9041
|
+
*
|
|
9042
|
+
* Mobile-first text input field component following the design system.
|
|
9043
|
+
* Supports email, phone, text, and other input types.
|
|
9044
|
+
*
|
|
9045
|
+
* Features:
|
|
9046
|
+
* - All design system states (default, hover, focus, error, disabled)
|
|
9047
|
+
* - Validation error state with destructive border color
|
|
9048
|
+
* - Automatic error clearing when input becomes valid (configurable)
|
|
9049
|
+
* - Built-in validation based on input type or custom validator function
|
|
9050
|
+
* - Accessible with proper ARIA attributes
|
|
9051
|
+
* - ControlValueAccessor for Angular forms integration
|
|
9052
|
+
*
|
|
9053
|
+
* @example
|
|
9054
|
+
* ```html
|
|
9055
|
+
* <!-- Basic usage -->
|
|
9056
|
+
* <ds-text-input
|
|
9057
|
+
* type="email"
|
|
9058
|
+
* placeholder="Enter your email"
|
|
9059
|
+
* [(ngModel)]="email">
|
|
9060
|
+
* </ds-text-input>
|
|
9061
|
+
*
|
|
9062
|
+
* <!-- With validation error and auto-clear -->
|
|
9063
|
+
* <ds-text-input
|
|
9064
|
+
* type="email"
|
|
9065
|
+
* placeholder="Enter your email"
|
|
9066
|
+
* [hasError]="emailInvalid"
|
|
9067
|
+
* errorMessage="Please enter a valid email"
|
|
9068
|
+
* [autoClearError]="true"
|
|
9069
|
+
* (errorCleared)="emailInvalid = false"
|
|
9070
|
+
* [(ngModel)]="email">
|
|
9071
|
+
* </ds-text-input>
|
|
9072
|
+
*
|
|
9073
|
+
* <!-- With custom validator -->
|
|
9074
|
+
* <ds-text-input
|
|
9075
|
+
* type="text"
|
|
9076
|
+
* placeholder="Enter phone number"
|
|
9077
|
+
* [validator]="phoneValidator"
|
|
9078
|
+
* [hasError]="phoneInvalid"
|
|
9079
|
+
* (errorCleared)="phoneInvalid = false"
|
|
9080
|
+
* [(ngModel)]="phone">
|
|
9081
|
+
* </ds-text-input>
|
|
9082
|
+
* ```
|
|
9572
9083
|
*/
|
|
9573
|
-
class
|
|
9574
|
-
//
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9084
|
+
class DsTextInputComponent {
|
|
9085
|
+
// Input properties
|
|
9086
|
+
type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : []));
|
|
9087
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
9088
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
9089
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
|
|
9090
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
|
|
9091
|
+
hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
|
|
9092
|
+
errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
9093
|
+
autocomplete = input('', ...(ngDevMode ? [{ debugName: "autocomplete" }] : []));
|
|
9094
|
+
inputmode = input(undefined, ...(ngDevMode ? [{ debugName: "inputmode" }] : []));
|
|
9095
|
+
autoClearError = input(true, ...(ngDevMode ? [{ debugName: "autoClearError" }] : []));
|
|
9096
|
+
validator = input(null, ...(ngDevMode ? [{ debugName: "validator" }] : []));
|
|
9097
|
+
// Output events
|
|
9098
|
+
valueChange = output();
|
|
9099
|
+
blur = output();
|
|
9100
|
+
focus = output();
|
|
9101
|
+
errorCleared = output();
|
|
9102
|
+
// Internal state
|
|
9103
|
+
_value = signal('', ...(ngDevMode ? [{ debugName: "_value" }] : []));
|
|
9104
|
+
value = computed(() => this._value(), ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
9105
|
+
// Generate unique ID for accessibility
|
|
9106
|
+
inputId = `ds-text-input-${Math.random().toString(36).substring(2, 9)}`;
|
|
9107
|
+
// ControlValueAccessor implementation
|
|
9108
|
+
onChange = (value) => { };
|
|
9109
|
+
onTouched = () => { };
|
|
9110
|
+
onInput(event) {
|
|
9111
|
+
const target = event.target;
|
|
9112
|
+
const newValue = target.value;
|
|
9113
|
+
this._value.set(newValue);
|
|
9114
|
+
this.onChange(newValue);
|
|
9115
|
+
this.valueChange.emit(newValue);
|
|
9116
|
+
// Auto-clear error if input becomes valid
|
|
9117
|
+
if (this.autoClearError() && this.hasError()) {
|
|
9118
|
+
const isValid = this.validateInput(newValue);
|
|
9119
|
+
if (isValid) {
|
|
9120
|
+
this.errorCleared.emit();
|
|
9121
|
+
}
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9582
9124
|
/**
|
|
9583
|
-
*
|
|
9125
|
+
* Validates the input value based on type or custom validator
|
|
9584
9126
|
*/
|
|
9585
|
-
|
|
9586
|
-
|
|
9127
|
+
validateInput(value) {
|
|
9128
|
+
// Use custom validator if provided
|
|
9129
|
+
const customValidator = this.validator();
|
|
9130
|
+
if (customValidator) {
|
|
9131
|
+
return customValidator(value);
|
|
9132
|
+
}
|
|
9133
|
+
// Use built-in validation based on input type
|
|
9134
|
+
const inputType = this.type();
|
|
9135
|
+
const inputElement = document.createElement('input');
|
|
9136
|
+
inputElement.type = inputType;
|
|
9137
|
+
inputElement.value = value;
|
|
9138
|
+
// For email type, use HTML5 validation
|
|
9139
|
+
if (inputType === 'email') {
|
|
9140
|
+
return inputElement.validity.valid;
|
|
9141
|
+
}
|
|
9142
|
+
// For required fields, check if value exists
|
|
9143
|
+
if (this.required() && !value.trim()) {
|
|
9144
|
+
return false;
|
|
9145
|
+
}
|
|
9146
|
+
// Default: valid if HTML5 validation passes
|
|
9147
|
+
return inputElement.validity.valid;
|
|
9587
9148
|
}
|
|
9588
|
-
|
|
9589
|
-
this.
|
|
9149
|
+
onBlur() {
|
|
9150
|
+
this.onTouched();
|
|
9590
9151
|
}
|
|
9591
|
-
|
|
9592
|
-
|
|
9152
|
+
onFocus() {
|
|
9153
|
+
// Focus event can be emitted if needed
|
|
9593
9154
|
}
|
|
9594
|
-
|
|
9595
|
-
|
|
9155
|
+
// ControlValueAccessor methods
|
|
9156
|
+
writeValue(value) {
|
|
9157
|
+
this._value.set(value || '');
|
|
9158
|
+
}
|
|
9159
|
+
registerOnChange(fn) {
|
|
9160
|
+
this.onChange = fn;
|
|
9161
|
+
}
|
|
9162
|
+
registerOnTouched(fn) {
|
|
9163
|
+
this.onTouched = fn;
|
|
9164
|
+
}
|
|
9165
|
+
setDisabledState(isDisabled) {
|
|
9166
|
+
// Angular forms will handle this via the disabled input
|
|
9167
|
+
}
|
|
9168
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsTextInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9169
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: DsTextInputComponent, isStandalone: true, selector: "ds-text-input", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, inputmode: { classPropertyName: "inputmode", publicName: "inputmode", isSignal: true, isRequired: false, transformFunction: null }, autoClearError: { classPropertyName: "autoClearError", publicName: "autoClearError", isSignal: true, isRequired: false, transformFunction: null }, validator: { classPropertyName: "validator", publicName: "validator", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", errorCleared: "errorCleared" }, providers: [
|
|
9170
|
+
{
|
|
9171
|
+
provide: NG_VALUE_ACCESSOR,
|
|
9172
|
+
useExisting: forwardRef(() => DsTextInputComponent),
|
|
9173
|
+
multi: true
|
|
9174
|
+
}
|
|
9175
|
+
], ngImport: i0, template: `
|
|
9176
|
+
<div class="text-input-wrapper">
|
|
9177
|
+
<input
|
|
9178
|
+
[type]="type()"
|
|
9179
|
+
[placeholder]="placeholder()"
|
|
9180
|
+
[value]="value()"
|
|
9181
|
+
[disabled]="disabled()"
|
|
9182
|
+
[readonly]="readonly()"
|
|
9183
|
+
[required]="required()"
|
|
9184
|
+
[autocomplete]="autocomplete() || null"
|
|
9185
|
+
[attr.inputmode]="inputmode() || null"
|
|
9186
|
+
[class.error]="hasError()"
|
|
9187
|
+
[attr.aria-invalid]="hasError()"
|
|
9188
|
+
[attr.aria-describedby]="hasError() && errorMessage() ? 'error-' + inputId : null"
|
|
9189
|
+
class="text-input"
|
|
9190
|
+
(input)="onInput($event)"
|
|
9191
|
+
(blur)="onBlur()"
|
|
9192
|
+
(focus)="onFocus()"
|
|
9193
|
+
[id]="inputId">
|
|
9194
|
+
|
|
9195
|
+
@if (hasError() && errorMessage()) {
|
|
9196
|
+
<div
|
|
9197
|
+
class="error-message"
|
|
9198
|
+
[id]="'error-' + inputId"
|
|
9199
|
+
role="alert">
|
|
9200
|
+
{{ errorMessage() }}
|
|
9201
|
+
</div>
|
|
9202
|
+
}
|
|
9203
|
+
</div>
|
|
9204
|
+
`, isInline: true, styles: [":host{display:block;width:100%}.text-input-wrapper{position:relative;width:100%}.text-input{width:100%;height:48px;padding:0 16px;box-sizing:border-box;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-base);font-weight:400;line-height:1.4;color:var(--text-color-default-primary);background-color:var(--color-background-neutral-primary);border:1px solid var(--border-color-default);border-radius:8px;transition:border-color var(--transition-duration-fast) var(--ease-smooth),background-color var(--transition-duration-fast) var(--ease-smooth),box-shadow var(--transition-duration-fast) var(--ease-smooth);outline:none;-webkit-appearance:none;appearance:none}.text-input::placeholder{color:var(--text-color-default-tertiary)}.text-input:hover:not(:disabled):not(:focus){border-color:var(--border-color-default);background-color:var(--color-background-neutral-primary-hover)}.text-input:focus{border-color:var(--color-brand-base);background-color:var(--color-background-neutral-primary);box-shadow:0 0 0 3px var(--outline-color-default)}.text-input.error{border-color:var(--color-destructive-base)}.text-input.error:focus{border-color:var(--color-destructive-base);box-shadow:0 0 0 3px #dc26261a}.text-input:disabled{background-color:var(--color-background-neutral-disabled);border-color:var(--border-color-default);color:var(--text-color-default-disabled);cursor:not-allowed}.text-input:disabled::placeholder{color:var(--text-color-default-disabled)}.error-message{margin-top:8px;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-destructive-base)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }] });
|
|
9596
9205
|
}
|
|
9597
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
9598
|
-
type:
|
|
9599
|
-
args: [{
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9206
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsTextInputComponent, decorators: [{
|
|
9207
|
+
type: Component,
|
|
9208
|
+
args: [{ selector: 'ds-text-input', standalone: true, imports: [CommonModule, FormsModule], providers: [
|
|
9209
|
+
{
|
|
9210
|
+
provide: NG_VALUE_ACCESSOR,
|
|
9211
|
+
useExisting: forwardRef(() => DsTextInputComponent),
|
|
9212
|
+
multi: true
|
|
9213
|
+
}
|
|
9214
|
+
], template: `
|
|
9215
|
+
<div class="text-input-wrapper">
|
|
9216
|
+
<input
|
|
9217
|
+
[type]="type()"
|
|
9218
|
+
[placeholder]="placeholder()"
|
|
9219
|
+
[value]="value()"
|
|
9220
|
+
[disabled]="disabled()"
|
|
9221
|
+
[readonly]="readonly()"
|
|
9222
|
+
[required]="required()"
|
|
9223
|
+
[autocomplete]="autocomplete() || null"
|
|
9224
|
+
[attr.inputmode]="inputmode() || null"
|
|
9225
|
+
[class.error]="hasError()"
|
|
9226
|
+
[attr.aria-invalid]="hasError()"
|
|
9227
|
+
[attr.aria-describedby]="hasError() && errorMessage() ? 'error-' + inputId : null"
|
|
9228
|
+
class="text-input"
|
|
9229
|
+
(input)="onInput($event)"
|
|
9230
|
+
(blur)="onBlur()"
|
|
9231
|
+
(focus)="onFocus()"
|
|
9232
|
+
[id]="inputId">
|
|
9233
|
+
|
|
9234
|
+
@if (hasError() && errorMessage()) {
|
|
9235
|
+
<div
|
|
9236
|
+
class="error-message"
|
|
9237
|
+
[id]="'error-' + inputId"
|
|
9238
|
+
role="alert">
|
|
9239
|
+
{{ errorMessage() }}
|
|
9240
|
+
</div>
|
|
9241
|
+
}
|
|
9242
|
+
</div>
|
|
9243
|
+
`, styles: [":host{display:block;width:100%}.text-input-wrapper{position:relative;width:100%}.text-input{width:100%;height:48px;padding:0 16px;box-sizing:border-box;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-base);font-weight:400;line-height:1.4;color:var(--text-color-default-primary);background-color:var(--color-background-neutral-primary);border:1px solid var(--border-color-default);border-radius:8px;transition:border-color var(--transition-duration-fast) var(--ease-smooth),background-color var(--transition-duration-fast) var(--ease-smooth),box-shadow var(--transition-duration-fast) var(--ease-smooth);outline:none;-webkit-appearance:none;appearance:none}.text-input::placeholder{color:var(--text-color-default-tertiary)}.text-input:hover:not(:disabled):not(:focus){border-color:var(--border-color-default);background-color:var(--color-background-neutral-primary-hover)}.text-input:focus{border-color:var(--color-brand-base);background-color:var(--color-background-neutral-primary);box-shadow:0 0 0 3px var(--outline-color-default)}.text-input.error{border-color:var(--color-destructive-base)}.text-input.error:focus{border-color:var(--color-destructive-base);box-shadow:0 0 0 3px #dc26261a}.text-input:disabled{background-color:var(--color-background-neutral-disabled);border-color:var(--border-color-default);color:var(--text-color-default-disabled);cursor:not-allowed}.text-input:disabled::placeholder{color:var(--text-color-default-disabled)}.error-message{margin-top:8px;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-destructive-base)}\n"] }]
|
|
9244
|
+
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], inputmode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputmode", required: false }] }], autoClearError: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClearError", required: false }] }], validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "validator", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], blur: [{ type: i0.Output, args: ["blur"] }], focus: [{ type: i0.Output, args: ["focus"] }], errorCleared: [{ type: i0.Output, args: ["errorCleared"] }] } });
|
|
9245
|
+
|
|
9246
|
+
// Mobile Page Components
|
|
9603
9247
|
|
|
9604
9248
|
class MobileCommunityPageComponent {
|
|
9605
9249
|
router;
|
|
@@ -10246,7 +9890,7 @@ class MobileCommunityPageComponent {
|
|
|
10246
9890
|
</div>
|
|
10247
9891
|
</ds-mobile-content>
|
|
10248
9892
|
</ds-mobile-page-main>
|
|
10249
|
-
`, isInline: true, styles: [".post-feed{display:flex;flex-direction:column;max-width:640px}.post-list-wrapper{display:flex;flex-direction:column}.pinned-posts-section{margin:-12px -12px 12px;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.clickable-image{cursor:pointer;transition:transform .2s ease,opacity .2s ease;border-radius:8px;display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.clickable-image:active{transform:scale(.98);opacity:.9}.community-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-image{width:96px;height:96px;margin-bottom:24px}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance"], outputs: ["avatarClick", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "clickable"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: DsMobilePostComposerComponent, selector: "ds-mobile-post-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "placeholder", "buttonText"], outputs: ["composerClick"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostMediaComponent, selector: "post-media" }, { kind: "component", type: PostAttachmentsComponent, selector: "post-attachments" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileInlinePhotoComponent, selector: "ds-mobile-inline-photo", inputs: ["images", "author", "maxVisible"], outputs: ["photoClick"] }] });
|
|
9893
|
+
`, isInline: true, styles: [".post-feed{display:flex;flex-direction:column;max-width:640px}.post-list-wrapper{display:flex;flex-direction:column}.pinned-posts-section{margin:-12px -12px 12px;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.clickable-image{cursor:pointer;transition:transform .2s ease,opacity .2s ease;border-radius:8px;display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.clickable-image:active{transform:scale(.98);opacity:.9}.community-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-image{width:96px;height:96px;margin-bottom:24px}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "clickable"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: DsMobilePostComposerComponent, selector: "ds-mobile-post-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "placeholder", "buttonText"], outputs: ["composerClick"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostMediaComponent, selector: "post-media" }, { kind: "component", type: PostAttachmentsComponent, selector: "post-attachments" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileInlinePhotoComponent, selector: "ds-mobile-inline-photo", inputs: ["images", "author", "maxVisible"], outputs: ["photoClick"] }] });
|
|
10250
9894
|
}
|
|
10251
9895
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MobileCommunityPageComponent, decorators: [{
|
|
10252
9896
|
type: Component,
|
|
@@ -10775,7 +10419,7 @@ class MobileHandbookPageComponent {
|
|
|
10775
10419
|
</ds-mobile-content-section>
|
|
10776
10420
|
</ds-mobile-content>
|
|
10777
10421
|
</ds-mobile-page-main>
|
|
10778
|
-
`, isInline: true, styles: [".folders-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;justify-items:center}@media (min-width: 768px){.folders-grid{grid-template-columns:repeat(3,1fr)}}ds-mobile-handbook-folder{width:100%}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance"], outputs: ["avatarClick", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileContentSectionComponent, selector: "ds-mobile-content-section" }, { kind: "component", type: DsMobileHandbookFolderComponent, selector: "ds-mobile-handbook-folder", inputs: ["variant", "iconName", "itemCount", "label", "items", "loading", "error"] }] });
|
|
10422
|
+
`, isInline: true, styles: [".folders-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;justify-items:center}@media (min-width: 768px){.folders-grid{grid-template-columns:repeat(3,1fr)}}ds-mobile-handbook-folder{width:100%}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileContentSectionComponent, selector: "ds-mobile-content-section" }, { kind: "component", type: DsMobileHandbookFolderComponent, selector: "ds-mobile-handbook-folder", inputs: ["variant", "iconName", "itemCount", "label", "items", "loading", "error"] }] });
|
|
10779
10423
|
}
|
|
10780
10424
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MobileHandbookPageComponent, decorators: [{
|
|
10781
10425
|
type: Component,
|
|
@@ -10966,7 +10610,7 @@ class MobileHomePageComponent {
|
|
|
10966
10610
|
</ds-mobile-content-section>
|
|
10967
10611
|
</ds-mobile-content>
|
|
10968
10612
|
</ds-mobile-page-main>
|
|
10969
|
-
`, isInline: true, styles: [".grey-box{height:120px;border-radius:12px;background:var(--color-background-neutral-tertiary);flex:1}.grey-box.clickable{background:var(--color-background-brand);cursor:pointer;transition:transform var(--transition-duration-fast) var(--ease-smooth)}.grey-box.clickable:active{transform:scale(.98)}\n"], dependencies: [{ kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance"], outputs: ["avatarClick", "refresh", "scroll"] }, { kind: "component", type: DsMobileHeaderContentComponent, selector: "ds-mobile-header-content" }, { kind: "component", type: DsMobileHeaderContentTileComponent, selector: "ds-mobile-header-content-tile" }, { kind: "component", type: TileIconComponent, selector: "tile-icon" }, { kind: "component", type: TileContentComponent, selector: "tile-content" }, { kind: "component", type: TileLabelComponent, selector: "tile-label" }, { kind: "component", type: TileValueComponent, selector: "tile-value" }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileContentSectionComponent, selector: "ds-mobile-content-section" }, { kind: "component", type: SectionHeaderComponent, selector: "section-header", inputs: ["width"] }, { kind: "component", type: ContentRowComponent, selector: "content-row" }] });
|
|
10613
|
+
`, isInline: true, styles: [".grey-box{height:120px;border-radius:12px;background:var(--color-background-neutral-tertiary);flex:1}.grey-box.clickable{background:var(--color-background-brand);cursor:pointer;transition:transform var(--transition-duration-fast) var(--ease-smooth)}.grey-box.clickable:active{transform:scale(.98)}\n"], dependencies: [{ kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileHeaderContentComponent, selector: "ds-mobile-header-content" }, { kind: "component", type: DsMobileHeaderContentTileComponent, selector: "ds-mobile-header-content-tile" }, { kind: "component", type: TileIconComponent, selector: "tile-icon" }, { kind: "component", type: TileContentComponent, selector: "tile-content" }, { kind: "component", type: TileLabelComponent, selector: "tile-label" }, { kind: "component", type: TileValueComponent, selector: "tile-value" }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileContentSectionComponent, selector: "ds-mobile-content-section" }, { kind: "component", type: SectionHeaderComponent, selector: "section-header", inputs: ["width"] }, { kind: "component", type: ContentRowComponent, selector: "content-row" }] });
|
|
10970
10614
|
}
|
|
10971
10615
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MobileHomePageComponent, decorators: [{
|
|
10972
10616
|
type: Component,
|
|
@@ -11294,7 +10938,7 @@ class MobileInquiriesPageComponent {
|
|
|
11294
10938
|
</div>
|
|
11295
10939
|
</ds-mobile-content>
|
|
11296
10940
|
</ds-mobile-page-main>
|
|
11297
|
-
`, isInline: true, styles: [".inquiries-container{display:flex;flex-direction:column;max-width:640px}.inquiry-list-wrapper{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin:16px 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance"], outputs: ["avatarClick", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileInteractiveListItemInquiryComponent, selector: "ds-mobile-interactive-list-item-inquiry", inputs: ["title", "description", "status", "statusLabel", "timestamp", "iconName", "iconColor", "variant", "clickable", "showChevron"], outputs: ["inquiryClick", "longPress"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileInlineTabsComponent, selector: "ds-mobile-inline-tabs", inputs: ["tabs", "activeTab"], outputs: ["tabChange"] }] });
|
|
10941
|
+
`, isInline: true, styles: [".inquiries-container{display:flex;flex-direction:column;max-width:640px}.inquiry-list-wrapper{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin:16px 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileContentComponent, selector: "ds-mobile-content", inputs: ["layout"] }, { kind: "component", type: DsMobileInteractiveListItemInquiryComponent, selector: "ds-mobile-interactive-list-item-inquiry", inputs: ["title", "description", "status", "statusLabel", "timestamp", "iconName", "iconColor", "variant", "clickable", "showChevron"], outputs: ["inquiryClick", "longPress"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileInlineTabsComponent, selector: "ds-mobile-inline-tabs", inputs: ["tabs", "activeTab"], outputs: ["tabChange"] }] });
|
|
11298
10942
|
}
|
|
11299
10943
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MobileInquiriesPageComponent, decorators: [{
|
|
11300
10944
|
type: Component,
|
|
@@ -11321,600 +10965,1187 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
11321
10965
|
</ds-mobile-inline-tabs>
|
|
11322
10966
|
</div>
|
|
11323
10967
|
|
|
11324
|
-
<ds-mobile-content>
|
|
11325
|
-
<div class="inquiries-container">
|
|
11326
|
-
@if (filteredInquiries().length > 0) {
|
|
11327
|
-
<div class="inquiry-list-wrapper">
|
|
11328
|
-
@for (inquiry of filteredInquiries(); track inquiry.id; let idx = $index) {
|
|
11329
|
-
<ds-mobile-interactive-list-item-inquiry
|
|
11330
|
-
[title]="inquiry.title"
|
|
11331
|
-
[description]="inquiry.description"
|
|
11332
|
-
[status]="inquiry.status"
|
|
11333
|
-
[timestamp]="inquiry.timestamp"
|
|
11334
|
-
[iconName]="getInquiryIcon(inquiry.category)"
|
|
11335
|
-
[clickable]="true"
|
|
11336
|
-
[showChevron]="false"
|
|
11337
|
-
(inquiryClick)="openInquiryDetail(inquiry.id)"
|
|
11338
|
-
(longPress)="showInquiryActions(inquiry.id)">
|
|
11339
|
-
</ds-mobile-interactive-list-item-inquiry>
|
|
11340
|
-
|
|
11341
|
-
}
|
|
11342
|
-
</div>
|
|
11343
|
-
} @else {
|
|
11344
|
-
<!-- Empty state -->
|
|
11345
|
-
<div class="empty-state">
|
|
11346
|
-
<ds-icon name="remixInboxLine" size="48px" color="tertiary" />
|
|
11347
|
-
<h3 class="empty-state-title">Ingen henvendelser endnu</h3>
|
|
11348
|
-
<p class="empty-state-description">
|
|
11349
|
-
@if (filterStatus() === 'open') {
|
|
11350
|
-
Du har ingen åbne henvendelser
|
|
11351
|
-
} @else if (filterStatus() === 'closed') {
|
|
11352
|
-
Du har ingen lukkede henvendelser
|
|
11353
|
-
} @else {
|
|
11354
|
-
Du har ikke oprettet nogen henvendelser endnu
|
|
11355
|
-
}
|
|
11356
|
-
</p>
|
|
11357
|
-
</div>
|
|
11358
|
-
}
|
|
10968
|
+
<ds-mobile-content>
|
|
10969
|
+
<div class="inquiries-container">
|
|
10970
|
+
@if (filteredInquiries().length > 0) {
|
|
10971
|
+
<div class="inquiry-list-wrapper">
|
|
10972
|
+
@for (inquiry of filteredInquiries(); track inquiry.id; let idx = $index) {
|
|
10973
|
+
<ds-mobile-interactive-list-item-inquiry
|
|
10974
|
+
[title]="inquiry.title"
|
|
10975
|
+
[description]="inquiry.description"
|
|
10976
|
+
[status]="inquiry.status"
|
|
10977
|
+
[timestamp]="inquiry.timestamp"
|
|
10978
|
+
[iconName]="getInquiryIcon(inquiry.category)"
|
|
10979
|
+
[clickable]="true"
|
|
10980
|
+
[showChevron]="false"
|
|
10981
|
+
(inquiryClick)="openInquiryDetail(inquiry.id)"
|
|
10982
|
+
(longPress)="showInquiryActions(inquiry.id)">
|
|
10983
|
+
</ds-mobile-interactive-list-item-inquiry>
|
|
10984
|
+
|
|
10985
|
+
}
|
|
10986
|
+
</div>
|
|
10987
|
+
} @else {
|
|
10988
|
+
<!-- Empty state -->
|
|
10989
|
+
<div class="empty-state">
|
|
10990
|
+
<ds-icon name="remixInboxLine" size="48px" color="tertiary" />
|
|
10991
|
+
<h3 class="empty-state-title">Ingen henvendelser endnu</h3>
|
|
10992
|
+
<p class="empty-state-description">
|
|
10993
|
+
@if (filterStatus() === 'open') {
|
|
10994
|
+
Du har ingen åbne henvendelser
|
|
10995
|
+
} @else if (filterStatus() === 'closed') {
|
|
10996
|
+
Du har ingen lukkede henvendelser
|
|
10997
|
+
} @else {
|
|
10998
|
+
Du har ikke oprettet nogen henvendelser endnu
|
|
10999
|
+
}
|
|
11000
|
+
</p>
|
|
11001
|
+
</div>
|
|
11002
|
+
}
|
|
11003
|
+
</div>
|
|
11004
|
+
</ds-mobile-content>
|
|
11005
|
+
</ds-mobile-page-main>
|
|
11006
|
+
`, styles: [".inquiries-container{display:flex;flex-direction:column;max-width:640px}.inquiry-list-wrapper{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin:16px 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}\n"] }]
|
|
11007
|
+
}], ctorParameters: () => [{ type: UserService }, { type: i1.NavController }] });
|
|
11008
|
+
|
|
11009
|
+
class MobileInquiryDetailPageComponent extends MobilePageBase {
|
|
11010
|
+
userService;
|
|
11011
|
+
navCtrl;
|
|
11012
|
+
elementRef;
|
|
11013
|
+
ionContent;
|
|
11014
|
+
// Platform detection
|
|
11015
|
+
platform = inject(Platform);
|
|
11016
|
+
// Computed property to check if running on native platform
|
|
11017
|
+
isNativePlatform = computed(() => this.platform.is('ios') ||
|
|
11018
|
+
this.platform.is('android') ||
|
|
11019
|
+
this.platform.is('capacitor'), ...(ngDevMode ? [{ debugName: "isNativePlatform" }] : []));
|
|
11020
|
+
inquiryTitle = 'Tørretumbler virker ikke';
|
|
11021
|
+
activeTab = signal('activity', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
11022
|
+
tabItems = [
|
|
11023
|
+
{ id: 'activity', label: 'Aktivitet' },
|
|
11024
|
+
{ id: 'messages', label: 'Beskeder', badge: 0 },
|
|
11025
|
+
{ id: 'details', label: 'Detaljer' }
|
|
11026
|
+
];
|
|
11027
|
+
activities = [
|
|
11028
|
+
{
|
|
11029
|
+
id: '1',
|
|
11030
|
+
type: 'assignment',
|
|
11031
|
+
actor: 'Martin Smith',
|
|
11032
|
+
actorInitials: 'MS',
|
|
11033
|
+
title: 'er blevet tildelt som din dedikerede tekniker.',
|
|
11034
|
+
timestamp: '2 dage siden',
|
|
11035
|
+
date: '28. feb 2025',
|
|
11036
|
+
iconName: 'remixUserAddLine'
|
|
11037
|
+
},
|
|
11038
|
+
{
|
|
11039
|
+
id: '2',
|
|
11040
|
+
type: 'assignment',
|
|
11041
|
+
actor: 'Ricki Meihlen',
|
|
11042
|
+
actorInitials: 'RM',
|
|
11043
|
+
title: 'er blevet tildelt til at håndtere din henvendelse.',
|
|
11044
|
+
timestamp: '8 dage siden',
|
|
11045
|
+
date: '22. feb 2025',
|
|
11046
|
+
iconName: 'remixUserLine'
|
|
11047
|
+
},
|
|
11048
|
+
{
|
|
11049
|
+
id: '3',
|
|
11050
|
+
type: 'creation',
|
|
11051
|
+
title: 'Henvendelse oprettet',
|
|
11052
|
+
timestamp: '8 dage siden',
|
|
11053
|
+
date: '22. feb 2025',
|
|
11054
|
+
iconName: 'remixAddCircleLine'
|
|
11055
|
+
}
|
|
11056
|
+
];
|
|
11057
|
+
messageThreads = [
|
|
11058
|
+
{
|
|
11059
|
+
id: '1',
|
|
11060
|
+
senderName: 'Ove Hindborg',
|
|
11061
|
+
senderAvatar: '',
|
|
11062
|
+
senderInitials: 'OH',
|
|
11063
|
+
message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',
|
|
11064
|
+
role: 'Sagsbehandler',
|
|
11065
|
+
timestamp: '2t siden',
|
|
11066
|
+
unread: true
|
|
11067
|
+
},
|
|
11068
|
+
{
|
|
11069
|
+
id: '2',
|
|
11070
|
+
senderName: 'Martin Smith',
|
|
11071
|
+
senderAvatar: '',
|
|
11072
|
+
senderInitials: 'MS',
|
|
11073
|
+
message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',
|
|
11074
|
+
role: 'Tekniker',
|
|
11075
|
+
timestamp: '4t siden',
|
|
11076
|
+
unread: true
|
|
11077
|
+
}
|
|
11078
|
+
];
|
|
11079
|
+
unreadMessagesCount = computed(() => {
|
|
11080
|
+
const count = this.messageThreads.filter(m => m.unread).length;
|
|
11081
|
+
// Update badge in tab items
|
|
11082
|
+
const messagesTab = this.tabItems.find(t => t.id === 'messages');
|
|
11083
|
+
if (messagesTab) {
|
|
11084
|
+
messagesTab.badge = count;
|
|
11085
|
+
}
|
|
11086
|
+
return count;
|
|
11087
|
+
}, ...(ngDevMode ? [{ debugName: "unreadMessagesCount" }] : []));
|
|
11088
|
+
constructor(userService, navCtrl, elementRef) {
|
|
11089
|
+
super();
|
|
11090
|
+
this.userService = userService;
|
|
11091
|
+
this.navCtrl = navCtrl;
|
|
11092
|
+
this.elementRef = elementRef;
|
|
11093
|
+
// Trigger initial badge update
|
|
11094
|
+
this.unreadMessagesCount();
|
|
11095
|
+
}
|
|
11096
|
+
ngAfterViewInit() {
|
|
11097
|
+
// Initial setup if needed
|
|
11098
|
+
}
|
|
11099
|
+
setActiveTab(tabId) {
|
|
11100
|
+
this.activeTab.set(tabId);
|
|
11101
|
+
}
|
|
11102
|
+
goBack() {
|
|
11103
|
+
this.navCtrl.back({ animation: customBackTransition });
|
|
11104
|
+
}
|
|
11105
|
+
handleScroll(event) {
|
|
11106
|
+
const scrollTop = event.detail.scrollTop;
|
|
11107
|
+
const threshold = 160;
|
|
11108
|
+
const fadeDistance = 200;
|
|
11109
|
+
const header = this.elementRef.nativeElement.querySelector('ion-header:not([collapse])');
|
|
11110
|
+
const headerExpandable = this.elementRef.nativeElement.querySelector('.header-expandable');
|
|
11111
|
+
// Show title in fixed header when scrolled past threshold
|
|
11112
|
+
if (scrollTop > threshold) {
|
|
11113
|
+
header?.classList.add('header-scrolled');
|
|
11114
|
+
}
|
|
11115
|
+
else {
|
|
11116
|
+
header?.classList.remove('header-scrolled');
|
|
11117
|
+
}
|
|
11118
|
+
// Fade out header-expandable content based on scroll
|
|
11119
|
+
if (headerExpandable) {
|
|
11120
|
+
const fadeProgress = Math.min(scrollTop / fadeDistance, 1);
|
|
11121
|
+
// Calculate opacity (1 to 0)
|
|
11122
|
+
const opacity = 1 - fadeProgress;
|
|
11123
|
+
// Calculate transform (0px to -20px upward)
|
|
11124
|
+
const translateY = fadeProgress * -20;
|
|
11125
|
+
// Apply styles
|
|
11126
|
+
headerExpandable.style.opacity = opacity.toString();
|
|
11127
|
+
headerExpandable.style.transform = `translateY(${translateY}px)`;
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
handleRefresh(event) {
|
|
11131
|
+
console.log('Pull-to-refresh triggered');
|
|
11132
|
+
setTimeout(() => {
|
|
11133
|
+
console.log('Refresh complete');
|
|
11134
|
+
event.target.complete();
|
|
11135
|
+
}, 1000);
|
|
11136
|
+
}
|
|
11137
|
+
openMessage(messageId) {
|
|
11138
|
+
console.log('Opening message:', messageId);
|
|
11139
|
+
// Navigate to message thread detail
|
|
11140
|
+
}
|
|
11141
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MobileInquiryDetailPageComponent, deps: [{ token: UserService }, { token: i1.NavController }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
11142
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: MobileInquiryDetailPageComponent, isStandalone: true, selector: "app-mobile-inquiry-detail-page", host: { classAttribute: "ion-page" }, viewQueries: [{ propertyName: "ionContent", first: true, predicate: IonContent, descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
11143
|
+
<!-- Fixed header at top -->
|
|
11144
|
+
<ion-header>
|
|
11145
|
+
<ion-toolbar>
|
|
11146
|
+
<div class="header-detail">
|
|
11147
|
+
<!-- Back Button -->
|
|
11148
|
+
<button class="back-button" (click)="goBack()" [attr.aria-label]="'Go back'">
|
|
11149
|
+
<ds-icon name="remixArrowLeftSLine" size="24px" color="white" />
|
|
11150
|
+
</button>
|
|
11151
|
+
|
|
11152
|
+
<!-- Title - fades in on scroll -->
|
|
11153
|
+
<ion-title class="header-detail__title">{{ inquiryTitle }}</ion-title>
|
|
11154
|
+
</div>
|
|
11155
|
+
</ion-toolbar>
|
|
11156
|
+
</ion-header>
|
|
11157
|
+
|
|
11158
|
+
<!-- Content with expandable header -->
|
|
11159
|
+
<ion-content [scrollEvents]="true" (ionScroll)="handleScroll($event)">
|
|
11160
|
+
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
11161
|
+
@if (isNativePlatform()) {
|
|
11162
|
+
<ion-refresher
|
|
11163
|
+
slot="fixed"
|
|
11164
|
+
(ionRefresh)="handleRefresh($event)"
|
|
11165
|
+
[pullFactor]="0.4"
|
|
11166
|
+
[pullMin]="80"
|
|
11167
|
+
[pullMax]="240"
|
|
11168
|
+
closeDuration="600ms">
|
|
11169
|
+
<ion-refresher-content
|
|
11170
|
+
pullingIcon="remixArrowDownS"
|
|
11171
|
+
refreshingSpinner="lines">
|
|
11172
|
+
</ion-refresher-content>
|
|
11173
|
+
</ion-refresher>
|
|
11174
|
+
}
|
|
11175
|
+
|
|
11176
|
+
<!-- Expandable header section (purple background) -->
|
|
11177
|
+
<div class="header-expandable">
|
|
11178
|
+
<div class="header-expandable-inner">
|
|
11179
|
+
<div class="header-expandable__text">
|
|
11180
|
+
<h1 class="header-expandable__title">{{ inquiryTitle }}</h1>
|
|
11181
|
+
</div>
|
|
11182
|
+
|
|
11183
|
+
<!-- Tabs in header -->
|
|
11184
|
+
<ds-mobile-inline-tabs
|
|
11185
|
+
[tabs]="tabItems"
|
|
11186
|
+
[activeTab]="activeTab()"
|
|
11187
|
+
(tabChange)="setActiveTab($event)">
|
|
11188
|
+
</ds-mobile-inline-tabs>
|
|
11189
|
+
</div>
|
|
11190
|
+
</div>
|
|
11191
|
+
|
|
11192
|
+
<!-- Content wrapper -->
|
|
11193
|
+
<div class="content-wrapper">
|
|
11194
|
+
<div class="content-inner">
|
|
11195
|
+
<!-- Activity Tab Content -->
|
|
11196
|
+
@if (activeTab() === 'activity') {
|
|
11197
|
+
<div class="activity-list">
|
|
11198
|
+
@for (activity of activities; track activity.id) {
|
|
11199
|
+
<div class="activity-item">
|
|
11200
|
+
@if (activity.actor) {
|
|
11201
|
+
<!-- Avatar with badge for actor activities -->
|
|
11202
|
+
<div class="avatar-wrapper">
|
|
11203
|
+
<ds-avatar
|
|
11204
|
+
[type]="'initials'"
|
|
11205
|
+
[initials]="activity.actorInitials || ''"
|
|
11206
|
+
size="md" />
|
|
11207
|
+
|
|
11208
|
+
<div class="avatar-badge">
|
|
11209
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 32" fill="none">
|
|
11210
|
+
<path d="M33.9862 5.51709H23.1724V8.82743H26.0413C26.2841 8.82743 26.4827 9.02606 26.4827 9.26881V12.7998C26.4827 13.0426 26.2841 13.2412 26.0413 13.2412H23.1724V14.3447H26.0413C26.2841 14.3447 26.4827 14.5433 26.4827 14.7861V18.3171C26.4827 18.5598 26.2841 18.7585 26.0413 18.7585H23.1724V19.8619H26.0413C26.2841 19.8619 26.4827 20.0605 26.4827 20.3033V23.8343C26.4827 24.0771 26.2841 24.2757 26.0413 24.2757H23.1724V26.2619C23.1724 26.7496 23.0267 27.2043 22.7773 27.5861H27.5862L32 31.9999V27.5861H33.9862C34.7167 27.5861 35.3103 26.9924 35.3103 26.2619V6.84123C35.3103 6.11075 34.7167 5.51709 33.9862 5.51709ZM32 23.8343C32 24.0771 31.8013 24.2757 31.5586 24.2757H28.0276C27.7848 24.2757 27.5862 24.0771 27.5862 23.8343V20.3033C27.5862 20.0605 27.7848 19.8619 28.0276 19.8619H31.5586C31.8013 19.8619 32 20.0605 32 20.3033V23.8343ZM32 18.3171C32 18.5598 31.8013 18.7585 31.5586 18.7585H28.0276C27.7848 18.7585 27.5862 18.5598 27.5862 18.3171V14.7861C27.5862 14.5433 27.7848 14.3447 28.0276 14.3447H31.5586C31.8013 14.3447 32 14.5433 32 14.7861V18.3171ZM32 12.7998C32 13.0426 31.8013 13.2412 31.5586 13.2412H28.0276C27.7848 13.2412 27.5862 13.0426 27.5862 12.7998V9.26881C27.5862 9.02606 27.7848 8.82743 28.0276 8.82743H31.5586C31.8013 8.82743 32 9.02606 32 9.26881V12.7998Z" fill="white"/>
|
|
11211
|
+
<path d="M20.7448 0H1.32414C0.593655 0 0 0.593655 0 1.32414V26.2621C0 26.9926 0.593655 27.5862 1.32414 27.5862H3.31034V32L7.72414 27.5862H20.7448C21.4753 27.5862 22.069 26.9926 22.069 26.2621V1.32414C22.069 0.593655 21.4753 0 20.7448 0ZM7.72414 23.8345C7.72414 24.0772 7.52552 24.2759 7.28276 24.2759H3.75172C3.50897 24.2759 3.31034 24.0772 3.31034 23.8345V20.3034C3.31034 20.0607 3.50897 19.8621 3.75172 19.8621H7.28276C7.52552 19.8621 7.72414 20.0607 7.72414 20.3034V23.8345ZM7.72414 18.3172C7.72414 18.56 7.52552 18.7586 7.28276 18.7586H3.75172C3.50897 18.7586 3.31034 18.56 3.31034 18.3172V14.7862C3.31034 14.5434 3.50897 14.3448 3.75172 14.3448H7.28276C7.52552 14.3448 7.72414 14.5434 7.72414 14.7862V18.3172ZM7.72414 12.8C7.72414 13.0428 7.52552 13.2414 7.28276 13.2414H3.75172C3.50897 13.2414 3.31034 13.0428 3.31034 12.8V9.26897C3.31034 9.02621 3.50897 8.82759 3.75172 8.82759H7.28276C7.52552 8.82759 7.72414 9.02621 7.72414 9.26897V12.8ZM7.72414 7.28276C7.72414 7.52552 7.52552 7.72414 7.28276 7.72414H3.75172C3.50897 7.72414 3.31034 7.52552 3.31034 7.28276V3.75172C3.31034 3.50897 3.50897 3.31034 3.75172 3.31034H7.28276C7.52552 3.31034 7.72414 3.50897 7.72414 3.75172V7.28276ZM13.2414 23.8345C13.2414 24.0772 13.0428 24.2759 12.8 24.2759H9.26897C9.02621 24.2759 8.82759 24.0772 8.82759 23.8345V20.3034C8.82759 20.0607 9.02621 19.8621 9.26897 19.8621H12.8C13.0428 19.8621 13.2414 20.0607 13.2414 20.3034V23.8345ZM13.2414 18.3172C13.2414 18.56 13.0428 18.7586 12.8 18.7586H9.26897C9.02621 18.7586 8.82759 18.56 8.82759 18.3172V14.7862C8.82759 14.5434 9.02621 14.3448 9.26897 14.3448H12.8C13.0428 14.3448 13.2414 14.5434 13.2414 14.7862V18.3172ZM13.2414 12.8C13.2414 13.0428 13.0428 13.2414 12.8 13.2414H9.26897C9.02621 13.2414 8.82759 13.0428 8.82759 12.8V9.26897C8.82759 9.02621 9.02621 8.82759 9.26897 8.82759H12.8C13.0428 8.82759 13.2414 9.02621 13.2414 9.26897V12.8ZM13.2414 6.84138V7.28276C13.2414 7.52552 13.0428 7.72414 12.8 7.72414H9.26897C9.02621 7.72414 8.82759 7.52552 8.82759 7.28276V3.75172C8.82759 3.50897 9.02621 3.31034 9.26897 3.31034H12.8C13.0428 3.31034 13.2414 3.50897 13.2414 3.75172V6.84138ZM18.7586 23.8345C18.7586 24.0772 18.56 24.2759 18.3172 24.2759H14.7862C14.5434 24.2759 14.3448 24.0772 14.3448 23.8345V20.3034C14.3448 20.0607 14.5434 19.8621 14.7862 19.8621H18.3172C18.56 19.8621 18.7586 20.0607 18.7586 20.3034V23.8345ZM18.7586 18.3172C18.7586 18.56 18.56 18.7586 18.3172 18.7586H14.7862C14.5434 18.7586 14.3448 18.56 14.3448 18.3172V14.7862C14.3448 14.5434 14.5434 14.3448 14.7862 14.3448H18.3172C18.56 14.3448 18.7586 14.5434 18.7586 14.7862V18.3172ZM18.7586 12.8C18.7586 13.0428 18.56 13.2414 18.3172 13.2414H14.7862C14.5434 13.2414 14.3448 13.0428 14.3448 12.8V9.26897C14.3448 9.02621 14.5434 8.82759 14.7862 8.82759H18.3172C18.56 8.82759 18.7586 9.02621 18.7586 9.26897V12.8ZM18.7586 5.51724V7.28276C18.7586 7.52552 18.56 7.72414 18.3172 7.72414H14.7862C14.5434 7.72414 14.3448 7.52552 14.3448 7.28276V3.75172C14.3448 3.50897 14.5434 3.31034 14.7862 3.31034H18.3172C18.56 3.31034 18.7586 3.50897 18.7586 3.75172V5.51724Z" fill="white"/>
|
|
11212
|
+
</svg>
|
|
11213
|
+
</div>
|
|
11214
|
+
</div>
|
|
11215
|
+
} @else {
|
|
11216
|
+
<!-- Icon wrapper for non-actor activities -->
|
|
11217
|
+
<div class="activity-icon-wrapper">
|
|
11218
|
+
<ds-icon
|
|
11219
|
+
[name]="activity.iconName"
|
|
11220
|
+
size="18px"
|
|
11221
|
+
color="secondary" />
|
|
11222
|
+
</div>
|
|
11223
|
+
}
|
|
11224
|
+
|
|
11225
|
+
<div class="activity-content">
|
|
11226
|
+
<p class="activity-title">
|
|
11227
|
+
@if (activity.actor) {
|
|
11228
|
+
<span class="actor-name">{{ activity.actor }}</span>
|
|
11229
|
+
<span class="activity-text"> {{ activity.title }}</span>
|
|
11230
|
+
} @else {
|
|
11231
|
+
<span class="actor-name">{{ activity.title }}</span>
|
|
11232
|
+
}
|
|
11233
|
+
</p>
|
|
11234
|
+
@if (activity.description) {
|
|
11235
|
+
<p class="activity-description">{{ activity.description }}</p>
|
|
11236
|
+
}
|
|
11237
|
+
<div class="activity-timestamp">
|
|
11238
|
+
<ds-icon name="remixCalendarLine" size="12px" color="--color-text-tertiary" />
|
|
11239
|
+
<span>{{ activity.date }}</span>
|
|
11240
|
+
</div>
|
|
11241
|
+
</div>
|
|
11242
|
+
</div>
|
|
11243
|
+
}
|
|
11244
|
+
</div>
|
|
11245
|
+
}
|
|
11246
|
+
|
|
11247
|
+
<!-- Messages Tab Content -->
|
|
11248
|
+
@if (activeTab() === 'messages') {
|
|
11249
|
+
<div class="messages-list">
|
|
11250
|
+
@for (message of messageThreads; track message.id) {
|
|
11251
|
+
<ds-mobile-interactive-list-item-message
|
|
11252
|
+
[senderName]="message.senderName"
|
|
11253
|
+
[senderRole]="message.role"
|
|
11254
|
+
[message]="message.message"
|
|
11255
|
+
[avatarInitials]="message.senderInitials"
|
|
11256
|
+
[unread]="message.unread"
|
|
11257
|
+
(messageClick)="openMessage(message.id)">
|
|
11258
|
+
</ds-mobile-interactive-list-item-message>
|
|
11259
|
+
}
|
|
11260
|
+
</div>
|
|
11261
|
+
}
|
|
11262
|
+
|
|
11263
|
+
<!-- Details Tab Content -->
|
|
11264
|
+
@if (activeTab() === 'details') {
|
|
11265
|
+
<div class="details-list">
|
|
11266
|
+
<!-- Assignee -->
|
|
11267
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11268
|
+
<div content-leading>
|
|
11269
|
+
<ds-avatar
|
|
11270
|
+
[size]="'sm'"
|
|
11271
|
+
[type]="'initials'"
|
|
11272
|
+
[initials]="'R'" />
|
|
11273
|
+
</div>
|
|
11274
|
+
<div content-main>
|
|
11275
|
+
<div class="detail-label">Sagsbehandler</div>
|
|
11276
|
+
<div class="detail-value">Ricki Meihlen</div>
|
|
11277
|
+
</div>
|
|
11278
|
+
</ds-mobile-list-item-static>
|
|
11279
|
+
|
|
11280
|
+
<!-- Technician -->
|
|
11281
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11282
|
+
<div content-leading>
|
|
11283
|
+
<ds-avatar
|
|
11284
|
+
[size]="'sm'"
|
|
11285
|
+
[type]="'initials'"
|
|
11286
|
+
[initials]="'M'" />
|
|
11287
|
+
</div>
|
|
11288
|
+
<div content-main>
|
|
11289
|
+
<div class="detail-label">Tekniker</div>
|
|
11290
|
+
<div class="detail-value">Martin Smith</div>
|
|
11291
|
+
</div>
|
|
11292
|
+
</ds-mobile-list-item-static>
|
|
11293
|
+
|
|
11294
|
+
<!-- Title -->
|
|
11295
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11296
|
+
<div content-leading>
|
|
11297
|
+
<ds-icon name="remixTextBlock" size="20px" color="tertiary" />
|
|
11298
|
+
</div>
|
|
11299
|
+
<div content-main>
|
|
11300
|
+
<div class="detail-value">{{ inquiryTitle }}</div>
|
|
11301
|
+
</div>
|
|
11302
|
+
</ds-mobile-list-item-static>
|
|
11303
|
+
|
|
11304
|
+
<!-- Description -->
|
|
11305
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11306
|
+
<div content-leading>
|
|
11307
|
+
<ds-icon name="remixAlignLeft" size="20px" color="tertiary" />
|
|
11308
|
+
</div>
|
|
11309
|
+
<div content-main>
|
|
11310
|
+
<div class="detail-value description-text">
|
|
11311
|
+
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.
|
|
11312
|
+
</div>
|
|
11313
|
+
<div class="detail-tag">Husholdningsapparater</div>
|
|
11314
|
+
</div>
|
|
11315
|
+
</ds-mobile-list-item-static>
|
|
11316
|
+
|
|
11317
|
+
<!-- Photos -->
|
|
11318
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11319
|
+
<div content-leading>
|
|
11320
|
+
<ds-icon name="remixCameraLine" size="20px" color="tertiary" />
|
|
11321
|
+
</div>
|
|
11322
|
+
<div content-main>
|
|
11323
|
+
<div class="photo-grid">
|
|
11324
|
+
<button class="photo-add">
|
|
11325
|
+
<ds-icon name="remixAddLine" size="20px" color="tertiary" />
|
|
11326
|
+
</button>
|
|
11327
|
+
<!-- Placeholder photos -->
|
|
11328
|
+
<div class="photo-item"></div>
|
|
11329
|
+
<div class="photo-item"></div>
|
|
11330
|
+
<div class="photo-item"></div>
|
|
11331
|
+
<div class="photo-item"></div>
|
|
11332
|
+
</div>
|
|
11333
|
+
</div>
|
|
11334
|
+
</ds-mobile-list-item-static>
|
|
11335
|
+
</div>
|
|
11336
|
+
}
|
|
11337
|
+
</div>
|
|
11338
|
+
</div>
|
|
11339
|
+
</ion-content>
|
|
11340
|
+
`, isInline: true, styles: ["ion-header{--background: var(--color-brand-secondary, #5d5fef);height:72px;min-height:72px}ion-toolbar{--background: var(--color-brand-secondary, #5d5fef);--color: white;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 72px;height:100%;min-height:72px}ion-toolbar ion-title{transition:transform .2s ease,opacity .2s ease!important}.header-detail{display:flex;align-items:center;gap:12px;padding:0 20px;height:100%}.back-button{width:36px;height:36px;border-radius:50%;background:#ffffff1a;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s ease;color:#fff;padding:0;flex-shrink:0}.back-button:hover,.back-button:active{background:#ffffff26}.header-detail__title{position:absolute;left:64px;transform:translateY(-100%);font-size:var(--font-size-base);font-weight:600;color:#fff;opacity:0!important;pointer-events:none;transition:transform .2s ease,opacity .2s ease!important;margin:0;padding:0;--color: white;text-align:left!important}.header-scrolled .header-detail__title{opacity:1!important;pointer-events:auto;transform:translateY(0)}@media (min-width: 768px){.header-detail{padding:16px 24px}}ion-content{--background: var(--color-brand-secondary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;border-radius:24px 24px 0 0;overflow:hidden}.plt-ios ion-content{--background: var(--color-background-neutral-primary)}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;display:flex;flex-direction:column}ion-refresher{z-index:0}ion-refresher-content{--color: white}.header-expandable{background:var(--color-brand-secondary);padding:32px 20px 24px;color:var(--header-content-color, white);position:sticky;top:0;z-index:5;transition:opacity .1s ease-out,transform .1s ease-out}.header-expandable-inner{display:flex;flex-direction:column;gap:20px;max-width:640px}.header-expandable__text{margin-bottom:0}@media (min-width: 768px){.header-expandable{padding:40px var(--content-padding-md) 32px var(--content-padding-md)}}@media (min-width: 992px){.header-expandable{padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.header-expandable{padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.header-expandable{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.header-expandable{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}.content-wrapper{background:var(--color-background-neutral-primary, white);border-radius:24px 24px 0 0;flex:1 1 auto;min-height:100%;position:relative;z-index:10;box-shadow:0 200vh 0 0 var(--color-background-neutral-primary)}.content-inner{padding:24px 20px 40px}@media (min-width: 768px){.content-inner{padding:32px}}.activity-list{display:flex;flex-direction:column;gap:32px}.activity-item{display:flex;gap:12px;position:relative}.activity-item:after{content:\"\";position:absolute;bottom:-16px;left:44px;right:8px;height:1px;background:var(--border-color-default, #e5e5e5)}.activity-item:last-child:after{display:none}.activity-icon-wrapper{width:32px;height:32px;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:32px;height:32px}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.messages-list{display:flex;flex-direction:column;gap:8px;margin:-8px}.details-list{display:flex;flex-direction:column;gap:20px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-value.description-text{padding:8px 0}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:flex;gap:8px;margin-top:8px;overflow-x:auto}.photo-add{width:80px;height:80px;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}.photo-item{width:80px;height:80px;border-radius:12px;background:var(--color-background-neutral-secondary, #e5e5e5);flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsMobileInlineTabsComponent, selector: "ds-mobile-inline-tabs", inputs: ["tabs", "activeTab"], outputs: ["tabChange"] }, { kind: "component", type: DsMobileListItemStaticComponent, selector: "ds-mobile-list-item-static", inputs: ["leadingSize"] }, { kind: "component", type: DsMobileInteractiveListItemMessageComponent, selector: "ds-mobile-interactive-list-item-message", inputs: ["senderName", "senderRole", "message", "avatarInitials", "avatarType", "avatarSrc", "unread", "clickable"], outputs: ["messageClick", "longPress"] }] });
|
|
11341
|
+
}
|
|
11342
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MobileInquiryDetailPageComponent, decorators: [{
|
|
11343
|
+
type: Component,
|
|
11344
|
+
args: [{ selector: 'app-mobile-inquiry-detail-page', standalone: true, imports: [
|
|
11345
|
+
CommonModule,
|
|
11346
|
+
IonHeader,
|
|
11347
|
+
IonToolbar,
|
|
11348
|
+
IonTitle,
|
|
11349
|
+
IonContent,
|
|
11350
|
+
IonRefresher,
|
|
11351
|
+
IonRefresherContent,
|
|
11352
|
+
DsIconComponent,
|
|
11353
|
+
DsAvatarComponent,
|
|
11354
|
+
DsMobileInlineTabsComponent,
|
|
11355
|
+
DsMobileListItemStaticComponent,
|
|
11356
|
+
DsMobileInteractiveListItemMessageComponent
|
|
11357
|
+
], host: {
|
|
11358
|
+
class: 'ion-page'
|
|
11359
|
+
}, template: `
|
|
11360
|
+
<!-- Fixed header at top -->
|
|
11361
|
+
<ion-header>
|
|
11362
|
+
<ion-toolbar>
|
|
11363
|
+
<div class="header-detail">
|
|
11364
|
+
<!-- Back Button -->
|
|
11365
|
+
<button class="back-button" (click)="goBack()" [attr.aria-label]="'Go back'">
|
|
11366
|
+
<ds-icon name="remixArrowLeftSLine" size="24px" color="white" />
|
|
11367
|
+
</button>
|
|
11368
|
+
|
|
11369
|
+
<!-- Title - fades in on scroll -->
|
|
11370
|
+
<ion-title class="header-detail__title">{{ inquiryTitle }}</ion-title>
|
|
11371
|
+
</div>
|
|
11372
|
+
</ion-toolbar>
|
|
11373
|
+
</ion-header>
|
|
11374
|
+
|
|
11375
|
+
<!-- Content with expandable header -->
|
|
11376
|
+
<ion-content [scrollEvents]="true" (ionScroll)="handleScroll($event)">
|
|
11377
|
+
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
11378
|
+
@if (isNativePlatform()) {
|
|
11379
|
+
<ion-refresher
|
|
11380
|
+
slot="fixed"
|
|
11381
|
+
(ionRefresh)="handleRefresh($event)"
|
|
11382
|
+
[pullFactor]="0.4"
|
|
11383
|
+
[pullMin]="80"
|
|
11384
|
+
[pullMax]="240"
|
|
11385
|
+
closeDuration="600ms">
|
|
11386
|
+
<ion-refresher-content
|
|
11387
|
+
pullingIcon="remixArrowDownS"
|
|
11388
|
+
refreshingSpinner="lines">
|
|
11389
|
+
</ion-refresher-content>
|
|
11390
|
+
</ion-refresher>
|
|
11391
|
+
}
|
|
11392
|
+
|
|
11393
|
+
<!-- Expandable header section (purple background) -->
|
|
11394
|
+
<div class="header-expandable">
|
|
11395
|
+
<div class="header-expandable-inner">
|
|
11396
|
+
<div class="header-expandable__text">
|
|
11397
|
+
<h1 class="header-expandable__title">{{ inquiryTitle }}</h1>
|
|
11398
|
+
</div>
|
|
11399
|
+
|
|
11400
|
+
<!-- Tabs in header -->
|
|
11401
|
+
<ds-mobile-inline-tabs
|
|
11402
|
+
[tabs]="tabItems"
|
|
11403
|
+
[activeTab]="activeTab()"
|
|
11404
|
+
(tabChange)="setActiveTab($event)">
|
|
11405
|
+
</ds-mobile-inline-tabs>
|
|
11406
|
+
</div>
|
|
11407
|
+
</div>
|
|
11408
|
+
|
|
11409
|
+
<!-- Content wrapper -->
|
|
11410
|
+
<div class="content-wrapper">
|
|
11411
|
+
<div class="content-inner">
|
|
11412
|
+
<!-- Activity Tab Content -->
|
|
11413
|
+
@if (activeTab() === 'activity') {
|
|
11414
|
+
<div class="activity-list">
|
|
11415
|
+
@for (activity of activities; track activity.id) {
|
|
11416
|
+
<div class="activity-item">
|
|
11417
|
+
@if (activity.actor) {
|
|
11418
|
+
<!-- Avatar with badge for actor activities -->
|
|
11419
|
+
<div class="avatar-wrapper">
|
|
11420
|
+
<ds-avatar
|
|
11421
|
+
[type]="'initials'"
|
|
11422
|
+
[initials]="activity.actorInitials || ''"
|
|
11423
|
+
size="md" />
|
|
11424
|
+
|
|
11425
|
+
<div class="avatar-badge">
|
|
11426
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 32" fill="none">
|
|
11427
|
+
<path d="M33.9862 5.51709H23.1724V8.82743H26.0413C26.2841 8.82743 26.4827 9.02606 26.4827 9.26881V12.7998C26.4827 13.0426 26.2841 13.2412 26.0413 13.2412H23.1724V14.3447H26.0413C26.2841 14.3447 26.4827 14.5433 26.4827 14.7861V18.3171C26.4827 18.5598 26.2841 18.7585 26.0413 18.7585H23.1724V19.8619H26.0413C26.2841 19.8619 26.4827 20.0605 26.4827 20.3033V23.8343C26.4827 24.0771 26.2841 24.2757 26.0413 24.2757H23.1724V26.2619C23.1724 26.7496 23.0267 27.2043 22.7773 27.5861H27.5862L32 31.9999V27.5861H33.9862C34.7167 27.5861 35.3103 26.9924 35.3103 26.2619V6.84123C35.3103 6.11075 34.7167 5.51709 33.9862 5.51709ZM32 23.8343C32 24.0771 31.8013 24.2757 31.5586 24.2757H28.0276C27.7848 24.2757 27.5862 24.0771 27.5862 23.8343V20.3033C27.5862 20.0605 27.7848 19.8619 28.0276 19.8619H31.5586C31.8013 19.8619 32 20.0605 32 20.3033V23.8343ZM32 18.3171C32 18.5598 31.8013 18.7585 31.5586 18.7585H28.0276C27.7848 18.7585 27.5862 18.5598 27.5862 18.3171V14.7861C27.5862 14.5433 27.7848 14.3447 28.0276 14.3447H31.5586C31.8013 14.3447 32 14.5433 32 14.7861V18.3171ZM32 12.7998C32 13.0426 31.8013 13.2412 31.5586 13.2412H28.0276C27.7848 13.2412 27.5862 13.0426 27.5862 12.7998V9.26881C27.5862 9.02606 27.7848 8.82743 28.0276 8.82743H31.5586C31.8013 8.82743 32 9.02606 32 9.26881V12.7998Z" fill="white"/>
|
|
11428
|
+
<path d="M20.7448 0H1.32414C0.593655 0 0 0.593655 0 1.32414V26.2621C0 26.9926 0.593655 27.5862 1.32414 27.5862H3.31034V32L7.72414 27.5862H20.7448C21.4753 27.5862 22.069 26.9926 22.069 26.2621V1.32414C22.069 0.593655 21.4753 0 20.7448 0ZM7.72414 23.8345C7.72414 24.0772 7.52552 24.2759 7.28276 24.2759H3.75172C3.50897 24.2759 3.31034 24.0772 3.31034 23.8345V20.3034C3.31034 20.0607 3.50897 19.8621 3.75172 19.8621H7.28276C7.52552 19.8621 7.72414 20.0607 7.72414 20.3034V23.8345ZM7.72414 18.3172C7.72414 18.56 7.52552 18.7586 7.28276 18.7586H3.75172C3.50897 18.7586 3.31034 18.56 3.31034 18.3172V14.7862C3.31034 14.5434 3.50897 14.3448 3.75172 14.3448H7.28276C7.52552 14.3448 7.72414 14.5434 7.72414 14.7862V18.3172ZM7.72414 12.8C7.72414 13.0428 7.52552 13.2414 7.28276 13.2414H3.75172C3.50897 13.2414 3.31034 13.0428 3.31034 12.8V9.26897C3.31034 9.02621 3.50897 8.82759 3.75172 8.82759H7.28276C7.52552 8.82759 7.72414 9.02621 7.72414 9.26897V12.8ZM7.72414 7.28276C7.72414 7.52552 7.52552 7.72414 7.28276 7.72414H3.75172C3.50897 7.72414 3.31034 7.52552 3.31034 7.28276V3.75172C3.31034 3.50897 3.50897 3.31034 3.75172 3.31034H7.28276C7.52552 3.31034 7.72414 3.50897 7.72414 3.75172V7.28276ZM13.2414 23.8345C13.2414 24.0772 13.0428 24.2759 12.8 24.2759H9.26897C9.02621 24.2759 8.82759 24.0772 8.82759 23.8345V20.3034C8.82759 20.0607 9.02621 19.8621 9.26897 19.8621H12.8C13.0428 19.8621 13.2414 20.0607 13.2414 20.3034V23.8345ZM13.2414 18.3172C13.2414 18.56 13.0428 18.7586 12.8 18.7586H9.26897C9.02621 18.7586 8.82759 18.56 8.82759 18.3172V14.7862C8.82759 14.5434 9.02621 14.3448 9.26897 14.3448H12.8C13.0428 14.3448 13.2414 14.5434 13.2414 14.7862V18.3172ZM13.2414 12.8C13.2414 13.0428 13.0428 13.2414 12.8 13.2414H9.26897C9.02621 13.2414 8.82759 13.0428 8.82759 12.8V9.26897C8.82759 9.02621 9.02621 8.82759 9.26897 8.82759H12.8C13.0428 8.82759 13.2414 9.02621 13.2414 9.26897V12.8ZM13.2414 6.84138V7.28276C13.2414 7.52552 13.0428 7.72414 12.8 7.72414H9.26897C9.02621 7.72414 8.82759 7.52552 8.82759 7.28276V3.75172C8.82759 3.50897 9.02621 3.31034 9.26897 3.31034H12.8C13.0428 3.31034 13.2414 3.50897 13.2414 3.75172V6.84138ZM18.7586 23.8345C18.7586 24.0772 18.56 24.2759 18.3172 24.2759H14.7862C14.5434 24.2759 14.3448 24.0772 14.3448 23.8345V20.3034C14.3448 20.0607 14.5434 19.8621 14.7862 19.8621H18.3172C18.56 19.8621 18.7586 20.0607 18.7586 20.3034V23.8345ZM18.7586 18.3172C18.7586 18.56 18.56 18.7586 18.3172 18.7586H14.7862C14.5434 18.7586 14.3448 18.56 14.3448 18.3172V14.7862C14.3448 14.5434 14.5434 14.3448 14.7862 14.3448H18.3172C18.56 14.3448 18.7586 14.5434 18.7586 14.7862V18.3172ZM18.7586 12.8C18.7586 13.0428 18.56 13.2414 18.3172 13.2414H14.7862C14.5434 13.2414 14.3448 13.0428 14.3448 12.8V9.26897C14.3448 9.02621 14.5434 8.82759 14.7862 8.82759H18.3172C18.56 8.82759 18.7586 9.02621 18.7586 9.26897V12.8ZM18.7586 5.51724V7.28276C18.7586 7.52552 18.56 7.72414 18.3172 7.72414H14.7862C14.5434 7.72414 14.3448 7.52552 14.3448 7.28276V3.75172C14.3448 3.50897 14.5434 3.31034 14.7862 3.31034H18.3172C18.56 3.31034 18.7586 3.50897 18.7586 3.75172V5.51724Z" fill="white"/>
|
|
11429
|
+
</svg>
|
|
11430
|
+
</div>
|
|
11431
|
+
</div>
|
|
11432
|
+
} @else {
|
|
11433
|
+
<!-- Icon wrapper for non-actor activities -->
|
|
11434
|
+
<div class="activity-icon-wrapper">
|
|
11435
|
+
<ds-icon
|
|
11436
|
+
[name]="activity.iconName"
|
|
11437
|
+
size="18px"
|
|
11438
|
+
color="secondary" />
|
|
11439
|
+
</div>
|
|
11440
|
+
}
|
|
11441
|
+
|
|
11442
|
+
<div class="activity-content">
|
|
11443
|
+
<p class="activity-title">
|
|
11444
|
+
@if (activity.actor) {
|
|
11445
|
+
<span class="actor-name">{{ activity.actor }}</span>
|
|
11446
|
+
<span class="activity-text"> {{ activity.title }}</span>
|
|
11447
|
+
} @else {
|
|
11448
|
+
<span class="actor-name">{{ activity.title }}</span>
|
|
11449
|
+
}
|
|
11450
|
+
</p>
|
|
11451
|
+
@if (activity.description) {
|
|
11452
|
+
<p class="activity-description">{{ activity.description }}</p>
|
|
11453
|
+
}
|
|
11454
|
+
<div class="activity-timestamp">
|
|
11455
|
+
<ds-icon name="remixCalendarLine" size="12px" color="--color-text-tertiary" />
|
|
11456
|
+
<span>{{ activity.date }}</span>
|
|
11457
|
+
</div>
|
|
11458
|
+
</div>
|
|
11459
|
+
</div>
|
|
11460
|
+
}
|
|
11461
|
+
</div>
|
|
11462
|
+
}
|
|
11463
|
+
|
|
11464
|
+
<!-- Messages Tab Content -->
|
|
11465
|
+
@if (activeTab() === 'messages') {
|
|
11466
|
+
<div class="messages-list">
|
|
11467
|
+
@for (message of messageThreads; track message.id) {
|
|
11468
|
+
<ds-mobile-interactive-list-item-message
|
|
11469
|
+
[senderName]="message.senderName"
|
|
11470
|
+
[senderRole]="message.role"
|
|
11471
|
+
[message]="message.message"
|
|
11472
|
+
[avatarInitials]="message.senderInitials"
|
|
11473
|
+
[unread]="message.unread"
|
|
11474
|
+
(messageClick)="openMessage(message.id)">
|
|
11475
|
+
</ds-mobile-interactive-list-item-message>
|
|
11476
|
+
}
|
|
11477
|
+
</div>
|
|
11478
|
+
}
|
|
11479
|
+
|
|
11480
|
+
<!-- Details Tab Content -->
|
|
11481
|
+
@if (activeTab() === 'details') {
|
|
11482
|
+
<div class="details-list">
|
|
11483
|
+
<!-- Assignee -->
|
|
11484
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11485
|
+
<div content-leading>
|
|
11486
|
+
<ds-avatar
|
|
11487
|
+
[size]="'sm'"
|
|
11488
|
+
[type]="'initials'"
|
|
11489
|
+
[initials]="'R'" />
|
|
11490
|
+
</div>
|
|
11491
|
+
<div content-main>
|
|
11492
|
+
<div class="detail-label">Sagsbehandler</div>
|
|
11493
|
+
<div class="detail-value">Ricki Meihlen</div>
|
|
11494
|
+
</div>
|
|
11495
|
+
</ds-mobile-list-item-static>
|
|
11496
|
+
|
|
11497
|
+
<!-- Technician -->
|
|
11498
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11499
|
+
<div content-leading>
|
|
11500
|
+
<ds-avatar
|
|
11501
|
+
[size]="'sm'"
|
|
11502
|
+
[type]="'initials'"
|
|
11503
|
+
[initials]="'M'" />
|
|
11504
|
+
</div>
|
|
11505
|
+
<div content-main>
|
|
11506
|
+
<div class="detail-label">Tekniker</div>
|
|
11507
|
+
<div class="detail-value">Martin Smith</div>
|
|
11508
|
+
</div>
|
|
11509
|
+
</ds-mobile-list-item-static>
|
|
11510
|
+
|
|
11511
|
+
<!-- Title -->
|
|
11512
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11513
|
+
<div content-leading>
|
|
11514
|
+
<ds-icon name="remixTextBlock" size="20px" color="tertiary" />
|
|
11515
|
+
</div>
|
|
11516
|
+
<div content-main>
|
|
11517
|
+
<div class="detail-value">{{ inquiryTitle }}</div>
|
|
11518
|
+
</div>
|
|
11519
|
+
</ds-mobile-list-item-static>
|
|
11520
|
+
|
|
11521
|
+
<!-- Description -->
|
|
11522
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11523
|
+
<div content-leading>
|
|
11524
|
+
<ds-icon name="remixAlignLeft" size="20px" color="tertiary" />
|
|
11525
|
+
</div>
|
|
11526
|
+
<div content-main>
|
|
11527
|
+
<div class="detail-value description-text">
|
|
11528
|
+
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.
|
|
11529
|
+
</div>
|
|
11530
|
+
<div class="detail-tag">Husholdningsapparater</div>
|
|
11531
|
+
</div>
|
|
11532
|
+
</ds-mobile-list-item-static>
|
|
11533
|
+
|
|
11534
|
+
<!-- Photos -->
|
|
11535
|
+
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11536
|
+
<div content-leading>
|
|
11537
|
+
<ds-icon name="remixCameraLine" size="20px" color="tertiary" />
|
|
11538
|
+
</div>
|
|
11539
|
+
<div content-main>
|
|
11540
|
+
<div class="photo-grid">
|
|
11541
|
+
<button class="photo-add">
|
|
11542
|
+
<ds-icon name="remixAddLine" size="20px" color="tertiary" />
|
|
11543
|
+
</button>
|
|
11544
|
+
<!-- Placeholder photos -->
|
|
11545
|
+
<div class="photo-item"></div>
|
|
11546
|
+
<div class="photo-item"></div>
|
|
11547
|
+
<div class="photo-item"></div>
|
|
11548
|
+
<div class="photo-item"></div>
|
|
11549
|
+
</div>
|
|
11550
|
+
</div>
|
|
11551
|
+
</ds-mobile-list-item-static>
|
|
11552
|
+
</div>
|
|
11553
|
+
}
|
|
11554
|
+
</div>
|
|
11555
|
+
</div>
|
|
11556
|
+
</ion-content>
|
|
11557
|
+
`, styles: ["ion-header{--background: var(--color-brand-secondary, #5d5fef);height:72px;min-height:72px}ion-toolbar{--background: var(--color-brand-secondary, #5d5fef);--color: white;--padding-top: 0;--padding-bottom: 0;--padding-start: 0;--padding-end: 0;--min-height: 72px;height:100%;min-height:72px}ion-toolbar ion-title{transition:transform .2s ease,opacity .2s ease!important}.header-detail{display:flex;align-items:center;gap:12px;padding:0 20px;height:100%}.back-button{width:36px;height:36px;border-radius:50%;background:#ffffff1a;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s ease;color:#fff;padding:0;flex-shrink:0}.back-button:hover,.back-button:active{background:#ffffff26}.header-detail__title{position:absolute;left:64px;transform:translateY(-100%);font-size:var(--font-size-base);font-weight:600;color:#fff;opacity:0!important;pointer-events:none;transition:transform .2s ease,opacity .2s ease!important;margin:0;padding:0;--color: white;text-align:left!important}.header-scrolled .header-detail__title{opacity:1!important;pointer-events:auto;transform:translateY(0)}@media (min-width: 768px){.header-detail{padding:16px 24px}}ion-content{--background: var(--color-brand-secondary);--padding-top: 0;--padding-start: 0;--padding-end: 0;--padding-bottom: 0;border-radius:24px 24px 0 0;overflow:hidden}.plt-ios ion-content{--background: var(--color-background-neutral-primary)}@media (min-width: 768px){ion-content{border-radius:24px 24px 0 0}}ion-content::part(scroll){-webkit-overflow-scrolling:touch;display:flex;flex-direction:column}ion-refresher{z-index:0}ion-refresher-content{--color: white}.header-expandable{background:var(--color-brand-secondary);padding:32px 20px 24px;color:var(--header-content-color, white);position:sticky;top:0;z-index:5;transition:opacity .1s ease-out,transform .1s ease-out}.header-expandable-inner{display:flex;flex-direction:column;gap:20px;max-width:640px}.header-expandable__text{margin-bottom:0}@media (min-width: 768px){.header-expandable{padding:40px var(--content-padding-md) 32px var(--content-padding-md)}}@media (min-width: 992px){.header-expandable{padding-left:var(--content-padding-lg);padding-right:var(--content-padding-lg)}}@media (min-width: 1440px){.header-expandable{padding-left:var(--content-padding-xl);padding-right:var(--content-padding-xl)}}@media (min-width: 1768px){.header-expandable{padding-left:var(--content-padding-2xl);padding-right:var(--content-padding-2xl)}}@media (min-width: 1920px){.header-expandable{padding-left:var(--content-padding-3xl);padding-right:var(--content-padding-3xl)}}.content-wrapper{background:var(--color-background-neutral-primary, white);border-radius:24px 24px 0 0;flex:1 1 auto;min-height:100%;position:relative;z-index:10;box-shadow:0 200vh 0 0 var(--color-background-neutral-primary)}.content-inner{padding:24px 20px 40px}@media (min-width: 768px){.content-inner{padding:32px}}.activity-list{display:flex;flex-direction:column;gap:32px}.activity-item{display:flex;gap:12px;position:relative}.activity-item:after{content:\"\";position:absolute;bottom:-16px;left:44px;right:8px;height:1px;background:var(--border-color-default, #e5e5e5)}.activity-item:last-child:after{display:none}.activity-icon-wrapper{width:32px;height:32px;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:32px;height:32px}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.messages-list{display:flex;flex-direction:column;gap:8px;margin:-8px}.details-list{display:flex;flex-direction:column;gap:20px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-value.description-text{padding:8px 0}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:flex;gap:8px;margin-top:8px;overflow-x:auto}.photo-add{width:80px;height:80px;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}.photo-item{width:80px;height:80px;border-radius:12px;background:var(--color-background-neutral-secondary, #e5e5e5);flex-shrink:0}\n"] }]
|
|
11558
|
+
}], ctorParameters: () => [{ type: UserService }, { type: i1.NavController }, { type: i0.ElementRef }], propDecorators: { ionContent: [{
|
|
11559
|
+
type: ViewChild,
|
|
11560
|
+
args: [IonContent]
|
|
11561
|
+
}] } });
|
|
11562
|
+
|
|
11563
|
+
/**
|
|
11564
|
+
* DsAvatarWithBadgeComponent
|
|
11565
|
+
*
|
|
11566
|
+
* Displays an avatar with a logomark badge overlay.
|
|
11567
|
+
* Useful for showing user avatars with organization branding.
|
|
11568
|
+
*
|
|
11569
|
+
* @example
|
|
11570
|
+
* ```html
|
|
11571
|
+
* <ds-avatar-with-badge
|
|
11572
|
+
* [type]="'initials'"
|
|
11573
|
+
* [initials]="'JD'"
|
|
11574
|
+
* [size]="'lg'"
|
|
11575
|
+
* [badgePosition]="'bottom-right'"
|
|
11576
|
+
* />
|
|
11577
|
+
* ```
|
|
11578
|
+
*/
|
|
11579
|
+
class DsAvatarWithBadgeComponent {
|
|
11580
|
+
whitelabelService = inject(WhitelabelService);
|
|
11581
|
+
// Avatar props
|
|
11582
|
+
type = 'initials';
|
|
11583
|
+
size = 'md';
|
|
11584
|
+
initials = '';
|
|
11585
|
+
src = '';
|
|
11586
|
+
iconName = 'remixUser3Fill';
|
|
11587
|
+
// Badge props
|
|
11588
|
+
showBadge = true;
|
|
11589
|
+
badgePosition = 'bottom-right';
|
|
11590
|
+
badgeClasses = computed(() => {
|
|
11591
|
+
return `avatar-badge avatar-badge--${this.badgePosition} avatar-badge--${this.size}`;
|
|
11592
|
+
}, ...(ngDevMode ? [{ debugName: "badgeClasses" }] : []));
|
|
11593
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsAvatarWithBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11594
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: DsAvatarWithBadgeComponent, isStandalone: true, selector: "ds-avatar-with-badge", inputs: { type: "type", size: "size", initials: "initials", src: "src", iconName: "iconName", showBadge: "showBadge", badgePosition: "badgePosition" }, ngImport: i0, template: `
|
|
11595
|
+
<div class="avatar-badge-container">
|
|
11596
|
+
<ds-avatar
|
|
11597
|
+
[type]="type"
|
|
11598
|
+
[size]="size"
|
|
11599
|
+
[initials]="initials"
|
|
11600
|
+
[src]="src"
|
|
11601
|
+
[iconName]="iconName"
|
|
11602
|
+
/>
|
|
11603
|
+
|
|
11604
|
+
@if (showBadge) {
|
|
11605
|
+
<div [class]="badgeClasses()">
|
|
11606
|
+
<img [src]="whitelabelService.logoMarkUrl()" [alt]="whitelabelService.logoAlt()" />
|
|
11607
|
+
</div>
|
|
11608
|
+
}
|
|
11609
|
+
</div>
|
|
11610
|
+
`, isInline: true, styles: [":host{display:inline-block;position:relative}.avatar-badge-container{position:relative;display:inline-block}.avatar-badge{position:absolute;background:var(--color-brand-secondary, #5d5fef);border-radius:8px;display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge img{width:10px;height:10px;object-fit:contain}.avatar-badge--bottom-right{bottom:-6px;right:-6px}.avatar-badge--bottom-left{bottom:-6px;left:-6px}.avatar-badge--top-right{top:-6px;right:-6px}.avatar-badge--top-left{top:-6px;left:-6px}.avatar-badge--xs{width:16px;height:16px}.avatar-badge--sm{width:18px;height:18px}.avatar-badge--md{width:20px;height:20px}.avatar-badge--lg{width:24px;height:24px}.avatar-badge--xl{width:28px;height:28px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }] });
|
|
11611
|
+
}
|
|
11612
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DsAvatarWithBadgeComponent, decorators: [{
|
|
11613
|
+
type: Component,
|
|
11614
|
+
args: [{ selector: 'ds-avatar-with-badge', standalone: true, imports: [CommonModule, DsAvatarComponent], encapsulation: ViewEncapsulation.Emulated, template: `
|
|
11615
|
+
<div class="avatar-badge-container">
|
|
11616
|
+
<ds-avatar
|
|
11617
|
+
[type]="type"
|
|
11618
|
+
[size]="size"
|
|
11619
|
+
[initials]="initials"
|
|
11620
|
+
[src]="src"
|
|
11621
|
+
[iconName]="iconName"
|
|
11622
|
+
/>
|
|
11623
|
+
|
|
11624
|
+
@if (showBadge) {
|
|
11625
|
+
<div [class]="badgeClasses()">
|
|
11626
|
+
<img [src]="whitelabelService.logoMarkUrl()" [alt]="whitelabelService.logoAlt()" />
|
|
11359
11627
|
</div>
|
|
11360
|
-
|
|
11361
|
-
</
|
|
11362
|
-
`, styles: ["
|
|
11363
|
-
}],
|
|
11628
|
+
}
|
|
11629
|
+
</div>
|
|
11630
|
+
`, styles: [":host{display:inline-block;position:relative}.avatar-badge-container{position:relative;display:inline-block}.avatar-badge{position:absolute;background:var(--color-brand-secondary, #5d5fef);border-radius:8px;display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge img{width:10px;height:10px;object-fit:contain}.avatar-badge--bottom-right{bottom:-6px;right:-6px}.avatar-badge--bottom-left{bottom:-6px;left:-6px}.avatar-badge--top-right{top:-6px;right:-6px}.avatar-badge--top-left{top:-6px;left:-6px}.avatar-badge--xs{width:16px;height:16px}.avatar-badge--sm{width:18px;height:18px}.avatar-badge--md{width:20px;height:20px}.avatar-badge--lg{width:24px;height:24px}.avatar-badge--xl{width:28px;height:28px}\n"] }]
|
|
11631
|
+
}], propDecorators: { type: [{
|
|
11632
|
+
type: Input
|
|
11633
|
+
}], size: [{
|
|
11634
|
+
type: Input
|
|
11635
|
+
}], initials: [{
|
|
11636
|
+
type: Input
|
|
11637
|
+
}], src: [{
|
|
11638
|
+
type: Input
|
|
11639
|
+
}], iconName: [{
|
|
11640
|
+
type: Input
|
|
11641
|
+
}], showBadge: [{
|
|
11642
|
+
type: Input
|
|
11643
|
+
}], badgePosition: [{
|
|
11644
|
+
type: Input
|
|
11645
|
+
}] } });
|
|
11364
11646
|
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
iconName: 'remixUserAddLine'
|
|
11393
|
-
},
|
|
11394
|
-
{
|
|
11395
|
-
id: '2',
|
|
11396
|
-
type: 'assignment',
|
|
11397
|
-
actor: 'Ricki Meihlen',
|
|
11398
|
-
actorInitials: 'RM',
|
|
11399
|
-
title: 'er blevet tildelt til at håndtere din henvendelse.',
|
|
11400
|
-
timestamp: '8 dage siden',
|
|
11401
|
-
date: '22. feb 2025',
|
|
11402
|
-
iconName: 'remixUserLine'
|
|
11403
|
-
},
|
|
11404
|
-
{
|
|
11405
|
-
id: '3',
|
|
11406
|
-
type: 'creation',
|
|
11407
|
-
title: 'Henvendelse oprettet',
|
|
11408
|
-
timestamp: '8 dage siden',
|
|
11409
|
-
date: '22. feb 2025',
|
|
11410
|
-
iconName: 'remixAddCircleLine'
|
|
11647
|
+
/**
|
|
11648
|
+
* Whitelabel Demo Modal Component
|
|
11649
|
+
*
|
|
11650
|
+
* Demonstrates the whitelabeling system with theme selection, brand colors, and logo previews.
|
|
11651
|
+
* Opens as a full-screen modal similar to post details.
|
|
11652
|
+
*/
|
|
11653
|
+
class WhitelabelDemoModalComponent {
|
|
11654
|
+
whitelabelService = inject(WhitelabelService);
|
|
11655
|
+
modalController = inject(ModalController);
|
|
11656
|
+
// Current active theme
|
|
11657
|
+
currentTheme = 'default';
|
|
11658
|
+
// Custom color inputs
|
|
11659
|
+
customPrimarySurface = '#6B5FF5';
|
|
11660
|
+
customPrimaryContent = '#FFFFFF';
|
|
11661
|
+
customSecondarySurface = '#221a4c';
|
|
11662
|
+
customSecondaryContent = '#FFFFFF';
|
|
11663
|
+
ngOnInit() {
|
|
11664
|
+
this.updateCustomColorInputs();
|
|
11665
|
+
this.detectCurrentTheme();
|
|
11666
|
+
}
|
|
11667
|
+
/**
|
|
11668
|
+
* Detect the current active theme based on colors
|
|
11669
|
+
*/
|
|
11670
|
+
detectCurrentTheme() {
|
|
11671
|
+
const secondarySurface = this.whitelabelService.secondarySurface().toUpperCase();
|
|
11672
|
+
if (secondarySurface === '#A70923') {
|
|
11673
|
+
this.currentTheme = 'cej';
|
|
11411
11674
|
}
|
|
11412
|
-
|
|
11413
|
-
|
|
11414
|
-
{
|
|
11415
|
-
id: '1',
|
|
11416
|
-
senderName: 'Ove Hindborg',
|
|
11417
|
-
senderAvatar: '',
|
|
11418
|
-
senderInitials: 'OH',
|
|
11419
|
-
message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',
|
|
11420
|
-
role: 'Sagsbehandler',
|
|
11421
|
-
timestamp: '2t siden',
|
|
11422
|
-
unread: true
|
|
11423
|
-
},
|
|
11424
|
-
{
|
|
11425
|
-
id: '2',
|
|
11426
|
-
senderName: 'Martin Smith',
|
|
11427
|
-
senderAvatar: '',
|
|
11428
|
-
senderInitials: 'MS',
|
|
11429
|
-
message: 'Dejligt at høre! Jeg venter på din teknikerbesøg tidsplan.',
|
|
11430
|
-
role: 'Tekniker',
|
|
11431
|
-
timestamp: '4t siden',
|
|
11432
|
-
unread: true
|
|
11675
|
+
else if (secondarySurface === '#660036') {
|
|
11676
|
+
this.currentTheme = 'pka';
|
|
11433
11677
|
}
|
|
11434
|
-
|
|
11435
|
-
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11439
|
-
if (messagesTab) {
|
|
11440
|
-
messagesTab.badge = count;
|
|
11678
|
+
else if (secondarySurface === '#262424') {
|
|
11679
|
+
this.currentTheme = 'clave';
|
|
11680
|
+
}
|
|
11681
|
+
else {
|
|
11682
|
+
this.currentTheme = 'default';
|
|
11441
11683
|
}
|
|
11442
|
-
return count;
|
|
11443
|
-
}, ...(ngDevMode ? [{ debugName: "unreadMessagesCount" }] : []));
|
|
11444
|
-
constructor(userService, navCtrl, elementRef) {
|
|
11445
|
-
super();
|
|
11446
|
-
this.userService = userService;
|
|
11447
|
-
this.navCtrl = navCtrl;
|
|
11448
|
-
this.elementRef = elementRef;
|
|
11449
|
-
// Trigger initial badge update
|
|
11450
|
-
this.unreadMessagesCount();
|
|
11451
11684
|
}
|
|
11452
|
-
|
|
11453
|
-
|
|
11685
|
+
/**
|
|
11686
|
+
* Close the modal
|
|
11687
|
+
*/
|
|
11688
|
+
close() {
|
|
11689
|
+
this.modalController.dismiss();
|
|
11454
11690
|
}
|
|
11455
|
-
|
|
11456
|
-
this.
|
|
11691
|
+
applyDefaultTheme() {
|
|
11692
|
+
this.currentTheme = 'default';
|
|
11693
|
+
this.whitelabelService.updateConfig({
|
|
11694
|
+
logoUrl: '/Assets/logos/propbinder-logomark.svg',
|
|
11695
|
+
logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',
|
|
11696
|
+
logoAlt: 'Propbinder',
|
|
11697
|
+
logoHeight: 28,
|
|
11698
|
+
primarySurface: '#6B5FF5',
|
|
11699
|
+
primaryContent: '#FFFFFF',
|
|
11700
|
+
secondarySurface: '#221a4c',
|
|
11701
|
+
secondaryContent: '#FFFFFF',
|
|
11702
|
+
organizationName: 'Propbinder',
|
|
11703
|
+
organizationId: 'default'
|
|
11704
|
+
});
|
|
11705
|
+
this.updateCustomColorInputs();
|
|
11457
11706
|
}
|
|
11458
|
-
|
|
11459
|
-
this.
|
|
11707
|
+
applyCejTheme() {
|
|
11708
|
+
this.currentTheme = 'cej';
|
|
11709
|
+
this.whitelabelService.updateConfig({
|
|
11710
|
+
logoUrl: '/Assets/logos/cej-logo.png',
|
|
11711
|
+
logoMarkUrl: '/Assets/logos/cej-logo.png',
|
|
11712
|
+
logoAlt: 'CEJ',
|
|
11713
|
+
logoHeight: 36,
|
|
11714
|
+
primarySurface: '#FFFFFF',
|
|
11715
|
+
primaryContent: '#A70923',
|
|
11716
|
+
secondarySurface: '#A70923',
|
|
11717
|
+
secondaryContent: '#FFFFFF',
|
|
11718
|
+
organizationName: 'CEJ',
|
|
11719
|
+
organizationId: 'cej'
|
|
11720
|
+
});
|
|
11721
|
+
this.updateCustomColorInputs();
|
|
11460
11722
|
}
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
const fadeProgress = Math.min(scrollTop / fadeDistance, 1);
|
|
11477
|
-
// Calculate opacity (1 to 0)
|
|
11478
|
-
const opacity = 1 - fadeProgress;
|
|
11479
|
-
// Calculate transform (0px to -20px upward)
|
|
11480
|
-
const translateY = fadeProgress * -20;
|
|
11481
|
-
// Apply styles
|
|
11482
|
-
headerExpandable.style.opacity = opacity.toString();
|
|
11483
|
-
headerExpandable.style.transform = `translateY(${translateY}px)`;
|
|
11484
|
-
}
|
|
11723
|
+
applyPkaTheme() {
|
|
11724
|
+
this.currentTheme = 'pka';
|
|
11725
|
+
this.whitelabelService.updateConfig({
|
|
11726
|
+
logoUrl: '/Assets/logos/pka-logo.svg',
|
|
11727
|
+
logoMarkUrl: '/Assets/logos/pka-logo.svg',
|
|
11728
|
+
logoAlt: 'PKA',
|
|
11729
|
+
logoHeight: 24,
|
|
11730
|
+
primarySurface: '#CC006C',
|
|
11731
|
+
primaryContent: '#FFFFFF',
|
|
11732
|
+
secondarySurface: '#660036',
|
|
11733
|
+
secondaryContent: '#FFFFFF',
|
|
11734
|
+
organizationName: 'PKA',
|
|
11735
|
+
organizationId: 'pka'
|
|
11736
|
+
});
|
|
11737
|
+
this.updateCustomColorInputs();
|
|
11485
11738
|
}
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11739
|
+
applyClaveTheme() {
|
|
11740
|
+
this.currentTheme = 'clave';
|
|
11741
|
+
this.whitelabelService.updateConfig({
|
|
11742
|
+
logoUrl: '/Assets/logos/clave-logo.svg',
|
|
11743
|
+
logoMarkUrl: '/Assets/logos/clave-logo.svg',
|
|
11744
|
+
logoAlt: 'Clave',
|
|
11745
|
+
logoHeight: 24,
|
|
11746
|
+
primarySurface: '#868764',
|
|
11747
|
+
primaryContent: '#262424',
|
|
11748
|
+
secondarySurface: '#262424',
|
|
11749
|
+
secondaryContent: '#FFFFFF',
|
|
11750
|
+
organizationName: 'Clave',
|
|
11751
|
+
organizationId: 'clave'
|
|
11752
|
+
});
|
|
11753
|
+
this.updateCustomColorInputs();
|
|
11492
11754
|
}
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11755
|
+
applyCustomColors() {
|
|
11756
|
+
this.whitelabelService.updateColors({
|
|
11757
|
+
primarySurface: this.customPrimarySurface,
|
|
11758
|
+
primaryContent: this.customPrimaryContent,
|
|
11759
|
+
secondarySurface: this.customSecondarySurface,
|
|
11760
|
+
secondaryContent: this.customSecondaryContent
|
|
11761
|
+
});
|
|
11496
11762
|
}
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
@if (isNativePlatform()) {
|
|
11518
|
-
<ion-refresher
|
|
11519
|
-
slot="fixed"
|
|
11520
|
-
(ionRefresh)="handleRefresh($event)"
|
|
11521
|
-
[pullFactor]="0.4"
|
|
11522
|
-
[pullMin]="80"
|
|
11523
|
-
[pullMax]="240"
|
|
11524
|
-
closeDuration="600ms">
|
|
11525
|
-
<ion-refresher-content
|
|
11526
|
-
pullingIcon="remixArrowDownS"
|
|
11527
|
-
refreshingSpinner="lines">
|
|
11528
|
-
</ion-refresher-content>
|
|
11529
|
-
</ion-refresher>
|
|
11530
|
-
}
|
|
11531
|
-
|
|
11532
|
-
<!-- Expandable header section (purple background) -->
|
|
11533
|
-
<div class="header-expandable">
|
|
11534
|
-
<div class="header-expandable-inner">
|
|
11535
|
-
<div class="header-expandable__text">
|
|
11536
|
-
<h1 class="header-expandable__title">{{ inquiryTitle }}</h1>
|
|
11537
|
-
</div>
|
|
11538
|
-
|
|
11539
|
-
<!-- Tabs in header -->
|
|
11540
|
-
<ds-mobile-inline-tabs
|
|
11541
|
-
[tabs]="tabItems"
|
|
11542
|
-
[activeTab]="activeTab()"
|
|
11543
|
-
(tabChange)="setActiveTab($event)">
|
|
11544
|
-
</ds-mobile-inline-tabs>
|
|
11545
|
-
</div>
|
|
11763
|
+
updateCustomColorInputs() {
|
|
11764
|
+
this.customPrimarySurface = this.whitelabelService.primarySurface();
|
|
11765
|
+
this.customPrimaryContent = this.whitelabelService.primaryContent();
|
|
11766
|
+
this.customSecondarySurface = this.whitelabelService.secondarySurface();
|
|
11767
|
+
this.customSecondaryContent = this.whitelabelService.secondaryContent();
|
|
11768
|
+
}
|
|
11769
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11770
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: WhitelabelDemoModalComponent, isStandalone: true, selector: "ds-whitelabel-demo-modal", ngImport: i0, template: `
|
|
11771
|
+
<!-- Fixed Header -->
|
|
11772
|
+
<div class="modal-header">
|
|
11773
|
+
<div class="header-content">
|
|
11774
|
+
<span class="header-title">Whitelabel</span>
|
|
11775
|
+
<ds-icon-button
|
|
11776
|
+
icon="remixCloseLine"
|
|
11777
|
+
variant="secondary"
|
|
11778
|
+
size="lg"
|
|
11779
|
+
(click)="close()"
|
|
11780
|
+
class="close-button"
|
|
11781
|
+
aria-label="Close">
|
|
11782
|
+
</ds-icon-button>
|
|
11546
11783
|
</div>
|
|
11547
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11552
|
-
|
|
11553
|
-
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11568
|
-
</svg>
|
|
11569
|
-
</div>
|
|
11570
|
-
</div>
|
|
11571
|
-
} @else {
|
|
11572
|
-
<!-- Icon wrapper for non-actor activities -->
|
|
11573
|
-
<div class="activity-icon-wrapper">
|
|
11574
|
-
<ds-icon
|
|
11575
|
-
[name]="activity.iconName"
|
|
11576
|
-
size="18px"
|
|
11577
|
-
color="secondary" />
|
|
11578
|
-
</div>
|
|
11579
|
-
}
|
|
11580
|
-
|
|
11581
|
-
<div class="activity-content">
|
|
11582
|
-
<p class="activity-title">
|
|
11583
|
-
@if (activity.actor) {
|
|
11584
|
-
<span class="actor-name">{{ activity.actor }}</span>
|
|
11585
|
-
<span class="activity-text"> {{ activity.title }}</span>
|
|
11586
|
-
} @else {
|
|
11587
|
-
<span class="actor-name">{{ activity.title }}</span>
|
|
11588
|
-
}
|
|
11589
|
-
</p>
|
|
11590
|
-
@if (activity.description) {
|
|
11591
|
-
<p class="activity-description">{{ activity.description }}</p>
|
|
11592
|
-
}
|
|
11593
|
-
<div class="activity-timestamp">
|
|
11594
|
-
<ds-icon name="remixCalendarLine" size="12px" color="--color-text-tertiary" />
|
|
11595
|
-
<span>{{ activity.date }}</span>
|
|
11596
|
-
</div>
|
|
11597
|
-
</div>
|
|
11598
|
-
</div>
|
|
11599
|
-
}
|
|
11600
|
-
</div>
|
|
11601
|
-
}
|
|
11602
|
-
|
|
11603
|
-
<!-- Messages Tab Content -->
|
|
11604
|
-
@if (activeTab() === 'messages') {
|
|
11605
|
-
<div class="messages-list">
|
|
11606
|
-
@for (message of messageThreads; track message.id) {
|
|
11607
|
-
<ds-mobile-interactive-list-item-message
|
|
11608
|
-
[senderName]="message.senderName"
|
|
11609
|
-
[senderRole]="message.role"
|
|
11610
|
-
[message]="message.message"
|
|
11611
|
-
[avatarInitials]="message.senderInitials"
|
|
11612
|
-
[unread]="message.unread"
|
|
11613
|
-
(messageClick)="openMessage(message.id)">
|
|
11614
|
-
</ds-mobile-interactive-list-item-message>
|
|
11615
|
-
}
|
|
11784
|
+
</div>
|
|
11785
|
+
|
|
11786
|
+
<!-- Scrollable Content -->
|
|
11787
|
+
<ion-content [scrollY]="true" class="modal-content">
|
|
11788
|
+
<div class="demo-container">
|
|
11789
|
+
<!-- Theme Selection -->
|
|
11790
|
+
<div class="demo-section">
|
|
11791
|
+
<h2>Theme</h2>
|
|
11792
|
+
<div class="theme-buttons">
|
|
11793
|
+
<button class="theme-btn" (click)="applyDefaultTheme()" [class.active]="currentTheme === 'default'">
|
|
11794
|
+
Propbinder
|
|
11795
|
+
</button>
|
|
11796
|
+
<button class="theme-btn" (click)="applyCejTheme()" [class.active]="currentTheme === 'cej'">
|
|
11797
|
+
CEJ
|
|
11798
|
+
</button>
|
|
11799
|
+
<button class="theme-btn" (click)="applyPkaTheme()" [class.active]="currentTheme === 'pka'">
|
|
11800
|
+
PKA
|
|
11801
|
+
</button>
|
|
11802
|
+
<button class="theme-btn" (click)="applyClaveTheme()" [class.active]="currentTheme === 'clave'">
|
|
11803
|
+
Clave
|
|
11804
|
+
</button>
|
|
11616
11805
|
</div>
|
|
11617
|
-
|
|
11806
|
+
</div>
|
|
11618
11807
|
|
|
11619
|
-
<!--
|
|
11620
|
-
|
|
11621
|
-
<
|
|
11622
|
-
|
|
11623
|
-
<
|
|
11624
|
-
<
|
|
11625
|
-
|
|
11626
|
-
|
|
11627
|
-
[type]="'initials'"
|
|
11628
|
-
[initials]="'R'" />
|
|
11629
|
-
</div>
|
|
11630
|
-
<div content-main>
|
|
11631
|
-
<div class="detail-label">Sagsbehandler</div>
|
|
11632
|
-
<div class="detail-value">Ricki Meihlen</div>
|
|
11808
|
+
<!-- Logo & Logomark Preview -->
|
|
11809
|
+
<div class="demo-section">
|
|
11810
|
+
<h2>Logo Preview</h2>
|
|
11811
|
+
<div class="preview-grid">
|
|
11812
|
+
<div class="preview-tile">
|
|
11813
|
+
<h3>Logo</h3>
|
|
11814
|
+
<div class="logo-preview">
|
|
11815
|
+
<ds-logo variant="full" />
|
|
11633
11816
|
</div>
|
|
11634
|
-
</
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
<ds-avatar
|
|
11640
|
-
[size]="'sm'"
|
|
11817
|
+
</div>
|
|
11818
|
+
<div class="preview-tile">
|
|
11819
|
+
<h3>Logomark</h3>
|
|
11820
|
+
<div class="logomark-preview">
|
|
11821
|
+
<ds-avatar-with-badge
|
|
11641
11822
|
[type]="'initials'"
|
|
11642
|
-
[initials]="'
|
|
11823
|
+
[initials]="'KN'"
|
|
11824
|
+
[size]="'md'"
|
|
11825
|
+
[badgePosition]="'bottom-right'"
|
|
11826
|
+
/>
|
|
11643
11827
|
</div>
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11828
|
+
</div>
|
|
11829
|
+
</div>
|
|
11830
|
+
</div>
|
|
11831
|
+
|
|
11832
|
+
<!-- Brand Colors -->
|
|
11833
|
+
<div class="demo-section">
|
|
11834
|
+
<h2>Brand Colors</h2>
|
|
11835
|
+
<div class="color-section">
|
|
11836
|
+
<div class="color-swatches">
|
|
11837
|
+
<div class="swatch swatch--primary-surface">
|
|
11838
|
+
<div class="swatch-label">Primary Surface</div>
|
|
11839
|
+
<div class="swatch-value">{{ whitelabelService.primarySurface() }}</div>
|
|
11840
|
+
</div>
|
|
11841
|
+
<div class="swatch swatch--primary-content">
|
|
11842
|
+
<div class="swatch-label">Primary Content</div>
|
|
11843
|
+
<div class="swatch-value">{{ whitelabelService.primaryContent() }}</div>
|
|
11647
11844
|
</div>
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11652
|
-
<div content-leading>
|
|
11653
|
-
<ds-icon name="remixTextBlock" size="20px" color="tertiary" />
|
|
11845
|
+
<div class="swatch swatch--secondary-surface">
|
|
11846
|
+
<div class="swatch-label">Secondary Surface</div>
|
|
11847
|
+
<div class="swatch-value">{{ whitelabelService.secondarySurface() }}</div>
|
|
11654
11848
|
</div>
|
|
11655
|
-
<div content
|
|
11656
|
-
<div class="
|
|
11849
|
+
<div class="swatch swatch--secondary-content">
|
|
11850
|
+
<div class="swatch-label">Secondary Content</div>
|
|
11851
|
+
<div class="swatch-value">{{ whitelabelService.secondaryContent() }}</div>
|
|
11657
11852
|
</div>
|
|
11658
|
-
</
|
|
11853
|
+
</div>
|
|
11659
11854
|
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
<div
|
|
11663
|
-
<
|
|
11855
|
+
<div class="color-inputs">
|
|
11856
|
+
<div class="color-group-label">Primary</div>
|
|
11857
|
+
<div class="color-row">
|
|
11858
|
+
<label>Surface</label>
|
|
11859
|
+
<input
|
|
11860
|
+
type="color"
|
|
11861
|
+
[(ngModel)]="customPrimarySurface"
|
|
11862
|
+
(change)="applyCustomColors()"
|
|
11863
|
+
/>
|
|
11864
|
+
<input
|
|
11865
|
+
type="text"
|
|
11866
|
+
[(ngModel)]="customPrimarySurface"
|
|
11867
|
+
(change)="applyCustomColors()"
|
|
11868
|
+
/>
|
|
11664
11869
|
</div>
|
|
11665
|
-
<div
|
|
11666
|
-
<
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11870
|
+
<div class="color-row">
|
|
11871
|
+
<label>Content</label>
|
|
11872
|
+
<input
|
|
11873
|
+
type="color"
|
|
11874
|
+
[(ngModel)]="customPrimaryContent"
|
|
11875
|
+
(change)="applyCustomColors()"
|
|
11876
|
+
/>
|
|
11877
|
+
<input
|
|
11878
|
+
type="text"
|
|
11879
|
+
[(ngModel)]="customPrimaryContent"
|
|
11880
|
+
(change)="applyCustomColors()"
|
|
11881
|
+
/>
|
|
11670
11882
|
</div>
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
|
|
11883
|
+
|
|
11884
|
+
<div class="color-group-label">Secondary</div>
|
|
11885
|
+
<div class="color-row">
|
|
11886
|
+
<label>Surface</label>
|
|
11887
|
+
<input
|
|
11888
|
+
type="color"
|
|
11889
|
+
[(ngModel)]="customSecondarySurface"
|
|
11890
|
+
(change)="applyCustomColors()"
|
|
11891
|
+
/>
|
|
11892
|
+
<input
|
|
11893
|
+
type="text"
|
|
11894
|
+
[(ngModel)]="customSecondarySurface"
|
|
11895
|
+
(change)="applyCustomColors()"
|
|
11896
|
+
/>
|
|
11677
11897
|
</div>
|
|
11678
|
-
<div
|
|
11679
|
-
<
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11898
|
+
<div class="color-row">
|
|
11899
|
+
<label>Content</label>
|
|
11900
|
+
<input
|
|
11901
|
+
type="color"
|
|
11902
|
+
[(ngModel)]="customSecondaryContent"
|
|
11903
|
+
(change)="applyCustomColors()"
|
|
11904
|
+
/>
|
|
11905
|
+
<input
|
|
11906
|
+
type="text"
|
|
11907
|
+
[(ngModel)]="customSecondaryContent"
|
|
11908
|
+
(change)="applyCustomColors()"
|
|
11909
|
+
/>
|
|
11689
11910
|
</div>
|
|
11690
|
-
</
|
|
11911
|
+
</div>
|
|
11691
11912
|
</div>
|
|
11692
|
-
|
|
11913
|
+
</div>
|
|
11693
11914
|
</div>
|
|
11694
|
-
</div>
|
|
11695
11915
|
</ion-content>
|
|
11696
|
-
`, isInline: true, styles: ["
|
|
11916
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;background:var(--color-background-neutral-primary, #ffffff)}.modal-header{flex-shrink:0;background:var(--color-background-neutral-primary, #ffffff);border-bottom:1px solid var(--border-color-default, #e0e0e0);padding:0 16px}ion-content,.modal-content{--background: #ffffff;flex:1;width:100%}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:56px}.header-title{font-family:Brockmann,sans-serif;font-size:17px;font-weight:600;color:var(--color-text-primary, #1a1a1a);flex:1}.close-button{flex-shrink:0;border-radius:50%}.close-button::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important;background:var(--color-background-neutral-secondary, #f5f5f5)!important;color:var(--color-text-primary, #1a1a1a)!important}.demo-container{padding:20px;max-width:600px;margin:0 auto;width:100%}.demo-section{margin-bottom:32px}.demo-section h2{margin-bottom:16px;font-size:18px;font-weight:600;color:#333}.theme-buttons{display:flex;gap:12px;flex-wrap:wrap}.theme-btn{padding:8px 16px;border-radius:8px;font-size:14px;font-weight:500;border:none;cursor:pointer;transition:all .2s ease;background:#e0e0e0;color:#333}.theme-btn:active{transform:scale(.98)}.theme-btn.active{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.logo-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:var(--color-brand-secondary);border-radius:12px;min-height:80px}.logomark-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:#fff;border:1px solid #e0e0e0;border-radius:12px;min-height:80px}.preview-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.preview-tile{background:#fff;border-radius:12px}.preview-tile h3{font-size:13px;font-weight:600;color:#666;margin-top:0;margin-bottom:12px}.color-section{background:#fff;border-radius:12px}.color-swatches{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}.swatch{padding:16px;border-radius:8px;text-align:center}.swatch-label{font-size:12px;font-weight:600;margin-bottom:4px}.swatch-value{font-size:11px;opacity:.8;font-family:monospace}.swatch--primary-surface{background:var(--color-primary-surface);color:var(--color-primary-content)}.swatch--primary-content{background:var(--color-primary-content);color:var(--color-primary-surface);border:1px solid #e0e0e0}.swatch--secondary-surface{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.swatch--secondary-content{background:var(--color-secondary-content);color:var(--color-secondary-surface);border:1px solid #e0e0e0}.color-inputs{display:flex;flex-direction:column;gap:12px}.color-group-label{font-size:13px;font-weight:600;color:#333;margin-top:8px}.color-row{display:flex;align-items:center;gap:12px}.color-row label{min-width:70px;font-size:13px;color:#666}.color-row input[type=color]{width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;padding:0}.color-row input[type=text]{flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-family:monospace;font-size:13px}@supports (padding: env(safe-area-inset-bottom)){.demo-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: DsLogoComponent, selector: "ds-logo", inputs: ["variant", "size", "customHeight", "customWidth"] }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
|
|
11697
11917
|
}
|
|
11698
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
11918
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalComponent, decorators: [{
|
|
11699
11919
|
type: Component,
|
|
11700
|
-
args: [{ selector: '
|
|
11920
|
+
args: [{ selector: 'ds-whitelabel-demo-modal', standalone: true, imports: [
|
|
11701
11921
|
CommonModule,
|
|
11702
|
-
|
|
11703
|
-
IonToolbar,
|
|
11704
|
-
IonTitle,
|
|
11922
|
+
FormsModule,
|
|
11705
11923
|
IonContent,
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
|
|
11722
|
-
<ds-icon name="remixArrowLeftSLine" size="24px" color="white" />
|
|
11723
|
-
</button>
|
|
11724
|
-
|
|
11725
|
-
<!-- Title - fades in on scroll -->
|
|
11726
|
-
<ion-title class="header-detail__title">{{ inquiryTitle }}</ion-title>
|
|
11727
|
-
</div>
|
|
11728
|
-
</ion-toolbar>
|
|
11729
|
-
</ion-header>
|
|
11730
|
-
|
|
11731
|
-
<!-- Content with expandable header -->
|
|
11732
|
-
<ion-content [scrollEvents]="true" (ionScroll)="handleScroll($event)">
|
|
11733
|
-
<!-- Pull to refresh (only on native iOS/Android) -->
|
|
11734
|
-
@if (isNativePlatform()) {
|
|
11735
|
-
<ion-refresher
|
|
11736
|
-
slot="fixed"
|
|
11737
|
-
(ionRefresh)="handleRefresh($event)"
|
|
11738
|
-
[pullFactor]="0.4"
|
|
11739
|
-
[pullMin]="80"
|
|
11740
|
-
[pullMax]="240"
|
|
11741
|
-
closeDuration="600ms">
|
|
11742
|
-
<ion-refresher-content
|
|
11743
|
-
pullingIcon="remixArrowDownS"
|
|
11744
|
-
refreshingSpinner="lines">
|
|
11745
|
-
</ion-refresher-content>
|
|
11746
|
-
</ion-refresher>
|
|
11747
|
-
}
|
|
11748
|
-
|
|
11749
|
-
<!-- Expandable header section (purple background) -->
|
|
11750
|
-
<div class="header-expandable">
|
|
11751
|
-
<div class="header-expandable-inner">
|
|
11752
|
-
<div class="header-expandable__text">
|
|
11753
|
-
<h1 class="header-expandable__title">{{ inquiryTitle }}</h1>
|
|
11754
|
-
</div>
|
|
11755
|
-
|
|
11756
|
-
<!-- Tabs in header -->
|
|
11757
|
-
<ds-mobile-inline-tabs
|
|
11758
|
-
[tabs]="tabItems"
|
|
11759
|
-
[activeTab]="activeTab()"
|
|
11760
|
-
(tabChange)="setActiveTab($event)">
|
|
11761
|
-
</ds-mobile-inline-tabs>
|
|
11762
|
-
</div>
|
|
11924
|
+
DsLogoComponent,
|
|
11925
|
+
DsAvatarWithBadgeComponent,
|
|
11926
|
+
DsIconButtonComponent
|
|
11927
|
+
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
|
|
11928
|
+
<!-- Fixed Header -->
|
|
11929
|
+
<div class="modal-header">
|
|
11930
|
+
<div class="header-content">
|
|
11931
|
+
<span class="header-title">Whitelabel</span>
|
|
11932
|
+
<ds-icon-button
|
|
11933
|
+
icon="remixCloseLine"
|
|
11934
|
+
variant="secondary"
|
|
11935
|
+
size="lg"
|
|
11936
|
+
(click)="close()"
|
|
11937
|
+
class="close-button"
|
|
11938
|
+
aria-label="Close">
|
|
11939
|
+
</ds-icon-button>
|
|
11763
11940
|
</div>
|
|
11764
|
-
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11775
|
-
|
|
11776
|
-
|
|
11777
|
-
|
|
11778
|
-
|
|
11779
|
-
|
|
11780
|
-
|
|
11781
|
-
|
|
11782
|
-
|
|
11783
|
-
|
|
11784
|
-
|
|
11785
|
-
</svg>
|
|
11786
|
-
</div>
|
|
11787
|
-
</div>
|
|
11788
|
-
} @else {
|
|
11789
|
-
<!-- Icon wrapper for non-actor activities -->
|
|
11790
|
-
<div class="activity-icon-wrapper">
|
|
11791
|
-
<ds-icon
|
|
11792
|
-
[name]="activity.iconName"
|
|
11793
|
-
size="18px"
|
|
11794
|
-
color="secondary" />
|
|
11795
|
-
</div>
|
|
11796
|
-
}
|
|
11797
|
-
|
|
11798
|
-
<div class="activity-content">
|
|
11799
|
-
<p class="activity-title">
|
|
11800
|
-
@if (activity.actor) {
|
|
11801
|
-
<span class="actor-name">{{ activity.actor }}</span>
|
|
11802
|
-
<span class="activity-text"> {{ activity.title }}</span>
|
|
11803
|
-
} @else {
|
|
11804
|
-
<span class="actor-name">{{ activity.title }}</span>
|
|
11805
|
-
}
|
|
11806
|
-
</p>
|
|
11807
|
-
@if (activity.description) {
|
|
11808
|
-
<p class="activity-description">{{ activity.description }}</p>
|
|
11809
|
-
}
|
|
11810
|
-
<div class="activity-timestamp">
|
|
11811
|
-
<ds-icon name="remixCalendarLine" size="12px" color="--color-text-tertiary" />
|
|
11812
|
-
<span>{{ activity.date }}</span>
|
|
11813
|
-
</div>
|
|
11814
|
-
</div>
|
|
11815
|
-
</div>
|
|
11816
|
-
}
|
|
11817
|
-
</div>
|
|
11818
|
-
}
|
|
11819
|
-
|
|
11820
|
-
<!-- Messages Tab Content -->
|
|
11821
|
-
@if (activeTab() === 'messages') {
|
|
11822
|
-
<div class="messages-list">
|
|
11823
|
-
@for (message of messageThreads; track message.id) {
|
|
11824
|
-
<ds-mobile-interactive-list-item-message
|
|
11825
|
-
[senderName]="message.senderName"
|
|
11826
|
-
[senderRole]="message.role"
|
|
11827
|
-
[message]="message.message"
|
|
11828
|
-
[avatarInitials]="message.senderInitials"
|
|
11829
|
-
[unread]="message.unread"
|
|
11830
|
-
(messageClick)="openMessage(message.id)">
|
|
11831
|
-
</ds-mobile-interactive-list-item-message>
|
|
11832
|
-
}
|
|
11941
|
+
</div>
|
|
11942
|
+
|
|
11943
|
+
<!-- Scrollable Content -->
|
|
11944
|
+
<ion-content [scrollY]="true" class="modal-content">
|
|
11945
|
+
<div class="demo-container">
|
|
11946
|
+
<!-- Theme Selection -->
|
|
11947
|
+
<div class="demo-section">
|
|
11948
|
+
<h2>Theme</h2>
|
|
11949
|
+
<div class="theme-buttons">
|
|
11950
|
+
<button class="theme-btn" (click)="applyDefaultTheme()" [class.active]="currentTheme === 'default'">
|
|
11951
|
+
Propbinder
|
|
11952
|
+
</button>
|
|
11953
|
+
<button class="theme-btn" (click)="applyCejTheme()" [class.active]="currentTheme === 'cej'">
|
|
11954
|
+
CEJ
|
|
11955
|
+
</button>
|
|
11956
|
+
<button class="theme-btn" (click)="applyPkaTheme()" [class.active]="currentTheme === 'pka'">
|
|
11957
|
+
PKA
|
|
11958
|
+
</button>
|
|
11959
|
+
<button class="theme-btn" (click)="applyClaveTheme()" [class.active]="currentTheme === 'clave'">
|
|
11960
|
+
Clave
|
|
11961
|
+
</button>
|
|
11833
11962
|
</div>
|
|
11834
|
-
|
|
11963
|
+
</div>
|
|
11835
11964
|
|
|
11836
|
-
<!--
|
|
11837
|
-
|
|
11838
|
-
<
|
|
11839
|
-
|
|
11840
|
-
<
|
|
11841
|
-
<
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
[type]="'initials'"
|
|
11845
|
-
[initials]="'R'" />
|
|
11846
|
-
</div>
|
|
11847
|
-
<div content-main>
|
|
11848
|
-
<div class="detail-label">Sagsbehandler</div>
|
|
11849
|
-
<div class="detail-value">Ricki Meihlen</div>
|
|
11965
|
+
<!-- Logo & Logomark Preview -->
|
|
11966
|
+
<div class="demo-section">
|
|
11967
|
+
<h2>Logo Preview</h2>
|
|
11968
|
+
<div class="preview-grid">
|
|
11969
|
+
<div class="preview-tile">
|
|
11970
|
+
<h3>Logo</h3>
|
|
11971
|
+
<div class="logo-preview">
|
|
11972
|
+
<ds-logo variant="full" />
|
|
11850
11973
|
</div>
|
|
11851
|
-
</
|
|
11852
|
-
|
|
11853
|
-
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
<ds-avatar
|
|
11857
|
-
[size]="'sm'"
|
|
11974
|
+
</div>
|
|
11975
|
+
<div class="preview-tile">
|
|
11976
|
+
<h3>Logomark</h3>
|
|
11977
|
+
<div class="logomark-preview">
|
|
11978
|
+
<ds-avatar-with-badge
|
|
11858
11979
|
[type]="'initials'"
|
|
11859
|
-
[initials]="'
|
|
11980
|
+
[initials]="'KN'"
|
|
11981
|
+
[size]="'md'"
|
|
11982
|
+
[badgePosition]="'bottom-right'"
|
|
11983
|
+
/>
|
|
11860
11984
|
</div>
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11985
|
+
</div>
|
|
11986
|
+
</div>
|
|
11987
|
+
</div>
|
|
11988
|
+
|
|
11989
|
+
<!-- Brand Colors -->
|
|
11990
|
+
<div class="demo-section">
|
|
11991
|
+
<h2>Brand Colors</h2>
|
|
11992
|
+
<div class="color-section">
|
|
11993
|
+
<div class="color-swatches">
|
|
11994
|
+
<div class="swatch swatch--primary-surface">
|
|
11995
|
+
<div class="swatch-label">Primary Surface</div>
|
|
11996
|
+
<div class="swatch-value">{{ whitelabelService.primarySurface() }}</div>
|
|
11864
11997
|
</div>
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
<ds-mobile-list-item-static [leadingSize]="'32px'">
|
|
11869
|
-
<div content-leading>
|
|
11870
|
-
<ds-icon name="remixTextBlock" size="20px" color="tertiary" />
|
|
11998
|
+
<div class="swatch swatch--primary-content">
|
|
11999
|
+
<div class="swatch-label">Primary Content</div>
|
|
12000
|
+
<div class="swatch-value">{{ whitelabelService.primaryContent() }}</div>
|
|
11871
12001
|
</div>
|
|
11872
|
-
<div
|
|
11873
|
-
<div class="
|
|
12002
|
+
<div class="swatch swatch--secondary-surface">
|
|
12003
|
+
<div class="swatch-label">Secondary Surface</div>
|
|
12004
|
+
<div class="swatch-value">{{ whitelabelService.secondarySurface() }}</div>
|
|
11874
12005
|
</div>
|
|
11875
|
-
|
|
12006
|
+
<div class="swatch swatch--secondary-content">
|
|
12007
|
+
<div class="swatch-label">Secondary Content</div>
|
|
12008
|
+
<div class="swatch-value">{{ whitelabelService.secondaryContent() }}</div>
|
|
12009
|
+
</div>
|
|
12010
|
+
</div>
|
|
11876
12011
|
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
<div
|
|
11880
|
-
<
|
|
12012
|
+
<div class="color-inputs">
|
|
12013
|
+
<div class="color-group-label">Primary</div>
|
|
12014
|
+
<div class="color-row">
|
|
12015
|
+
<label>Surface</label>
|
|
12016
|
+
<input
|
|
12017
|
+
type="color"
|
|
12018
|
+
[(ngModel)]="customPrimarySurface"
|
|
12019
|
+
(change)="applyCustomColors()"
|
|
12020
|
+
/>
|
|
12021
|
+
<input
|
|
12022
|
+
type="text"
|
|
12023
|
+
[(ngModel)]="customPrimarySurface"
|
|
12024
|
+
(change)="applyCustomColors()"
|
|
12025
|
+
/>
|
|
11881
12026
|
</div>
|
|
11882
|
-
<div
|
|
11883
|
-
<
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
12027
|
+
<div class="color-row">
|
|
12028
|
+
<label>Content</label>
|
|
12029
|
+
<input
|
|
12030
|
+
type="color"
|
|
12031
|
+
[(ngModel)]="customPrimaryContent"
|
|
12032
|
+
(change)="applyCustomColors()"
|
|
12033
|
+
/>
|
|
12034
|
+
<input
|
|
12035
|
+
type="text"
|
|
12036
|
+
[(ngModel)]="customPrimaryContent"
|
|
12037
|
+
(change)="applyCustomColors()"
|
|
12038
|
+
/>
|
|
11887
12039
|
</div>
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
12040
|
+
|
|
12041
|
+
<div class="color-group-label">Secondary</div>
|
|
12042
|
+
<div class="color-row">
|
|
12043
|
+
<label>Surface</label>
|
|
12044
|
+
<input
|
|
12045
|
+
type="color"
|
|
12046
|
+
[(ngModel)]="customSecondarySurface"
|
|
12047
|
+
(change)="applyCustomColors()"
|
|
12048
|
+
/>
|
|
12049
|
+
<input
|
|
12050
|
+
type="text"
|
|
12051
|
+
[(ngModel)]="customSecondarySurface"
|
|
12052
|
+
(change)="applyCustomColors()"
|
|
12053
|
+
/>
|
|
11894
12054
|
</div>
|
|
11895
|
-
<div
|
|
11896
|
-
<
|
|
11897
|
-
|
|
11898
|
-
|
|
11899
|
-
|
|
11900
|
-
|
|
11901
|
-
|
|
11902
|
-
|
|
11903
|
-
|
|
11904
|
-
|
|
11905
|
-
|
|
12055
|
+
<div class="color-row">
|
|
12056
|
+
<label>Content</label>
|
|
12057
|
+
<input
|
|
12058
|
+
type="color"
|
|
12059
|
+
[(ngModel)]="customSecondaryContent"
|
|
12060
|
+
(change)="applyCustomColors()"
|
|
12061
|
+
/>
|
|
12062
|
+
<input
|
|
12063
|
+
type="text"
|
|
12064
|
+
[(ngModel)]="customSecondaryContent"
|
|
12065
|
+
(change)="applyCustomColors()"
|
|
12066
|
+
/>
|
|
11906
12067
|
</div>
|
|
11907
|
-
</
|
|
12068
|
+
</div>
|
|
11908
12069
|
</div>
|
|
11909
|
-
|
|
12070
|
+
</div>
|
|
11910
12071
|
</div>
|
|
11911
|
-
</div>
|
|
11912
12072
|
</ion-content>
|
|
11913
|
-
`, styles: ["
|
|
11914
|
-
}]
|
|
11915
|
-
|
|
11916
|
-
|
|
11917
|
-
|
|
12073
|
+
`, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%;background:var(--color-background-neutral-primary, #ffffff)}.modal-header{flex-shrink:0;background:var(--color-background-neutral-primary, #ffffff);border-bottom:1px solid var(--border-color-default, #e0e0e0);padding:0 16px}ion-content,.modal-content{--background: #ffffff;flex:1;width:100%}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:56px}.header-title{font-family:Brockmann,sans-serif;font-size:17px;font-weight:600;color:var(--color-text-primary, #1a1a1a);flex:1}.close-button{flex-shrink:0;border-radius:50%}.close-button::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important;background:var(--color-background-neutral-secondary, #f5f5f5)!important;color:var(--color-text-primary, #1a1a1a)!important}.demo-container{padding:20px;max-width:600px;margin:0 auto;width:100%}.demo-section{margin-bottom:32px}.demo-section h2{margin-bottom:16px;font-size:18px;font-weight:600;color:#333}.theme-buttons{display:flex;gap:12px;flex-wrap:wrap}.theme-btn{padding:8px 16px;border-radius:8px;font-size:14px;font-weight:500;border:none;cursor:pointer;transition:all .2s ease;background:#e0e0e0;color:#333}.theme-btn:active{transform:scale(.98)}.theme-btn.active{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.logo-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:var(--color-brand-secondary);border-radius:12px;min-height:80px}.logomark-preview{display:flex;align-items:center;justify-content:center;padding:24px;background:#fff;border:1px solid #e0e0e0;border-radius:12px;min-height:80px}.preview-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.preview-tile{background:#fff;border-radius:12px}.preview-tile h3{font-size:13px;font-weight:600;color:#666;margin-top:0;margin-bottom:12px}.color-section{background:#fff;border-radius:12px}.color-swatches{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}.swatch{padding:16px;border-radius:8px;text-align:center}.swatch-label{font-size:12px;font-weight:600;margin-bottom:4px}.swatch-value{font-size:11px;opacity:.8;font-family:monospace}.swatch--primary-surface{background:var(--color-primary-surface);color:var(--color-primary-content)}.swatch--primary-content{background:var(--color-primary-content);color:var(--color-primary-surface);border:1px solid #e0e0e0}.swatch--secondary-surface{background:var(--color-secondary-surface);color:var(--color-secondary-content)}.swatch--secondary-content{background:var(--color-secondary-content);color:var(--color-secondary-surface);border:1px solid #e0e0e0}.color-inputs{display:flex;flex-direction:column;gap:12px}.color-group-label{font-size:13px;font-weight:600;color:#333;margin-top:8px}.color-row{display:flex;align-items:center;gap:12px}.color-row label{min-width:70px;font-size:13px;color:#666}.color-row input[type=color]{width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;padding:0}.color-row input[type=text]{flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:6px;font-family:monospace;font-size:13px}@supports (padding: env(safe-area-inset-bottom)){.demo-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"] }]
|
|
12074
|
+
}] });
|
|
12075
|
+
|
|
12076
|
+
/**
|
|
12077
|
+
* WhitelabelDemoModalService
|
|
12078
|
+
*
|
|
12079
|
+
* Service for displaying the whitelabel demo in a full-screen modal.
|
|
12080
|
+
* Built on Ionic's modal system with native gestures and animations.
|
|
12081
|
+
*
|
|
12082
|
+
* @example
|
|
12083
|
+
* ```typescript
|
|
12084
|
+
* constructor(private whitelabelModal: WhitelabelDemoModalService) {}
|
|
12085
|
+
*
|
|
12086
|
+
* async openDemo() {
|
|
12087
|
+
* await this.whitelabelModal.open();
|
|
12088
|
+
* }
|
|
12089
|
+
* ```
|
|
12090
|
+
*/
|
|
12091
|
+
class WhitelabelDemoModalService {
|
|
12092
|
+
modalController;
|
|
12093
|
+
constructor(modalController) {
|
|
12094
|
+
this.modalController = modalController;
|
|
12095
|
+
}
|
|
12096
|
+
/**
|
|
12097
|
+
* Open the whitelabel demo modal
|
|
12098
|
+
*
|
|
12099
|
+
* @returns Promise that resolves when the modal is presented
|
|
12100
|
+
*/
|
|
12101
|
+
async open() {
|
|
12102
|
+
try {
|
|
12103
|
+
console.log('[WhitelabelDemoModal] Opening...');
|
|
12104
|
+
const modal = await this.modalController.create({
|
|
12105
|
+
component: WhitelabelDemoModalComponent,
|
|
12106
|
+
cssClass: 'ds-whitelabel-demo-modal',
|
|
12107
|
+
mode: 'ios',
|
|
12108
|
+
presentingElement: document.querySelector('ion-router-outlet') || undefined,
|
|
12109
|
+
backdropDismiss: true,
|
|
12110
|
+
showBackdrop: true,
|
|
12111
|
+
animated: true,
|
|
12112
|
+
keyboardClose: true
|
|
12113
|
+
});
|
|
12114
|
+
console.log('[WhitelabelDemoModal] Modal created, presenting...');
|
|
12115
|
+
await modal.present();
|
|
12116
|
+
console.log('[WhitelabelDemoModal] Modal presented');
|
|
12117
|
+
}
|
|
12118
|
+
catch (error) {
|
|
12119
|
+
console.error('[WhitelabelDemoModal] Error opening modal:', error);
|
|
12120
|
+
throw error;
|
|
12121
|
+
}
|
|
12122
|
+
}
|
|
12123
|
+
/**
|
|
12124
|
+
* Close the currently open whitelabel demo modal
|
|
12125
|
+
*
|
|
12126
|
+
* @param data Optional data to pass back when dismissing
|
|
12127
|
+
* @returns Promise that resolves when the modal is dismissed
|
|
12128
|
+
*/
|
|
12129
|
+
async close(data) {
|
|
12130
|
+
return this.modalController.dismiss(data);
|
|
12131
|
+
}
|
|
12132
|
+
/**
|
|
12133
|
+
* Get the top-most modal if one exists
|
|
12134
|
+
*
|
|
12135
|
+
* @returns Promise that resolves to the modal element or undefined
|
|
12136
|
+
*/
|
|
12137
|
+
async getTop() {
|
|
12138
|
+
return this.modalController.getTop();
|
|
12139
|
+
}
|
|
12140
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
12141
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalService, providedIn: 'root' });
|
|
12142
|
+
}
|
|
12143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: WhitelabelDemoModalService, decorators: [{
|
|
12144
|
+
type: Injectable,
|
|
12145
|
+
args: [{
|
|
12146
|
+
providedIn: 'root'
|
|
12147
|
+
}]
|
|
12148
|
+
}], ctorParameters: () => [{ type: i1.ModalController }] });
|
|
11918
12149
|
|
|
11919
12150
|
/**
|
|
11920
12151
|
* MobileTabsExampleComponent
|
|
@@ -11939,6 +12170,8 @@ class MobileTabsExampleComponent {
|
|
|
11939
12170
|
// Configure user avatar globally - this is now the single source of truth
|
|
11940
12171
|
this.userService.setAvatarInitials('LM');
|
|
11941
12172
|
this.userService.setAvatarType('initials');
|
|
12173
|
+
// Set profile menu items globally - this will be used by both tab bar and page-main components
|
|
12174
|
+
this.userService.setProfileMenuItems(this.profileMenuItems);
|
|
11942
12175
|
}
|
|
11943
12176
|
tabs = [
|
|
11944
12177
|
{
|
|
@@ -11972,7 +12205,9 @@ class MobileTabsExampleComponent {
|
|
|
11972
12205
|
];
|
|
11973
12206
|
/**
|
|
11974
12207
|
* Profile menu items configuration.
|
|
11975
|
-
* Define once here
|
|
12208
|
+
* Define once here - this is set globally in UserService in ngOnInit(),
|
|
12209
|
+
* so it will be used by both ds-mobile-tab-bar and ds-mobile-page-main components
|
|
12210
|
+
* throughout the entire application.
|
|
11976
12211
|
*/
|
|
11977
12212
|
profileMenuItems = [
|
|
11978
12213
|
{
|
|
@@ -13034,5 +13269,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
13034
13269
|
* Generated bundle index. Do not edit.
|
|
13035
13270
|
*/
|
|
13036
13271
|
|
|
13037
|
-
export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsMobileActionsBottomSheetComponent, DsMobileBottomSheetService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLongPressDirective, DsMobileModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileTabBarComponent, DsMobileTabsComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoPage, WhitelabelService, customBackTransition, customPageTransition };
|
|
13272
|
+
export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsMobileActionsBottomSheetComponent, DsMobileBottomSheetService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLongPressDirective, DsMobileModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileTabBarComponent, DsMobileTabsComponent, DsTextInputComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoPage, WhitelabelService, customBackTransition, customPageTransition };
|
|
13038
13273
|
//# sourceMappingURL=propbinder-mobile-design.mjs.map
|