@propbinder/mobile-design 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { AfterViewInit, OnInit, ElementRef, OnDestroy, EventEmitter, ApplicationRef, EnvironmentInjector, Type, AfterContentInit, ChangeDetectorRef } from '@angular/core';
2
+ import { AfterViewInit, OnInit, ElementRef, Injector, TemplateRef, OnDestroy, EventEmitter, ApplicationRef, EnvironmentInjector, Type, AfterContentInit, ChangeDetectorRef } from '@angular/core';
3
3
  import { ModalController, IonContent, NavController, GestureController, ModalOptions as ModalOptions$1 } from '@ionic/angular/standalone';
4
4
  import { ImpactStyle } from '@capacitor/haptics';
5
5
  import { DsTextareaComponent } from '@propbinder/design-system';
@@ -71,6 +71,9 @@ interface ActionItem {
71
71
  title: string;
72
72
  icon: string;
73
73
  destructive?: boolean;
74
+ subtitle?: string;
75
+ showChevron?: boolean;
76
+ flagIcon?: string;
74
77
  }
75
78
  interface ActionGroup {
76
79
  actions: ActionItem[];
@@ -231,6 +234,27 @@ declare class DsMobileBottomSheetService {
231
234
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobileBottomSheetService>;
232
235
  }
233
236
 
237
+ /**
238
+ * DsMobileBottomSheetWrapperComponent
239
+ *
240
+ * A wrapper component that provides common layout styling for all bottom sheets.
241
+ * Handles safe area insets and provides consistent layout structure.
242
+ *
243
+ * Usage:
244
+ * Wrap your bottom sheet content with this component using ng-content projection.
245
+ *
246
+ * @example
247
+ * ```html
248
+ * <ds-mobile-bottom-sheet-wrapper>
249
+ * <!-- Your bottom sheet content here -->
250
+ * </ds-mobile-bottom-sheet-wrapper>
251
+ * ```
252
+ */
253
+ declare class DsMobileBottomSheetWrapperComponent {
254
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileBottomSheetWrapperComponent, never>;
255
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileBottomSheetWrapperComponent, "ds-mobile-bottom-sheet-wrapper", never, {}, {}, never, ["*"], true, never>;
256
+ }
257
+
234
258
  /**
235
259
  * DsMobilePostCreateBottomSheetComponent
236
260
  *
@@ -294,6 +318,127 @@ declare class DsMobilePostCreateBottomSheetComponent implements AfterViewInit, O
294
318
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostCreateBottomSheetComponent, "ds-mobile-post-create-bottom-sheet", never, {}, {}, never, never, true, never>;
295
319
  }
296
320
 
321
+ interface Language {
322
+ code: string;
323
+ nativeName: string;
324
+ englishName: string;
325
+ flagIcon: string;
326
+ }
327
+ /**
328
+ * DsMobileProfileActionsSheetComponent
329
+ *
330
+ * Bottom sheet for profile actions with navigable language selection.
331
+ * Features a smooth slide-in navigation pattern for sub-menus.
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * const sheet = await this.modalController.create({
336
+ * component: DsMobileProfileActionsSheetComponent,
337
+ * componentProps: {
338
+ * actionGroups: [...],
339
+ * currentLanguage: 'da',
340
+ * availableLanguages: [...]
341
+ * },
342
+ * breakpoints: [0, 1],
343
+ * initialBreakpoint: 1,
344
+ * handle: true,
345
+ * cssClass: ['ds-bottom-sheet', 'auto-height']
346
+ * });
347
+ *
348
+ * const result = await sheet.onWillDismiss();
349
+ * if (result.data?.action) {
350
+ * // Handle the action (e.g., 'language:da', 'profile', 'logout')
351
+ * }
352
+ * ```
353
+ */
354
+ declare class DsMobileProfileActionsSheetComponent {
355
+ private modalController;
356
+ private injector;
357
+ /**
358
+ * Action groups to display in main view
359
+ */
360
+ actionGroups: ActionGroup[];
361
+ /**
362
+ * Currently selected language code
363
+ */
364
+ currentLanguage: string;
365
+ /**
366
+ * Initial language (for tracking changes)
367
+ */
368
+ private initialLanguage;
369
+ /**
370
+ * Currently selected language in the view (before confirmation)
371
+ */
372
+ selectedLanguage: _angular_core.WritableSignal<string>;
373
+ /**
374
+ * Check if language has changed
375
+ */
376
+ hasLanguageChanged: _angular_core.Signal<boolean>;
377
+ /**
378
+ * Available languages for selection
379
+ */
380
+ availableLanguages: Language[];
381
+ /**
382
+ * Current view state
383
+ */
384
+ currentView: _angular_core.WritableSignal<"main" | "language">;
385
+ /**
386
+ * Reference to the view container for height calculations
387
+ */
388
+ viewContainer?: ElementRef<HTMLDivElement>;
389
+ /**
390
+ * Reference to the profile actions sheet wrapper
391
+ */
392
+ sheetWrapper?: ElementRef<HTMLDivElement>;
393
+ /**
394
+ * Current container height (for dynamic transitions)
395
+ */
396
+ containerHeight: _angular_core.WritableSignal<number | null>;
397
+ /**
398
+ * Is animating between views
399
+ */
400
+ isAnimating: _angular_core.WritableSignal<boolean>;
401
+ constructor(modalController: ModalController, injector: Injector);
402
+ /**
403
+ * Handle action item click
404
+ */
405
+ handleActionClick(actionItem: ActionItem): void;
406
+ /**
407
+ * Navigate back to main view
408
+ */
409
+ navigateBack(): void;
410
+ /**
411
+ * Confirm language selection and dismiss
412
+ */
413
+ confirmLanguageSelection(): void;
414
+ /**
415
+ * Handle language selection (update selection, don't dismiss)
416
+ */
417
+ selectLanguage(languageCode: string): void;
418
+ /**
419
+ * Get current language flag icon
420
+ */
421
+ getCurrentLanguageFlag(): string;
422
+ /**
423
+ * Update container height based on active view
424
+ */
425
+ private updateHeight;
426
+ /**
427
+ * Animate view transition with height change
428
+ */
429
+ private animateViewTransition;
430
+ /**
431
+ * Helper to create delay promise
432
+ */
433
+ private delay;
434
+ /**
435
+ * Handle regular action selection
436
+ */
437
+ selectAction(action: string): void;
438
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileProfileActionsSheetComponent, never>;
439
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileProfileActionsSheetComponent, "ds-mobile-profile-actions-sheet", never, { "actionGroups": { "alias": "actionGroups"; "required": false; }; "currentLanguage": { "alias": "currentLanguage"; "required": false; }; "availableLanguages": { "alias": "availableLanguages"; "required": false; }; }, {}, never, never, true, never>;
440
+ }
441
+
297
442
  /**
298
443
  * DsMobilePageMainComponent
299
444
  *
@@ -716,6 +861,13 @@ declare class TileValueComponent {
716
861
  * ```
717
862
  */
718
863
  declare class DsMobileCommentComponent {
864
+ private platformId;
865
+ /**
866
+ * Detect if viewport is desktop size
867
+ * Use viewport width for breakpoint detection (show button on tablet and above)
868
+ */
869
+ isDesktop: _angular_core.WritableSignal<boolean>;
870
+ constructor();
719
871
  /**
720
872
  * Author's display name
721
873
  */
@@ -751,7 +903,7 @@ declare class DsMobileCommentComponent {
751
903
  /**
752
904
  * Whether the comment is liked by current user
753
905
  */
754
- isLiked: _angular_core.ModelSignal<boolean>;
906
+ isLiked: _angular_core.InputSignal<boolean>;
755
907
  /**
756
908
  * Emits when like is toggled (after UI is opdateret)
757
909
  */
@@ -762,7 +914,15 @@ declare class DsMobileCommentComponent {
762
914
  /**
763
915
  * Number of likes
764
916
  */
765
- likeCount: _angular_core.ModelSignal<number>;
917
+ likeCount: _angular_core.InputSignal<number>;
918
+ /**
919
+ * Internal signal to track like state for UI updates
920
+ */
921
+ internalIsLiked: _angular_core.WritableSignal<boolean>;
922
+ /**
923
+ * Internal signal to track like count for UI updates
924
+ */
925
+ internalLikeCount: _angular_core.WritableSignal<number>;
766
926
  /**
767
927
  * Signal to control pulse animation
768
928
  */
@@ -822,7 +982,7 @@ declare class DsMobileCommentComponent {
822
982
  */
823
983
  handleMoreButtonClick(event: Event): void;
824
984
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCommentComponent, never>;
825
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCommentComponent, "ds-mobile-comment", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "content": { "alias": "content"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "isOwnComment": { "alias": "isOwnComment"; "required": false; "isSignal": true; }; "isLiked": { "alias": "isLiked"; "required": false; "isSignal": true; }; "likeCount": { "alias": "likeCount"; "required": false; "isSignal": true; }; }, { "isLiked": "isLikedChange"; "likeToggled": "likeToggled"; "likeCount": "likeCountChange"; "commentClick": "commentClick"; "replyClick": "replyClick"; "editClick": "editClick"; "longPress": "longPress"; }, never, never, true, never>;
985
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCommentComponent, "ds-mobile-comment", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "content": { "alias": "content"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "isOwnComment": { "alias": "isOwnComment"; "required": false; "isSignal": true; }; "isLiked": { "alias": "isLiked"; "required": false; "isSignal": true; }; "likeCount": { "alias": "likeCount"; "required": false; "isSignal": true; }; }, { "likeToggled": "likeToggled"; "commentClick": "commentClick"; "replyClick": "replyClick"; "editClick": "editClick"; "longPress": "longPress"; }, never, never, true, never>;
826
986
  }
827
987
 
828
988
  /**
@@ -889,6 +1049,7 @@ interface AttachmentData {
889
1049
  type: AttachmentFileType;
890
1050
  name?: string;
891
1051
  size?: string;
1052
+ isLoading?: boolean;
892
1053
  }
893
1054
  /**
894
1055
  * DsMobileAttachmentPreviewComponent
@@ -936,12 +1097,164 @@ declare class DsMobileAttachmentPreviewComponent {
936
1097
  getIconName(): string;
937
1098
  /**
938
1099
  * Handle remove button click
1100
+ * Uses mousedown to prevent keyboard from closing
939
1101
  */
940
- handleRemove(): void;
1102
+ handleRemove(event?: MouseEvent): void;
941
1103
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileAttachmentPreviewComponent, never>;
942
1104
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileAttachmentPreviewComponent, "ds-mobile-attachment-preview", never, { "attachment": { "alias": "attachment"; "required": true; "isSignal": true; }; }, { "remove": "remove"; }, never, never, true, never>;
943
1105
  }
944
1106
 
1107
+ interface DsMobileDropdownItem {
1108
+ id: string;
1109
+ /** Optional leading icon */
1110
+ leadingIcon?: string;
1111
+ /** Optional trailing icon */
1112
+ trailingIcon?: string;
1113
+ /** Main label text */
1114
+ label?: string;
1115
+ /** Whether the item is disabled */
1116
+ disabled?: boolean;
1117
+ /** Optional action callback */
1118
+ action?: () => void;
1119
+ /** Custom data for template rendering */
1120
+ data?: any;
1121
+ }
1122
+ type DropdownPosition = 'above' | 'below';
1123
+ type DropdownAlign = 'start' | 'end';
1124
+ /**
1125
+ * DsMobileDropdownComponent
1126
+ *
1127
+ * A mobile-optimized dropdown component for action menus, mention lists, and selection lists.
1128
+ * Uses Ionic Popover for robust mobile positioning and backdrop management.
1129
+ *
1130
+ * Features:
1131
+ * - Vertical list layout with leading/main/trailing slots
1132
+ * - Custom template support via content projection
1133
+ * - Mobile-friendly touch interactions (mousedown events)
1134
+ * - Ionic-powered backdrop overlay for dismissal
1135
+ * - Configurable positioning (above/below) and alignment (start/end)
1136
+ * - Max height with scroll support
1137
+ * - Smooth enter/exit animations
1138
+ *
1139
+ * @example
1140
+ * Basic dropdown with default items:
1141
+ * ```html
1142
+ * <button (click)="toggleMenu()">Open Menu</button>
1143
+ * <ds-mobile-dropdown
1144
+ * [items]="menuItems"
1145
+ * [isOpen]="isMenuOpen()"
1146
+ * position="below"
1147
+ * align="start"
1148
+ * (itemSelected)="handleSelection($event)"
1149
+ * (closed)="closeMenu()">
1150
+ * </ds-mobile-dropdown>
1151
+ * ```
1152
+ *
1153
+ * @example
1154
+ * Custom template for mention menu with avatars:
1155
+ * ```html
1156
+ * <textarea (input)="handleInput($event)"></textarea>
1157
+ * <ds-mobile-dropdown
1158
+ * [items]="users"
1159
+ * [isOpen]="showMentions()"
1160
+ * position="above"
1161
+ * [maxHeight]="200"
1162
+ * (itemSelected)="selectUser($event)"
1163
+ * (closed)="closeMentions()">
1164
+ * <ng-template #itemTemplate let-item>
1165
+ * <ds-avatar
1166
+ * [initials]="item.data.initials"
1167
+ * size="sm" />
1168
+ * <div class="user-info">
1169
+ * <span>{{ item.data.name }}</span>
1170
+ * <span>{{ item.data.role }}</span>
1171
+ * </div>
1172
+ * </ng-template>
1173
+ * </ds-mobile-dropdown>
1174
+ * ```
1175
+ */
1176
+ declare class DsMobileDropdownComponent {
1177
+ private elementRef;
1178
+ constructor();
1179
+ /**
1180
+ * Content projection for custom item template
1181
+ */
1182
+ customItemTemplate?: TemplateRef<any>;
1183
+ /**
1184
+ * Optional trigger element ID for Ionic Popover positioning
1185
+ */
1186
+ trigger: _angular_core.InputSignal<string | undefined>;
1187
+ /**
1188
+ * Optional element to keep focused (prevent keyboard from dismissing)
1189
+ * Pass ElementRef to maintain focus when popover opens
1190
+ */
1191
+ keepFocusOn: _angular_core.InputSignal<ElementRef<any> | undefined>;
1192
+ /**
1193
+ * Array of dropdown items to display
1194
+ */
1195
+ items: _angular_core.InputSignal<DsMobileDropdownItem[]>;
1196
+ /**
1197
+ * Whether the dropdown is open
1198
+ */
1199
+ isOpen: _angular_core.InputSignal<boolean>;
1200
+ /**
1201
+ * Position relative to parent container
1202
+ * - 'above': Appears above the anchor
1203
+ * - 'below': Appears below the anchor
1204
+ */
1205
+ position: _angular_core.InputSignal<DropdownPosition>;
1206
+ /**
1207
+ * Horizontal alignment
1208
+ * - 'start': Left-aligned (default)
1209
+ * - 'end': Right-aligned
1210
+ */
1211
+ align: _angular_core.InputSignal<DropdownAlign>;
1212
+ /**
1213
+ * Maximum height in pixels before scrolling
1214
+ */
1215
+ maxHeight: _angular_core.InputSignal<number>;
1216
+ /**
1217
+ * Message to show when items array is empty
1218
+ */
1219
+ emptyMessage: _angular_core.InputSignal<string>;
1220
+ /**
1221
+ * ARIA label for the dropdown menu
1222
+ */
1223
+ ariaLabel: _angular_core.InputSignal<string>;
1224
+ /**
1225
+ * Emits when an item is selected
1226
+ */
1227
+ itemSelected: _angular_core.OutputEmitterRef<DsMobileDropdownItem>;
1228
+ /**
1229
+ * Emits when the dropdown should be closed (backdrop click)
1230
+ */
1231
+ closed: _angular_core.OutputEmitterRef<void>;
1232
+ /**
1233
+ * Computed dropdown CSS classes
1234
+ */
1235
+ dropdownClasses: _angular_core.Signal<string>;
1236
+ /**
1237
+ * Computed offset Y for Ionic Popover
1238
+ * Uses CSS variable for precise control
1239
+ */
1240
+ offsetY: _angular_core.Signal<"4px" | "-4px">;
1241
+ /**
1242
+ * Computed offset X for Ionic Popover
1243
+ * Negative value to shift left by trigger position + add 20px left margin
1244
+ */
1245
+ offsetX: _angular_core.Signal<string>;
1246
+ /**
1247
+ * Get CSS classes for a dropdown item
1248
+ */
1249
+ getItemClass(item: DsMobileDropdownItem): string;
1250
+ /**
1251
+ * Handle item click with mousedown to prevent keyboard loss
1252
+ */
1253
+ handleItemClick(item: DsMobileDropdownItem, event: MouseEvent): void;
1254
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileDropdownComponent, never>;
1255
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileDropdownComponent, "ds-mobile-dropdown", never, { "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "keepFocusOn": { "alias": "keepFocusOn"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": true; "isSignal": true; }; "isOpen": { "alias": "isOpen"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "itemSelected": "itemSelected"; "closed": "closed"; }, ["customItemTemplate"], never, true, never>;
1256
+ }
1257
+
945
1258
  /**
946
1259
  * DsMobileMessageComposerComponent
947
1260
  *
@@ -1022,7 +1335,7 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1022
1335
  /**
1023
1336
  * ViewChild for message input
1024
1337
  */
1025
- messageInput?: ElementRef<HTMLTextAreaElement>;
1338
+ messageInputRef?: ElementRef<HTMLTextAreaElement>;
1026
1339
  /**
1027
1340
  * ViewChild for file input
1028
1341
  */
@@ -1035,6 +1348,10 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1035
1348
  * Attachments signal
1036
1349
  */
1037
1350
  attachments: _angular_core.WritableSignal<AttachmentData[]>;
1351
+ /**
1352
+ * Attachment menu open state
1353
+ */
1354
+ isAttachmentMenuOpen: _angular_core.WritableSignal<boolean>;
1038
1355
  /**
1039
1356
  * Editing message state (optional)
1040
1357
  */
@@ -1066,6 +1383,14 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1066
1383
  initials: string;
1067
1384
  role: string;
1068
1385
  }[]>;
1386
+ /**
1387
+ * Convert filtered users to dropdown items
1388
+ */
1389
+ mentionDropdownItems: _angular_core.Signal<DsMobileDropdownItem[]>;
1390
+ /**
1391
+ * Attachment menu items
1392
+ */
1393
+ attachmentMenuItems: _angular_core.Signal<DsMobileDropdownItem[]>;
1069
1394
  /**
1070
1395
  * Emits when a message is sent
1071
1396
  */
@@ -1094,6 +1419,11 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1094
1419
  * Emits when attachment button is clicked
1095
1420
  */
1096
1421
  attachmentClicked: _angular_core.OutputEmitterRef<void>;
1422
+ /**
1423
+ * Emits when attachments array changes (added or removed)
1424
+ * Parent components (like chat modal) can use this to scroll to bottom
1425
+ */
1426
+ attachmentsChanged: _angular_core.OutputEmitterRef<void>;
1097
1427
  ngAfterViewInit(): void;
1098
1428
  ngOnDestroy(): void;
1099
1429
  /**
@@ -1116,6 +1446,18 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1116
1446
  * Handle input changes and detect @ mentions
1117
1447
  */
1118
1448
  handleInput(event: Event): void;
1449
+ /**
1450
+ * Handle mention selection from dropdown
1451
+ */
1452
+ handleMentionSelect(item: DsMobileDropdownItem): void;
1453
+ /**
1454
+ * Close mention menu
1455
+ */
1456
+ closeMentionMenu(): void;
1457
+ /**
1458
+ * Handle attachment menu selection from dropdown
1459
+ */
1460
+ handleAttachmentMenuSelect(item: DsMobileDropdownItem): void;
1119
1461
  /**
1120
1462
  * Select a user from mention menu
1121
1463
  */
@@ -1145,9 +1487,25 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1145
1487
  */
1146
1488
  focus(): void;
1147
1489
  /**
1148
- * Handle attachment button click
1490
+ * Toggle attachment menu open/closed
1491
+ * Uses mousedown/touchstart to prevent focus loss from textarea
1492
+ */
1493
+ toggleAttachmentMenu(event?: MouseEvent | TouchEvent): void;
1494
+ /**
1495
+ * Close attachment menu
1496
+ */
1497
+ closeAttachmentMenu(event?: MouseEvent): void;
1498
+ /**
1499
+ * Handle add photo button click from menu
1500
+ * Uses Capacitor Camera API to open photo library directly
1501
+ * Allows multiple photo selection
1502
+ */
1503
+ handleAddPhoto(event?: MouseEvent): Promise<void>;
1504
+ /**
1505
+ * Handle add file button click from menu
1506
+ * Opens file picker
1149
1507
  */
1150
- handleAttachmentClick(): void;
1508
+ handleAddFile(event?: MouseEvent): void;
1151
1509
  /**
1152
1510
  * Detect file type from file name or mime type
1153
1511
  */
@@ -1162,6 +1520,7 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1162
1520
  handleFileSelect(event: Event): void;
1163
1521
  /**
1164
1522
  * Remove an attachment from the list
1523
+ * Keeps keyboard open by maintaining focus
1165
1524
  */
1166
1525
  removeAttachment(attachmentId: string): void;
1167
1526
  /**
@@ -1169,7 +1528,7 @@ declare class DsMobileMessageComposerComponent implements AfterViewInit, OnDestr
1169
1528
  */
1170
1529
  sendMessage(): void;
1171
1530
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileMessageComposerComponent, never>;
1172
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileMessageComposerComponent, "ds-mobile-message-composer", never, { "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "sendButtonLabel": { "alias": "sendButtonLabel"; "required": false; "isSignal": true; }; "attachmentButtonLabel": { "alias": "attachmentButtonLabel"; "required": false; "isSignal": true; }; "showAttachmentButton": { "alias": "showAttachmentButton"; "required": false; "isSignal": true; }; "editIndicatorText": { "alias": "editIndicatorText"; "required": false; "isSignal": true; }; "replyIndicatorText": { "alias": "replyIndicatorText"; "required": false; "isSignal": true; }; "enableMentions": { "alias": "enableMentions"; "required": false; "isSignal": true; }; "mentionUsers": { "alias": "mentionUsers"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; }, { "messageSent": "messageSent"; "editCancelled": "editCancelled"; "replyCancelled": "replyCancelled"; "mentionSelected": "mentionSelected"; "attachmentClicked": "attachmentClicked"; }, never, never, true, never>;
1531
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileMessageComposerComponent, "ds-mobile-message-composer", never, { "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "sendButtonLabel": { "alias": "sendButtonLabel"; "required": false; "isSignal": true; }; "attachmentButtonLabel": { "alias": "attachmentButtonLabel"; "required": false; "isSignal": true; }; "showAttachmentButton": { "alias": "showAttachmentButton"; "required": false; "isSignal": true; }; "editIndicatorText": { "alias": "editIndicatorText"; "required": false; "isSignal": true; }; "replyIndicatorText": { "alias": "replyIndicatorText"; "required": false; "isSignal": true; }; "enableMentions": { "alias": "enableMentions"; "required": false; "isSignal": true; }; "mentionUsers": { "alias": "mentionUsers"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; }, { "messageSent": "messageSent"; "editCancelled": "editCancelled"; "replyCancelled": "replyCancelled"; "mentionSelected": "mentionSelected"; "attachmentClicked": "attachmentClicked"; "attachmentsChanged": "attachmentsChanged"; }, never, never, true, never>;
1173
1532
  }
1174
1533
 
1175
1534
  /**
@@ -1253,6 +1612,14 @@ declare class DsMobileMessageBubbleComponent {
1253
1612
  * Avatar photo source (for photo type)
1254
1613
  */
1255
1614
  avatarSrc: _angular_core.InputSignal<string>;
1615
+ /**
1616
+ * Whether to show the avatar (for clustering logic)
1617
+ */
1618
+ showAvatar: _angular_core.InputSignal<boolean>;
1619
+ /**
1620
+ * Cluster position for border radius styling
1621
+ */
1622
+ clusterPosition: _angular_core.InputSignal<"single" | "first" | "middle" | "last">;
1256
1623
  /**
1257
1624
  * Whether to show read receipt (only for user's messages)
1258
1625
  */
@@ -1264,6 +1631,10 @@ declare class DsMobileMessageBubbleComponent {
1264
1631
  * Whether the message is clickable
1265
1632
  */
1266
1633
  clickable: _angular_core.InputSignal<boolean>;
1634
+ /**
1635
+ * Whether this is a newly sent message (triggers appearance animation)
1636
+ */
1637
+ isNewMessage: _angular_core.InputSignal<boolean>;
1267
1638
  /**
1268
1639
  * Emits when attachment is clicked
1269
1640
  */
@@ -1286,6 +1657,10 @@ declare class DsMobileMessageBubbleComponent {
1286
1657
  private readonly LONG_PRESS_DURATION;
1287
1658
  private readonly MOVE_THRESHOLD;
1288
1659
  private clickStartTime;
1660
+ /**
1661
+ * Tap animation state
1662
+ */
1663
+ isTapped: boolean;
1289
1664
  /**
1290
1665
  * Handle attachment click
1291
1666
  */
@@ -1311,7 +1686,7 @@ declare class DsMobileMessageBubbleComponent {
1311
1686
  */
1312
1687
  handleContextMenu(event: Event): void;
1313
1688
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileMessageBubbleComponent, never>;
1314
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileMessageBubbleComponent, "ds-mobile-message-bubble", never, { "content": { "alias": "content"; "required": true; "isSignal": true; }; "isOwnMessage": { "alias": "isOwnMessage"; "required": false; "isSignal": true; }; "senderName": { "alias": "senderName"; "required": false; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "showTimestamp": { "alias": "showTimestamp"; "required": false; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "attachmentClick": "attachmentClick"; "longPress": "longPress"; "messageClick": "messageClick"; }, never, never, true, never>;
1689
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileMessageBubbleComponent, "ds-mobile-message-bubble", never, { "content": { "alias": "content"; "required": true; "isSignal": true; }; "isOwnMessage": { "alias": "isOwnMessage"; "required": false; "isSignal": true; }; "senderName": { "alias": "senderName"; "required": false; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "showTimestamp": { "alias": "showTimestamp"; "required": false; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "showAvatar": { "alias": "showAvatar"; "required": false; "isSignal": true; }; "clusterPosition": { "alias": "clusterPosition"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "isNewMessage": { "alias": "isNewMessage"; "required": false; "isSignal": true; }; }, { "attachmentClick": "attachmentClick"; "longPress": "longPress"; "messageClick": "messageClick"; }, never, never, true, never>;
1315
1690
  }
1316
1691
 
1317
1692
  /**
@@ -2245,259 +2620,9 @@ declare class DsMobileTabsComponent implements OnInit {
2245
2620
  }
2246
2621
 
2247
2622
  /**
2248
- * DsMobileCardInlineComponent
2249
- *
2250
- * A versatile, always-interactive inline card component for standalone or small-group usage.
2251
- * Designed for tappable card-like elements such as file attachments, contact cards, etc.
2252
- * Not intended for long scrolling lists - use ds-mobile-list-item for that purpose.
2253
- *
2254
- * Features:
2255
- * - Always interactive/tappable (unless disabled)
2256
- * - Two layout variants: default (column) and compact (row)
2257
- * - Flexible content projection with leading/main/trailing slots
2258
- * - Consistent styling with rounded corners and neutral background
2259
- * - Built-in hover and active states
2260
- * - Accessibility features (role, tabindex, aria attributes)
2261
- *
2262
- * @example
2263
- * ```html
2264
- * <!-- Default variant (column layout) -->
2265
- * <ds-mobile-card-inline
2266
- * [variant]="'default'"
2267
- * (cardClick)="handleClick()">
2268
- *
2269
- * <div content-leading>
2270
- * <ds-avatar initials="JD" />
2271
- * </div>
2272
- *
2273
- * <div content-main>
2274
- * <div class="title">Document Title</div>
2275
- * <div class="subtitle">PDF · 1.2 MB</div>
2276
- * </div>
2277
- *
2278
- * <ds-icon content-trailing name="remixArrowRightSLine" />
2279
- * </ds-mobile-card-inline>
2280
- *
2281
- * <!-- Compact variant (row layout) -->
2282
- * <ds-mobile-card-inline
2283
- * [variant]="'compact'"
2284
- * (cardClick)="handleClick()">
2285
- *
2286
- * <ds-avatar content-leading size="sm" />
2287
- *
2288
- * <div content-main>
2289
- * <span class="name">File.pdf</span>
2290
- * <span class="size">245 KB</span>
2291
- * </div>
2292
- *
2293
- * <ds-icon content-trailing name="remixArrowRightSLine" />
2294
- * </ds-mobile-card-inline>
2295
- *
2296
- * <!-- Disabled state -->
2297
- * <ds-mobile-card-inline [disabled]="true">
2298
- * <div content-main>Disabled card</div>
2299
- * </ds-mobile-card-inline>
2300
- * ```
2623
+ * Media file types supported by the lightbox
2301
2624
  */
2302
- declare class DsMobileCardInlineComponent {
2303
- /**
2304
- * Display variant
2305
- * - 'default' - Column layout with standard padding (gap: 12px, padding: 10px 12px)
2306
- * - 'compact' - Row layout with reduced padding (gap: 8px, padding: 10px)
2307
- */
2308
- variant: _angular_core.InputSignal<"default" | "compact">;
2309
- /**
2310
- * Whether the card is disabled
2311
- * Disables all interactions and reduces opacity
2312
- */
2313
- disabled: _angular_core.InputSignal<boolean>;
2314
- /**
2315
- * Emits when the card is clicked (if not disabled)
2316
- */
2317
- cardClick: _angular_core.OutputEmitterRef<void>;
2318
- /**
2319
- * Handle click events
2320
- */
2321
- handleClick(event: Event): void;
2322
- /**
2323
- * Handle keyboard events (Enter/Space)
2324
- */
2325
- handleKeyDown(event: KeyboardEvent): void;
2326
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineComponent, never>;
2327
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineComponent, "ds-mobile-card-inline", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "cardClick": "cardClick"; }, never, ["[content-leading]", "[content-main]", "*", "[content-trailing]"], true, never>;
2328
- }
2329
-
2330
- /**
2331
- * DsMobileCardInlineBannerComponent
2332
- *
2333
- * Specialized interactive component for displaying notification banners.
2334
- * Used to show unread message notifications above inquiry details.
2335
- *
2336
- * Features:
2337
- * - Neutral background matching file/contact cards
2338
- * - Avatar icon with message symbol
2339
- * - Title and timestamp
2340
- * - Unread count badge
2341
- * - Chevron for navigation indication
2342
- *
2343
- * @example
2344
- * ```html
2345
- * <ds-mobile-card-inline-banner
2346
- * [title]="'New messages'"
2347
- * [timestamp]="'2 min ago'"
2348
- * [unreadCount]="3"
2349
- * (bannerClick)="navigateToMessages()">
2350
- * </ds-mobile-card-inline-banner>
2351
- * ```
2352
- */
2353
- declare class DsMobileCardInlineBannerComponent {
2354
- /**
2355
- * Banner title (e.g., "New messages", "Unread messages")
2356
- */
2357
- title: _angular_core.InputSignal<string>;
2358
- /**
2359
- * Timestamp text (e.g., "2 min ago", "Just now")
2360
- */
2361
- timestamp: _angular_core.InputSignal<string>;
2362
- /**
2363
- * Number of unread items (optional, shows badge if > 0)
2364
- */
2365
- unreadCount: _angular_core.InputSignal<number>;
2366
- /**
2367
- * Layout variant
2368
- * - 'default' - Standard padding and column layout
2369
- * - 'compact' - Reduced padding and row layout
2370
- */
2371
- layout: _angular_core.InputSignal<"default" | "compact">;
2372
- /**
2373
- * Emits when the banner is clicked
2374
- */
2375
- bannerClick: _angular_core.OutputEmitterRef<void>;
2376
- handleBannerClick(): void;
2377
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineBannerComponent, never>;
2378
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineBannerComponent, "ds-mobile-card-inline-banner", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": false; "isSignal": true; }; "unreadCount": { "alias": "unreadCount"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, { "bannerClick": "bannerClick"; }, never, never, true, never>;
2379
- }
2380
-
2381
- /**
2382
- * DsMobileCardInlineContactComponent
2383
- *
2384
- * Specialized interactive component for displaying contacts.
2385
- * Displays contact name with avatar initials and metadata (person name + phone number).
2386
- * Similar styling to file attachments with rounded corners and hover states.
2387
- *
2388
- * @example
2389
- * ```html
2390
- * <ds-mobile-card-inline-contact
2391
- * [name]="'Mortensen & Søn ApS'"
2392
- * [initials]="'M'"
2393
- * [contactPerson]="'John Mortensen'"
2394
- * [phoneNumber]="'+45 12 34 56 78'"
2395
- * [clickable]="true"
2396
- * (contactClick)="openContact()">
2397
- * </ds-mobile-card-inline-contact>
2398
- * ```
2399
- */
2400
- declare class DsMobileCardInlineContactComponent {
2401
- /**
2402
- * Contact/company name
2403
- */
2404
- name: _angular_core.InputSignal<string>;
2405
- /**
2406
- * Avatar initials (usually 1-2 letters)
2407
- */
2408
- initials: _angular_core.InputSignal<string>;
2409
- /**
2410
- * Contact person name (optional)
2411
- */
2412
- contactPerson: _angular_core.InputSignal<string>;
2413
- /**
2414
- * Phone number (optional)
2415
- */
2416
- phoneNumber: _angular_core.InputSignal<string>;
2417
- /**
2418
- * Layout variant
2419
- * - 'default' - Standard padding and column layout
2420
- * - 'compact' - Reduced padding and row layout
2421
- */
2422
- layout: _angular_core.InputSignal<"default" | "compact">;
2423
- /**
2424
- * Whether the contact item is clickable
2425
- */
2426
- clickable: _angular_core.InputSignal<boolean>;
2427
- /**
2428
- * Whether to show chevron icon
2429
- */
2430
- showChevron: _angular_core.InputSignal<boolean>;
2431
- /**
2432
- * Emits when the contact item is clicked (if clickable)
2433
- */
2434
- contactClick: _angular_core.OutputEmitterRef<void>;
2435
- handleContactClick(): void;
2436
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineContactComponent, never>;
2437
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineContactComponent, "ds-mobile-card-inline-contact", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "initials": { "alias": "initials"; "required": true; "isSignal": true; }; "contactPerson": { "alias": "contactPerson"; "required": false; "isSignal": true; }; "phoneNumber": { "alias": "phoneNumber"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "contactClick": "contactClick"; }, never, never, true, never>;
2438
- }
2439
-
2440
- /**
2441
- * DsMobileCardInlineFileComponent
2442
- *
2443
- * File attachment display for various document types.
2444
- * Shows file info card with icon, filename, and file size.
2445
- * Supports PDF and generic document formats.
2446
- * Emits click event to open file in viewer.
2447
- *
2448
- * @example
2449
- * ```html
2450
- * <ds-mobile-card-inline-file
2451
- * [fileName]="'Document.pdf'"
2452
- * [fileSize]="'1.2 MB'"
2453
- * [variant]="'pdf'"
2454
- * [layout]="'compact'"
2455
- * (fileClick)="openFile()">
2456
- * </ds-mobile-card-inline-file>
2457
- * ```
2458
- */
2459
- declare class DsMobileCardInlineFileComponent {
2460
- /**
2461
- * File name
2462
- */
2463
- fileName: _angular_core.InputSignal<string>;
2464
- /**
2465
- * File size display (e.g., "1.2 MB")
2466
- */
2467
- fileSize: _angular_core.InputSignal<string>;
2468
- /**
2469
- * File type variant
2470
- * - 'pdf' - PDF document (red icon)
2471
- * - 'doc' - Generic document (blue icon)
2472
- */
2473
- variant: _angular_core.InputSignal<"pdf" | "doc">;
2474
- /**
2475
- * Layout variant
2476
- * - 'default' - Standard padding and column layout
2477
- * - 'compact' - Reduced padding and row layout
2478
- */
2479
- layout: _angular_core.InputSignal<"default" | "compact">;
2480
- /**
2481
- * Emits when the file attachment is clicked
2482
- */
2483
- fileClick: _angular_core.OutputEmitterRef<void>;
2484
- /**
2485
- * Get the appropriate icon name based on variant
2486
- */
2487
- getIconName(): string;
2488
- /**
2489
- * Get the file type label based on variant
2490
- */
2491
- getFileTypeLabel(): string;
2492
- handleClick(): void;
2493
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineFileComponent, never>;
2494
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineFileComponent, "ds-mobile-card-inline-file", never, { "fileName": { "alias": "fileName"; "required": false; "isSignal": true; }; "fileSize": { "alias": "fileSize"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, { "fileClick": "fileClick"; }, never, never, true, never>;
2495
- }
2496
-
2497
- /**
2498
- * Media file types supported by the lightbox
2499
- */
2500
- type LightboxMediaType = 'image' | 'pdf';
2625
+ type LightboxMediaType = 'image' | 'pdf';
2501
2626
  /**
2502
2627
  * Base media file interface
2503
2628
  */
@@ -3236,6 +3361,10 @@ declare abstract class MobileModalBase implements OnInit, OnDestroy {
3236
3361
  * ResizeObserver for tracking fixed bottom height
3237
3362
  */
3238
3363
  private fixedBottomObserver?;
3364
+ /**
3365
+ * Flag to prevent ResizeObserver from updating padding during keyboard animations
3366
+ */
3367
+ private isKeyboardAnimating;
3239
3368
  /**
3240
3369
  * Loading state - when true, shows loading indicator
3241
3370
  * @default false
@@ -3277,6 +3406,17 @@ declare abstract class MobileModalBase implements OnInit, OnDestroy {
3277
3406
  * Emitted when modal is closed
3278
3407
  */
3279
3408
  closed: _angular_core.OutputEmitterRef<void>;
3409
+ /**
3410
+ * Emitted when keyboard is about to show
3411
+ * Provides keyboard height in pixels
3412
+ * Child components can listen to this to react to keyboard appearance
3413
+ */
3414
+ keyboardWillShow: _angular_core.OutputEmitterRef<number>;
3415
+ /**
3416
+ * Emitted when keyboard is about to hide
3417
+ * Child components can listen to this to react to keyboard dismissal
3418
+ */
3419
+ keyboardWillHide: _angular_core.OutputEmitterRef<void>;
3280
3420
  ngOnInit(): void;
3281
3421
  ngOnDestroy(): void;
3282
3422
  /**
@@ -3286,7 +3426,8 @@ declare abstract class MobileModalBase implements OnInit, OnDestroy {
3286
3426
  close(): void;
3287
3427
  /**
3288
3428
  * Set up keyboard event listeners to adjust component position
3289
- * Uses --keyboard-height for fixed bottom composer and adds padding to scroll area
3429
+ * Uses --keyboard-height for fixed bottom composer and adds padding to scroll area.
3430
+ * Adjusts scroll position so content smoothly follows the keyboard up (like Messenger/Telegram).
3290
3431
  * @protected
3291
3432
  */
3292
3433
  protected setupKeyboardListeners(): void;
@@ -3302,7 +3443,7 @@ declare abstract class MobileModalBase implements OnInit, OnDestroy {
3302
3443
  */
3303
3444
  protected cleanupKeyboardListeners(): void;
3304
3445
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MobileModalBase, never>;
3305
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MobileModalBase, never, never, { "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "headerTitle": { "alias": "headerTitle"; "required": false; "isSignal": true; }; "headerMeta": { "alias": "headerMeta"; "required": false; "isSignal": true; }; "closeButtonLabel": { "alias": "closeButtonLabel"; "required": false; "isSignal": true; }; "enableKeyboardHandling": { "alias": "enableKeyboardHandling"; "required": false; "isSignal": true; }; "hasFixedBottom": { "alias": "hasFixedBottom"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, never, true, never>;
3446
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MobileModalBase, never, never, { "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "headerTitle": { "alias": "headerTitle"; "required": false; "isSignal": true; }; "headerMeta": { "alias": "headerMeta"; "required": false; "isSignal": true; }; "closeButtonLabel": { "alias": "closeButtonLabel"; "required": false; "isSignal": true; }; "enableKeyboardHandling": { "alias": "enableKeyboardHandling"; "required": false; "isSignal": true; }; "hasFixedBottom": { "alias": "hasFixedBottom"; "required": false; "isSignal": true; }; }, { "closed": "closed"; "keyboardWillShow": "keyboardWillShow"; "keyboardWillHide": "keyboardWillHide"; }, never, never, true, never>;
3306
3447
  }
3307
3448
 
3308
3449
  /**
@@ -3372,7 +3513,7 @@ declare abstract class MobileModalBase implements OnInit, OnDestroy {
3372
3513
  * </ds-mobile-modal-base>
3373
3514
  * ```
3374
3515
  */
3375
- declare class DsMobileModalBaseComponent extends MobileModalBase implements AfterContentInit {
3516
+ declare class DsMobileModalBaseComponent extends MobileModalBase implements OnInit, AfterContentInit, OnDestroy {
3376
3517
  private cdr;
3377
3518
  /**
3378
3519
  * Reference to ion-content for keyboard handling
@@ -3407,7 +3548,9 @@ declare class DsMobileModalBaseComponent extends MobileModalBase implements Afte
3407
3548
  hasCustomLoadingState: boolean;
3408
3549
  hasCustomErrorState: boolean;
3409
3550
  constructor(cdr: ChangeDetectorRef);
3551
+ ngOnInit(): void;
3410
3552
  ngAfterContentInit(): void;
3553
+ ngOnDestroy(): void;
3411
3554
  /**
3412
3555
  * Determine if header should be shown based on showHeader input and content detection
3413
3556
  */
@@ -3578,18 +3721,6 @@ declare class DsMobilePostDetailModalComponent implements OnInit, AfterViewInit
3578
3721
  originalContent: string;
3579
3722
  timestamp: string;
3580
3723
  } | null>;
3581
- showMentionMenu: _angular_core.WritableSignal<boolean>;
3582
- mentionQuery: _angular_core.WritableSignal<string>;
3583
- availableUsers: _angular_core.Signal<{
3584
- name: string;
3585
- initials: string;
3586
- role: string;
3587
- }[]>;
3588
- filteredUsers: _angular_core.Signal<{
3589
- name: string;
3590
- initials: string;
3591
- role: string;
3592
- }[]>;
3593
3724
  constructor(lightbox: DsMobileLightboxService, bottomSheet: DsMobileBottomSheetService);
3594
3725
  ngOnInit(): void;
3595
3726
  ngAfterViewInit(): void;
@@ -3602,13 +3733,9 @@ declare class DsMobilePostDetailModalComponent implements OnInit, AfterViewInit
3602
3733
  */
3603
3734
  focusCommentInput(): void;
3604
3735
  /**
3605
- * Handle input changes and detect @ mentions
3736
+ * Handle input changes for auto-resize
3606
3737
  */
3607
3738
  handleInput(event: Event): void;
3608
- /**
3609
- * Select a user from mention menu - show as reply indicator instead of inline mention
3610
- */
3611
- selectMention(userName: string): void;
3612
3739
  /**
3613
3740
  * Handle reply to a comment
3614
3741
  */
@@ -3803,6 +3930,256 @@ declare class DsMobilePostDetailModalService extends BaseModalService {
3803
3930
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobilePostDetailModalService>;
3804
3931
  }
3805
3932
 
3933
+ /**
3934
+ * DsMobileCardInlineComponent
3935
+ *
3936
+ * A versatile, always-interactive inline card component for standalone or small-group usage.
3937
+ * Designed for tappable card-like elements such as file attachments, contact cards, etc.
3938
+ * Not intended for long scrolling lists - use ds-mobile-list-item for that purpose.
3939
+ *
3940
+ * Features:
3941
+ * - Always interactive/tappable (unless disabled)
3942
+ * - Two layout variants: default (column) and compact (row)
3943
+ * - Flexible content projection with leading/main/trailing slots
3944
+ * - Consistent styling with rounded corners and neutral background
3945
+ * - Built-in hover and active states
3946
+ * - Accessibility features (role, tabindex, aria attributes)
3947
+ *
3948
+ * @example
3949
+ * ```html
3950
+ * <!-- Default variant (column layout) -->
3951
+ * <ds-mobile-card-inline
3952
+ * [variant]="'default'"
3953
+ * (cardClick)="handleClick()">
3954
+ *
3955
+ * <div content-leading>
3956
+ * <ds-avatar initials="JD" />
3957
+ * </div>
3958
+ *
3959
+ * <div content-main>
3960
+ * <div class="title">Document Title</div>
3961
+ * <div class="subtitle">PDF · 1.2 MB</div>
3962
+ * </div>
3963
+ *
3964
+ * <ds-icon content-trailing name="remixArrowRightSLine" />
3965
+ * </ds-mobile-card-inline>
3966
+ *
3967
+ * <!-- Compact variant (row layout) -->
3968
+ * <ds-mobile-card-inline
3969
+ * [variant]="'compact'"
3970
+ * (cardClick)="handleClick()">
3971
+ *
3972
+ * <ds-avatar content-leading size="sm" />
3973
+ *
3974
+ * <div content-main>
3975
+ * <span class="name">File.pdf</span>
3976
+ * <span class="size">245 KB</span>
3977
+ * </div>
3978
+ *
3979
+ * <ds-icon content-trailing name="remixArrowRightSLine" />
3980
+ * </ds-mobile-card-inline>
3981
+ *
3982
+ * <!-- Disabled state -->
3983
+ * <ds-mobile-card-inline [disabled]="true">
3984
+ * <div content-main>Disabled card</div>
3985
+ * </ds-mobile-card-inline>
3986
+ * ```
3987
+ */
3988
+ declare class DsMobileCardInlineComponent {
3989
+ /**
3990
+ * Display variant
3991
+ * - 'default' - Column layout with standard padding (gap: 12px, padding: 10px 12px)
3992
+ * - 'compact' - Row layout with reduced padding (gap: 8px, padding: 10px)
3993
+ */
3994
+ variant: _angular_core.InputSignal<"default" | "compact">;
3995
+ /**
3996
+ * Whether the card is disabled
3997
+ * Disables all interactions and reduces opacity
3998
+ */
3999
+ disabled: _angular_core.InputSignal<boolean>;
4000
+ /**
4001
+ * Emits when the card is clicked (if not disabled)
4002
+ */
4003
+ cardClick: _angular_core.OutputEmitterRef<void>;
4004
+ /**
4005
+ * Handle click events
4006
+ */
4007
+ handleClick(event: Event): void;
4008
+ /**
4009
+ * Handle keyboard events (Enter/Space)
4010
+ */
4011
+ handleKeyDown(event: KeyboardEvent): void;
4012
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineComponent, never>;
4013
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineComponent, "ds-mobile-card-inline", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "cardClick": "cardClick"; }, never, ["[content-leading]", "[content-main]", "*", "[content-trailing]"], true, never>;
4014
+ }
4015
+
4016
+ /**
4017
+ * DsMobileCardInlineBannerComponent
4018
+ *
4019
+ * Specialized interactive component for displaying notification banners.
4020
+ * Used to show unread message notifications above inquiry details.
4021
+ *
4022
+ * Features:
4023
+ * - Neutral background matching file/contact cards
4024
+ * - Avatar icon with message symbol
4025
+ * - Title and timestamp
4026
+ * - Unread count badge
4027
+ * - Chevron for navigation indication
4028
+ *
4029
+ * @example
4030
+ * ```html
4031
+ * <ds-mobile-card-inline-banner
4032
+ * [title]="'New messages'"
4033
+ * [timestamp]="'2 min ago'"
4034
+ * [unreadCount]="3"
4035
+ * (bannerClick)="navigateToMessages()">
4036
+ * </ds-mobile-card-inline-banner>
4037
+ * ```
4038
+ */
4039
+ declare class DsMobileCardInlineBannerComponent {
4040
+ /**
4041
+ * Banner title (e.g., "New messages", "Unread messages")
4042
+ */
4043
+ title: _angular_core.InputSignal<string>;
4044
+ /**
4045
+ * Timestamp text (e.g., "2 min ago", "Just now")
4046
+ */
4047
+ timestamp: _angular_core.InputSignal<string>;
4048
+ /**
4049
+ * Number of unread items (optional, shows badge if > 0)
4050
+ */
4051
+ unreadCount: _angular_core.InputSignal<number>;
4052
+ /**
4053
+ * Layout variant
4054
+ * - 'default' - Standard padding and column layout
4055
+ * - 'compact' - Reduced padding and row layout
4056
+ */
4057
+ layout: _angular_core.InputSignal<"default" | "compact">;
4058
+ /**
4059
+ * Emits when the banner is clicked
4060
+ */
4061
+ bannerClick: _angular_core.OutputEmitterRef<void>;
4062
+ handleBannerClick(): void;
4063
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineBannerComponent, never>;
4064
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineBannerComponent, "ds-mobile-card-inline-banner", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": false; "isSignal": true; }; "unreadCount": { "alias": "unreadCount"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, { "bannerClick": "bannerClick"; }, never, never, true, never>;
4065
+ }
4066
+
4067
+ /**
4068
+ * DsMobileCardInlineContactComponent
4069
+ *
4070
+ * Specialized interactive component for displaying contacts.
4071
+ * Displays contact name with avatar initials and metadata (person name + phone number).
4072
+ * Similar styling to file attachments with rounded corners and hover states.
4073
+ *
4074
+ * @example
4075
+ * ```html
4076
+ * <ds-mobile-card-inline-contact
4077
+ * [name]="'Mortensen & Søn ApS'"
4078
+ * [initials]="'M'"
4079
+ * [contactPerson]="'John Mortensen'"
4080
+ * [phoneNumber]="'+45 12 34 56 78'"
4081
+ * [clickable]="true"
4082
+ * (contactClick)="openContact()">
4083
+ * </ds-mobile-card-inline-contact>
4084
+ * ```
4085
+ */
4086
+ declare class DsMobileCardInlineContactComponent {
4087
+ /**
4088
+ * Contact/company name
4089
+ */
4090
+ name: _angular_core.InputSignal<string>;
4091
+ /**
4092
+ * Avatar initials (usually 1-2 letters)
4093
+ */
4094
+ initials: _angular_core.InputSignal<string>;
4095
+ /**
4096
+ * Contact person name (optional)
4097
+ */
4098
+ contactPerson: _angular_core.InputSignal<string>;
4099
+ /**
4100
+ * Phone number (optional)
4101
+ */
4102
+ phoneNumber: _angular_core.InputSignal<string>;
4103
+ /**
4104
+ * Layout variant
4105
+ * - 'default' - Standard padding and column layout
4106
+ * - 'compact' - Reduced padding and row layout
4107
+ */
4108
+ layout: _angular_core.InputSignal<"default" | "compact">;
4109
+ /**
4110
+ * Whether the contact item is clickable
4111
+ */
4112
+ clickable: _angular_core.InputSignal<boolean>;
4113
+ /**
4114
+ * Whether to show chevron icon
4115
+ */
4116
+ showChevron: _angular_core.InputSignal<boolean>;
4117
+ /**
4118
+ * Emits when the contact item is clicked (if clickable)
4119
+ */
4120
+ contactClick: _angular_core.OutputEmitterRef<void>;
4121
+ handleContactClick(): void;
4122
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineContactComponent, never>;
4123
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineContactComponent, "ds-mobile-card-inline-contact", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "initials": { "alias": "initials"; "required": true; "isSignal": true; }; "contactPerson": { "alias": "contactPerson"; "required": false; "isSignal": true; }; "phoneNumber": { "alias": "phoneNumber"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "contactClick": "contactClick"; }, never, never, true, never>;
4124
+ }
4125
+
4126
+ /**
4127
+ * DsMobileCardInlineFileComponent
4128
+ *
4129
+ * File attachment display for various document types.
4130
+ * Shows file info card with icon, filename, and file size.
4131
+ * Supports PDF and generic document formats.
4132
+ * Emits click event to open file in viewer.
4133
+ *
4134
+ * @example
4135
+ * ```html
4136
+ * <ds-mobile-card-inline-file
4137
+ * [fileName]="'Document.pdf'"
4138
+ * [fileSize]="'1.2 MB'"
4139
+ * [variant]="'pdf'"
4140
+ * [layout]="'compact'"
4141
+ * (fileClick)="openFile()">
4142
+ * </ds-mobile-card-inline-file>
4143
+ * ```
4144
+ */
4145
+ declare class DsMobileCardInlineFileComponent {
4146
+ /**
4147
+ * File name
4148
+ */
4149
+ fileName: _angular_core.InputSignal<string>;
4150
+ /**
4151
+ * File size display (e.g., "1.2 MB")
4152
+ */
4153
+ fileSize: _angular_core.InputSignal<string>;
4154
+ /**
4155
+ * File type variant
4156
+ * - 'pdf' - PDF document (red icon)
4157
+ * - 'doc' - Generic document (blue icon)
4158
+ */
4159
+ variant: _angular_core.InputSignal<"pdf" | "doc">;
4160
+ /**
4161
+ * Layout variant
4162
+ * - 'default' - Standard padding and column layout
4163
+ * - 'compact' - Reduced padding and row layout
4164
+ */
4165
+ layout: _angular_core.InputSignal<"default" | "compact">;
4166
+ /**
4167
+ * Emits when the file attachment is clicked
4168
+ */
4169
+ fileClick: _angular_core.OutputEmitterRef<void>;
4170
+ /**
4171
+ * Get the appropriate icon name based on variant
4172
+ */
4173
+ getIconName(): string;
4174
+ /**
4175
+ * Get the file type label based on variant
4176
+ */
4177
+ getFileTypeLabel(): string;
4178
+ handleClick(): void;
4179
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCardInlineFileComponent, never>;
4180
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCardInlineFileComponent, "ds-mobile-card-inline-file", never, { "fileName": { "alias": "fileName"; "required": false; "isSignal": true; }; "fileSize": { "alias": "fileSize"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, { "fileClick": "fileClick"; }, never, never, true, never>;
4181
+ }
4182
+
3806
4183
  /**
3807
4184
  * Chat message data interface
3808
4185
  */
@@ -3819,6 +4196,7 @@ interface ChatMessage {
3819
4196
  isOwnMessage: boolean;
3820
4197
  attachments?: ChatAttachment[];
3821
4198
  fileAttachments?: AttachmentData[];
4199
+ isNewMessage?: boolean;
3822
4200
  }
3823
4201
  /**
3824
4202
  * Message group interface for grouped timestamp display
@@ -3828,6 +4206,14 @@ interface MessageGroup {
3828
4206
  displayTimestamp: string;
3829
4207
  messages: ChatMessage[];
3830
4208
  }
4209
+ /**
4210
+ * Extended message interface with display metadata
4211
+ */
4212
+ interface MessageDisplay extends ChatMessage {
4213
+ showAvatar: boolean;
4214
+ clusterPosition: 'single' | 'first' | 'middle' | 'last';
4215
+ isNewMessage?: boolean;
4216
+ }
3831
4217
  /**
3832
4218
  * Chat participant interface
3833
4219
  */
@@ -3838,6 +4224,9 @@ interface ChatParticipant {
3838
4224
  avatarInitials?: string;
3839
4225
  avatarType?: 'initials' | 'photo' | 'icon';
3840
4226
  avatarSrc?: string;
4227
+ badge?: string;
4228
+ verified?: boolean;
4229
+ lastActive?: string;
3841
4230
  }
3842
4231
  /**
3843
4232
  * Chat modal data interface
@@ -3955,6 +4344,10 @@ declare class DsMobileChatModalComponent implements OnInit, AfterViewInit {
3955
4344
  * Error state - when set, shows error message
3956
4345
  */
3957
4346
  error?: string;
4347
+ /**
4348
+ * Back button click event
4349
+ */
4350
+ back: EventEmitter<void>;
3958
4351
  participant: _angular_core.WritableSignal<ChatParticipant>;
3959
4352
  messages: _angular_core.WritableSignal<ChatMessage[]>;
3960
4353
  currentUserInitials: _angular_core.WritableSignal<string>;
@@ -3965,6 +4358,10 @@ declare class DsMobileChatModalComponent implements OnInit, AfterViewInit {
3965
4358
  * Selected message ID for showing timestamp
3966
4359
  */
3967
4360
  selectedMessageId: _angular_core.WritableSignal<string | null>;
4361
+ /**
4362
+ * Track if keyboard is currently visible
4363
+ */
4364
+ private isKeyboardVisible;
3968
4365
  /**
3969
4366
  * Timeout for auto-hiding timestamp
3970
4367
  */
@@ -3973,9 +4370,30 @@ declare class DsMobileChatModalComponent implements OnInit, AfterViewInit {
3973
4370
  * Computed signal for grouped messages with timestamp headers
3974
4371
  */
3975
4372
  messageGroups: _angular_core.Signal<MessageGroup[]>;
4373
+ /**
4374
+ * Computed signal for messages with display metadata (avatar visibility)
4375
+ */
4376
+ messagesWithDisplay: _angular_core.Signal<(MessageGroup & {
4377
+ messages: MessageDisplay[];
4378
+ })[]>;
3976
4379
  constructor(lightboxService: DsMobileLightboxService);
3977
4380
  ngOnInit(): void;
3978
4381
  ngAfterViewInit(): void;
4382
+ /**
4383
+ * Handle back button click
4384
+ */
4385
+ handleBack(): void;
4386
+ /**
4387
+ * Handle keyboard show event from base modal
4388
+ * Only scrolls to bottom if user is already near the bottom, otherwise lets
4389
+ * the natural padding expansion push content up (like Messenger/Signal/Telegram)
4390
+ */
4391
+ handleKeyboardShow(keyboardHeight: number): void;
4392
+ /**
4393
+ * Check if scroll position is near the bottom
4394
+ * Used to determine if we should auto-scroll when keyboard appears
4395
+ */
4396
+ private isNearBottom;
3979
4397
  /**
3980
4398
  * Scroll to bottom of messages
3981
4399
  */
@@ -3998,6 +4416,16 @@ declare class DsMobileChatModalComponent implements OnInit, AfterViewInit {
3998
4416
  * Handle composer attachment button click
3999
4417
  */
4000
4418
  handleComposerAttachmentClick(): void;
4419
+ /**
4420
+ * Handle attachments changed (added or removed)
4421
+ * ResizeObserver automatically updates padding, which naturally pushes content up.
4422
+ * Only scroll to bottom if user is already viewing the latest messages.
4423
+ */
4424
+ handleAttachmentsChanged(): void;
4425
+ /**
4426
+ * Handle content area click - dismiss keyboard when tapping messages
4427
+ */
4428
+ handleContentClick(): void;
4001
4429
  /**
4002
4430
  * Get file variant for card-inline-file component
4003
4431
  */
@@ -4016,12 +4444,18 @@ declare class DsMobileChatModalComponent implements OnInit, AfterViewInit {
4016
4444
  handleMessageLongPress(message: ChatMessage): void;
4017
4445
  /**
4018
4446
  * Handle message click to show/hide timestamp
4447
+ * Only shows timestamp if keyboard is already hidden
4019
4448
  */
4020
4449
  handleMessageClick(messageId: string): void;
4021
4450
  /**
4022
4451
  * Format message timestamp for display (EU 24-hour format, Danish)
4023
4452
  */
4024
4453
  formatMessageTimestamp(date: Date): string;
4454
+ /**
4455
+ * Get initial timestamp for empty chat state
4456
+ * Returns current time formatted with smart date display
4457
+ */
4458
+ getInitialTimestamp(): string;
4025
4459
  /**
4026
4460
  * Group messages by time threshold
4027
4461
  * Messages within the threshold and on the same day are grouped together
@@ -4036,8 +4470,14 @@ declare class DsMobileChatModalComponent implements OnInit, AfterViewInit {
4036
4470
  * Uses 24-hour EU time format with Danish locale
4037
4471
  */
4038
4472
  private formatGroupTimestamp;
4473
+ /**
4474
+ * Add display metadata to message groups
4475
+ * Determines which messages should show avatars (only last in cluster)
4476
+ * and calculates cluster positions for border radius styling
4477
+ */
4478
+ private addDisplayMetadata;
4039
4479
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileChatModalComponent, never>;
4040
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileChatModalComponent, "ds-mobile-chat-modal", never, { "chatData": { "alias": "chatData"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; }, {}, never, never, true, never>;
4480
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileChatModalComponent, "ds-mobile-chat-modal", never, { "chatData": { "alias": "chatData"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; }, { "back": "back"; }, never, never, true, never>;
4041
4481
  }
4042
4482
 
4043
4483
  /**
@@ -4735,6 +5175,8 @@ declare class DsTextInputComponent implements ControlValueAccessor {
4735
5175
  * Features:
4736
5176
  * - Configurable positioning (bottom-right, bottom-left, bottom-center)
4737
5177
  * - Uses design system theming variables
5178
+ * - Dynamically calculates position above tab bar (including safe areas)
5179
+ * - Maintains consistent 20px gap from tab bar
4738
5180
  * - Handles iOS safe areas
4739
5181
  * - Accessible with ARIA labels
4740
5182
  * - Smooth entrance animation
@@ -4749,7 +5191,10 @@ declare class DsTextInputComponent implements ControlValueAccessor {
4749
5191
  * </ds-mobile-fab>
4750
5192
  * ```
4751
5193
  */
4752
- declare class DsMobileFabComponent {
5194
+ declare class DsMobileFabComponent implements AfterViewInit, OnDestroy {
5195
+ private elementRef;
5196
+ private platform;
5197
+ private resizeObserver?;
4753
5198
  /**
4754
5199
  * Icon name from the design system icon library
4755
5200
  * @default 'remixAddLine'
@@ -4780,10 +5225,21 @@ declare class DsMobileFabComponent {
4780
5225
  * Emitted when the FAB is clicked
4781
5226
  */
4782
5227
  fabClick: _angular_core.OutputEmitterRef<void>;
5228
+ ngAfterViewInit(): void;
5229
+ /**
5230
+ * Calculate the FAB position dynamically based on actual tab bar height
5231
+ */
5232
+ private calculatePosition;
5233
+ /**
5234
+ * Setup ResizeObserver to recalculate position when tab bar size changes
5235
+ * (e.g., when device rotates or safe area changes)
5236
+ */
5237
+ private setupResizeObserver;
4783
5238
  /**
4784
5239
  * Handle button click
4785
5240
  */
4786
5241
  handleClick(): void;
5242
+ ngOnDestroy(): void;
4787
5243
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileFabComponent, never>;
4788
5244
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileFabComponent, "ds-mobile-fab", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "fabClick": "fabClick"; }, never, never, true, never>;
4789
5245
  }
@@ -4873,6 +5329,28 @@ declare class WhitelabelService {
4873
5329
  * Convert hex color to RGB values
4874
5330
  */
4875
5331
  private hexToRgb;
5332
+ /**
5333
+ * Generate a hover state color by applying a black overlay
5334
+ * This simulates the effect of overlaying #000000 with 10% opacity
5335
+ *
5336
+ * @param baseColor - Hex color to overlay on (e.g., '#6B5FF5')
5337
+ * @param overlayColor - Overlay color (default: '#000000' for darkening)
5338
+ * @param overlayAlpha - Opacity of overlay (0-1, default: 0.1 = 10%)
5339
+ * @returns Hex color with overlay applied
5340
+ *
5341
+ * @example
5342
+ * generateHoverColor('#6B5FF5') // Returns darker purple for hover state
5343
+ * generateHoverColor('#FF0000', '#FFFFFF', 0.2) // Lighten red by 20%
5344
+ */
5345
+ private generateHoverColor;
5346
+ /**
5347
+ * Generate an active/pressed state color (darker than hover)
5348
+ * Uses 20% black overlay for a more pronounced pressed effect
5349
+ *
5350
+ * @param baseColor - Hex color to overlay on
5351
+ * @returns Hex color for active/pressed state
5352
+ */
5353
+ private generateActiveColor;
4876
5354
  /**
4877
5355
  * Apply colors to CSS custom properties and native StatusBar
4878
5356
  * This updates the actual CSS variables used throughout the app
@@ -4922,6 +5400,56 @@ declare class DsAvatarWithBadgeComponent {
4922
5400
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsAvatarWithBadgeComponent, "ds-avatar-with-badge", never, { "type": { "alias": "type"; "required": false; }; "size": { "alias": "size"; "required": false; }; "initials": { "alias": "initials"; "required": false; }; "src": { "alias": "src"; "required": false; }; "iconName": { "alias": "iconName"; "required": false; }; "showBadge": { "alias": "showBadge"; "required": false; }; "badgePosition": { "alias": "badgePosition"; "required": false; }; }, {}, never, never, true, never>;
4923
5401
  }
4924
5402
 
5403
+ /**
5404
+ * DsMobileEmptyStateComponent
5405
+ *
5406
+ * Reusable empty state component for displaying when there's no content.
5407
+ * Used in chat modals, comment sections, and other list-based views.
5408
+ *
5409
+ * Features:
5410
+ * - Optional image display
5411
+ * - Customizable title and description
5412
+ * - Consistent styling across the app
5413
+ * - Flexible image sizing
5414
+ *
5415
+ * @example
5416
+ * ```html
5417
+ * <!-- With image -->
5418
+ * <ds-mobile-empty-state
5419
+ * [imageSrc]="'/Assets/Empty state-chat.png'"
5420
+ * [imageAlt]="'No messages'"
5421
+ * [title]="'Ingen beskeder endnu'"
5422
+ * [description]="'Start samtalen ved at sende en besked'">
5423
+ * </ds-mobile-empty-state>
5424
+ *
5425
+ * <!-- Without image -->
5426
+ * <ds-mobile-empty-state
5427
+ * [title]="'Ingen resultater'"
5428
+ * [description]="'Prøv at justere dine søgekriterier'">
5429
+ * </ds-mobile-empty-state>
5430
+ * ```
5431
+ */
5432
+ declare class DsMobileEmptyStateComponent {
5433
+ /**
5434
+ * Source URL for the empty state image (optional)
5435
+ */
5436
+ imageSrc: _angular_core.InputSignal<string>;
5437
+ /**
5438
+ * Alt text for the image
5439
+ */
5440
+ imageAlt: _angular_core.InputSignal<string>;
5441
+ /**
5442
+ * Title text for the empty state
5443
+ */
5444
+ title: _angular_core.InputSignal<string>;
5445
+ /**
5446
+ * Description text for the empty state (optional)
5447
+ */
5448
+ description: _angular_core.InputSignal<string>;
5449
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileEmptyStateComponent, never>;
5450
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileEmptyStateComponent, "ds-mobile-empty-state", never, { "imageSrc": { "alias": "imageSrc"; "required": false; "isSignal": true; }; "imageAlt": { "alias": "imageAlt"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
5451
+ }
5452
+
4925
5453
  /**
4926
5454
  * User service for managing current user data globally
4927
5455
  */
@@ -4955,6 +5483,7 @@ declare class UserService {
4955
5483
  * Unified data structures for community posts
4956
5484
  */
4957
5485
  interface Comment {
5486
+ id?: string;
4958
5487
  authorName: string;
4959
5488
  authorRole: string;
4960
5489
  timestamp: string;
@@ -5104,7 +5633,9 @@ declare class MobileHomePageComponent {
5104
5633
  userService: UserService;
5105
5634
  constructor(navCtrl: NavController, userService: UserService);
5106
5635
  handleRefresh(event: any): void;
5107
- navigateToDetail(): void;
5636
+ handlePostClick(): void;
5637
+ handleContactClick(contactType: string): void;
5638
+ handleFileClick(fileType: string): void;
5108
5639
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MobileHomePageComponent, never>;
5109
5640
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MobileHomePageComponent, "app-home-page", never, {}, {}, never, never, true, never>;
5110
5641
  }
@@ -5132,6 +5663,7 @@ declare class MobileInquiriesPageComponent {
5132
5663
  getInquiryIcon(category: string): string;
5133
5664
  openInquiryDetail(inquiryId: string): void;
5134
5665
  showInquiryActions(inquiryId: string): void;
5666
+ handleRefresh(event: any): void;
5135
5667
  createNewInquiry(): Promise<void>;
5136
5668
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MobileInquiriesPageComponent, never>;
5137
5669
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MobileInquiriesPageComponent, "app-mobile-inquiries-page", never, {}, {}, never, never, true, never>;
@@ -5197,7 +5729,7 @@ declare class MobileTabsExampleComponent implements OnInit {
5197
5729
  * so it will be used by both ds-mobile-tab-bar and ds-mobile-page-main components
5198
5730
  * throughout the entire application.
5199
5731
  */
5200
- profileMenuItems: ActionGroup[];
5732
+ get profileMenuItems(): ActionGroup[];
5201
5733
  /**
5202
5734
  * Handle profile menu action selection.
5203
5735
  * The tab bar component handles the UI (opening/closing menu),
@@ -5319,5 +5851,5 @@ declare const customPageTransition: (_: HTMLElement, opts: any) => Animation;
5319
5851
  */
5320
5852
  declare const customBackTransition: (_: HTMLElement, opts: any) => Animation;
5321
5853
 
5322
- export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsAvatarWithBadgeComponent, DsMobileActionsBottomSheetComponent, DsMobileAttachmentPreviewComponent, DsMobileBottomSheetService, DsMobileCardInlineBannerComponent, DsMobileCardInlineComponent, DsMobileCardInlineContactComponent, DsMobileCardInlineFileComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, 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, 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 };
5323
- export type { ActionGroup, ActionItem, ActionResult, AttachmentData, AttachmentFileType, AttachmentItem, AvatarSize, AvatarType, BadgePosition, BottomSheetOptions, ChatAttachment, ChatMessage, ChatModalData, ChatParticipant, Comment, ActionResult as CommentActionResult, CommentData, ContactItem, ContentWidth, HandbookDetailData, HandbookItem, InlineTabItem, InquiryPhoto, LightboxAuthor, LightboxImage, LightboxImageOptions, LightboxMediaFile, LightboxMediaType, LightboxOptions, LightboxPdf, LightboxPdfOptions, ModalOptions, NewInquiryData, NewInquiryModalOptions, Post, ActionResult as PostActionResult, PostDetailData, TabConfig, WhitelabelConfig };
5854
+ 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 };
5855
+ export type { ActionGroup, ActionItem, ActionResult, AttachmentData, AttachmentFileType, AttachmentItem, AvatarSize, AvatarType, BadgePosition, BottomSheetOptions, ChatAttachment, ChatMessage, ChatModalData, ChatParticipant, Comment, ActionResult as CommentActionResult, CommentData, ContactItem, ContentWidth, DropdownAlign, DropdownPosition, DsMobileDropdownItem, HandbookDetailData, HandbookItem, InlineTabItem, InquiryPhoto, Language, LightboxAuthor, LightboxImage, LightboxImageOptions, LightboxMediaFile, LightboxMediaType, LightboxOptions, LightboxPdf, LightboxPdfOptions, ModalOptions, NewInquiryData, NewInquiryModalOptions, Post, ActionResult as PostActionResult, PostDetailData, TabConfig, WhitelabelConfig };