@propbinder/mobile-design 0.2.7 → 0.2.9

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.
@@ -11799,6 +11799,264 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11799
11799
  `, styles: [":host{display:flex;align-items:center;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease;box-sizing:border-box}:host(.variant-default){gap:12px;padding:10px 12px}:host(.variant-compact){gap:8px;padding:10px}@media (hover: hover) and (pointer: fine){:host(:hover):not(.disabled){background:var(--color-background-neutral-secondary-hover, #ebebeb)}}:host(:active):not(.disabled){transform:scale(.98);background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host(:focus-visible):not(.disabled){outline:2px solid var(--color-brand-primary, #5d5fef);outline-offset:2px}:host(.disabled){opacity:.5;pointer-events:none;cursor:not-allowed}.card-inline-inner{display:flex;align-items:center;gap:inherit;width:100%;min-width:0}.content-leading{flex-shrink:0;display:flex;align-items:center;justify-content:center}.content-main{flex:1;min-width:0;display:flex;align-items:center}:host(.variant-compact) .content-main{flex-direction:row;gap:8px}:host(.variant-default) .content-main{flex-direction:column;align-items:flex-start;gap:2px}.content-trailing{flex-shrink:0;display:flex;align-items:center}::ng-deep .item-avatar{flex-shrink:0}::ng-deep .item-content{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:2px}:host(.variant-compact) ::ng-deep .item-content{flex-direction:row;align-items:center;justify-content:flex-start;gap:8px}::ng-deep .item-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left}::ng-deep .item-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);margin:0;display:flex;align-items:center;justify-content:flex-start;gap:4px;white-space:nowrap;flex-shrink:0}::ng-deep .item-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"] }]
11800
11800
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], cardClick: [{ type: i0.Output, args: ["cardClick"] }] } });
11801
11801
 
11802
+ /**
11803
+ * DsMobileCardInlineBannerComponent
11804
+ *
11805
+ * Specialized interactive component for displaying notification banners.
11806
+ * Used to show unread message notifications above inquiry details.
11807
+ *
11808
+ * Features:
11809
+ * - Neutral background matching file/contact cards
11810
+ * - Avatar icon with message symbol
11811
+ * - Title and timestamp
11812
+ * - Unread count badge
11813
+ * - Chevron for navigation indication
11814
+ *
11815
+ * @example
11816
+ * ```html
11817
+ * <ds-mobile-card-inline-banner
11818
+ * [title]="'New messages'"
11819
+ * [timestamp]="'2 min ago'"
11820
+ * [unreadCount]="3"
11821
+ * (bannerClick)="navigateToMessages()">
11822
+ * </ds-mobile-card-inline-banner>
11823
+ * ```
11824
+ */
11825
+ class DsMobileCardInlineBannerComponent {
11826
+ /**
11827
+ * Banner title (e.g., "New messages", "Unread messages")
11828
+ */
11829
+ title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
11830
+ /**
11831
+ * Timestamp text (e.g., "2 min ago", "Just now")
11832
+ */
11833
+ timestamp = input('', ...(ngDevMode ? [{ debugName: "timestamp" }] : []));
11834
+ /**
11835
+ * Number of unread items (optional, shows badge if > 0)
11836
+ */
11837
+ unreadCount = input(0, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
11838
+ /**
11839
+ * Layout variant
11840
+ * - 'default' - Standard padding and column layout
11841
+ * - 'compact' - Reduced padding and row layout
11842
+ */
11843
+ layout = input('default', ...(ngDevMode ? [{ debugName: "layout" }] : []));
11844
+ /**
11845
+ * Emits when the banner is clicked
11846
+ */
11847
+ bannerClick = output();
11848
+ handleBannerClick() {
11849
+ this.bannerClick.emit();
11850
+ }
11851
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11852
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineBannerComponent, isStandalone: true, selector: "ds-mobile-card-inline-banner", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, timestamp: { classPropertyName: "timestamp", publicName: "timestamp", isSignal: true, isRequired: false, transformFunction: null }, unreadCount: { classPropertyName: "unreadCount", publicName: "unreadCount", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bannerClick: "bannerClick" }, ngImport: i0, template: `
11853
+ <ds-mobile-card-inline
11854
+ [variant]="layout()"
11855
+ (cardClick)="handleBannerClick()">
11856
+
11857
+ <div content-leading class="item-avatar">
11858
+ <ds-avatar
11859
+ type="icon"
11860
+ [iconName]="'remixNotificationLine'"
11861
+ [size]="layout() === 'compact' ? 'sm' : 'md'"
11862
+ />
11863
+ </div>
11864
+
11865
+ <div content-main class="item-content">
11866
+ <div class="item-name">{{ title() }}</div>
11867
+
11868
+ @if (timestamp()) {
11869
+ <div class="item-meta">
11870
+ <span>{{ timestamp() }}</span>
11871
+ </div>
11872
+ }
11873
+ </div>
11874
+
11875
+ <div content-trailing class="item-trailing">
11876
+ @if (unreadCount() && unreadCount()! > 0) {
11877
+ <span class="unread-badge">{{ unreadCount() }}</span>
11878
+ }
11879
+ <ds-icon name="remixArrowRightSLine" size="20px" />
11880
+ </div>
11881
+ </ds-mobile-card-inline>
11882
+ `, isInline: true, styles: [".unread-badge{min-width:24px;height:16px;padding:0 6px;border-radius:10px;background:var(--color-primary-surface, #6B5FF5);color:var(--color-primary-content, #ffffff);font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:600;display:flex;align-items:center;justify-content:center;line-height:1;margin-right:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
11883
+ }
11884
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineBannerComponent, decorators: [{
11885
+ type: Component,
11886
+ args: [{ selector: 'ds-mobile-card-inline-banner', standalone: true, imports: [CommonModule, DsIconComponent, DsAvatarComponent, DsMobileCardInlineComponent], template: `
11887
+ <ds-mobile-card-inline
11888
+ [variant]="layout()"
11889
+ (cardClick)="handleBannerClick()">
11890
+
11891
+ <div content-leading class="item-avatar">
11892
+ <ds-avatar
11893
+ type="icon"
11894
+ [iconName]="'remixNotificationLine'"
11895
+ [size]="layout() === 'compact' ? 'sm' : 'md'"
11896
+ />
11897
+ </div>
11898
+
11899
+ <div content-main class="item-content">
11900
+ <div class="item-name">{{ title() }}</div>
11901
+
11902
+ @if (timestamp()) {
11903
+ <div class="item-meta">
11904
+ <span>{{ timestamp() }}</span>
11905
+ </div>
11906
+ }
11907
+ </div>
11908
+
11909
+ <div content-trailing class="item-trailing">
11910
+ @if (unreadCount() && unreadCount()! > 0) {
11911
+ <span class="unread-badge">{{ unreadCount() }}</span>
11912
+ }
11913
+ <ds-icon name="remixArrowRightSLine" size="20px" />
11914
+ </div>
11915
+ </ds-mobile-card-inline>
11916
+ `, styles: [".unread-badge{min-width:24px;height:16px;padding:0 6px;border-radius:10px;background:var(--color-primary-surface, #6B5FF5);color:var(--color-primary-content, #ffffff);font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:600;display:flex;align-items:center;justify-content:center;line-height:1;margin-right:8px}\n"] }]
11917
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], timestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "timestamp", required: false }] }], unreadCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "unreadCount", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], bannerClick: [{ type: i0.Output, args: ["bannerClick"] }] } });
11918
+
11919
+ /**
11920
+ * DsMobileCardInlineContactComponent
11921
+ *
11922
+ * Specialized interactive component for displaying contacts.
11923
+ * Displays contact name with avatar initials and metadata (person name + phone number).
11924
+ * Similar styling to file attachments with rounded corners and hover states.
11925
+ *
11926
+ * @example
11927
+ * ```html
11928
+ * <ds-mobile-card-inline-contact
11929
+ * [name]="'Mortensen & Søn ApS'"
11930
+ * [initials]="'M'"
11931
+ * [contactPerson]="'John Mortensen'"
11932
+ * [phoneNumber]="'+45 12 34 56 78'"
11933
+ * [clickable]="true"
11934
+ * (contactClick)="openContact()">
11935
+ * </ds-mobile-card-inline-contact>
11936
+ * ```
11937
+ */
11938
+ class DsMobileCardInlineContactComponent {
11939
+ /**
11940
+ * Contact/company name
11941
+ */
11942
+ name = input.required(...(ngDevMode ? [{ debugName: "name" }] : []));
11943
+ /**
11944
+ * Avatar initials (usually 1-2 letters)
11945
+ */
11946
+ initials = input.required(...(ngDevMode ? [{ debugName: "initials" }] : []));
11947
+ /**
11948
+ * Contact person name (optional)
11949
+ */
11950
+ contactPerson = input('', ...(ngDevMode ? [{ debugName: "contactPerson" }] : []));
11951
+ /**
11952
+ * Phone number (optional)
11953
+ */
11954
+ phoneNumber = input('', ...(ngDevMode ? [{ debugName: "phoneNumber" }] : []));
11955
+ /**
11956
+ * Layout variant
11957
+ * - 'default' - Standard padding and column layout
11958
+ * - 'compact' - Reduced padding and row layout
11959
+ */
11960
+ layout = input('default', ...(ngDevMode ? [{ debugName: "layout" }] : []));
11961
+ /**
11962
+ * Whether the contact item is clickable
11963
+ */
11964
+ clickable = input(true, ...(ngDevMode ? [{ debugName: "clickable" }] : []));
11965
+ /**
11966
+ * Whether to show chevron icon
11967
+ */
11968
+ showChevron = input(true, ...(ngDevMode ? [{ debugName: "showChevron" }] : []));
11969
+ /**
11970
+ * Emits when the contact item is clicked (if clickable)
11971
+ */
11972
+ contactClick = output();
11973
+ handleContactClick() {
11974
+ this.contactClick.emit();
11975
+ }
11976
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineContactComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11977
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineContactComponent, isStandalone: true, selector: "ds-mobile-card-inline-contact", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: true, transformFunction: null }, contactPerson: { classPropertyName: "contactPerson", publicName: "contactPerson", isSignal: true, isRequired: false, transformFunction: null }, phoneNumber: { classPropertyName: "phoneNumber", publicName: "phoneNumber", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contactClick: "contactClick" }, ngImport: i0, template: `
11978
+ <ds-mobile-card-inline
11979
+ [variant]="layout()"
11980
+ [disabled]="!clickable()"
11981
+ (cardClick)="handleContactClick()">
11982
+
11983
+ <div content-leading class="item-avatar">
11984
+ <ds-avatar
11985
+ [initials]="initials()"
11986
+ type="initials"
11987
+ [size]="layout() === 'compact' ? 'sm' : 'md'"
11988
+ />
11989
+ </div>
11990
+
11991
+ <div content-main class="item-content">
11992
+ <div class="item-name">{{ name() }}</div>
11993
+
11994
+ @if (contactPerson() || phoneNumber()) {
11995
+ <div class="item-meta">
11996
+ @if (contactPerson()) {
11997
+ <span>{{ contactPerson() }}</span>
11998
+ }
11999
+ @if (contactPerson() && phoneNumber()) {
12000
+ <span>·</span>
12001
+ }
12002
+ @if (phoneNumber()) {
12003
+ <span>{{ phoneNumber() }}</span>
12004
+ }
12005
+ </div>
12006
+ }
12007
+ </div>
12008
+
12009
+ @if (showChevron()) {
12010
+ <div content-trailing class="item-trailing">
12011
+ <ds-icon name="remixArrowRightSLine" size="20px" />
12012
+ </div>
12013
+ }
12014
+ </ds-mobile-card-inline>
12015
+ `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
12016
+ }
12017
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineContactComponent, decorators: [{
12018
+ type: Component,
12019
+ args: [{ selector: 'ds-mobile-card-inline-contact', standalone: true, imports: [CommonModule, DsIconComponent, DsAvatarComponent, DsMobileCardInlineComponent], template: `
12020
+ <ds-mobile-card-inline
12021
+ [variant]="layout()"
12022
+ [disabled]="!clickable()"
12023
+ (cardClick)="handleContactClick()">
12024
+
12025
+ <div content-leading class="item-avatar">
12026
+ <ds-avatar
12027
+ [initials]="initials()"
12028
+ type="initials"
12029
+ [size]="layout() === 'compact' ? 'sm' : 'md'"
12030
+ />
12031
+ </div>
12032
+
12033
+ <div content-main class="item-content">
12034
+ <div class="item-name">{{ name() }}</div>
12035
+
12036
+ @if (contactPerson() || phoneNumber()) {
12037
+ <div class="item-meta">
12038
+ @if (contactPerson()) {
12039
+ <span>{{ contactPerson() }}</span>
12040
+ }
12041
+ @if (contactPerson() && phoneNumber()) {
12042
+ <span>·</span>
12043
+ }
12044
+ @if (phoneNumber()) {
12045
+ <span>{{ phoneNumber() }}</span>
12046
+ }
12047
+ </div>
12048
+ }
12049
+ </div>
12050
+
12051
+ @if (showChevron()) {
12052
+ <div content-trailing class="item-trailing">
12053
+ <ds-icon name="remixArrowRightSLine" size="20px" />
12054
+ </div>
12055
+ }
12056
+ </ds-mobile-card-inline>
12057
+ ` }]
12058
+ }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: true }] }], contactPerson: [{ type: i0.Input, args: [{ isSignal: true, alias: "contactPerson", required: false }] }], phoneNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneNumber", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], contactClick: [{ type: i0.Output, args: ["contactClick"] }] } });
12059
+
11802
12060
  /**
11803
12061
  * DsMobileCardInlineFileComponent
11804
12062
  *
@@ -11824,7 +12082,7 @@ class DsMobileCardInlineFileComponent {
11824
12082
  */
11825
12083
  fileName = input('Document', ...(ngDevMode ? [{ debugName: "fileName" }] : []));
11826
12084
  /**
11827
- * File size display (e.g., "1.2 MB")
12085
+ * File size display (e.g., '1.2 MB')
11828
12086
  */
11829
12087
  fileSize = input('', ...(ngDevMode ? [{ debugName: "fileSize" }] : []));
11830
12088
  /**
@@ -11839,6 +12097,11 @@ class DsMobileCardInlineFileComponent {
11839
12097
  * - 'compact' - Reduced padding and row layout
11840
12098
  */
11841
12099
  layout = input('default', ...(ngDevMode ? [{ debugName: "layout" }] : []));
12100
+ /**
12101
+ * Optional URL to open when clicked
12102
+ * If provided, clicking the card will open this URL in a new tab
12103
+ */
12104
+ fileUrl = input(undefined, ...(ngDevMode ? [{ debugName: "fileUrl" }] : []));
11842
12105
  /**
11843
12106
  * Emits when the file attachment is clicked
11844
12107
  */
@@ -11847,7 +12110,9 @@ class DsMobileCardInlineFileComponent {
11847
12110
  * Get the appropriate icon name based on variant
11848
12111
  */
11849
12112
  getIconName() {
11850
- return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';
12113
+ return this.variant() === 'pdf'
12114
+ ? 'remixFileTextLine'
12115
+ : 'remixAttachmentLine';
11851
12116
  }
11852
12117
  /**
11853
12118
  * Get the file type label based on variant
@@ -11856,73 +12121,87 @@ class DsMobileCardInlineFileComponent {
11856
12121
  return this.variant() === 'pdf' ? 'PDF' : 'DOC';
11857
12122
  }
11858
12123
  handleClick() {
12124
+ const url = this.fileUrl();
12125
+ console.log(url);
12126
+ if (url) {
12127
+ window.open(url, '_blank', 'noopener,noreferrer');
12128
+ }
11859
12129
  this.fileClick.emit();
11860
12130
  }
11861
12131
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11862
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineFileComponent, isStandalone: true, selector: "ds-mobile-card-inline-file", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, ngImport: i0, template: `
11863
- <ds-mobile-card-inline
11864
- [variant]="layout()"
11865
- (cardClick)="handleClick()">
11866
-
11867
- <div content-leading class="item-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
12132
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineFileComponent, isStandalone: true, selector: "ds-mobile-card-inline-file", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, fileUrl: { classPropertyName: "fileUrl", publicName: "fileUrl", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, ngImport: i0, template: `
12133
+ <ds-mobile-card-inline [variant]="layout()" (cardClick)="handleClick()">
12134
+ <div
12135
+ content-leading
12136
+ class="item-avatar"
12137
+ [class.pdf]="variant() === 'pdf'"
12138
+ [class.doc]="variant() === 'doc'"
12139
+ >
11868
12140
  <ds-avatar
11869
12141
  type="icon"
11870
12142
  [iconName]="getIconName()"
11871
12143
  [size]="layout() === 'compact' ? 'sm' : 'md'"
11872
12144
  />
11873
12145
  </div>
11874
-
12146
+
11875
12147
  <div content-main class="item-content">
11876
12148
  <div class="item-name">{{ fileName() }}</div>
11877
12149
  @if (fileSize()) {
11878
- <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
12150
+ <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
11879
12151
  } @else {
11880
- <div class="item-meta">{{ getFileTypeLabel() }}</div>
12152
+ <div class="item-meta">{{ getFileTypeLabel() }}</div>
11881
12153
  }
11882
12154
  </div>
11883
-
11884
- <ds-icon
12155
+
12156
+ <ds-icon
11885
12157
  content-trailing
11886
- name="remixArrowRightSLine"
12158
+ name="remixArrowRightSLine"
11887
12159
  size="20px"
11888
12160
  class="item-trailing"
11889
12161
  />
11890
12162
  </ds-mobile-card-inline>
11891
- `, isInline: true, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
12163
+ `, isInline: true, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3b82f6)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
11892
12164
  }
11893
12165
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineFileComponent, decorators: [{
11894
12166
  type: Component,
11895
- args: [{ selector: 'ds-mobile-card-inline-file', standalone: true, imports: [CommonModule, DsAvatarComponent, DsIconComponent, DsMobileCardInlineComponent], template: `
11896
- <ds-mobile-card-inline
11897
- [variant]="layout()"
11898
- (cardClick)="handleClick()">
11899
-
11900
- <div content-leading class="item-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
12167
+ args: [{ selector: 'ds-mobile-card-inline-file', standalone: true, imports: [
12168
+ CommonModule,
12169
+ DsAvatarComponent,
12170
+ DsIconComponent,
12171
+ DsMobileCardInlineComponent,
12172
+ ], template: `
12173
+ <ds-mobile-card-inline [variant]="layout()" (cardClick)="handleClick()">
12174
+ <div
12175
+ content-leading
12176
+ class="item-avatar"
12177
+ [class.pdf]="variant() === 'pdf'"
12178
+ [class.doc]="variant() === 'doc'"
12179
+ >
11901
12180
  <ds-avatar
11902
12181
  type="icon"
11903
12182
  [iconName]="getIconName()"
11904
12183
  [size]="layout() === 'compact' ? 'sm' : 'md'"
11905
12184
  />
11906
12185
  </div>
11907
-
12186
+
11908
12187
  <div content-main class="item-content">
11909
12188
  <div class="item-name">{{ fileName() }}</div>
11910
12189
  @if (fileSize()) {
11911
- <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
12190
+ <div class="item-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
11912
12191
  } @else {
11913
- <div class="item-meta">{{ getFileTypeLabel() }}</div>
12192
+ <div class="item-meta">{{ getFileTypeLabel() }}</div>
11914
12193
  }
11915
12194
  </div>
11916
-
11917
- <ds-icon
12195
+
12196
+ <ds-icon
11918
12197
  content-trailing
11919
- name="remixArrowRightSLine"
12198
+ name="remixArrowRightSLine"
11920
12199
  size="20px"
11921
12200
  class="item-trailing"
11922
12201
  />
11923
12202
  </ds-mobile-card-inline>
11924
- `, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}\n"] }]
11925
- }], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
12203
+ `, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3b82f6)!important}\n"] }]
12204
+ }], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], fileUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileUrl", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
11926
12205
 
11927
12206
  /**
11928
12207
  * DsMobileSystemMessageBannerComponent
@@ -12126,7 +12405,7 @@ class DsMobileChatModalComponent {
12126
12405
  // Track keyboard state
12127
12406
  this.isKeyboardVisible = true;
12128
12407
  // Check if user is near bottom before auto-scrolling
12129
- this.isNearBottom().then(isNear => {
12408
+ this.isNearBottom().then((isNear) => {
12130
12409
  if (isNear) {
12131
12410
  // User is already viewing latest messages, maintain that position
12132
12411
  // Small delay to synchronize with keyboard animation
@@ -12185,7 +12464,7 @@ class DsMobileChatModalComponent {
12185
12464
  avatarType: this.currentUserAvatarType(),
12186
12465
  avatarSrc: this.currentUserAvatarSrc(),
12187
12466
  fileAttachments: event.attachments || [],
12188
- isNewMessage: true // Mark as new message to trigger animation
12467
+ isNewMessage: true, // Mark as new message to trigger animation
12189
12468
  };
12190
12469
  // Add message to list
12191
12470
  const updatedMessages = [...this.messages(), newMessage];
@@ -12193,7 +12472,7 @@ class DsMobileChatModalComponent {
12193
12472
  // Remove the isNewMessage flag after animation completes (using spring-bouncy duration ~600ms)
12194
12473
  setTimeout(() => {
12195
12474
  const msgs = this.messages();
12196
- const msgIndex = msgs.findIndex(m => m.id === newMessage.id);
12475
+ const msgIndex = msgs.findIndex((m) => m.id === newMessage.id);
12197
12476
  if (msgIndex !== -1) {
12198
12477
  msgs[msgIndex].isNewMessage = false;
12199
12478
  this.messages.set([...msgs]);
@@ -12250,7 +12529,10 @@ class DsMobileChatModalComponent {
12250
12529
  timestamp: this.formatMessageTimestamp(ownerMessage.timestamp),
12251
12530
  avatarInitials: ownerMessage.avatarInitials,
12252
12531
  avatarSrc: ownerMessage.avatarSrc,
12253
- avatarType: ownerMessage.avatarType === 'photo' || ownerMessage.avatarType === 'initials' ? ownerMessage.avatarType : undefined,
12532
+ avatarType: ownerMessage.avatarType === 'photo' ||
12533
+ ownerMessage.avatarType === 'initials'
12534
+ ? ownerMessage.avatarType
12535
+ : undefined,
12254
12536
  }
12255
12537
  : undefined;
12256
12538
  this.lightboxService.openImages({
@@ -12287,7 +12569,7 @@ class DsMobileChatModalComponent {
12287
12569
  requestAnimationFrame(() => {
12288
12570
  requestAnimationFrame(() => {
12289
12571
  setTimeout(() => {
12290
- this.isNearBottom().then(isNear => {
12572
+ this.isNearBottom().then((isNear) => {
12291
12573
  if (isNear) {
12292
12574
  // User is at bottom, maintain that position as composer expands
12293
12575
  this.scrollToBottom();
@@ -12307,7 +12589,7 @@ class DsMobileChatModalComponent {
12307
12589
  .then(() => {
12308
12590
  this.isKeyboardVisible = false;
12309
12591
  })
12310
- .catch(e => console.log('[ChatModal] Keyboard.hide() not available:', e));
12592
+ .catch((e) => console.log('[ChatModal] Keyboard.hide() not available:', e));
12311
12593
  }
12312
12594
  /**
12313
12595
  * Get file variant for card-inline-file component
@@ -12327,26 +12609,28 @@ class DsMobileChatModalComponent {
12327
12609
  */
12328
12610
  async handleImageClick(attachment, message) {
12329
12611
  await this.lightboxService.openImages({
12330
- images: [{
12612
+ images: [
12613
+ {
12331
12614
  type: 'image',
12332
12615
  src: attachment.src,
12333
12616
  title: attachment.name || 'Image',
12334
- alt: attachment.name || 'Chat image'
12335
- }],
12617
+ alt: attachment.name || 'Chat image',
12618
+ },
12619
+ ],
12336
12620
  author: {
12337
12621
  name: message.senderName,
12338
12622
  role: message.senderRole,
12339
12623
  avatarInitials: message.avatarInitials,
12340
12624
  avatarType: message.avatarType === 'initials' ? 'initials' : 'photo',
12341
12625
  avatarSrc: message.avatarSrc,
12342
- timestamp: this.formatMessageTimestamp(message.timestamp)
12626
+ timestamp: this.formatMessageTimestamp(message.timestamp),
12343
12627
  },
12344
12628
  initialIndex: 0,
12345
12629
  enableZoom: true,
12346
12630
  showControls: false,
12347
12631
  enableSwipe: false,
12348
12632
  showInfo: false,
12349
- showActions: false
12633
+ showActions: false,
12350
12634
  });
12351
12635
  }
12352
12636
  /**
@@ -12367,7 +12651,7 @@ class DsMobileChatModalComponent {
12367
12651
  .then(() => {
12368
12652
  this.isKeyboardVisible = false;
12369
12653
  })
12370
- .catch(e => console.log('[ChatModal] Keyboard.hide() not available:', e));
12654
+ .catch((e) => console.log('[ChatModal] Keyboard.hide() not available:', e));
12371
12655
  return; // Exit early, don't toggle timestamp
12372
12656
  }
12373
12657
  // Keyboard is hidden, proceed with timestamp toggle
@@ -12376,7 +12660,7 @@ class DsMobileChatModalComponent {
12376
12660
  clearTimeout(this.timestampTimeout);
12377
12661
  }
12378
12662
  // Toggle timestamp - if clicking same message, hide it; otherwise show new one
12379
- this.selectedMessageId.update(current => current === messageId ? null : messageId);
12663
+ this.selectedMessageId.update((current) => current === messageId ? null : messageId);
12380
12664
  // Auto-hide after 3 seconds if showing
12381
12665
  if (this.selectedMessageId() === messageId) {
12382
12666
  this.timestampTimeout = setTimeout(() => {
@@ -12391,7 +12675,7 @@ class DsMobileChatModalComponent {
12391
12675
  return date.toLocaleTimeString('da-DK', {
12392
12676
  hour: '2-digit',
12393
12677
  minute: '2-digit',
12394
- hour12: false
12678
+ hour12: false,
12395
12679
  });
12396
12680
  }
12397
12681
  /**
@@ -12414,11 +12698,12 @@ class DsMobileChatModalComponent {
12414
12698
  // 1. It's the first message
12415
12699
  // 2. More than threshold minutes have passed since last message
12416
12700
  // 3. Date changed (new day)
12417
- if (!currentGroup || this.shouldStartNewGroup(currentGroup.timestamp, messageDate, thresholdMinutes)) {
12701
+ if (!currentGroup ||
12702
+ this.shouldStartNewGroup(currentGroup.timestamp, messageDate, thresholdMinutes)) {
12418
12703
  currentGroup = {
12419
12704
  timestamp: messageDate,
12420
12705
  displayTimestamp: this.formatGroupTimestamp(messageDate),
12421
- messages: []
12706
+ messages: [],
12422
12707
  };
12423
12708
  groups.push(currentGroup);
12424
12709
  }
@@ -12452,7 +12737,7 @@ class DsMobileChatModalComponent {
12452
12737
  const timeStr = date.toLocaleTimeString('da-DK', {
12453
12738
  hour: '2-digit',
12454
12739
  minute: '2-digit',
12455
- hour12: false
12740
+ hour12: false,
12456
12741
  });
12457
12742
  // Today: "14:34"
12458
12743
  if (messageDate.getTime() === today.getTime()) {
@@ -12465,12 +12750,12 @@ class DsMobileChatModalComponent {
12465
12750
  // This week: "Mandag, 14:34"
12466
12751
  const daysAgo = Math.floor((today.getTime() - messageDate.getTime()) / (1000 * 60 * 60 * 24));
12467
12752
  if (daysAgo < 7) {
12468
- return date.toLocaleDateString('da-DK', { weekday: 'long' }) + `, ${timeStr}`;
12753
+ return (date.toLocaleDateString('da-DK', { weekday: 'long' }) + `, ${timeStr}`);
12469
12754
  }
12470
12755
  // Older: "15. jan, 14:34" or "20. dec. 2024, 14:34" if different year
12471
12756
  const dateFormat = {
12472
12757
  month: 'short',
12473
- day: 'numeric'
12758
+ day: 'numeric',
12474
12759
  };
12475
12760
  if (date.getFullYear() !== now.getFullYear()) {
12476
12761
  dateFormat.year = 'numeric';
@@ -12483,7 +12768,7 @@ class DsMobileChatModalComponent {
12483
12768
  * and calculates cluster positions for border radius styling
12484
12769
  */
12485
12770
  addDisplayMetadata(groups) {
12486
- return groups.map(group => {
12771
+ return groups.map((group) => {
12487
12772
  const messagesWithDisplay = [];
12488
12773
  for (let i = 0; i < group.messages.length; i++) {
12489
12774
  const currentMsg = group.messages[i];
@@ -12512,12 +12797,12 @@ class DsMobileChatModalComponent {
12512
12797
  messagesWithDisplay.push({
12513
12798
  ...currentMsg,
12514
12799
  showAvatar,
12515
- clusterPosition
12800
+ clusterPosition,
12516
12801
  });
12517
12802
  }
12518
12803
  return {
12519
12804
  ...group,
12520
- messages: messagesWithDisplay
12805
+ messages: messagesWithDisplay,
12521
12806
  };
12522
12807
  });
12523
12808
  }
@@ -12531,8 +12816,8 @@ class DsMobileChatModalComponent {
12531
12816
  [hasFixedBottom]="true"
12532
12817
  [enableKeyboardHandling]="true"
12533
12818
  (keyboardWillShow)="handleKeyboardShow($event)"
12534
- closeButtonLabel="Luk chat">
12535
-
12819
+ closeButtonLabel="Luk chat"
12820
+ >
12536
12821
  <!-- Header Avatar -->
12537
12822
  <ds-avatar-with-badge
12538
12823
  header-leading
@@ -12557,94 +12842,109 @@ class DsMobileChatModalComponent {
12557
12842
  <div class="chat-avatar-name">
12558
12843
  {{ participant().name }}
12559
12844
  @if (participant().verified) {
12560
- <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
12845
+ <ds-icon
12846
+ name="remixCheckboxCircleFill"
12847
+ size="24px"
12848
+ [style.color]="'var(--color-primary-base)'"
12849
+ ></ds-icon>
12561
12850
  }
12562
12851
  </div>
12563
12852
  @if (participant().role) {
12564
- <div class="chat-avatar-role">{{ participant().role }}</div>
12565
- }
12566
- @if (participant().lastActive) {
12567
- <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
12853
+ <div class="chat-avatar-role">{{ participant().role }}</div>
12854
+ } @if (participant().lastActive) {
12855
+ <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
12568
12856
  }
12569
12857
  </div>
12570
12858
  </div>
12571
12859
 
12572
12860
  <div class="messages-list">
12573
12861
  @if (messages().length === 0) {
12574
- <!-- Empty State - Timestamp and System Message -->
12575
- <div class="timestamp-header">
12576
- <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
12577
- </div>
12578
-
12579
- <ds-mobile-system-message-banner
12580
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12581
- [afterTimestamp]="true">
12582
- </ds-mobile-system-message-banner>
12583
- } @else {
12584
- @for (group of messagesWithDisplay(); track group.timestamp) {
12585
- <!-- Timestamp Header -->
12586
- <div class="timestamp-header">
12587
- <span class="timestamp-text">{{ group.displayTimestamp }}</span>
12588
- </div>
12589
-
12590
- <!-- System message example (shown after first timestamp) -->
12591
- @if ($first) {
12592
- <ds-mobile-system-message-banner
12593
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12594
- [afterTimestamp]="true">
12595
- </ds-mobile-system-message-banner>
12596
- }
12597
-
12598
- @for (message of group.messages; track message.id) {
12599
- <!-- Only show bubble if has content -->
12600
- @if (message.content.trim()) {
12601
- <ds-mobile-message-bubble
12602
- [content]="message.content"
12603
- [isOwnMessage]="message.isOwnMessage"
12604
- [timestamp]="formatMessageTimestamp(message.timestamp)"
12605
- [showTimestamp]="selectedMessageId() === message.id"
12606
- [avatarInitials]="message.avatarInitials || ''"
12607
- [avatarType]="message.avatarType || 'initials'"
12608
- [avatarSrc]="message.avatarSrc || ''"
12609
- [showAvatar]="message.showAvatar"
12610
- [clusterPosition]="message.clusterPosition"
12611
- [attachments]="message.attachments"
12612
- [clickable]="true"
12613
- [isNewMessage]="message.isNewMessage || false"
12614
- (messageClick)="handleMessageClick(message.id)"
12615
- (attachmentClick)="handleAttachmentClick($event)"
12616
- (longPress)="handleMessageLongPress(message)">
12617
- </ds-mobile-message-bubble>
12618
- }
12619
-
12620
- <!-- File attachments displayed below message bubble -->
12621
- @if (message.fileAttachments && message.fileAttachments.length > 0) {
12622
- <div class="message-file-attachments" [class.own-message]="message.isOwnMessage">
12623
- @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
12624
- <!-- Show inline image preview for image attachments -->
12625
- @if (fileAttachment.type === 'image') {
12626
- <div class="message-image-attachment" (click)="handleImageClick(fileAttachment, message)">
12627
- <img
12628
- [src]="fileAttachment.src"
12629
- [alt]="fileAttachment.name || 'Image'"
12630
- class="inline-image">
12631
- </div>
12632
- } @else {
12633
- <!-- Show file card for non-image attachments -->
12634
- <ds-mobile-card-inline-file
12635
- [fileName]="fileAttachment.name || 'Unknown file'"
12636
- [fileSize]="fileAttachment.size || ''"
12637
- [variant]="getFileVariant(fileAttachment.type)"
12638
- [layout]="'compact'"
12639
- (fileClick)="handleFileAttachmentClick(fileAttachment)">
12640
- </ds-mobile-card-inline-file>
12641
- }
12642
- }
12643
- </div>
12644
- }
12645
- }
12646
- }
12862
+ <!-- Empty State - Timestamp and System Message -->
12863
+ <div class="timestamp-header">
12864
+ <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
12865
+ </div>
12866
+
12867
+ <ds-mobile-system-message-banner
12868
+ [message]="
12869
+ participant().name +
12870
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
12871
+ "
12872
+ [afterTimestamp]="true"
12873
+ >
12874
+ </ds-mobile-system-message-banner>
12875
+ } @else { @for (group of messagesWithDisplay(); track group.timestamp)
12876
+ {
12877
+ <!-- Timestamp Header -->
12878
+ <div class="timestamp-header">
12879
+ <span class="timestamp-text">{{ group.displayTimestamp }}</span>
12880
+ </div>
12881
+
12882
+ <!-- System message example (shown after first timestamp) -->
12883
+ @if ($first) {
12884
+ <ds-mobile-system-message-banner
12885
+ [message]="
12886
+ participant().name +
12887
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
12888
+ "
12889
+ [afterTimestamp]="true"
12890
+ >
12891
+ </ds-mobile-system-message-banner>
12892
+ } @for (message of group.messages; track message.id) {
12893
+ <!-- Only show bubble if has content -->
12894
+ @if (message.content.trim()) {
12895
+ <ds-mobile-message-bubble
12896
+ [content]="message.content"
12897
+ [isOwnMessage]="message.isOwnMessage"
12898
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
12899
+ [showTimestamp]="selectedMessageId() === message.id"
12900
+ [avatarInitials]="message.avatarInitials || ''"
12901
+ [avatarType]="message.avatarType || 'initials'"
12902
+ [avatarSrc]="message.avatarSrc || ''"
12903
+ [showAvatar]="message.showAvatar"
12904
+ [clusterPosition]="message.clusterPosition"
12905
+ [attachments]="message.attachments"
12906
+ [clickable]="true"
12907
+ [isNewMessage]="message.isNewMessage || false"
12908
+ (messageClick)="handleMessageClick(message.id)"
12909
+ (attachmentClick)="handleAttachmentClick($event)"
12910
+ (longPress)="handleMessageLongPress(message)"
12911
+ >
12912
+ </ds-mobile-message-bubble>
12647
12913
  }
12914
+
12915
+ <!-- File attachments displayed below message bubble -->
12916
+ @if (message.fileAttachments && message.fileAttachments.length > 0) {
12917
+ <div
12918
+ class="message-file-attachments"
12919
+ [class.own-message]="message.isOwnMessage"
12920
+ >
12921
+ @for (fileAttachment of message.fileAttachments; track
12922
+ fileAttachment.id) {
12923
+ <!-- Show inline image preview for image attachments -->
12924
+ @if (fileAttachment.type === 'image') {
12925
+ <div
12926
+ class="message-image-attachment"
12927
+ (click)="handleImageClick(fileAttachment, message)"
12928
+ >
12929
+ <img
12930
+ [src]="fileAttachment.src"
12931
+ [alt]="fileAttachment.name || 'Image'"
12932
+ class="inline-image"
12933
+ />
12934
+ </div>
12935
+ } @else {
12936
+ <!-- Show file card for non-image attachments -->
12937
+ <ds-mobile-card-inline-file
12938
+ [fileName]="fileAttachment.name || 'Unknown file'"
12939
+ [fileSize]="fileAttachment.size || ''"
12940
+ [variant]="getFileVariant(fileAttachment.type)"
12941
+ [layout]="'compact'"
12942
+ (fileClick)="handleFileAttachmentClick(fileAttachment)"
12943
+ >
12944
+ </ds-mobile-card-inline-file>
12945
+ } }
12946
+ </div>
12947
+ } } } }
12648
12948
  </div>
12649
12949
  </div>
12650
12950
 
@@ -12659,11 +12959,12 @@ class DsMobileChatModalComponent {
12659
12959
  [showAttachmentButton]="true"
12660
12960
  (messageSent)="handleMessageSent($event)"
12661
12961
  (attachmentClicked)="handleComposerAttachmentClick()"
12662
- (attachmentsChanged)="handleAttachmentsChanged()">
12962
+ (attachmentsChanged)="handleAttachmentsChanged()"
12963
+ >
12663
12964
  </ds-mobile-message-composer>
12664
12965
  </div>
12665
12966
  </ds-mobile-modal-base>
12666
- `, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-sm);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ":host ::ng-deep .modal-content-container{padding-top:0}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 20px 0;background:var(--color-background-neutral-primary, #ffffff)}.chat-avatar-info{display:flex;flex-direction:column;align-items:center;gap:4px}.chat-avatar-name{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.chat-avatar-role{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-secondary, #666666)}.chat-avatar-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:4px}.messages-list{display:flex;flex-direction:column;width:100%;padding:16px 20px 0;align-items:stretch}.messages-list ds-mobile-message-bubble{width:100%;display:flex}.timestamp-header{display:flex;justify-content:center;margin:16px 0 8px}.timestamp-text{font-family:Brockmann,sans-serif;font-size:12px;font-weight:400;color:var(--color-text-secondary);padding:4px 12px}.message-file-attachments{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:0 20px 0 60px;max-width:100%}.message-file-attachments.own-message{padding:0 0 0 96px;align-items:flex-end}.message-file-attachments ds-mobile-card-inline-file{max-width:280px;width:100%}.message-image-attachment{width:96px;height:96px;cursor:pointer;border-radius:12px;overflow:hidden;position:relative;transition:transform .2s ease;border:1px solid var(--border-color-default, #e5e5e5)}.message-image-attachment:active{transform:scale(.98)}.message-image-attachment .inline-image{width:100%;height:100%;display:block;-o-object-fit:cover;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileSystemMessageBannerComponent, selector: "ds-mobile-system-message-banner", inputs: ["message", "iconName", "afterTimestamp"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
12967
+ `, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-sm);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ":host ::ng-deep .modal-content-container{padding-top:0}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 20px 0;background:var(--color-background-neutral-primary, #ffffff)}.chat-avatar-info{display:flex;flex-direction:column;align-items:center;gap:4px}.chat-avatar-name{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.chat-avatar-role{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-secondary, #666666)}.chat-avatar-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:4px}.messages-list{display:flex;flex-direction:column;width:100%;padding:16px 20px 0;align-items:stretch}.messages-list ds-mobile-message-bubble{width:100%;display:flex}.timestamp-header{display:flex;justify-content:center;margin:16px 0 8px}.timestamp-text{font-family:Brockmann,sans-serif;font-size:12px;font-weight:400;color:var(--color-text-secondary);padding:4px 12px}.message-file-attachments{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:0 20px 0 60px;max-width:100%}.message-file-attachments.own-message{padding:0 0 0 96px;align-items:flex-end}.message-file-attachments ds-mobile-card-inline-file{max-width:280px;width:100%}.message-image-attachment{width:96px;height:96px;cursor:pointer;border-radius:12px;overflow:hidden;position:relative;transition:transform .2s ease;border:1px solid var(--border-color-default, #e5e5e5)}.message-image-attachment:active{transform:scale(.98)}.message-image-attachment .inline-image{width:100%;height:100%;display:block;-o-object-fit:cover;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileSystemMessageBannerComponent, selector: "ds-mobile-system-message-banner", inputs: ["message", "iconName", "afterTimestamp"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
12667
12968
  }
12668
12969
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileChatModalComponent, decorators: [{
12669
12970
  type: Component,
@@ -12675,8 +12976,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12675
12976
  DsMobileModalBaseComponent,
12676
12977
  DsMobileCardInlineFileComponent,
12677
12978
  DsMobileSystemMessageBannerComponent,
12678
- DsMobileEmptyStateComponent,
12679
- DsIconComponent
12979
+ DsIconComponent,
12680
12980
  ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
12681
12981
  <ds-mobile-modal-base
12682
12982
  [loading]="loading"
@@ -12686,8 +12986,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12686
12986
  [hasFixedBottom]="true"
12687
12987
  [enableKeyboardHandling]="true"
12688
12988
  (keyboardWillShow)="handleKeyboardShow($event)"
12689
- closeButtonLabel="Luk chat">
12690
-
12989
+ closeButtonLabel="Luk chat"
12990
+ >
12691
12991
  <!-- Header Avatar -->
12692
12992
  <ds-avatar-with-badge
12693
12993
  header-leading
@@ -12712,94 +13012,109 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12712
13012
  <div class="chat-avatar-name">
12713
13013
  {{ participant().name }}
12714
13014
  @if (participant().verified) {
12715
- <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
13015
+ <ds-icon
13016
+ name="remixCheckboxCircleFill"
13017
+ size="24px"
13018
+ [style.color]="'var(--color-primary-base)'"
13019
+ ></ds-icon>
12716
13020
  }
12717
13021
  </div>
12718
13022
  @if (participant().role) {
12719
- <div class="chat-avatar-role">{{ participant().role }}</div>
12720
- }
12721
- @if (participant().lastActive) {
12722
- <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
13023
+ <div class="chat-avatar-role">{{ participant().role }}</div>
13024
+ } @if (participant().lastActive) {
13025
+ <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
12723
13026
  }
12724
13027
  </div>
12725
13028
  </div>
12726
13029
 
12727
13030
  <div class="messages-list">
12728
13031
  @if (messages().length === 0) {
12729
- <!-- Empty State - Timestamp and System Message -->
12730
- <div class="timestamp-header">
12731
- <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
12732
- </div>
12733
-
12734
- <ds-mobile-system-message-banner
12735
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12736
- [afterTimestamp]="true">
12737
- </ds-mobile-system-message-banner>
12738
- } @else {
12739
- @for (group of messagesWithDisplay(); track group.timestamp) {
12740
- <!-- Timestamp Header -->
12741
- <div class="timestamp-header">
12742
- <span class="timestamp-text">{{ group.displayTimestamp }}</span>
12743
- </div>
12744
-
12745
- <!-- System message example (shown after first timestamp) -->
12746
- @if ($first) {
12747
- <ds-mobile-system-message-banner
12748
- [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'"
12749
- [afterTimestamp]="true">
12750
- </ds-mobile-system-message-banner>
12751
- }
12752
-
12753
- @for (message of group.messages; track message.id) {
12754
- <!-- Only show bubble if has content -->
12755
- @if (message.content.trim()) {
12756
- <ds-mobile-message-bubble
12757
- [content]="message.content"
12758
- [isOwnMessage]="message.isOwnMessage"
12759
- [timestamp]="formatMessageTimestamp(message.timestamp)"
12760
- [showTimestamp]="selectedMessageId() === message.id"
12761
- [avatarInitials]="message.avatarInitials || ''"
12762
- [avatarType]="message.avatarType || 'initials'"
12763
- [avatarSrc]="message.avatarSrc || ''"
12764
- [showAvatar]="message.showAvatar"
12765
- [clusterPosition]="message.clusterPosition"
12766
- [attachments]="message.attachments"
12767
- [clickable]="true"
12768
- [isNewMessage]="message.isNewMessage || false"
12769
- (messageClick)="handleMessageClick(message.id)"
12770
- (attachmentClick)="handleAttachmentClick($event)"
12771
- (longPress)="handleMessageLongPress(message)">
12772
- </ds-mobile-message-bubble>
12773
- }
12774
-
12775
- <!-- File attachments displayed below message bubble -->
12776
- @if (message.fileAttachments && message.fileAttachments.length > 0) {
12777
- <div class="message-file-attachments" [class.own-message]="message.isOwnMessage">
12778
- @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
12779
- <!-- Show inline image preview for image attachments -->
12780
- @if (fileAttachment.type === 'image') {
12781
- <div class="message-image-attachment" (click)="handleImageClick(fileAttachment, message)">
12782
- <img
12783
- [src]="fileAttachment.src"
12784
- [alt]="fileAttachment.name || 'Image'"
12785
- class="inline-image">
12786
- </div>
12787
- } @else {
12788
- <!-- Show file card for non-image attachments -->
12789
- <ds-mobile-card-inline-file
12790
- [fileName]="fileAttachment.name || 'Unknown file'"
12791
- [fileSize]="fileAttachment.size || ''"
12792
- [variant]="getFileVariant(fileAttachment.type)"
12793
- [layout]="'compact'"
12794
- (fileClick)="handleFileAttachmentClick(fileAttachment)">
12795
- </ds-mobile-card-inline-file>
12796
- }
12797
- }
12798
- </div>
12799
- }
12800
- }
12801
- }
13032
+ <!-- Empty State - Timestamp and System Message -->
13033
+ <div class="timestamp-header">
13034
+ <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
13035
+ </div>
13036
+
13037
+ <ds-mobile-system-message-banner
13038
+ [message]="
13039
+ participant().name +
13040
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
13041
+ "
13042
+ [afterTimestamp]="true"
13043
+ >
13044
+ </ds-mobile-system-message-banner>
13045
+ } @else { @for (group of messagesWithDisplay(); track group.timestamp)
13046
+ {
13047
+ <!-- Timestamp Header -->
13048
+ <div class="timestamp-header">
13049
+ <span class="timestamp-text">{{ group.displayTimestamp }}</span>
13050
+ </div>
13051
+
13052
+ <!-- System message example (shown after first timestamp) -->
13053
+ @if ($first) {
13054
+ <ds-mobile-system-message-banner
13055
+ [message]="
13056
+ participant().name +
13057
+ ' har overtaget din henvendelse og vil kontakte dig snart.'
13058
+ "
13059
+ [afterTimestamp]="true"
13060
+ >
13061
+ </ds-mobile-system-message-banner>
13062
+ } @for (message of group.messages; track message.id) {
13063
+ <!-- Only show bubble if has content -->
13064
+ @if (message.content.trim()) {
13065
+ <ds-mobile-message-bubble
13066
+ [content]="message.content"
13067
+ [isOwnMessage]="message.isOwnMessage"
13068
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
13069
+ [showTimestamp]="selectedMessageId() === message.id"
13070
+ [avatarInitials]="message.avatarInitials || ''"
13071
+ [avatarType]="message.avatarType || 'initials'"
13072
+ [avatarSrc]="message.avatarSrc || ''"
13073
+ [showAvatar]="message.showAvatar"
13074
+ [clusterPosition]="message.clusterPosition"
13075
+ [attachments]="message.attachments"
13076
+ [clickable]="true"
13077
+ [isNewMessage]="message.isNewMessage || false"
13078
+ (messageClick)="handleMessageClick(message.id)"
13079
+ (attachmentClick)="handleAttachmentClick($event)"
13080
+ (longPress)="handleMessageLongPress(message)"
13081
+ >
13082
+ </ds-mobile-message-bubble>
12802
13083
  }
13084
+
13085
+ <!-- File attachments displayed below message bubble -->
13086
+ @if (message.fileAttachments && message.fileAttachments.length > 0) {
13087
+ <div
13088
+ class="message-file-attachments"
13089
+ [class.own-message]="message.isOwnMessage"
13090
+ >
13091
+ @for (fileAttachment of message.fileAttachments; track
13092
+ fileAttachment.id) {
13093
+ <!-- Show inline image preview for image attachments -->
13094
+ @if (fileAttachment.type === 'image') {
13095
+ <div
13096
+ class="message-image-attachment"
13097
+ (click)="handleImageClick(fileAttachment, message)"
13098
+ >
13099
+ <img
13100
+ [src]="fileAttachment.src"
13101
+ [alt]="fileAttachment.name || 'Image'"
13102
+ class="inline-image"
13103
+ />
13104
+ </div>
13105
+ } @else {
13106
+ <!-- Show file card for non-image attachments -->
13107
+ <ds-mobile-card-inline-file
13108
+ [fileName]="fileAttachment.name || 'Unknown file'"
13109
+ [fileSize]="fileAttachment.size || ''"
13110
+ [variant]="getFileVariant(fileAttachment.type)"
13111
+ [layout]="'compact'"
13112
+ (fileClick)="handleFileAttachmentClick(fileAttachment)"
13113
+ >
13114
+ </ds-mobile-card-inline-file>
13115
+ } }
13116
+ </div>
13117
+ } } } }
12803
13118
  </div>
12804
13119
  </div>
12805
13120
 
@@ -12814,7 +13129,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
12814
13129
  [showAttachmentButton]="true"
12815
13130
  (messageSent)="handleMessageSent($event)"
12816
13131
  (attachmentClicked)="handleComposerAttachmentClick()"
12817
- (attachmentsChanged)="handleAttachmentsChanged()">
13132
+ (attachmentsChanged)="handleAttachmentsChanged()"
13133
+ >
12818
13134
  </ds-mobile-message-composer>
12819
13135
  </div>
12820
13136
  </ds-mobile-modal-base>
@@ -13570,147 +13886,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
13570
13886
  type: Input
13571
13887
  }] } });
13572
13888
 
13573
- /**
13574
- * DsMobileCardInlineContactComponent
13575
- *
13576
- * Specialized interactive component for displaying contacts.
13577
- * Displays contact name with avatar initials and metadata (person name + phone number).
13578
- * Similar styling to file attachments with rounded corners and hover states.
13579
- *
13580
- * @example
13581
- * ```html
13582
- * <ds-mobile-card-inline-contact
13583
- * [name]="'Mortensen & Søn ApS'"
13584
- * [initials]="'M'"
13585
- * [contactPerson]="'John Mortensen'"
13586
- * [phoneNumber]="'+45 12 34 56 78'"
13587
- * [clickable]="true"
13588
- * (contactClick)="openContact()">
13589
- * </ds-mobile-card-inline-contact>
13590
- * ```
13591
- */
13592
- class DsMobileCardInlineContactComponent {
13593
- /**
13594
- * Contact/company name
13595
- */
13596
- name = input.required(...(ngDevMode ? [{ debugName: "name" }] : []));
13597
- /**
13598
- * Avatar initials (usually 1-2 letters)
13599
- */
13600
- initials = input.required(...(ngDevMode ? [{ debugName: "initials" }] : []));
13601
- /**
13602
- * Contact person name (optional)
13603
- */
13604
- contactPerson = input('', ...(ngDevMode ? [{ debugName: "contactPerson" }] : []));
13605
- /**
13606
- * Phone number (optional)
13607
- */
13608
- phoneNumber = input('', ...(ngDevMode ? [{ debugName: "phoneNumber" }] : []));
13609
- /**
13610
- * Layout variant
13611
- * - 'default' - Standard padding and column layout
13612
- * - 'compact' - Reduced padding and row layout
13613
- */
13614
- layout = input('default', ...(ngDevMode ? [{ debugName: "layout" }] : []));
13615
- /**
13616
- * Whether the contact item is clickable
13617
- */
13618
- clickable = input(true, ...(ngDevMode ? [{ debugName: "clickable" }] : []));
13619
- /**
13620
- * Whether to show chevron icon
13621
- */
13622
- showChevron = input(true, ...(ngDevMode ? [{ debugName: "showChevron" }] : []));
13623
- /**
13624
- * Emits when the contact item is clicked (if clickable)
13625
- */
13626
- contactClick = output();
13627
- handleContactClick() {
13628
- this.contactClick.emit();
13629
- }
13630
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineContactComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13631
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineContactComponent, isStandalone: true, selector: "ds-mobile-card-inline-contact", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: true, transformFunction: null }, contactPerson: { classPropertyName: "contactPerson", publicName: "contactPerson", isSignal: true, isRequired: false, transformFunction: null }, phoneNumber: { classPropertyName: "phoneNumber", publicName: "phoneNumber", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contactClick: "contactClick" }, ngImport: i0, template: `
13632
- <ds-mobile-card-inline
13633
- [variant]="layout()"
13634
- [disabled]="!clickable()"
13635
- (cardClick)="handleContactClick()">
13636
-
13637
- <div content-leading class="item-avatar">
13638
- <ds-avatar
13639
- [initials]="initials()"
13640
- type="initials"
13641
- [size]="layout() === 'compact' ? 'sm' : 'md'"
13642
- />
13643
- </div>
13644
-
13645
- <div content-main class="item-content">
13646
- <div class="item-name">{{ name() }}</div>
13647
-
13648
- @if (contactPerson() || phoneNumber()) {
13649
- <div class="item-meta">
13650
- @if (contactPerson()) {
13651
- <span>{{ contactPerson() }}</span>
13652
- }
13653
- @if (contactPerson() && phoneNumber()) {
13654
- <span>·</span>
13655
- }
13656
- @if (phoneNumber()) {
13657
- <span>{{ phoneNumber() }}</span>
13658
- }
13659
- </div>
13660
- }
13661
- </div>
13662
-
13663
- @if (showChevron()) {
13664
- <div content-trailing class="item-trailing">
13665
- <ds-icon name="remixArrowRightSLine" size="20px" />
13666
- </div>
13667
- }
13668
- </ds-mobile-card-inline>
13669
- `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
13670
- }
13671
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineContactComponent, decorators: [{
13672
- type: Component,
13673
- args: [{ selector: 'ds-mobile-card-inline-contact', standalone: true, imports: [CommonModule, DsIconComponent, DsAvatarComponent, DsMobileCardInlineComponent], template: `
13674
- <ds-mobile-card-inline
13675
- [variant]="layout()"
13676
- [disabled]="!clickable()"
13677
- (cardClick)="handleContactClick()">
13678
-
13679
- <div content-leading class="item-avatar">
13680
- <ds-avatar
13681
- [initials]="initials()"
13682
- type="initials"
13683
- [size]="layout() === 'compact' ? 'sm' : 'md'"
13684
- />
13685
- </div>
13686
-
13687
- <div content-main class="item-content">
13688
- <div class="item-name">{{ name() }}</div>
13689
-
13690
- @if (contactPerson() || phoneNumber()) {
13691
- <div class="item-meta">
13692
- @if (contactPerson()) {
13693
- <span>{{ contactPerson() }}</span>
13694
- }
13695
- @if (contactPerson() && phoneNumber()) {
13696
- <span>·</span>
13697
- }
13698
- @if (phoneNumber()) {
13699
- <span>{{ phoneNumber() }}</span>
13700
- }
13701
- </div>
13702
- }
13703
- </div>
13704
-
13705
- @if (showChevron()) {
13706
- <div content-trailing class="item-trailing">
13707
- <ds-icon name="remixArrowRightSLine" size="20px" />
13708
- </div>
13709
- }
13710
- </ds-mobile-card-inline>
13711
- ` }]
13712
- }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: true }] }], contactPerson: [{ type: i0.Input, args: [{ isSignal: true, alias: "contactPerson", required: false }] }], phoneNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneNumber", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], contactClick: [{ type: i0.Output, args: ["contactClick"] }] } });
13713
-
13714
13889
  /**
13715
13890
  * DsMobileSwiperComponent
13716
13891
  *
@@ -13827,7 +14002,7 @@ class DsMobileHandbookDetailModalComponent {
13827
14002
  variant: 'light-purple',
13828
14003
  iconName: 'remixFolder3Line',
13829
14004
  itemCount: 0,
13830
- items: []
14005
+ items: [],
13831
14006
  }, ...(ngDevMode ? [{ debugName: "handbook" }] : []));
13832
14007
  ngOnInit() {
13833
14008
  // Initialize handbook data from input
@@ -13848,41 +14023,27 @@ class DsMobileHandbookDetailModalComponent {
13848
14023
  const hasImages = item.images && item.images.length > 0;
13849
14024
  const hasContacts = item.contacts && item.contacts.length > 0;
13850
14025
  const hasAttachments = item.attachments && item.attachments.length > 0;
13851
- // Case 1: Only one type of content - keep as is
13852
- const contentTypeCount = [hasImages, hasContacts, hasAttachments].filter(Boolean).length;
13853
- if (contentTypeCount <= 1) {
13854
- return [item];
13855
- }
13856
- // Case 2: Has images + contacts (allowed together) but no attachments
13857
- if (hasImages && hasContacts && !hasAttachments) {
13858
- return [item];
13859
- }
13860
- // Case 3: Violates rules - need to split
13861
- // First item: Text + Images (if present)
13862
- if (hasImages) {
14026
+ const hasContent = hasContacts || hasAttachments;
14027
+ // Case 1: Images AND other content -> Split Pictures from (Contacts + Attachments)
14028
+ if (hasImages && hasContent) {
14029
+ // Part 1: Images
13863
14030
  displayItems.push({
13864
14031
  title: item.title,
13865
14032
  description: item.description,
13866
- images: item.images
13867
- });
13868
- }
13869
- // Second item: Text + Contacts (if present and no images shown yet)
13870
- if (hasContacts) {
13871
- displayItems.push({
13872
- title: item.title,
13873
- description: hasImages ? undefined : item.description, // Only show description if not shown before
13874
- contacts: item.contacts
14033
+ images: item.images,
13875
14034
  });
13876
- }
13877
- // Third item: Text + Attachments (if present)
13878
- if (hasAttachments) {
14035
+ // Part 2: Contacts + Attachments
13879
14036
  displayItems.push({
13880
- title: item.title,
13881
- description: (!hasImages && !hasContacts) ? item.description : undefined, // Only show description if not shown before
13882
- attachments: item.attachments
14037
+ title: '', // No title for the continuation
14038
+ description: undefined,
14039
+ contacts: item.contacts,
14040
+ attachments: item.attachments,
13883
14041
  });
14042
+ return displayItems;
13884
14043
  }
13885
- return displayItems;
14044
+ // Case 2: No splitting needed (Images only, or No Images)
14045
+ // This allows Contacts and Attachments to coexist in one item
14046
+ return [item];
13886
14047
  }
13887
14048
  /**
13888
14049
  * Get all display items with enforced content structure rules applied
@@ -13908,7 +14069,7 @@ class DsMobileHandbookDetailModalComponent {
13908
14069
  */
13909
14070
  handleAttachmentClick(attachment) {
13910
14071
  console.log('Attachment clicked:', attachment);
13911
- // Implement attachment action (e.g., open file viewer, download, etc.)
14072
+ // Attachment action is now handled by DsMobileCardInlineFileComponent via fileUrl input
13912
14073
  }
13913
14074
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13914
14075
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileHandbookDetailModalComponent, isStandalone: true, selector: "ds-mobile-handbook-detail-modal", inputs: { handbookData: "handbookData", loading: "loading", error: "error" }, ngImport: i0, template: `
@@ -13917,88 +14078,90 @@ class DsMobileHandbookDetailModalComponent {
13917
14078
  [error]="error"
13918
14079
  [headerTitle]="handbook().title"
13919
14080
  [headerMeta]="handbook().itemCount + ' emner'"
13920
- closeButtonLabel="Luk">
13921
-
14081
+ closeButtonLabel="Luk"
14082
+ >
13922
14083
  <!-- Header Folder Icon -->
13923
14084
  <ds-mobile-handbook-folder-mini
13924
14085
  header-leading
13925
14086
  [variant]="handbook().variant"
13926
- [iconName]="handbook().iconName">
14087
+ [iconName]="handbook().iconName"
14088
+ >
13927
14089
  </ds-mobile-handbook-folder-mini>
13928
14090
 
13929
14091
  <!-- Content (main content slot) -->
13930
14092
  <div class="handbook-detail-container">
13931
- @if (handbook().items && handbook().items!.length > 0) {
13932
- @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {
13933
- <div class="handbook-item" [class.last-item]="isLast">
13934
- <div class="item-text-group">
13935
- <h2 class="item-title">{{ item.title }}</h2>
13936
-
13937
- @if (item.description) {
13938
- <p class="item-description">{{ item.description }}</p>
13939
- }
13940
- </div>
13941
-
13942
- <!-- Images -->
13943
- @if (item.images && item.images.length > 0) {
13944
- <ds-mobile-swiper [slideWidth]="item.images.length === 1 ? '100%' : '85%'" [gap]="16">
13945
- @for (image of item.images; track image) {
13946
- <div class="swiper-slide">
13947
- <img
13948
- [src]="image"
13949
- [alt]="item.title"
13950
- class="item-image"
13951
- />
13952
- </div>
13953
- }
13954
- </ds-mobile-swiper>
13955
- }
13956
-
13957
- <!-- Contacts -->
13958
- @if (item.contacts && item.contacts.length > 0) {
13959
- <div class="contacts-list">
13960
- @for (contact of item.contacts; track contact.name) {
13961
- <ds-mobile-card-inline-contact
13962
- [name]="contact.name"
13963
- [initials]="contact.initials"
13964
- [contactPerson]="contact.contactPerson || ''"
13965
- [phoneNumber]="contact.phoneNumber || ''"
13966
- [clickable]="true"
13967
- (contactClick)="handleContactClick(contact)">
13968
- </ds-mobile-card-inline-contact>
13969
- }
13970
- </div>
13971
- }
13972
-
13973
- <!-- Attachments -->
13974
- @if (item.attachments && item.attachments.length > 0) {
13975
- <div class="attachments-list">
13976
- @for (attachment of item.attachments; track attachment.name) {
13977
- <ds-mobile-card-inline-file
13978
- [fileName]="attachment.name"
13979
- [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
13980
- (fileClick)="handleAttachmentClick(attachment)">
13981
- </ds-mobile-card-inline-file>
13982
- }
13983
- </div>
13984
- }
13985
- </div>
14093
+ @if (handbook().items && handbook().items!.length > 0) { @for (item of
14094
+ getDisplayItems(); track item.title + $index; let isLast = $last) {
14095
+ <div class="handbook-item" [class.last-item]="isLast">
14096
+ <div class="item-text-group">
14097
+ @if (item.title) {
14098
+ <h2 class="item-title">{{ item.title }}</h2>
14099
+ } @if (item.description) {
14100
+ <p class="item-description" [innerHTML]="item.description"></p>
14101
+ }
14102
+ </div>
14103
+
14104
+ <!-- Images -->
14105
+ @if (item.images && item.images.length > 0) {
14106
+ <ds-mobile-swiper
14107
+ [slideWidth]="item.images.length === 1 ? '100%' : '85%'"
14108
+ [gap]="16"
14109
+ >
14110
+ @for (image of item.images; track image) {
14111
+ <div class="swiper-slide">
14112
+ <img [src]="image" [alt]="item.title" class="item-image" />
14113
+ </div>
14114
+ }
14115
+ </ds-mobile-swiper>
14116
+ }
14117
+
14118
+ <!-- Contacts -->
14119
+ @if (item.contacts && item.contacts.length > 0) {
14120
+ <div class="contacts-list">
14121
+ @for (contact of item.contacts; track contact.name) {
14122
+ <ds-mobile-card-inline-contact
14123
+ [name]="contact.name"
14124
+ [initials]="contact.initials"
14125
+ [contactPerson]="contact.contactPerson || ''"
14126
+ [phoneNumber]="contact.phoneNumber || ''"
14127
+ [clickable]="true"
14128
+ (contactClick)="handleContactClick(contact)"
14129
+ >
14130
+ </ds-mobile-card-inline-contact>
14131
+ }
14132
+ </div>
14133
+ }
14134
+
14135
+ <!-- Attachments -->
14136
+ @if (item.attachments && item.attachments.length > 0) {
14137
+ <div class="attachments-list">
14138
+ @for (attachment of item.attachments; track attachment.name) {
14139
+ <ds-mobile-card-inline-file
14140
+ [fileName]="attachment.name"
14141
+ [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14142
+ [fileUrl]="attachment.url"
14143
+ (fileClick)="handleAttachmentClick(attachment)"
14144
+ >
14145
+ </ds-mobile-card-inline-file>
13986
14146
  }
13987
- } @else {
13988
- <!-- Empty State -->
13989
- <div class="handbook-empty-state">
13990
- <img
13991
- src="/Assets/Empty%20state-chat.png"
13992
- alt="No items yet"
13993
- class="empty-state-image"
13994
- />
13995
- <h3 class="empty-state-title">No items yet</h3>
13996
- <p class="empty-state-description">This folder is empty</p>
13997
14147
  </div>
14148
+ }
14149
+ </div>
14150
+ } } @else {
14151
+ <!-- Empty State -->
14152
+ <div class="handbook-empty-state">
14153
+ <img
14154
+ src="/Assets/Empty%20state-chat.png"
14155
+ alt="No items yet"
14156
+ class="empty-state-image"
14157
+ />
14158
+ <h3 class="empty-state-title">No items yet</h3>
14159
+ <p class="empty-state-description">This folder is empty</p>
14160
+ </div>
13998
14161
  }
13999
14162
  </div>
14000
14163
  </ds-mobile-modal-base>
14001
- `, isInline: true, styles: [".handbook-detail-container{display:flex;flex-direction:column;width:100%;flex:1}.handbook-item{width:100%;display:flex;flex-direction:column;gap:24px;padding:24px 20px;border-bottom:1px solid var(--border-color-default)}.handbook-item.last-item{border-bottom:none}.item-text-group{display:flex;flex-direction:column;gap:8px}.item-title{font-family:Brockmann,sans-serif;font-size:16px;font-weight:600;line-height:24px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);line-height:20px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-image{width:100%;max-width:100%;height:280px;-o-object-fit:cover;object-fit:cover;border-radius:12px;display:block}.contacts-list,.attachments-list{display:flex;flex-direction:column;gap:8px}.handbook-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}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-text-secondary, #737373)}@supports (padding: env(safe-area-inset-bottom)){.handbook-detail-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileHandbookFolderMiniComponent, selector: "ds-mobile-handbook-folder-mini", inputs: ["variant", "iconName"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileSwiperComponent, selector: "ds-mobile-swiper", inputs: ["slideWidth", "gap"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }] });
14164
+ `, isInline: true, styles: [".handbook-detail-container{display:flex;flex-direction:column;width:100%;flex:1}.handbook-item{width:100%;display:flex;flex-direction:column;gap:24px;padding:24px 20px;border-bottom:1px solid var(--border-color-default)}.handbook-item.last-item{border-bottom:none}.item-text-group{display:flex;flex-direction:column;gap:8px}.item-title{font-family:Brockmann,sans-serif;font-size:16px;font-weight:600;line-height:24px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);line-height:20px;color:var(--color-text-primary, #1a1a1a);margin:0}.item-image{width:100%;max-width:100%;height:280px;-o-object-fit:cover;object-fit:cover;border-radius:12px;display:block}.contacts-list,.attachments-list{display:flex;flex-direction:column;gap:8px}.handbook-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}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-text-secondary, #737373)}@supports (padding: env(safe-area-inset-bottom)){.handbook-detail-container{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileHandbookFolderMiniComponent, selector: "ds-mobile-handbook-folder-mini", inputs: ["variant", "iconName"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileSwiperComponent, selector: "ds-mobile-swiper", inputs: ["slideWidth", "gap"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["showHeader"] }] });
14002
14165
  }
14003
14166
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookDetailModalComponent, decorators: [{
14004
14167
  type: Component,
@@ -14008,91 +14171,93 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
14008
14171
  DsMobileCardInlineFileComponent,
14009
14172
  DsMobileCardInlineContactComponent,
14010
14173
  DsMobileSwiperComponent,
14011
- DsMobileModalBaseComponent
14174
+ DsMobileModalBaseComponent,
14012
14175
  ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
14013
14176
  <ds-mobile-modal-base
14014
14177
  [loading]="loading"
14015
14178
  [error]="error"
14016
14179
  [headerTitle]="handbook().title"
14017
14180
  [headerMeta]="handbook().itemCount + ' emner'"
14018
- closeButtonLabel="Luk">
14019
-
14181
+ closeButtonLabel="Luk"
14182
+ >
14020
14183
  <!-- Header Folder Icon -->
14021
14184
  <ds-mobile-handbook-folder-mini
14022
14185
  header-leading
14023
14186
  [variant]="handbook().variant"
14024
- [iconName]="handbook().iconName">
14187
+ [iconName]="handbook().iconName"
14188
+ >
14025
14189
  </ds-mobile-handbook-folder-mini>
14026
14190
 
14027
- <!-- Content (main content slot) -->
14028
- <div class="handbook-detail-container">
14029
- @if (handbook().items && handbook().items!.length > 0) {
14030
- @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {
14031
- <div class="handbook-item" [class.last-item]="isLast">
14032
- <div class="item-text-group">
14033
- <h2 class="item-title">{{ item.title }}</h2>
14034
-
14035
- @if (item.description) {
14036
- <p class="item-description">{{ item.description }}</p>
14037
- }
14038
- </div>
14039
-
14040
- <!-- Images -->
14041
- @if (item.images && item.images.length > 0) {
14042
- <ds-mobile-swiper [slideWidth]="item.images.length === 1 ? '100%' : '85%'" [gap]="16">
14043
- @for (image of item.images; track image) {
14044
- <div class="swiper-slide">
14045
- <img
14046
- [src]="image"
14047
- [alt]="item.title"
14048
- class="item-image"
14049
- />
14050
- </div>
14051
- }
14052
- </ds-mobile-swiper>
14053
- }
14054
-
14055
- <!-- Contacts -->
14056
- @if (item.contacts && item.contacts.length > 0) {
14057
- <div class="contacts-list">
14058
- @for (contact of item.contacts; track contact.name) {
14059
- <ds-mobile-card-inline-contact
14060
- [name]="contact.name"
14061
- [initials]="contact.initials"
14062
- [contactPerson]="contact.contactPerson || ''"
14063
- [phoneNumber]="contact.phoneNumber || ''"
14064
- [clickable]="true"
14065
- (contactClick)="handleContactClick(contact)">
14066
- </ds-mobile-card-inline-contact>
14067
- }
14068
- </div>
14069
- }
14070
-
14071
- <!-- Attachments -->
14072
- @if (item.attachments && item.attachments.length > 0) {
14073
- <div class="attachments-list">
14074
- @for (attachment of item.attachments; track attachment.name) {
14075
- <ds-mobile-card-inline-file
14076
- [fileName]="attachment.name"
14077
- [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14078
- (fileClick)="handleAttachmentClick(attachment)">
14079
- </ds-mobile-card-inline-file>
14080
- }
14081
- </div>
14082
- }
14083
- </div>
14191
+ <!-- Content (main content slot) -->
14192
+ <div class="handbook-detail-container">
14193
+ @if (handbook().items && handbook().items!.length > 0) { @for (item of
14194
+ getDisplayItems(); track item.title + $index; let isLast = $last) {
14195
+ <div class="handbook-item" [class.last-item]="isLast">
14196
+ <div class="item-text-group">
14197
+ @if (item.title) {
14198
+ <h2 class="item-title">{{ item.title }}</h2>
14199
+ } @if (item.description) {
14200
+ <p class="item-description" [innerHTML]="item.description"></p>
14201
+ }
14202
+ </div>
14203
+
14204
+ <!-- Images -->
14205
+ @if (item.images && item.images.length > 0) {
14206
+ <ds-mobile-swiper
14207
+ [slideWidth]="item.images.length === 1 ? '100%' : '85%'"
14208
+ [gap]="16"
14209
+ >
14210
+ @for (image of item.images; track image) {
14211
+ <div class="swiper-slide">
14212
+ <img [src]="image" [alt]="item.title" class="item-image" />
14213
+ </div>
14214
+ }
14215
+ </ds-mobile-swiper>
14216
+ }
14217
+
14218
+ <!-- Contacts -->
14219
+ @if (item.contacts && item.contacts.length > 0) {
14220
+ <div class="contacts-list">
14221
+ @for (contact of item.contacts; track contact.name) {
14222
+ <ds-mobile-card-inline-contact
14223
+ [name]="contact.name"
14224
+ [initials]="contact.initials"
14225
+ [contactPerson]="contact.contactPerson || ''"
14226
+ [phoneNumber]="contact.phoneNumber || ''"
14227
+ [clickable]="true"
14228
+ (contactClick)="handleContactClick(contact)"
14229
+ >
14230
+ </ds-mobile-card-inline-contact>
14231
+ }
14232
+ </div>
14233
+ }
14234
+
14235
+ <!-- Attachments -->
14236
+ @if (item.attachments && item.attachments.length > 0) {
14237
+ <div class="attachments-list">
14238
+ @for (attachment of item.attachments; track attachment.name) {
14239
+ <ds-mobile-card-inline-file
14240
+ [fileName]="attachment.name"
14241
+ [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
14242
+ [fileUrl]="attachment.url"
14243
+ (fileClick)="handleAttachmentClick(attachment)"
14244
+ >
14245
+ </ds-mobile-card-inline-file>
14084
14246
  }
14085
- } @else {
14086
- <!-- Empty State -->
14087
- <div class="handbook-empty-state">
14088
- <img
14089
- src="/Assets/Empty%20state-chat.png"
14090
- alt="No items yet"
14091
- class="empty-state-image"
14092
- />
14093
- <h3 class="empty-state-title">No items yet</h3>
14094
- <p class="empty-state-description">This folder is empty</p>
14095
14247
  </div>
14248
+ }
14249
+ </div>
14250
+ } } @else {
14251
+ <!-- Empty State -->
14252
+ <div class="handbook-empty-state">
14253
+ <img
14254
+ src="/Assets/Empty%20state-chat.png"
14255
+ alt="No items yet"
14256
+ class="empty-state-image"
14257
+ />
14258
+ <h3 class="empty-state-title">No items yet</h3>
14259
+ <p class="empty-state-description">This folder is empty</p>
14260
+ </div>
14096
14261
  }
14097
14262
  </div>
14098
14263
  </ds-mobile-modal-base>
@@ -14256,7 +14421,7 @@ class DsMobileHandbookFolderComponent {
14256
14421
  'salmon-orange': 'salmon-orange',
14257
14422
  'orange': 'orange',
14258
14423
  'lime-green': 'lime-green',
14259
- 'grey': 'grey'
14424
+ 'grey': 'grey',
14260
14425
  };
14261
14426
  const colorName = variantMap[this.variant] || 'light-purple';
14262
14427
  return `var(--color-${colorName}-${suffix})`;
@@ -14305,11 +14470,11 @@ class DsMobileHandbookFolderComponent {
14305
14470
  variant: this.variant,
14306
14471
  iconName: this.iconName,
14307
14472
  itemCount: this.itemCount,
14308
- items: this.items
14473
+ items: this.items,
14309
14474
  };
14310
14475
  await this.handbookModal.open(handbookData, {
14311
14476
  loading: this.loading,
14312
- error: this.error
14477
+ error: this.error,
14313
14478
  });
14314
14479
  }
14315
14480
  /**
@@ -14325,55 +14490,43 @@ class DsMobileHandbookFolderComponent {
14325
14490
  }
14326
14491
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookFolderComponent, deps: [{ token: DsMobileHandbookDetailModalService }], target: i0.ɵɵFactoryTarget.Component });
14327
14492
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileHandbookFolderComponent, isStandalone: true, selector: "ds-mobile-handbook-folder", inputs: { variant: "variant", iconName: "iconName", itemCount: "itemCount", label: "label", items: "items", loading: "loading", error: "error" }, host: { listeners: { "mouseenter": "open()", "mouseleave": "close()", "touchstart": "onTouchStart($event)", "touchend": "onTouchEnd()", "touchcancel": "onTouchCancel()", "click": "onClick()" } }, ngImport: i0, template: `
14328
- <div class="folder-container"
14329
- [class.open]="isOpen()">
14493
+ <div class="folder-container" [class.open]="isOpen()">
14330
14494
  <!-- Folder Tab SVG -->
14331
- <svg
14332
- class="folder-tab"
14333
- width="101"
14334
- height="24"
14335
- viewBox="0 0 101 24"
14336
- fill="none"
14337
- xmlns="http://www.w3.org/2000/svg">
14338
- <path
14339
- d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14340
- [attr.fill]="getColorVar('strong')"/>
14495
+ <svg class="folder-tab" width="101" height="24" viewBox="0 0 101 24" fill="none" xmlns="http://www.w3.org/2000/svg">
14496
+ <path
14497
+ d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14498
+ [attr.fill]="getColorVar('strong')"
14499
+ />
14341
14500
  </svg>
14342
-
14501
+
14343
14502
  <!-- Folder Back -->
14344
14503
  <div class="folder-back" [style.background-color]="getColorVar('strong')">
14345
14504
  <!-- Page Sheets -->
14346
14505
  @for (sheet of getPageSheets(); track $index) {
14347
- <div class="page-sheet"></div>
14506
+ <div class="page-sheet"></div>
14348
14507
  }
14349
-
14508
+
14350
14509
  <!-- Folder Front -->
14351
- <div
14352
- class="folder-front"
14353
- [style.--border-color]="getColorVar('strong')"
14354
- [style.background-color]="getColorVar('base')">
14510
+ <div class="folder-front" [style.--border-color]="getColorVar('strong')" [style.background-color]="getColorVar('base')">
14355
14511
  <!-- Icon (Centered) -->
14356
14512
  <div class="folder-icon">
14357
- <ds-icon
14358
- [name]="iconName"
14359
- [size]="'32px'"
14360
- [style.color]="'white'" />
14513
+ <ds-icon [name]="iconName" [size]="'32px'" [style.color]="'white'" />
14361
14514
  </div>
14362
14515
  </div>
14363
14516
  </div>
14364
14517
  </div>
14365
-
14518
+
14366
14519
  <!-- Label and Item Count -->
14367
14520
  <div class="folder-label-container">
14368
14521
  <div class="folder-label ui-sm-semiBold">{{ label }}</div>
14369
14522
  <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
14370
14523
  @if (loading) {
14371
- <span class="loading-indicator">Loading...</span>
14524
+ <span class="loading-indicator">Loading...</span>
14372
14525
  } @else if (error) {
14373
- <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14526
+ <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14374
14527
  } @else {
14375
- <span>{{ itemCount }}</span>
14376
- <span class="item-count-label">emner</span>
14528
+ <span>{{ itemCount }}</span>
14529
+ <span class="item-count-label">emner</span>
14377
14530
  }
14378
14531
  </div>
14379
14532
  </div>
@@ -14382,55 +14535,43 @@ class DsMobileHandbookFolderComponent {
14382
14535
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileHandbookFolderComponent, decorators: [{
14383
14536
  type: Component,
14384
14537
  args: [{ selector: 'ds-mobile-handbook-folder', standalone: true, imports: [CommonModule, DsIconComponent], template: `
14385
- <div class="folder-container"
14386
- [class.open]="isOpen()">
14538
+ <div class="folder-container" [class.open]="isOpen()">
14387
14539
  <!-- Folder Tab SVG -->
14388
- <svg
14389
- class="folder-tab"
14390
- width="101"
14391
- height="24"
14392
- viewBox="0 0 101 24"
14393
- fill="none"
14394
- xmlns="http://www.w3.org/2000/svg">
14395
- <path
14396
- d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14397
- [attr.fill]="getColorVar('strong')"/>
14540
+ <svg class="folder-tab" width="101" height="24" viewBox="0 0 101 24" fill="none" xmlns="http://www.w3.org/2000/svg">
14541
+ <path
14542
+ d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
14543
+ [attr.fill]="getColorVar('strong')"
14544
+ />
14398
14545
  </svg>
14399
-
14546
+
14400
14547
  <!-- Folder Back -->
14401
14548
  <div class="folder-back" [style.background-color]="getColorVar('strong')">
14402
14549
  <!-- Page Sheets -->
14403
14550
  @for (sheet of getPageSheets(); track $index) {
14404
- <div class="page-sheet"></div>
14551
+ <div class="page-sheet"></div>
14405
14552
  }
14406
-
14553
+
14407
14554
  <!-- Folder Front -->
14408
- <div
14409
- class="folder-front"
14410
- [style.--border-color]="getColorVar('strong')"
14411
- [style.background-color]="getColorVar('base')">
14555
+ <div class="folder-front" [style.--border-color]="getColorVar('strong')" [style.background-color]="getColorVar('base')">
14412
14556
  <!-- Icon (Centered) -->
14413
14557
  <div class="folder-icon">
14414
- <ds-icon
14415
- [name]="iconName"
14416
- [size]="'32px'"
14417
- [style.color]="'white'" />
14558
+ <ds-icon [name]="iconName" [size]="'32px'" [style.color]="'white'" />
14418
14559
  </div>
14419
14560
  </div>
14420
14561
  </div>
14421
14562
  </div>
14422
-
14563
+
14423
14564
  <!-- Label and Item Count -->
14424
14565
  <div class="folder-label-container">
14425
14566
  <div class="folder-label ui-sm-semiBold">{{ label }}</div>
14426
14567
  <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
14427
14568
  @if (loading) {
14428
- <span class="loading-indicator">Loading...</span>
14569
+ <span class="loading-indicator">Loading...</span>
14429
14570
  } @else if (error) {
14430
- <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14571
+ <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
14431
14572
  } @else {
14432
- <span>{{ itemCount }}</span>
14433
- <span class="item-count-label">emner</span>
14573
+ <span>{{ itemCount }}</span>
14574
+ <span class="item-count-label">emner</span>
14434
14575
  }
14435
14576
  </div>
14436
14577
  </div>
@@ -15799,7 +15940,7 @@ class MobileCommunityPageComponent {
15799
15940
  </div>
15800
15941
  </ds-mobile-content>
15801
15942
  </ds-mobile-page-main>
15802
- `, isInline: true, styles: [".post-feed,.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}ion-infinite-scroll{--color: var(--color-primary-surface)}ion-infinite-scroll-content{--color: var(--color-primary-surface)}ion-infinite-scroll-content::part(spinner){color:var(--color-primary-surface)}\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"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }] });
15943
+ `, isInline: true, styles: [".post-feed,.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}ion-infinite-scroll{--color: var(--color-primary-surface)}ion-infinite-scroll-content{--color: var(--color-primary-surface)}ion-infinite-scroll-content::part(spinner){color:var(--color-primary-surface)}\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", "fileUrl"], 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"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }] });
15803
15944
  }
15804
15945
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MobileCommunityPageComponent, decorators: [{
15805
15946
  type: Component,
@@ -16039,58 +16180,72 @@ class MobileHandbookPageComponent {
16039
16180
  title: 'El',
16040
16181
  description: 'Hovedeltavle placeret i kælderrum B-12. Nødafbryderknap er ved hovedindgangen. Alle kredsløb er mærket.',
16041
16182
  contacts: [
16042
- { name: 'ElektroTek ApS', initials: 'E', contactPerson: 'Lars Nielsen', phoneNumber: '+45 23 45 67 89' }
16043
- ]
16183
+ {
16184
+ name: 'ElektroTek ApS',
16185
+ initials: 'E',
16186
+ contactPerson: 'Lars Nielsen',
16187
+ phoneNumber: '+45 23 45 67 89',
16188
+ },
16189
+ ],
16044
16190
  },
16045
16191
  {
16046
16192
  title: 'Elektrisk diagram',
16047
16193
  description: 'Komplet diagram over bygningens elektriske installation med alle kredsløb og afbrydere.',
16048
- attachments: [
16049
- { name: 'Elektrisk_Diagram.pdf', type: 'pdf' }
16050
- ]
16194
+ attachments: [{ name: 'Elektrisk_Diagram.pdf', type: 'pdf' }],
16051
16195
  },
16052
16196
  {
16053
16197
  title: 'Vandforsyning',
16054
16198
  description: 'Hovedvandhane er placeret i kælderens tekniske rum. Individuelle lejlighedsafspærringer er i gangpanelerne. Vandtryk overvåges automatisk.',
16055
16199
  contacts: [
16056
- { name: 'VVS Hansen', initials: 'V', contactPerson: 'Peter Hansen', phoneNumber: '+45 34 56 78 90' }
16057
- ]
16200
+ {
16201
+ name: 'VVS Hansen',
16202
+ initials: 'V',
16203
+ contactPerson: 'Peter Hansen',
16204
+ phoneNumber: '+45 34 56 78 90',
16205
+ },
16206
+ ],
16058
16207
  },
16059
16208
  {
16060
16209
  title: 'Varmesystem',
16061
16210
  description: 'Fjernvarmetilslutning i kælder. Termostater i hver enhed kan justeres individuelt. Systemet vedligeholdes kvartalsvis af certificerede teknikere.',
16062
16211
  contacts: [
16063
- { name: 'Varme Service A/S', initials: 'V', contactPerson: 'Maria Jensen', phoneNumber: '+45 45 67 89 01' }
16064
- ]
16212
+ {
16213
+ name: 'Varme Service A/S',
16214
+ initials: 'V',
16215
+ contactPerson: 'Maria Jensen',
16216
+ phoneNumber: '+45 45 67 89 01',
16217
+ },
16218
+ ],
16065
16219
  },
16066
16220
  {
16067
16221
  title: 'Varmeanlæg dokumentation',
16068
16222
  description: 'Teknisk dokumentation og vedligeholdelseshistorik for bygningens varmesystem.',
16069
16223
  attachments: [
16070
16224
  { name: 'Varmeplan.pdf', type: 'pdf' },
16071
- { name: 'Vedligeholdelseslog.pdf', type: 'pdf' }
16072
- ]
16225
+ { name: 'Vedligeholdelseslog.pdf', type: 'pdf' },
16226
+ ],
16073
16227
  },
16074
16228
  {
16075
16229
  title: 'Internet & TV',
16076
16230
  description: 'Fiberforbindelse i bygningen. Distributionspanel er i stueetageteknisk rum. Hver lejlighed har ethernet-stik i stue og soveværelser.',
16077
16231
  contacts: [
16078
- { name: 'TeleCom Solutions', initials: 'T', contactPerson: 'Anders Petersen', phoneNumber: '+45 56 78 90 12' }
16079
- ]
16232
+ {
16233
+ name: 'TeleCom Solutions',
16234
+ initials: 'T',
16235
+ contactPerson: 'Anders Petersen',
16236
+ phoneNumber: '+45 56 78 90 12',
16237
+ },
16238
+ ],
16080
16239
  },
16081
16240
  {
16082
16241
  title: 'Netværksopsætning guide',
16083
- attachments: [
16084
- { name: 'Netværksopsætning.pdf', type: 'pdf' }
16085
- ]
16242
+ attachments: [{ name: 'Netværksopsætning.pdf', type: 'pdf' }],
16086
16243
  },
16087
16244
  {
16088
16245
  title: 'Affaldshåndtering',
16089
16246
  description: 'Affaldssorteringsstation placeret i gården. Afhentninger: Dagrenovation (man/tor), Genbrug (ons), Organisk (tir/fre). Storskrald kræver booking.',
16090
- attachments: [
16091
- { name: 'Affaldsretningslinjer.pdf', type: 'pdf' }
16092
- ]
16093
- }
16247
+ attachments: [{ name: 'Affaldsretningslinjer.pdf', type: 'pdf' }],
16248
+ },
16094
16249
  ];
16095
16250
  // Safety Equipment folder data
16096
16251
  sikkerhedsudstyrItems = [
@@ -16099,30 +16254,45 @@ class MobileHandbookPageComponent {
16099
16254
  description: 'Trappeopgange med nødbelysning og brandsikre døre. Postkasser placeret i indgangspartiet. Hold altid flugtveje fri.',
16100
16255
  images: [
16101
16256
  '/Assets/Dummy-photos/staircase.jpg',
16102
- '/Assets/Dummy-photos/mailboxes.jpg'
16103
- ]
16257
+ '/Assets/Dummy-photos/mailboxes.jpg',
16258
+ ],
16104
16259
  },
16105
16260
  {
16106
16261
  title: 'Hjertestarter (AED)',
16107
16262
  description: 'Automatisk hjertestarter placeret i stueetagen ved hovedindgangen. Tilgængelig 24/7. Ingen særlig uddannelse kræves - enheden guider dig gennem processen.',
16108
16263
  contacts: [
16109
- { name: 'MediTech Service', initials: 'M', contactPerson: 'John Mortensen', phoneNumber: '+45 12 34 56 78' }
16110
- ]
16264
+ {
16265
+ name: 'MediTech Service',
16266
+ initials: 'M',
16267
+ contactPerson: 'John Mortensen',
16268
+ phoneNumber: '+45 12 34 56 78',
16269
+ },
16270
+ ],
16271
+ attachments: [
16272
+ {
16273
+ name: 'Brandplan.pdf',
16274
+ type: 'pdf',
16275
+ url: 'https://portal-api.propbinder.com/Handbook/GetFile/50145267-d9a2-448b-a0e1-1af39d344818',
16276
+ },
16277
+ ],
16111
16278
  },
16112
16279
  {
16113
16280
  title: 'Brandslukningsudstyr',
16114
16281
  description: 'Brandslukkere placeret på hver etage. Eftersyn udføres årligt. Brandalarm aktiveres automatisk ved røg.',
16115
- attachments: [
16116
- { name: 'Brandplan.pdf', type: 'pdf' }
16117
- ]
16282
+ attachments: [{ name: 'Brandplan.pdf', type: 'pdf' }],
16118
16283
  },
16119
16284
  {
16120
16285
  title: 'Alarmsystem',
16121
16286
  description: 'Adgangskontrol med kodesystem ved alle indgange. Kode ændres kvartalsvis. Ved indbrud kontakt straks politiet og ejendomsadministrationen.',
16122
16287
  contacts: [
16123
- { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 98 76 54 32' }
16124
- ]
16125
- }
16288
+ {
16289
+ name: 'SecureHome A/S',
16290
+ initials: 'S',
16291
+ contactPerson: 'Henrik Johansen',
16292
+ phoneNumber: '+45 98 76 54 32',
16293
+ },
16294
+ ],
16295
+ },
16126
16296
  ];
16127
16297
  // Service Contracts folder data
16128
16298
  serviceContractsItems = [
@@ -16130,100 +16300,124 @@ class MobileHandbookPageComponent {
16130
16300
  title: 'Rengøringsservice',
16131
16301
  description: 'Ugentlig rengøring af fællesarealer inklusiv indgangshal, trapper og elevatorer. Hovedrengøring kvartalsvis. Service leveres mandag-fredag, 6:00-9:00.',
16132
16302
  contacts: [
16133
- { name: 'CleanCo Denmark', initials: 'C', contactPerson: 'Anne Kristensen', phoneNumber: '+45 89 01 23 45' }
16134
- ]
16303
+ {
16304
+ name: 'CleanCo Denmark',
16305
+ initials: 'C',
16306
+ contactPerson: 'Anne Kristensen',
16307
+ phoneNumber: '+45 89 01 23 45',
16308
+ },
16309
+ ],
16135
16310
  },
16136
16311
  {
16137
16312
  title: 'Rengøringskontrakt',
16138
16313
  attachments: [
16139
16314
  { name: 'Rengøringskontrakt_2024.pdf', type: 'pdf' },
16140
- { name: 'Rengøringsplan.pdf', type: 'pdf' }
16141
- ]
16315
+ { name: 'Rengøringsplan.pdf', type: 'pdf' },
16316
+ ],
16142
16317
  },
16143
16318
  {
16144
16319
  title: 'Udendørs arealer',
16145
16320
  description: 'Fælles grønne områder med bede, siddepladser og terrasse. Beboere må frit benytte området. Respektér planterne og hold området pænt.',
16146
16321
  images: [
16147
16322
  '/Assets/Dummy-photos/park.jpg',
16148
- '/Assets/Dummy-photos/yard.jpg'
16149
- ]
16323
+ '/Assets/Dummy-photos/yard.jpg',
16324
+ ],
16150
16325
  },
16151
16326
  {
16152
16327
  title: 'Havevedligeholdelse',
16153
16328
  description: 'Professionel havepleje inklusiv plæneklipning, hækklipning og blomsterbedvedligeholdelse. Vintersnefjerning inkluderet.',
16154
16329
  contacts: [
16155
- { name: 'Green Gardens ApS', initials: 'G', contactPerson: 'Michael Olsen', phoneNumber: '+45 90 12 34 56' }
16156
- ]
16330
+ {
16331
+ name: 'Green Gardens ApS',
16332
+ initials: 'G',
16333
+ contactPerson: 'Michael Olsen',
16334
+ phoneNumber: '+45 90 12 34 56',
16335
+ },
16336
+ ],
16157
16337
  },
16158
16338
  {
16159
16339
  title: 'Haveserviceaftale',
16160
- attachments: [
16161
- { name: 'Haveserviceaftale.pdf', type: 'pdf' }
16162
- ]
16340
+ attachments: [{ name: 'Haveserviceaftale.pdf', type: 'pdf' }],
16163
16341
  },
16164
16342
  {
16165
16343
  title: 'Vinduespolering',
16166
16344
  description: 'Professionel vinduespoleringsservice for alle udvendige vinduer to gange årligt - forår og efterår.',
16167
16345
  contacts: [
16168
- { name: 'Crystal Clear Windows', initials: 'C', contactPerson: 'Lene Schmidt', phoneNumber: '+45 01 23 45 67' }
16169
- ]
16346
+ {
16347
+ name: 'Crystal Clear Windows',
16348
+ initials: 'C',
16349
+ contactPerson: 'Lene Schmidt',
16350
+ phoneNumber: '+45 01 23 45 67',
16351
+ },
16352
+ ],
16170
16353
  },
16171
16354
  {
16172
16355
  title: 'Sikkerhedsservice',
16173
16356
  description: '24/7 overvågningsservice med alarmrespons. Direkte forbindelse til politi og brandvæsen.',
16174
16357
  contacts: [
16175
- { name: 'SecureHome A/S', initials: 'S', contactPerson: 'Henrik Johansen', phoneNumber: '+45 12 34 56 78' }
16176
- ]
16358
+ {
16359
+ name: 'SecureHome A/S',
16360
+ initials: 'S',
16361
+ contactPerson: 'Henrik Johansen',
16362
+ phoneNumber: '+45 12 34 56 78',
16363
+ },
16364
+ ],
16177
16365
  },
16178
16366
  {
16179
16367
  title: 'Sikkerhedskontrakt og procedurer',
16180
16368
  attachments: [
16181
16369
  { name: 'Sikkerhedskontrakt.pdf', type: 'pdf' },
16182
- { name: 'Nødprocedurer.pdf', type: 'pdf' }
16183
- ]
16184
- }
16370
+ { name: 'Nødprocedurer.pdf', type: 'pdf' },
16371
+ ],
16372
+ },
16185
16373
  ];
16186
16374
  // Equipment folder data
16187
16375
  equipmentItems = [
16188
16376
  {
16189
16377
  title: 'Balkon udsigt',
16190
16378
  description: 'Eksempel på udsigt fra øverste etagers balkoner. Flere lejligheder har privat altan med fantastisk udsyn.',
16191
- images: [
16192
- '/Assets/Dummy-photos/balcony-view.jpg'
16193
- ]
16379
+ images: ['/Assets/Dummy-photos/balcony-view.jpg'],
16194
16380
  },
16195
16381
  {
16196
16382
  title: 'Vaskerum',
16197
16383
  description: 'Fælles vaskerum med 4 vaskemaskiner og 4 tørretumblere. Bookingsystem tilgængeligt via beboerportal. Maskiner accepterer betalingskort. Åbningstider: 7:00-22:00.',
16198
16384
  contacts: [
16199
- { name: 'WashTech Service', initials: 'W', contactPerson: 'Kirsten Berg', phoneNumber: '+45 34 56 78 90' }
16200
- ]
16385
+ {
16386
+ name: 'WashTech Service',
16387
+ initials: 'W',
16388
+ contactPerson: 'Kirsten Berg',
16389
+ phoneNumber: '+45 34 56 78 90',
16390
+ },
16391
+ ],
16201
16392
  },
16202
16393
  {
16203
16394
  title: 'Vaskeri instruktioner',
16204
16395
  attachments: [
16205
16396
  { name: 'Vaskeinstruktioner.pdf', type: 'pdf' },
16206
- { name: 'Bookingguide.pdf', type: 'pdf' }
16207
- ]
16397
+ { name: 'Bookingguide.pdf', type: 'pdf' },
16398
+ ],
16208
16399
  },
16209
16400
  {
16210
16401
  title: 'Vedligeholdelse og reparationer',
16211
16402
  description: 'Ved behov for reparationer eller vedligeholdelse i din lejlighed, kontakt vores hausmeister. Akutte problemer håndteres samme dag.',
16212
- images: [
16213
- '/Assets/Dummy-photos/handyman.jpg'
16214
- ],
16403
+ images: ['/Assets/Dummy-photos/handyman.jpg'],
16215
16404
  contacts: [
16216
- { name: 'Hausmeister Service', initials: 'H', contactPerson: 'Erik Sørensen', phoneNumber: '+45 56 78 90 12' }
16217
- ]
16405
+ {
16406
+ name: 'Hausmeister Service',
16407
+ initials: 'H',
16408
+ contactPerson: 'Erik Sørensen',
16409
+ phoneNumber: '+45 56 78 90 12',
16410
+ },
16411
+ ],
16218
16412
  },
16219
16413
  {
16220
16414
  title: 'Værktøjsudlån',
16221
16415
  description: 'Basis håndværktøj tilgængeligt til beboerbrug. Kvittér for værktøj ved receptionen. Returnér inden for 48 timer.',
16222
16416
  attachments: [
16223
16417
  { name: 'Værktøjsliste.pdf', type: 'pdf' },
16224
- { name: 'Udlånspolitik.pdf', type: 'pdf' }
16225
- ]
16226
- }
16418
+ { name: 'Udlånspolitik.pdf', type: 'pdf' },
16419
+ ],
16420
+ },
16227
16421
  ];
16228
16422
  constructor(userService) {
16229
16423
  this.userService = userService;
@@ -16241,8 +16435,8 @@ class MobileHandbookPageComponent {
16241
16435
  title="Håndbog"
16242
16436
  [avatarInitials]="userService.avatarInitials()"
16243
16437
  [avatarType]="userService.avatarType()"
16244
- (refresh)="handleRefresh($event)">
16245
-
16438
+ (refresh)="handleRefresh($event)"
16439
+ >
16246
16440
  <ds-mobile-content>
16247
16441
  <ds-mobile-content-section>
16248
16442
  <div class="folders-grid">
@@ -16251,7 +16445,8 @@ class MobileHandbookPageComponent {
16251
16445
  [iconName]="'remixLightbulbLine'"
16252
16446
  [itemCount]="8"
16253
16447
  [label]="'Forsyninger'"
16254
- [items]="utilitiesItems">
16448
+ [items]="utilitiesItems"
16449
+ >
16255
16450
  </ds-mobile-handbook-folder>
16256
16451
 
16257
16452
  <ds-mobile-handbook-folder
@@ -16259,7 +16454,8 @@ class MobileHandbookPageComponent {
16259
16454
  [iconName]="'remixKey2Line'"
16260
16455
  [itemCount]="4"
16261
16456
  [label]="'Sikkerhedsudstyr'"
16262
- [items]="sikkerhedsudstyrItems">
16457
+ [items]="sikkerhedsudstyrItems"
16458
+ >
16263
16459
  </ds-mobile-handbook-folder>
16264
16460
 
16265
16461
  <ds-mobile-handbook-folder
@@ -16267,7 +16463,8 @@ class MobileHandbookPageComponent {
16267
16463
  [iconName]="'remixFileList3Line'"
16268
16464
  [itemCount]="8"
16269
16465
  [label]="'Servicekontrakter'"
16270
- [items]="serviceContractsItems">
16466
+ [items]="serviceContractsItems"
16467
+ >
16271
16468
  </ds-mobile-handbook-folder>
16272
16469
 
16273
16470
  <ds-mobile-handbook-folder
@@ -16275,7 +16472,8 @@ class MobileHandbookPageComponent {
16275
16472
  [iconName]="'remixToolsLine'"
16276
16473
  [itemCount]="5"
16277
16474
  [label]="'Udstyr'"
16278
- [items]="equipmentItems">
16475
+ [items]="equipmentItems"
16476
+ >
16279
16477
  </ds-mobile-handbook-folder>
16280
16478
  </div>
16281
16479
  </ds-mobile-content-section>
@@ -16289,14 +16487,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16289
16487
  DsMobilePageMainComponent,
16290
16488
  DsMobileContentComponent,
16291
16489
  DsMobileContentSectionComponent,
16292
- DsMobileHandbookFolderComponent
16490
+ DsMobileHandbookFolderComponent,
16293
16491
  ], template: `
16294
16492
  <ds-mobile-page-main
16295
16493
  title="Håndbog"
16296
16494
  [avatarInitials]="userService.avatarInitials()"
16297
16495
  [avatarType]="userService.avatarType()"
16298
- (refresh)="handleRefresh($event)">
16299
-
16496
+ (refresh)="handleRefresh($event)"
16497
+ >
16300
16498
  <ds-mobile-content>
16301
16499
  <ds-mobile-content-section>
16302
16500
  <div class="folders-grid">
@@ -16305,7 +16503,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16305
16503
  [iconName]="'remixLightbulbLine'"
16306
16504
  [itemCount]="8"
16307
16505
  [label]="'Forsyninger'"
16308
- [items]="utilitiesItems">
16506
+ [items]="utilitiesItems"
16507
+ >
16309
16508
  </ds-mobile-handbook-folder>
16310
16509
 
16311
16510
  <ds-mobile-handbook-folder
@@ -16313,7 +16512,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16313
16512
  [iconName]="'remixKey2Line'"
16314
16513
  [itemCount]="4"
16315
16514
  [label]="'Sikkerhedsudstyr'"
16316
- [items]="sikkerhedsudstyrItems">
16515
+ [items]="sikkerhedsudstyrItems"
16516
+ >
16317
16517
  </ds-mobile-handbook-folder>
16318
16518
 
16319
16519
  <ds-mobile-handbook-folder
@@ -16321,7 +16521,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16321
16521
  [iconName]="'remixFileList3Line'"
16322
16522
  [itemCount]="8"
16323
16523
  [label]="'Servicekontrakter'"
16324
- [items]="serviceContractsItems">
16524
+ [items]="serviceContractsItems"
16525
+ >
16325
16526
  </ds-mobile-handbook-folder>
16326
16527
 
16327
16528
  <ds-mobile-handbook-folder
@@ -16329,7 +16530,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16329
16530
  [iconName]="'remixToolsLine'"
16330
16531
  [itemCount]="5"
16331
16532
  [label]="'Udstyr'"
16332
- [items]="equipmentItems">
16533
+ [items]="equipmentItems"
16534
+ >
16333
16535
  </ds-mobile-handbook-folder>
16334
16536
  </div>
16335
16537
  </ds-mobile-content-section>
@@ -16506,7 +16708,7 @@ class MobileHomePageComponent {
16506
16708
  </div>
16507
16709
  </ds-mobile-content>
16508
16710
  </ds-mobile-page-main>
16509
- `, isInline: true, styles: [".section-headline{font-size:var(--font-size-sm);font-weight:600;color:var(--text-color-default-primary);margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px;padding:0}.pinned-posts-section{margin:-12px -12px 0;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.pinned-posts-section .section-headline{padding:16px 0}.content-section{display:flex;flex-direction:column;gap:12px}.items-container{display:flex;flex-direction:column;gap:4px}\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: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout"], outputs: ["fileClick"] }, { 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: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { 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"] }] });
16711
+ `, isInline: true, styles: [".section-headline{font-size:var(--font-size-sm);font-weight:600;color:var(--text-color-default-primary);margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px;padding:0}.pinned-posts-section{margin:-12px -12px 0;padding:0 12px 12px;box-shadow:var(--box-shadow-sm);border-radius:16px;border:1px solid var(--border-color-default)}.pinned-posts-section .section-headline{padding:16px 0}.content-section{display:flex;flex-direction:column;gap:12px}.items-container{display:flex;flex-direction:column;gap:4px}\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: DsMobileCardInlineContactComponent, selector: "ds-mobile-card-inline-contact", inputs: ["name", "initials", "contactPerson", "phoneNumber", "layout", "clickable", "showChevron"], outputs: ["contactClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { 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: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { 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"] }] });
16510
16712
  }
16511
16713
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MobileHomePageComponent, decorators: [{
16512
16714
  type: Component,
@@ -16921,123 +17123,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
16921
17123
  `, styles: [".inquiries-container{display:flex;flex-direction:column}.inquiry-list-wrapper{display:flex;flex-direction:column;margin-top:-8px}.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"] }]
16922
17124
  }], ctorParameters: () => [{ type: UserService }, { type: i1.NavController }, { type: DsMobileNewInquiryModalService }] });
16923
17125
 
16924
- /**
16925
- * DsMobileCardInlineBannerComponent
16926
- *
16927
- * Specialized interactive component for displaying notification banners.
16928
- * Used to show unread message notifications above inquiry details.
16929
- *
16930
- * Features:
16931
- * - Neutral background matching file/contact cards
16932
- * - Avatar icon with message symbol
16933
- * - Title and timestamp
16934
- * - Unread count badge
16935
- * - Chevron for navigation indication
16936
- *
16937
- * @example
16938
- * ```html
16939
- * <ds-mobile-card-inline-banner
16940
- * [title]="'New messages'"
16941
- * [timestamp]="'2 min ago'"
16942
- * [unreadCount]="3"
16943
- * (bannerClick)="navigateToMessages()">
16944
- * </ds-mobile-card-inline-banner>
16945
- * ```
16946
- */
16947
- class DsMobileCardInlineBannerComponent {
16948
- /**
16949
- * Banner title (e.g., "New messages", "Unread messages")
16950
- */
16951
- title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
16952
- /**
16953
- * Timestamp text (e.g., "2 min ago", "Just now")
16954
- */
16955
- timestamp = input('', ...(ngDevMode ? [{ debugName: "timestamp" }] : []));
16956
- /**
16957
- * Number of unread items (optional, shows badge if > 0)
16958
- */
16959
- unreadCount = input(0, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
16960
- /**
16961
- * Layout variant
16962
- * - 'default' - Standard padding and column layout
16963
- * - 'compact' - Reduced padding and row layout
16964
- */
16965
- layout = input('default', ...(ngDevMode ? [{ debugName: "layout" }] : []));
16966
- /**
16967
- * Emits when the banner is clicked
16968
- */
16969
- bannerClick = output();
16970
- handleBannerClick() {
16971
- this.bannerClick.emit();
16972
- }
16973
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16974
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsMobileCardInlineBannerComponent, isStandalone: true, selector: "ds-mobile-card-inline-banner", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, timestamp: { classPropertyName: "timestamp", publicName: "timestamp", isSignal: true, isRequired: false, transformFunction: null }, unreadCount: { classPropertyName: "unreadCount", publicName: "unreadCount", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bannerClick: "bannerClick" }, ngImport: i0, template: `
16975
- <ds-mobile-card-inline
16976
- [variant]="layout()"
16977
- (cardClick)="handleBannerClick()">
16978
-
16979
- <div content-leading class="item-avatar">
16980
- <ds-avatar
16981
- type="icon"
16982
- [iconName]="'remixNotificationLine'"
16983
- [size]="layout() === 'compact' ? 'sm' : 'md'"
16984
- />
16985
- </div>
16986
-
16987
- <div content-main class="item-content">
16988
- <div class="item-name">{{ title() }}</div>
16989
-
16990
- @if (timestamp()) {
16991
- <div class="item-meta">
16992
- <span>{{ timestamp() }}</span>
16993
- </div>
16994
- }
16995
- </div>
16996
-
16997
- <div content-trailing class="item-trailing">
16998
- @if (unreadCount() && unreadCount()! > 0) {
16999
- <span class="unread-badge">{{ unreadCount() }}</span>
17000
- }
17001
- <ds-icon name="remixArrowRightSLine" size="20px" />
17002
- </div>
17003
- </ds-mobile-card-inline>
17004
- `, isInline: true, styles: [".unread-badge{min-width:24px;height:16px;padding:0 6px;border-radius:10px;background:var(--color-primary-surface, #6B5FF5);color:var(--color-primary-content, #ffffff);font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:600;display:flex;align-items:center;justify-content:center;line-height:1;margin-right:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: DsMobileCardInlineComponent, selector: "ds-mobile-card-inline", inputs: ["variant", "disabled"], outputs: ["cardClick"] }] });
17005
- }
17006
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsMobileCardInlineBannerComponent, decorators: [{
17007
- type: Component,
17008
- args: [{ selector: 'ds-mobile-card-inline-banner', standalone: true, imports: [CommonModule, DsIconComponent, DsAvatarComponent, DsMobileCardInlineComponent], template: `
17009
- <ds-mobile-card-inline
17010
- [variant]="layout()"
17011
- (cardClick)="handleBannerClick()">
17012
-
17013
- <div content-leading class="item-avatar">
17014
- <ds-avatar
17015
- type="icon"
17016
- [iconName]="'remixNotificationLine'"
17017
- [size]="layout() === 'compact' ? 'sm' : 'md'"
17018
- />
17019
- </div>
17020
-
17021
- <div content-main class="item-content">
17022
- <div class="item-name">{{ title() }}</div>
17023
-
17024
- @if (timestamp()) {
17025
- <div class="item-meta">
17026
- <span>{{ timestamp() }}</span>
17027
- </div>
17028
- }
17029
- </div>
17030
-
17031
- <div content-trailing class="item-trailing">
17032
- @if (unreadCount() && unreadCount()! > 0) {
17033
- <span class="unread-badge">{{ unreadCount() }}</span>
17034
- }
17035
- <ds-icon name="remixArrowRightSLine" size="20px" />
17036
- </div>
17037
- </ds-mobile-card-inline>
17038
- `, styles: [".unread-badge{min-width:24px;height:16px;padding:0 6px;border-radius:10px;background:var(--color-primary-surface, #6B5FF5);color:var(--color-primary-content, #ffffff);font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:600;display:flex;align-items:center;justify-content:center;line-height:1;margin-right:8px}\n"] }]
17039
- }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], timestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "timestamp", required: false }] }], unreadCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "unreadCount", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], bannerClick: [{ type: i0.Output, args: ["bannerClick"] }] } });
17040
-
17041
17126
  class MobileInquiryDetailPageComponent {
17042
17127
  userService;
17043
17128
  lightbox;
@@ -18916,5 +19001,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
18916
19001
  * Generated bundle index. Do not edit.
18917
19002
  */
18918
19003
 
18919
- export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsAvatarWithBadgeComponent, DsMobileActionsBottomSheetComponent, DsMobileAttachmentPreviewComponent, DsMobileBottomSheetService, DsMobileBottomSheetWrapperComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileDropdownComponent, DsMobileEmptyStateComponent, DsMobileFabComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLongPressDirective, DsMobileMessageBubbleComponent, DsMobileMessageComposerComponent, DsMobileModalBaseComponent, DsMobileModalService, DsMobileNewInquiryModalComponent, DsMobileNewInquiryModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileProfileActionsSheetComponent, DsMobileTabBarComponent, DsMobileTabsComponent, DsTextInputComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobileModalBase, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, SignInPageComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoPage, WhitelabelService, customBackTransition, customPageTransition };
19004
+ export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsAvatarWithBadgeComponent, DsMobileActionsBottomSheetComponent, DsMobileAttachmentPreviewComponent, DsMobileBottomSheetService, DsMobileBottomSheetWrapperComponent, DsMobileCardInlineBannerComponent, DsMobileCardInlineComponent, DsMobileCardInlineContactComponent, DsMobileCardInlineFileComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileDropdownComponent, DsMobileEmptyStateComponent, DsMobileFabComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLongPressDirective, DsMobileMessageBubbleComponent, DsMobileMessageComposerComponent, DsMobileModalBaseComponent, DsMobileModalService, DsMobileNewInquiryModalComponent, DsMobileNewInquiryModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileProfileActionsSheetComponent, DsMobileTabBarComponent, DsMobileTabsComponent, DsTextInputComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobileModalBase, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, SignInPageComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoPage, WhitelabelService, customBackTransition, customPageTransition };
18920
19005
  //# sourceMappingURL=propbinder-mobile-design.mjs.map