@propbinder/mobile-design 0.1.14 → 0.1.15

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
@@ -105,6 +105,7 @@ declare class DsMobilePageMainComponent extends MobilePageBase implements AfterV
105
105
  private platform;
106
106
  private modalController;
107
107
  private router;
108
+ private whitelabelDemoModal;
108
109
  isNativePlatform: _angular_core.Signal<boolean>;
109
110
  title: _angular_core.InputSignal<string>;
110
111
  headerTitle: _angular_core.InputSignal<string>;
@@ -375,226 +376,6 @@ declare class TileValueComponent {
375
376
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileValueComponent, "tile-value", never, {}, {}, never, ["*"], true, never>;
376
377
  }
377
378
 
378
- /**
379
- * DsMobilePostCardComponent
380
- *
381
- * Individual post card for community feed and post details.
382
- * Displays user posts with avatar, content, media, and action buttons.
383
- * Follows Threads-inspired design with clean layout and interactions.
384
- *
385
- * @example
386
- * ```html
387
- * <ds-mobile-post-card
388
- * [authorName]="'John Doe'"
389
- * [authorRole]="'Tenant'"
390
- * [timestamp]="'2h ago'"
391
- * [avatarInitials]="'JD'"
392
- * [clickable]="true"
393
- * (postClick)="openPost()">
394
- *
395
- * <post-content>
396
- * <post-text>This is a sample post...</post-text>
397
- * </post-content>
398
- *
399
- * <post-actions>
400
- * <action-like [active]="true" count="42" />
401
- * <action-comment count="12" />
402
- * <action-share />
403
- * </post-actions>
404
- * </ds-mobile-post-card>
405
- * ```
406
- */
407
- declare class DsMobilePostCardComponent {
408
- /**
409
- * Author's display name
410
- */
411
- authorName: _angular_core.InputSignal<string>;
412
- /**
413
- * Author's role (e.g., "Tenant", "Property Manager")
414
- */
415
- authorRole: _angular_core.InputSignal<string>;
416
- /**
417
- * Timestamp text (e.g., "2h ago", "1d ago")
418
- */
419
- timestamp: _angular_core.InputSignal<string>;
420
- /**
421
- * Avatar initials (for initials type)
422
- */
423
- avatarInitials: _angular_core.InputSignal<string>;
424
- /**
425
- * Avatar type
426
- */
427
- avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
428
- /**
429
- * Avatar photo source (for photo type)
430
- */
431
- avatarSrc: _angular_core.InputSignal<string>;
432
- /**
433
- * Icon name (for icon type avatars)
434
- */
435
- avatarIconName: _angular_core.InputSignal<string>;
436
- /**
437
- * Show badge on avatar (e.g., for property managers)
438
- */
439
- showBadge: _angular_core.InputSignal<boolean>;
440
- /**
441
- * Display variant
442
- * - 'feed' - Standard feed display (default)
443
- * - 'detail' - Full detail view
444
- * - 'compact' - Compact display for nested/related posts
445
- */
446
- variant: _angular_core.InputSignal<"feed" | "detail" | "compact">;
447
- /**
448
- * Whether the post card is clickable
449
- */
450
- clickable: _angular_core.InputSignal<boolean>;
451
- /**
452
- * Emits when the post card is clicked (if clickable)
453
- */
454
- postClick: _angular_core.OutputEmitterRef<void>;
455
- /**
456
- * Emits when the comment button is clicked
457
- */
458
- commentClick: _angular_core.OutputEmitterRef<void>;
459
- /**
460
- * Emits when the post card is long-pressed
461
- */
462
- longPress: _angular_core.OutputEmitterRef<void>;
463
- /**
464
- * Long press tracking
465
- */
466
- private longPressTimer;
467
- private longPressTriggered;
468
- private touchStartX;
469
- private touchStartY;
470
- private readonly LONG_PRESS_DURATION;
471
- private readonly MOVE_THRESHOLD;
472
- handlePostClick(event: Event): void;
473
- handleCommentClick(): void;
474
- /**
475
- * Handle touch start for long press detection
476
- */
477
- handleTouchStart(event: TouchEvent): void;
478
- /**
479
- * Handle touch end to clear long press timer
480
- */
481
- handleTouchEnd(event: TouchEvent): void;
482
- /**
483
- * Handle touch move to cancel long press if moved too much
484
- */
485
- handleTouchMove(event: TouchEvent): void;
486
- /**
487
- * Handle context menu (right-click on desktop) to trigger long press action
488
- */
489
- handleContextMenu(event: Event): void;
490
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostCardComponent, never>;
491
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostCardComponent, "ds-mobile-post-card", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; "showBadge": { "alias": "showBadge"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "postClick": "postClick"; "commentClick": "commentClick"; "longPress": "longPress"; }, never, ["post-menu", "post-content", "post-actions"], true, never>;
492
- }
493
- /**
494
- * PostContentComponent
495
- *
496
- * Main content section of the post.
497
- *
498
- * Contains:
499
- * - `<post-text>` - Text content
500
- * - `<post-media>` - Optional images/videos
501
- * - `<post-attachments>` - Optional file attachments
502
- */
503
- declare class PostContentComponent {
504
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostContentComponent, never>;
505
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostContentComponent, "post-content", never, {}, {}, never, ["post-text", "post-media", "ds-mobile-inline-photo", "post-attachments"], true, never>;
506
- }
507
- /**
508
- * PostTextComponent
509
- *
510
- * Text content of the post.
511
- */
512
- declare class PostTextComponent {
513
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostTextComponent, never>;
514
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostTextComponent, "post-text", never, {}, {}, never, ["*"], true, never>;
515
- }
516
- /**
517
- * PostMediaComponent
518
- *
519
- * Media container for images/videos.
520
- */
521
- declare class PostMediaComponent {
522
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostMediaComponent, never>;
523
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostMediaComponent, "post-media", never, {}, {}, never, ["*"], true, never>;
524
- }
525
- /**
526
- * PostAttachmentsComponent
527
- *
528
- * Container for file attachments, links, etc.
529
- */
530
- declare class PostAttachmentsComponent {
531
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostAttachmentsComponent, never>;
532
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostAttachmentsComponent, "post-attachments", never, {}, {}, never, ["*"], true, never>;
533
- }
534
- /**
535
- * PostActionsComponent
536
- *
537
- * Action buttons container (like, comment, share).
538
- *
539
- * Contains:
540
- * - `<action-like>` - Like button with count
541
- * - `<action-comment>` - Comment button with count
542
- * - `<action-share>` - Share button
543
- */
544
- declare class PostActionsComponent {
545
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostActionsComponent, never>;
546
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostActionsComponent, "post-actions", never, {}, {}, never, ["*"], true, never>;
547
- }
548
- /**
549
- * ActionLikeComponent
550
- *
551
- * Like action button with count display and animated heart icon.
552
- */
553
- declare class ActionLikeComponent {
554
- /**
555
- * Whether the like is active (user has liked)
556
- * Using model() for two-way binding
557
- */
558
- active: _angular_core.ModelSignal<boolean>;
559
- /**
560
- * Number of likes
561
- * Using model() for two-way binding
562
- */
563
- count: _angular_core.ModelSignal<number>;
564
- /**
565
- * Emits when the like button is clicked
566
- */
567
- likeClick: _angular_core.OutputEmitterRef<{
568
- active: boolean;
569
- count: number;
570
- }>;
571
- /**
572
- * Signal to control pulse animation
573
- */
574
- isPulsing: _angular_core.WritableSignal<boolean>;
575
- handleClick(event: Event): Promise<void>;
576
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionLikeComponent, never>;
577
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionLikeComponent, "action-like", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "count": { "alias": "count"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; "count": "countChange"; "likeClick": "likeClick"; }, never, never, true, never>;
578
- }
579
- /**
580
- * ActionCommentComponent
581
- *
582
- * Comment action button with count display.
583
- */
584
- declare class ActionCommentComponent {
585
- /**
586
- * Number of comments
587
- */
588
- count: _angular_core.InputSignal<number>;
589
- /**
590
- * Emits when the comment button is clicked
591
- */
592
- commentClick: _angular_core.OutputEmitterRef<void>;
593
- handleClick(event: Event): void;
594
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionCommentComponent, never>;
595
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionCommentComponent, "action-comment", never, { "count": { "alias": "count"; "required": false; "isSignal": true; }; }, { "commentClick": "commentClick"; }, never, never, true, never>;
596
- }
597
-
598
379
  /**
599
380
  * DsMobileCommentComponent
600
381
  *
@@ -1188,6 +969,110 @@ declare class DsMobileInteractiveListItemPostComponent {
1188
969
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInteractiveListItemPostComponent, never>;
1189
970
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInteractiveListItemPostComponent, "ds-mobile-interactive-list-item-post", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; "showBadge": { "alias": "showBadge"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "postClick": "postClick"; "commentClick": "commentClick"; "longPress": "longPress"; }, never, ["post-menu", "post-content", "post-actions"], true, never>;
1190
971
  }
972
+ /**
973
+ * PostContentComponent
974
+ *
975
+ * Main content section of the post.
976
+ *
977
+ * Contains:
978
+ * - `<post-text>` - Text content
979
+ * - `<post-media>` - Optional images/videos
980
+ * - `<post-attachments>` - Optional file attachments
981
+ */
982
+ declare class PostContentComponent {
983
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostContentComponent, never>;
984
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostContentComponent, "post-content", never, {}, {}, never, ["post-text", "post-media", "ds-mobile-inline-photo", "post-attachments"], true, never>;
985
+ }
986
+ /**
987
+ * PostTextComponent
988
+ *
989
+ * Text content of the post.
990
+ */
991
+ declare class PostTextComponent {
992
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostTextComponent, never>;
993
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostTextComponent, "post-text", never, {}, {}, never, ["*"], true, never>;
994
+ }
995
+ /**
996
+ * PostMediaComponent
997
+ *
998
+ * Media container for images/videos.
999
+ */
1000
+ declare class PostMediaComponent {
1001
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostMediaComponent, never>;
1002
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostMediaComponent, "post-media", never, {}, {}, never, ["*"], true, never>;
1003
+ }
1004
+ /**
1005
+ * PostAttachmentsComponent
1006
+ *
1007
+ * Container for file attachments, links, etc.
1008
+ */
1009
+ declare class PostAttachmentsComponent {
1010
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostAttachmentsComponent, never>;
1011
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostAttachmentsComponent, "post-attachments", never, {}, {}, never, ["*"], true, never>;
1012
+ }
1013
+ /**
1014
+ * PostActionsComponent
1015
+ *
1016
+ * Action buttons container (like, comment, share).
1017
+ *
1018
+ * Contains:
1019
+ * - `<action-like>` - Like button with count
1020
+ * - `<action-comment>` - Comment button with count
1021
+ * - `<action-share>` - Share button
1022
+ */
1023
+ declare class PostActionsComponent {
1024
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostActionsComponent, never>;
1025
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostActionsComponent, "post-actions", never, {}, {}, never, ["*"], true, never>;
1026
+ }
1027
+ /**
1028
+ * ActionLikeComponent
1029
+ *
1030
+ * Like action button with count display and animated heart icon.
1031
+ */
1032
+ declare class ActionLikeComponent {
1033
+ /**
1034
+ * Whether the like is active (user has liked)
1035
+ * Using model() for two-way binding
1036
+ */
1037
+ active: _angular_core.ModelSignal<boolean>;
1038
+ /**
1039
+ * Number of likes
1040
+ * Using model() for two-way binding
1041
+ */
1042
+ count: _angular_core.ModelSignal<number>;
1043
+ /**
1044
+ * Emits when the like button is clicked
1045
+ */
1046
+ likeClick: _angular_core.OutputEmitterRef<{
1047
+ active: boolean;
1048
+ count: number;
1049
+ }>;
1050
+ /**
1051
+ * Signal to control pulse animation
1052
+ */
1053
+ isPulsing: _angular_core.WritableSignal<boolean>;
1054
+ handleClick(event: Event): Promise<void>;
1055
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionLikeComponent, never>;
1056
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionLikeComponent, "action-like", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "count": { "alias": "count"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; "count": "countChange"; "likeClick": "likeClick"; }, never, never, true, never>;
1057
+ }
1058
+ /**
1059
+ * ActionCommentComponent
1060
+ *
1061
+ * Comment action button with count display.
1062
+ */
1063
+ declare class ActionCommentComponent {
1064
+ /**
1065
+ * Number of comments
1066
+ */
1067
+ count: _angular_core.InputSignal<number>;
1068
+ /**
1069
+ * Emits when the comment button is clicked
1070
+ */
1071
+ commentClick: _angular_core.OutputEmitterRef<void>;
1072
+ handleClick(event: Event): void;
1073
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionCommentComponent, never>;
1074
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionCommentComponent, "action-comment", never, { "count": { "alias": "count"; "required": false; "isSignal": true; }; }, { "commentClick": "commentClick"; }, never, never, true, never>;
1075
+ }
1191
1076
 
1192
1077
  /**
1193
1078
  * PostPdfAttachmentComponent
@@ -1390,170 +1275,32 @@ declare class DsMobileContactListItemComponent {
1390
1275
  */
1391
1276
  name: _angular_core.InputSignal<string>;
1392
1277
  /**
1393
- * Avatar initials (usually 1-2 letters)
1394
- */
1395
- initials: _angular_core.InputSignal<string>;
1396
- /**
1397
- * Contact person name (optional)
1398
- */
1399
- contactPerson: _angular_core.InputSignal<string>;
1400
- /**
1401
- * Phone number (optional)
1402
- */
1403
- phoneNumber: _angular_core.InputSignal<string>;
1404
- /**
1405
- * Whether the contact item is clickable
1406
- */
1407
- clickable: _angular_core.InputSignal<boolean>;
1408
- /**
1409
- * Whether to show chevron icon
1410
- */
1411
- showChevron: _angular_core.InputSignal<boolean>;
1412
- /**
1413
- * Emits when the contact item is clicked (if clickable)
1414
- */
1415
- contactClick: _angular_core.OutputEmitterRef<void>;
1416
- handleContactClick(): void;
1417
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileContactListItemComponent, never>;
1418
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileContactListItemComponent, "ds-mobile-contact-list-item", 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; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "contactClick": "contactClick"; }, never, never, true, never>;
1419
- }
1420
-
1421
- interface TabConfig$1 {
1422
- id: string;
1423
- label: string;
1424
- route: string;
1425
- icon: string;
1426
- iconActive: string;
1427
- }
1428
- /**
1429
- * DsMobileTabBarComponent
1430
- *
1431
- * Responsive navigation tab bar that adapts from mobile to desktop:
1432
- * - Mobile (< 768px): Bottom tab bar with icons + labels
1433
- * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar
1434
- *
1435
- * Use this component INSIDE your own `ion-tabs` when Angular routing
1436
- * requires `ion-tabs` to be a direct child in your component.
1437
- *
1438
- * @example
1439
- * ```html
1440
- * <!-- In your component with child routes -->
1441
- * <ion-tabs>
1442
- * <ds-mobile-tab-bar
1443
- * [tabs]="tabs"
1444
- * [avatarInitials]="'JD'"
1445
- * (avatarClick)="handleAvatarClick()"
1446
- * />
1447
- * </ion-tabs>
1448
- * ```
1449
- */
1450
- declare class DsMobileTabBarComponent implements OnInit, AfterViewInit, OnDestroy {
1451
- private elementRef;
1452
- tabs: TabConfig$1[];
1453
- avatarType: 'initials' | 'photo' | 'icon';
1454
- avatarInitials: string;
1455
- avatarSrc: string;
1456
- avatarIconName: string;
1457
- avatarClick: EventEmitter<void>;
1458
- activeTab: _angular_core.WritableSignal<string>;
1459
- isDesktop: _angular_core.WritableSignal<boolean>;
1460
- private mutationObserver?;
1461
- private resizeObserver?;
1462
- private mediaQuery?;
1463
- constructor(elementRef: ElementRef);
1464
- ngOnInit(): void;
1465
- ngAfterViewInit(): void;
1466
- ngOnDestroy(): void;
1467
- private setupBreakpointDetection;
1468
- private handleBreakpointChange;
1469
- private setupTitleRemovalObserver;
1470
- private removeTitleAttributes;
1471
- trackByTabId(index: number, tab: TabConfig$1): string;
1472
- isTabActive(tabId: string): boolean;
1473
- handleAvatarClick(): void;
1474
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileTabBarComponent, never>;
1475
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileTabBarComponent, "ds-mobile-tab-bar", never, { "tabs": { "alias": "tabs"; "required": false; }; "avatarType": { "alias": "avatarType"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; }; }, { "avatarClick": "avatarClick"; }, never, never, true, never>;
1476
- }
1477
-
1478
- /**
1479
- * DsMobileTabsComponent
1480
- *
1481
- * Responsive tab navigation that adapts from mobile to desktop:
1482
- * - Mobile (< 768px): Bottom tab bar with icons + labels
1483
- * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar
1484
- *
1485
- * Wraps ion-tabs to maintain native routing functionality while
1486
- * providing a responsive navigation experience with branding.
1487
- *
1488
- * NOTE: This component wraps `ion-tabs` internally. If your Angular
1489
- * routing requires `ion-tabs` to be a direct child in your component
1490
- * (e.g., when using `ion-router-outlet` in app.html), use the
1491
- * `DsMobileTabBarComponent` directly inside your own `ion-tabs` instead.
1492
- *
1493
- * @example
1494
- * ```html
1495
- * <ds-mobile-tabs
1496
- * [tabs]="tabsConfig"
1497
- * [avatarInitials]="'JD'"
1498
- * (avatarClick)="handleAvatarClick()"
1499
- * />
1500
- * ```
1501
- */
1502
- declare class DsMobileTabsComponent implements OnInit {
1503
- tabs: TabConfig$1[];
1504
- avatarType: 'initials' | 'photo' | 'icon';
1505
- avatarInitials: string;
1506
- avatarSrc: string;
1507
- avatarIconName: string;
1508
- avatarClick: EventEmitter<void>;
1509
- constructor();
1510
- ngOnInit(): void;
1511
- trackByTabId(index: number, tab: TabConfig$1): string;
1512
- handleAvatarClick(): void;
1513
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileTabsComponent, never>;
1514
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileTabsComponent, "ds-mobile-tabs", never, { "tabs": { "alias": "tabs"; "required": false; }; "avatarType": { "alias": "avatarType"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; }; }, { "avatarClick": "avatarClick"; }, never, never, true, never>;
1515
- }
1516
-
1517
- interface InlineTabItem {
1518
- id: string;
1519
- label: string;
1520
- badge?: number;
1521
- }
1522
- /**
1523
- * DsMobileInlineTabsComponent
1524
- *
1525
- * Pill-style inline tabs for filtering/switching views
1526
- * Used in the purple header section of pages
1527
- *
1528
- * @example
1529
- * ```html
1530
- * <ds-mobile-inline-tabs
1531
- * [tabs]="[
1532
- * { id: 'all', label: 'All' },
1533
- * { id: 'open', label: 'Open' },
1534
- * { id: 'closed', label: 'Closed' }
1535
- * ]"
1536
- * [activeTab]="'all'"
1537
- * (tabChange)="handleTabChange($event)">
1538
- * </ds-mobile-inline-tabs>
1539
- * ```
1540
- */
1541
- declare class DsMobileInlineTabsComponent {
1542
- /**
1543
- * Array of tab items to display
1278
+ * Avatar initials (usually 1-2 letters)
1544
1279
  */
1545
- tabs: _angular_core.InputSignal<InlineTabItem[]>;
1280
+ initials: _angular_core.InputSignal<string>;
1546
1281
  /**
1547
- * Currently active tab ID
1282
+ * Contact person name (optional)
1548
1283
  */
1549
- activeTab: _angular_core.InputSignal<string>;
1284
+ contactPerson: _angular_core.InputSignal<string>;
1550
1285
  /**
1551
- * Emitted when a tab is clicked
1286
+ * Phone number (optional)
1552
1287
  */
1553
- tabChange: _angular_core.OutputEmitterRef<string>;
1554
- handleTabClick(tabId: string): void;
1555
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInlineTabsComponent, never>;
1556
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInlineTabsComponent, "ds-mobile-inline-tabs", never, { "tabs": { "alias": "tabs"; "required": true; "isSignal": true; }; "activeTab": { "alias": "activeTab"; "required": true; "isSignal": true; }; }, { "tabChange": "tabChange"; }, never, never, true, never>;
1288
+ phoneNumber: _angular_core.InputSignal<string>;
1289
+ /**
1290
+ * Whether the contact item is clickable
1291
+ */
1292
+ clickable: _angular_core.InputSignal<boolean>;
1293
+ /**
1294
+ * Whether to show chevron icon
1295
+ */
1296
+ showChevron: _angular_core.InputSignal<boolean>;
1297
+ /**
1298
+ * Emits when the contact item is clicked (if clickable)
1299
+ */
1300
+ contactClick: _angular_core.OutputEmitterRef<void>;
1301
+ handleContactClick(): void;
1302
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileContactListItemComponent, never>;
1303
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileContactListItemComponent, "ds-mobile-contact-list-item", 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; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "contactClick": "contactClick"; }, never, never, true, never>;
1557
1304
  }
1558
1305
 
1559
1306
  interface ActionResult {
@@ -1787,6 +1534,213 @@ declare class DsMobilePostCreateBottomSheetComponent implements AfterViewInit, O
1787
1534
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostCreateBottomSheetComponent, "ds-mobile-post-create-bottom-sheet", never, {}, {}, never, never, true, never>;
1788
1535
  }
1789
1536
 
1537
+ interface TabConfig {
1538
+ id: string;
1539
+ label: string;
1540
+ route: string;
1541
+ icon: string;
1542
+ iconActive: string;
1543
+ }
1544
+ /**
1545
+ * DsMobileTabBarComponent
1546
+ *
1547
+ * Responsive navigation tab bar that adapts from mobile to desktop:
1548
+ * - Mobile (< 768px): Bottom tab bar with icons + labels
1549
+ * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar
1550
+ *
1551
+ * Use this component INSIDE your own `ion-tabs` when Angular routing
1552
+ * requires `ion-tabs` to be a direct child in your component.
1553
+ *
1554
+ * @example
1555
+ * ```html
1556
+ * <!-- In your component with child routes -->
1557
+ * <!-- IMPORTANT: Add class="ds-tabs-wrapper" to ion-tabs for proper styling -->
1558
+ * <ion-tabs class="ds-tabs-wrapper">
1559
+ * <ds-mobile-tab-bar
1560
+ * [tabs]="tabs"
1561
+ * [avatarInitials]="'JD'"
1562
+ * [profileMenuItems]="profileMenuItems"
1563
+ * (profileActionSelected)="handleProfileAction($event)"
1564
+ * />
1565
+ * </ion-tabs>
1566
+ * ```
1567
+ *
1568
+ * @example With profile menu configuration
1569
+ * ```typescript
1570
+ * profileMenuItems: ActionGroup[] = [
1571
+ * {
1572
+ * actions: [
1573
+ * { action: 'profile', title: 'My Profile', icon: 'remixUser3Line' },
1574
+ * { action: 'settings', title: 'Settings', icon: 'remixSettings3Line' }
1575
+ * ]
1576
+ * },
1577
+ * {
1578
+ * actions: [
1579
+ * { action: 'logout', title: 'Log Out', icon: 'remixLogoutBoxLine', destructive: true }
1580
+ * ]
1581
+ * }
1582
+ * ];
1583
+ *
1584
+ * handleProfileAction(result: ActionResult): void {
1585
+ * switch (result.action) {
1586
+ * case 'profile': // Navigate to profile
1587
+ * case 'settings': // Navigate to settings
1588
+ * case 'logout': // Handle logout
1589
+ * }
1590
+ * }
1591
+ * ```
1592
+ *
1593
+ * @note When using this component, you must add the class "ds-tabs-wrapper"
1594
+ * to your `ion-tabs` element, or manually apply these styles:
1595
+ * ```css
1596
+ * ion-tabs {
1597
+ * height: 100%;
1598
+ * background: var(--color-brand-secondary);
1599
+ * }
1600
+ * ```
1601
+ */
1602
+ declare class DsMobileTabBarComponent implements OnInit, AfterViewInit, OnDestroy {
1603
+ private elementRef;
1604
+ tabs: TabConfig[];
1605
+ avatarType: 'initials' | 'photo' | 'icon';
1606
+ avatarInitials: string;
1607
+ avatarSrc: string;
1608
+ avatarIconName: string;
1609
+ /**
1610
+ * Profile menu action groups to display when avatar is clicked.
1611
+ * If not provided, only the avatarClick event will be emitted.
1612
+ *
1613
+ * @example
1614
+ * ```typescript
1615
+ * profileMenuItems: ActionGroup[] = [
1616
+ * {
1617
+ * actions: [
1618
+ * { action: 'profile', title: 'My Profile', icon: 'remixUser3Line' },
1619
+ * { action: 'settings', title: 'Settings', icon: 'remixSettings3Line' }
1620
+ * ]
1621
+ * }
1622
+ * ];
1623
+ * ```
1624
+ */
1625
+ profileMenuItems?: ActionGroup[];
1626
+ avatarClick: EventEmitter<void>;
1627
+ /**
1628
+ * Emitted when a profile menu action is selected.
1629
+ * Parent component should handle the action logic (navigation, logout, etc.).
1630
+ */
1631
+ profileActionSelected: EventEmitter<ActionResult>;
1632
+ activeTab: _angular_core.WritableSignal<string>;
1633
+ isDesktop: _angular_core.WritableSignal<boolean>;
1634
+ private mutationObserver?;
1635
+ private slotEnforcementObserver?;
1636
+ private resizeObserver?;
1637
+ private mediaQuery?;
1638
+ private routerSubscription?;
1639
+ private router?;
1640
+ private modalController;
1641
+ constructor(elementRef: ElementRef);
1642
+ ngOnInit(): void;
1643
+ ngAfterViewInit(): void;
1644
+ private updateSlot;
1645
+ private setupSlotEnforcement;
1646
+ ngOnDestroy(): void;
1647
+ private setupBreakpointDetection;
1648
+ private handleBreakpointChange;
1649
+ private setupTitleRemovalObserver;
1650
+ private removeTitleAttributes;
1651
+ private setupActiveTabDetection;
1652
+ private updateActiveTabFromDOM;
1653
+ trackByTabId(index: number, tab: TabConfig): string;
1654
+ isTabActive(tabRoute: string): boolean;
1655
+ /**
1656
+ * Handle avatar click - opens profile menu if configured, otherwise just emits avatarClick
1657
+ */
1658
+ handleAvatarClick(): Promise<void>;
1659
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileTabBarComponent, never>;
1660
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileTabBarComponent, "ds-mobile-tab-bar", never, { "tabs": { "alias": "tabs"; "required": false; }; "avatarType": { "alias": "avatarType"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; }; "profileMenuItems": { "alias": "profileMenuItems"; "required": false; }; }, { "avatarClick": "avatarClick"; "profileActionSelected": "profileActionSelected"; }, never, never, true, never>;
1661
+ }
1662
+
1663
+ /**
1664
+ * DsMobileTabsComponent
1665
+ *
1666
+ * Responsive tab navigation that adapts from mobile to desktop:
1667
+ * - Mobile (< 768px): Bottom tab bar with icons + labels
1668
+ * - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar
1669
+ *
1670
+ * Wraps ion-tabs to maintain native routing functionality while
1671
+ * providing a responsive navigation experience with branding.
1672
+ *
1673
+ * NOTE: This component wraps `ion-tabs` internally. If your Angular
1674
+ * routing requires `ion-tabs` to be a direct child in your component
1675
+ * (e.g., when using `ion-router-outlet` in app.html), use the
1676
+ * `DsMobileTabBarComponent` directly inside your own `ion-tabs` instead.
1677
+ *
1678
+ * @example
1679
+ * ```html
1680
+ * <ds-mobile-tabs
1681
+ * [tabs]="tabsConfig"
1682
+ * [avatarInitials]="'JD'"
1683
+ * (avatarClick)="handleAvatarClick()"
1684
+ * />
1685
+ * ```
1686
+ */
1687
+ declare class DsMobileTabsComponent implements OnInit {
1688
+ tabs: TabConfig[];
1689
+ avatarType: 'initials' | 'photo' | 'icon';
1690
+ avatarInitials: string;
1691
+ avatarSrc: string;
1692
+ avatarIconName: string;
1693
+ avatarClick: EventEmitter<void>;
1694
+ constructor();
1695
+ ngOnInit(): void;
1696
+ trackByTabId(index: number, tab: TabConfig): string;
1697
+ handleAvatarClick(): void;
1698
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileTabsComponent, never>;
1699
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileTabsComponent, "ds-mobile-tabs", never, { "tabs": { "alias": "tabs"; "required": false; }; "avatarType": { "alias": "avatarType"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; }; }, { "avatarClick": "avatarClick"; }, never, never, true, never>;
1700
+ }
1701
+
1702
+ interface InlineTabItem {
1703
+ id: string;
1704
+ label: string;
1705
+ badge?: number;
1706
+ }
1707
+ /**
1708
+ * DsMobileInlineTabsComponent
1709
+ *
1710
+ * Pill-style inline tabs for filtering/switching views
1711
+ * Used in the purple header section of pages
1712
+ *
1713
+ * @example
1714
+ * ```html
1715
+ * <ds-mobile-inline-tabs
1716
+ * [tabs]="[
1717
+ * { id: 'all', label: 'All' },
1718
+ * { id: 'open', label: 'Open' },
1719
+ * { id: 'closed', label: 'Closed' }
1720
+ * ]"
1721
+ * [activeTab]="'all'"
1722
+ * (tabChange)="handleTabChange($event)">
1723
+ * </ds-mobile-inline-tabs>
1724
+ * ```
1725
+ */
1726
+ declare class DsMobileInlineTabsComponent {
1727
+ /**
1728
+ * Array of tab items to display
1729
+ */
1730
+ tabs: _angular_core.InputSignal<InlineTabItem[]>;
1731
+ /**
1732
+ * Currently active tab ID
1733
+ */
1734
+ activeTab: _angular_core.InputSignal<string>;
1735
+ /**
1736
+ * Emitted when a tab is clicked
1737
+ */
1738
+ tabChange: _angular_core.OutputEmitterRef<string>;
1739
+ handleTabClick(tabId: string): void;
1740
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInlineTabsComponent, never>;
1741
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInlineTabsComponent, "ds-mobile-inline-tabs", never, { "tabs": { "alias": "tabs"; "required": true; "isSignal": true; }; "activeTab": { "alias": "activeTab"; "required": true; "isSignal": true; }; }, { "tabChange": "tabChange"; }, never, never, true, never>;
1742
+ }
1743
+
1790
1744
  /**
1791
1745
  * Media file types supported by the lightbox
1792
1746
  */
@@ -2489,32 +2443,92 @@ declare class DsMobileModalService {
2489
2443
 
2490
2444
  /**
2491
2445
  * Post data interface for the modal
2446
+ *
2447
+ * Represents a post with its content, author info, and comments.
2448
+ * Use this interface to map your API response data to the component.
2449
+ *
2450
+ * @example
2451
+ * ```typescript
2452
+ * const postData: PostDetailData = {
2453
+ * postId: '123',
2454
+ * authorName: 'John Doe',
2455
+ * authorRole: 'Tenant',
2456
+ * timestamp: '2h ago',
2457
+ * avatarInitials: 'JD',
2458
+ * content: 'Post content here...',
2459
+ * likeCount: 42,
2460
+ * commentCount: 12,
2461
+ * comments: [...]
2462
+ * };
2463
+ * ```
2492
2464
  */
2493
2465
  interface PostDetailData {
2466
+ /** Unique post identifier */
2494
2467
  postId: string;
2468
+ /** Post author name */
2495
2469
  authorName: string;
2470
+ /** Author role (e.g., 'Tenant', 'Manager') */
2496
2471
  authorRole: string;
2472
+ /** Post timestamp (e.g., '2h ago', 'Yesterday') */
2497
2473
  timestamp: string;
2474
+ /** Author avatar initials (1-2 letters) */
2498
2475
  avatarInitials?: string;
2476
+ /** Avatar display type */
2499
2477
  avatarType?: 'photo' | 'initials';
2478
+ /** Author avatar image URL */
2500
2479
  avatarSrc?: string;
2480
+ /** Post text content */
2501
2481
  content: string;
2482
+ /** Optional post image URL */
2502
2483
  imageSrc?: string;
2484
+ /** Image alt text */
2503
2485
  imageAlt?: string;
2486
+ /** Whether the current user has liked this post */
2504
2487
  isLiked?: boolean;
2488
+ /** Number of likes */
2505
2489
  likeCount?: number;
2490
+ /** Number of comments */
2506
2491
  commentCount?: number;
2492
+ /** Array of comments */
2507
2493
  comments?: CommentData[];
2494
+ /** Auto-focus comment input when modal opens */
2508
2495
  focusComment?: boolean;
2509
2496
  }
2497
+ /**
2498
+ * Comment data interface
2499
+ *
2500
+ * Represents a single comment on a post.
2501
+ *
2502
+ * @example
2503
+ * ```typescript
2504
+ * const comment: CommentData = {
2505
+ * authorName: 'Jane Smith',
2506
+ * authorRole: 'Tenant',
2507
+ * timestamp: '1h ago',
2508
+ * avatarInitials: 'JS',
2509
+ * content: 'Great post!',
2510
+ * isLiked: false,
2511
+ * likeCount: 5,
2512
+ * isOwnComment: false
2513
+ * };
2514
+ * ```
2515
+ */
2510
2516
  interface CommentData {
2517
+ /** Comment author name */
2511
2518
  authorName: string;
2519
+ /** Author role */
2512
2520
  authorRole: string;
2521
+ /** Comment timestamp */
2513
2522
  timestamp: string;
2523
+ /** Author avatar initials */
2514
2524
  avatarInitials: string;
2525
+ /** Comment text content */
2515
2526
  content: string;
2527
+ /** Whether the current user has liked this comment */
2516
2528
  isLiked?: boolean;
2529
+ /** Number of likes on this comment */
2517
2530
  likeCount?: number;
2531
+ /** Whether this comment belongs to the current user */
2518
2532
  isOwnComment?: boolean;
2519
2533
  }
2520
2534
  /**
@@ -2551,6 +2565,16 @@ declare class DsMobilePostDetailModalComponent implements AfterViewInit, OnDestr
2551
2565
  private lightbox;
2552
2566
  private bottomSheet;
2553
2567
  postData: PostDetailData;
2568
+ /**
2569
+ * Loading state - when true, shows loading indicator
2570
+ * Set this to true while fetching post data from your API
2571
+ */
2572
+ loading: boolean;
2573
+ /**
2574
+ * Error state - when set, shows error message
2575
+ * Set this to an error message string if API call fails
2576
+ */
2577
+ error?: string;
2554
2578
  commentInput?: ElementRef<HTMLTextAreaElement>;
2555
2579
  post: _angular_core.WritableSignal<PostDetailData>;
2556
2580
  commentText: _angular_core.WritableSignal<string>;
@@ -2638,7 +2662,7 @@ declare class DsMobilePostDetailModalComponent implements AfterViewInit, OnDestr
2638
2662
  */
2639
2663
  handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void>;
2640
2664
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostDetailModalComponent, never>;
2641
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostDetailModalComponent, "ds-mobile-post-detail-modal", never, { "postData": { "alias": "postData"; "required": false; }; }, {}, never, never, true, never>;
2665
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostDetailModalComponent, "ds-mobile-post-detail-modal", never, { "postData": { "alias": "postData"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; }, {}, never, never, true, never>;
2642
2666
  }
2643
2667
 
2644
2668
  /**
@@ -2691,9 +2715,13 @@ declare class DsMobilePostDetailModalService {
2691
2715
  * Open the post detail modal
2692
2716
  *
2693
2717
  * @param postData Post data to display
2718
+ * @param options Optional loading and error states
2694
2719
  * @returns Promise that resolves when the modal is presented
2695
2720
  */
2696
- open(postData: PostDetailData): Promise<void>;
2721
+ open(postData: PostDetailData, options?: {
2722
+ loading?: boolean;
2723
+ error?: string;
2724
+ }): Promise<void>;
2697
2725
  /**
2698
2726
  * Close the currently open post detail modal
2699
2727
  *
@@ -2713,30 +2741,111 @@ declare class DsMobilePostDetailModalService {
2713
2741
 
2714
2742
  /**
2715
2743
  * Handbook detail data interface
2744
+ *
2745
+ * Represents a handbook category/folder with its sections/items.
2746
+ * Use this interface to map your API response data to the component.
2747
+ *
2748
+ * @example
2749
+ * ```typescript
2750
+ * const handbookData: HandbookDetailData = {
2751
+ * title: 'Access Systems',
2752
+ * variant: 'blue',
2753
+ * iconName: 'remixKey2Line',
2754
+ * itemCount: 5,
2755
+ * items: [...]
2756
+ * };
2757
+ * ```
2716
2758
  */
2717
2759
  interface HandbookDetailData {
2760
+ /** Category/folder title */
2718
2761
  title: string;
2762
+ /** Color variant: 'success', 'warning', 'destructive', 'blue', 'light-purple', 'pink', 'salmon-orange', 'orange', 'lime-green', 'grey' */
2719
2763
  variant: string;
2764
+ /** Icon name from design system (e.g., 'remixKey2Line', 'remixLightbulbLine') */
2720
2765
  iconName: string;
2766
+ /** Total number of items/sections in this category */
2721
2767
  itemCount: number;
2768
+ /** Array of handbook sections/items */
2722
2769
  items?: HandbookItem[];
2723
2770
  }
2771
+ /**
2772
+ * Handbook section/item interface
2773
+ *
2774
+ * Represents a single section within a handbook category.
2775
+ * Each section can have a title, description, images, contacts, and attachments.
2776
+ *
2777
+ * @example
2778
+ * ```typescript
2779
+ * const item: HandbookItem = {
2780
+ * title: 'Key Box Entrance',
2781
+ * description: 'Key box located at main entrance...',
2782
+ * images: ['https://api.example.com/images/keybox.jpg'],
2783
+ * contacts: [{ name: 'Security Co', initials: 'S', phoneNumber: '+45 12345678' }],
2784
+ * attachments: [{ name: 'Manual.pdf', type: 'pdf', url: 'https://...' }]
2785
+ * };
2786
+ * ```
2787
+ */
2724
2788
  interface HandbookItem {
2789
+ /** Section title */
2725
2790
  title: string;
2791
+ /** Optional section description */
2726
2792
  description?: string;
2793
+ /** Array of image URLs to display */
2727
2794
  images?: string[];
2795
+ /** Array of file attachments */
2728
2796
  attachments?: AttachmentItem[];
2797
+ /** Array of contact information */
2729
2798
  contacts?: ContactItem[];
2730
2799
  }
2800
+ /**
2801
+ * File attachment interface
2802
+ *
2803
+ * Represents a file attachment in a handbook section.
2804
+ *
2805
+ * @example
2806
+ * ```typescript
2807
+ * const attachment: AttachmentItem = {
2808
+ * name: 'Installation_Manual.pdf',
2809
+ * type: 'pdf',
2810
+ * url: 'https://api.example.com/files/manual.pdf'
2811
+ * };
2812
+ * ```
2813
+ */
2731
2814
  interface AttachmentItem {
2815
+ /** File name to display */
2732
2816
  name: string;
2817
+ /** File type: 'pdf', 'doc', etc. (used for icon display) */
2733
2818
  type?: string;
2819
+ /** Optional URL for downloading/opening the file */
2820
+ url?: string;
2734
2821
  }
2822
+ /**
2823
+ * Contact information interface
2824
+ *
2825
+ * Represents contact information in a handbook section.
2826
+ *
2827
+ * @example
2828
+ * ```typescript
2829
+ * const contact: ContactItem = {
2830
+ * name: 'Propbinder ApS',
2831
+ * initials: 'P',
2832
+ * contactPerson: 'John Doe',
2833
+ * phoneNumber: '+45 12345678',
2834
+ * email: 'support@propbinder.dk'
2835
+ * };
2836
+ * ```
2837
+ */
2735
2838
  interface ContactItem {
2839
+ /** Company or contact name */
2736
2840
  name: string;
2841
+ /** Initials for avatar (1-2 letters) */
2737
2842
  initials: string;
2843
+ /** Optional contact person name */
2738
2844
  contactPerson?: string;
2845
+ /** Optional phone number */
2739
2846
  phoneNumber?: string;
2847
+ /** Optional email address */
2848
+ email?: string;
2740
2849
  }
2741
2850
  /**
2742
2851
  * DsMobileHandbookDetailModalComponent
@@ -2756,6 +2865,14 @@ interface ContactItem {
2756
2865
  declare class DsMobileHandbookDetailModalComponent {
2757
2866
  private modalController;
2758
2867
  handbookData: HandbookDetailData;
2868
+ /**
2869
+ * Loading state - when true, shows loading indicator
2870
+ */
2871
+ loading: boolean;
2872
+ /**
2873
+ * Error state - when set, shows error message
2874
+ */
2875
+ error?: string;
2759
2876
  handbook: _angular_core.WritableSignal<HandbookDetailData>;
2760
2877
  constructor(modalController: ModalController);
2761
2878
  ngOnInit(): void;
@@ -2785,7 +2902,7 @@ declare class DsMobileHandbookDetailModalComponent {
2785
2902
  */
2786
2903
  handleAttachmentClick(attachment: AttachmentItem): void;
2787
2904
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHandbookDetailModalComponent, never>;
2788
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHandbookDetailModalComponent, "ds-mobile-handbook-detail-modal", never, { "handbookData": { "alias": "handbookData"; "required": false; }; }, {}, never, never, true, never>;
2905
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHandbookDetailModalComponent, "ds-mobile-handbook-detail-modal", never, { "handbookData": { "alias": "handbookData"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; }, {}, never, never, true, never>;
2789
2906
  }
2790
2907
 
2791
2908
  /**
@@ -2833,9 +2950,13 @@ declare class DsMobileHandbookDetailModalService {
2833
2950
  * Open the handbook detail modal
2834
2951
  *
2835
2952
  * @param handbookData Handbook data to display
2953
+ * @param options Optional loading and error states
2836
2954
  * @returns Promise that resolves when the modal is presented
2837
2955
  */
2838
- open(handbookData: HandbookDetailData): Promise<void>;
2956
+ open(handbookData: HandbookDetailData, options?: {
2957
+ loading?: boolean;
2958
+ error?: string;
2959
+ }): Promise<void>;
2839
2960
  /**
2840
2961
  * Close the currently open handbook detail modal
2841
2962
  *
@@ -2892,16 +3013,28 @@ declare class DsMobileHandbookFolderComponent {
2892
3013
  iconName: string;
2893
3014
  /**
2894
3015
  * Number of items in the folder
3016
+ * This should match the length of the items array when data is loaded
2895
3017
  */
2896
3018
  itemCount: number;
2897
3019
  /**
2898
- * Label text displayed below the folder
3020
+ * Label text displayed below the folder (category name)
2899
3021
  */
2900
3022
  label: string;
2901
3023
  /**
2902
3024
  * Optional items data for the handbook folder
3025
+ * Pass the HandbookItem[] array from your API response here
2903
3026
  */
2904
3027
  items?: HandbookItem[];
3028
+ /**
3029
+ * Loading state - when true, shows "Loading..." indicator instead of item count
3030
+ * Set this to true while fetching data from your API
3031
+ */
3032
+ loading: boolean;
3033
+ /**
3034
+ * Error state - when set, shows "Error" indicator instead of item count
3035
+ * Set this to an error message string if API call fails
3036
+ */
3037
+ error?: string;
2905
3038
  /**
2906
3039
  * Track open/closed state for animation
2907
3040
  */
@@ -2932,6 +3065,7 @@ declare class DsMobileHandbookFolderComponent {
2932
3065
  onTouchCancel(): void;
2933
3066
  /**
2934
3067
  * Handle click - open modal
3068
+ * Only opens modal if not in loading or error state
2935
3069
  */
2936
3070
  onClick(): Promise<void>;
2937
3071
  /**
@@ -2941,7 +3075,7 @@ declare class DsMobileHandbookFolderComponent {
2941
3075
  getPageSheets(): number[];
2942
3076
  constructor(handbookModal: DsMobileHandbookDetailModalService);
2943
3077
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHandbookFolderComponent, never>;
2944
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHandbookFolderComponent, "ds-mobile-handbook-folder", never, { "variant": { "alias": "variant"; "required": false; }; "iconName": { "alias": "iconName"; "required": false; }; "itemCount": { "alias": "itemCount"; "required": false; }; "label": { "alias": "label"; "required": false; }; "items": { "alias": "items"; "required": false; }; }, {}, never, never, true, never>;
3078
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHandbookFolderComponent, "ds-mobile-handbook-folder", never, { "variant": { "alias": "variant"; "required": false; }; "iconName": { "alias": "iconName"; "required": false; }; "itemCount": { "alias": "itemCount"; "required": false; }; "label": { "alias": "label"; "required": false; }; "items": { "alias": "items"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; }, {}, never, never, true, never>;
2945
3079
  }
2946
3080
 
2947
3081
  /**
@@ -3129,23 +3263,33 @@ declare class MobileInquiryDetailPageComponent extends MobilePageBase implements
3129
3263
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MobileInquiryDetailPageComponent, "app-mobile-inquiry-detail-page", never, {}, {}, never, never, true, never>;
3130
3264
  }
3131
3265
 
3132
- interface TabConfig {
3133
- id: string;
3134
- label: string;
3135
- route: string;
3136
- icon: string;
3137
- iconActive: string;
3138
- }
3139
-
3266
+ /**
3267
+ * MobileTabsExampleComponent
3268
+ *
3269
+ * Example page using the TenantApp pattern:
3270
+ * - Uses ion-tabs as wrapper (required for Angular routing)
3271
+ * - Uses ds-mobile-tab-bar inside (not ds-mobile-tabs)
3272
+ *
3273
+ * This matches the pattern used in TenantApp for consistency.
3274
+ */
3140
3275
  declare class MobileTabsExampleComponent implements OnInit {
3141
3276
  userService: UserService;
3142
- private modalController;
3143
3277
  private router;
3144
3278
  private whitelabelDemoModal;
3145
- constructor(userService: UserService, modalController: ModalController, router: Router);
3279
+ constructor(userService: UserService, router: Router);
3146
3280
  ngOnInit(): void;
3147
3281
  tabs: TabConfig[];
3148
- handleAvatarClick(): Promise<void>;
3282
+ /**
3283
+ * Profile menu items configuration.
3284
+ * Define once here, and the tab bar component handles opening/closing the menu.
3285
+ */
3286
+ profileMenuItems: ActionGroup[];
3287
+ /**
3288
+ * Handle profile menu action selection.
3289
+ * The tab bar component handles the UI (opening/closing menu),
3290
+ * this method handles the business logic.
3291
+ */
3292
+ handleProfileAction(result: ActionResult): void;
3149
3293
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MobileTabsExampleComponent, never>;
3150
3294
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MobileTabsExampleComponent, "app-mobile-tabs-example", never, {}, {}, never, never, true, never>;
3151
3295
  }
@@ -3341,5 +3485,5 @@ declare const customPageTransition: (_: HTMLElement, opts: any) => Animation;
3341
3485
  */
3342
3486
  declare const customBackTransition: (_: HTMLElement, opts: any) => Animation;
3343
3487
 
3344
- export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsMobileActionsBottomSheetComponent, DsMobileBottomSheetService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLongPressDirective, DsMobileModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostCardComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileTabBarComponent, DsMobileTabsComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoPage, WhitelabelService, customBackTransition, customPageTransition };
3345
- export type { ActionGroup, ActionItem, ActionResult, AttachmentItem, BottomSheetOptions, ActionResult as CommentActionResult, CommentData, ContactItem, ContentWidth, HandbookDetailData, HandbookItem, InlineTabItem, LightboxAuthor, LightboxImage, LightboxImageOptions, LightboxMediaFile, LightboxMediaType, LightboxOptions, LightboxPdf, LightboxPdfOptions, ModalOptions, ActionResult as PostActionResult, PostDetailData, TabConfig$1 as TabConfig, WhitelabelConfig };
3488
+ export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsMobileActionsBottomSheetComponent, DsMobileBottomSheetService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLongPressDirective, DsMobileModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileTabBarComponent, DsMobileTabsComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoPage, WhitelabelService, customBackTransition, customPageTransition };
3489
+ export type { ActionGroup, ActionItem, ActionResult, AttachmentItem, BottomSheetOptions, ActionResult as CommentActionResult, CommentData, ContactItem, ContentWidth, HandbookDetailData, HandbookItem, InlineTabItem, LightboxAuthor, LightboxImage, LightboxImageOptions, LightboxMediaFile, LightboxMediaType, LightboxOptions, LightboxPdf, LightboxPdfOptions, ModalOptions, ActionResult as PostActionResult, PostDetailData, TabConfig, WhitelabelConfig };