@propbinder/mobile-design 0.2.47 → 0.2.50

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.
Files changed (221) hide show
  1. package/ng-package.json +24 -0
  2. package/package.json +3 -39
  3. package/src/animations/page-transitions.ts +165 -0
  4. package/src/assets/fonts/brockmann-mediumitalic-webfont.woff2 +0 -0
  5. package/src/assets/fonts/brockmann-regularitalic-webfont.woff2 +0 -0
  6. package/src/assets/fonts/brockmann-semibolditalic-webfont.woff2 +0 -0
  7. package/src/components/action-list-item/ds-mobile-action-list-item.ts +102 -0
  8. package/src/components/action-list-item/index.ts +2 -0
  9. package/src/components/app-icon/ds-app-icon.ts +133 -0
  10. package/src/components/app-icon/index.ts +2 -0
  11. package/src/components/attachment-preview/ds-mobile-attachment-preview.css +139 -0
  12. package/src/components/attachment-preview/ds-mobile-attachment-preview.ts +164 -0
  13. package/src/components/attachment-preview/index.ts +1 -0
  14. package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +142 -0
  15. package/src/components/avatar-with-badge/index.ts +2 -0
  16. package/src/components/booking-modal/ds-mobile-booking-confirmation-wrapper.ts +71 -0
  17. package/src/components/booking-modal/ds-mobile-booking-modal.service.ts +121 -0
  18. package/src/components/booking-modal/ds-mobile-booking-modal.ts +598 -0
  19. package/src/components/booking-modal/ds-mobile-booking-summary.ts +161 -0
  20. package/src/components/booking-modal/index.ts +4 -0
  21. package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +266 -0
  22. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-header.ts +146 -0
  23. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-wrapper.ts +156 -0
  24. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +101 -0
  25. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +169 -0
  26. package/src/components/bottom-sheet/ds-mobile-confirmation-sheet.ts +211 -0
  27. package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +578 -0
  28. package/src/components/bottom-sheet/ds-mobile-profile-actions-sheet.ts +614 -0
  29. package/src/components/bottom-sheet/index.ts +8 -0
  30. package/src/components/bottom-sheet/modal-shadow-fix.ts +42 -0
  31. package/src/components/card-inline/ds-mobile-card-inline.ts +301 -0
  32. package/src/components/card-inline/index.ts +2 -0
  33. package/src/components/card-inline-banner/ds-mobile-card-inline-banner.ts +118 -0
  34. package/src/components/card-inline-banner/index.ts +1 -0
  35. package/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts +120 -0
  36. package/src/components/card-inline-contact/index.ts +1 -0
  37. package/src/components/card-inline-file/ds-mobile-card-inline-file.ts +141 -0
  38. package/src/components/card-inline-file/index.ts +1 -0
  39. package/src/components/chat-modal/ds-mobile-chat-modal.css +159 -0
  40. package/src/components/chat-modal/ds-mobile-chat-modal.service.ts +105 -0
  41. package/src/components/chat-modal/ds-mobile-chat-modal.ts +918 -0
  42. package/src/components/chat-modal/index.ts +8 -0
  43. package/src/components/comment/ds-mobile-comment.ts +568 -0
  44. package/src/components/comment/index.ts +2 -0
  45. package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +182 -0
  46. package/src/components/contact-list-item/index.ts +2 -0
  47. package/src/components/content/ds-mobile-content.ts +139 -0
  48. package/src/components/content/index.ts +2 -0
  49. package/src/components/dropdown/ds-mobile-dropdown.css +199 -0
  50. package/src/components/dropdown/ds-mobile-dropdown.ts +340 -0
  51. package/src/components/dropdown/index.ts +2 -0
  52. package/src/components/ds-mobile-tabs.css +407 -0
  53. package/src/components/ds-mobile-tabs.ts +216 -0
  54. package/src/components/empty-state/ds-mobile-empty-state.ts +120 -0
  55. package/src/components/empty-state/index.ts +2 -0
  56. package/src/components/fab/ds-mobile-fab.ts +315 -0
  57. package/src/components/fab/index.ts +1 -0
  58. package/src/components/facility-creation-modal/ds-mobile-facility-creation-confirmation-wrapper.ts +121 -0
  59. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.css +189 -0
  60. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.service.ts +135 -0
  61. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.ts +656 -0
  62. package/src/components/facility-creation-modal/index.ts +9 -0
  63. package/src/components/facility-creation-modal/sheets/ds-mobile-access-sheet.ts +105 -0
  64. package/src/components/facility-creation-modal/sheets/ds-mobile-price-sheet.ts +188 -0
  65. package/src/components/facility-creation-modal/sheets/ds-mobile-when-can-book-sheet.ts +460 -0
  66. package/src/components/facility-creation-modal/sheets/ds-mobile-who-can-book-sheet.ts +134 -0
  67. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.service.ts +69 -0
  68. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.ts +379 -0
  69. package/src/components/facility-detail-modal/index.ts +2 -0
  70. package/src/components/file-attachment/ds-mobile-file-attachment.ts +164 -0
  71. package/src/components/file-attachment/index.ts +2 -0
  72. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.css +214 -0
  73. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +84 -0
  74. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +424 -0
  75. package/src/components/handbook-detail-modal/index.ts +3 -0
  76. package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +175 -0
  77. package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +533 -0
  78. package/src/components/handbook-folder/index.ts +4 -0
  79. package/src/components/header-content/ds-mobile-header-content.ts +222 -0
  80. package/src/components/header-content/index.ts +2 -0
  81. package/src/components/illustration/ds-mobile-illustration.ts +124 -0
  82. package/src/components/illustration/index.ts +2 -0
  83. package/src/components/index.ts +124 -0
  84. package/src/components/inline-photo/ds-mobile-inline-photo.ts +361 -0
  85. package/src/components/inline-photo/index.ts +1 -0
  86. package/src/components/inline-tabs/ds-mobile-inline-tabs.ts +132 -0
  87. package/src/components/inline-tabs/index.ts +2 -0
  88. package/src/components/interactive-list-item-booking/ds-mobile-interactive-list-item-booking.ts +350 -0
  89. package/src/components/interactive-list-item-booking/index.ts +1 -0
  90. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +321 -0
  91. package/src/components/interactive-list-item-inquiry/index.ts +2 -0
  92. package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +237 -0
  93. package/src/components/interactive-list-item-message/index.ts +2 -0
  94. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +549 -0
  95. package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +124 -0
  96. package/src/components/interactive-list-item-post/index.ts +13 -0
  97. package/src/components/lightbox/ds-mobile-lightbox-footer.ts +315 -0
  98. package/src/components/lightbox/ds-mobile-lightbox-header.ts +202 -0
  99. package/src/components/lightbox/ds-mobile-lightbox-image.ts +484 -0
  100. package/src/components/lightbox/ds-mobile-lightbox-pdf.css +377 -0
  101. package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +374 -0
  102. package/src/components/lightbox/ds-mobile-lightbox.css +587 -0
  103. package/src/components/lightbox/ds-mobile-lightbox.service.ts +296 -0
  104. package/src/components/lightbox/ds-mobile-lightbox.ts +529 -0
  105. package/src/components/lightbox/index.ts +22 -0
  106. package/src/components/list-item/ds-mobile-list-item.ts +603 -0
  107. package/src/components/list-item/index.ts +2 -0
  108. package/src/components/list-item-static/ds-mobile-list-item-static.ts +133 -0
  109. package/src/components/list-item-static/index.ts +2 -0
  110. package/src/components/loader-overlay/ds-mobile-loader-overlay.css +49 -0
  111. package/src/components/loader-overlay/ds-mobile-loader-overlay.ts +77 -0
  112. package/src/components/loader-overlay/index.ts +1 -0
  113. package/src/components/logo/ds-logo.ts +95 -0
  114. package/src/components/logo/index.ts +2 -0
  115. package/src/components/message-bubble/ds-mobile-message-bubble.ts +633 -0
  116. package/src/components/message-bubble/index.ts +7 -0
  117. package/src/components/message-composer/ds-mobile-message-composer.ts +1146 -0
  118. package/src/components/message-composer/index.ts +7 -0
  119. package/src/components/modal/ds-mobile-modal.css +163 -0
  120. package/src/components/modal/ds-mobile-modal.service.ts +329 -0
  121. package/src/components/modal/index.ts +8 -0
  122. package/src/components/modal-base/ds-mobile-modal-base.css +378 -0
  123. package/src/components/modal-base/ds-mobile-modal-base.ts +261 -0
  124. package/src/components/modal-base/index.ts +2 -0
  125. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.css +112 -0
  126. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.service.ts +93 -0
  127. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.ts +442 -0
  128. package/src/components/new-inquiry-modal/index.ts +4 -0
  129. package/src/components/offline-banner/ds-mobile-offline-banner.ts +135 -0
  130. package/src/components/offline-banner/index.ts +1 -0
  131. package/src/components/page-details/ds-mobile-page-details.css +83 -0
  132. package/src/components/page-details/ds-mobile-page-details.ts +282 -0
  133. package/src/components/page-details/index.ts +2 -0
  134. package/src/components/page-main/ds-mobile-page-main.css +68 -0
  135. package/src/components/page-main/ds-mobile-page-main.ts +421 -0
  136. package/src/components/page-main/index.ts +2 -0
  137. package/src/components/post-composer/ds-mobile-post-composer.ts +140 -0
  138. package/src/components/post-composer/index.ts +2 -0
  139. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.css +390 -0
  140. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +108 -0
  141. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +722 -0
  142. package/src/components/post-detail-modal/index.ts +9 -0
  143. package/src/components/property-banner/ds-mobile-property-banner.ts +95 -0
  144. package/src/components/property-banner/index.ts +2 -0
  145. package/src/components/section/ds-mobile-section.ts +263 -0
  146. package/src/components/section/index.ts +2 -0
  147. package/src/components/shared/directives/index.ts +2 -0
  148. package/src/components/shared/directives/long-press.directive.ts +212 -0
  149. package/src/components/shared/index.ts +3 -0
  150. package/src/components/shared/mobile-modal-base.ts +457 -0
  151. package/src/components/shared/mobile-page-base.ts +204 -0
  152. package/src/components/swiper/ds-mobile-swiper-with-nav.ts +160 -0
  153. package/src/components/swiper/ds-mobile-swiper.ts +327 -0
  154. package/src/components/swiper/index.ts +3 -0
  155. package/src/components/system-message-banner/ds-mobile-system-message-banner.ts +129 -0
  156. package/src/components/system-message-banner/index.ts +2 -0
  157. package/src/components/tab-bar/ds-mobile-tab-bar.css +533 -0
  158. package/src/components/tab-bar/ds-mobile-tab-bar.ts +735 -0
  159. package/src/components/tab-bar/index.ts +2 -0
  160. package/src/components/tabs/ds-mobile-tabs.css +25 -0
  161. package/src/components/tabs/ds-mobile-tabs.ts +89 -0
  162. package/src/components/tabs/index.ts +2 -0
  163. package/src/components/text-input/ds-text-input.ts +287 -0
  164. package/src/components/text-input/index.ts +2 -0
  165. package/src/examples/booking.page.ts +434 -0
  166. package/src/examples/community.page.ts +776 -0
  167. package/src/examples/handbook.page.ts +324 -0
  168. package/src/examples/home.page.ts +347 -0
  169. package/src/examples/index.ts +12 -0
  170. package/src/examples/inquiries.example.ts +273 -0
  171. package/src/examples/inquiry-detail.example.css +189 -0
  172. package/src/examples/inquiry-detail.example.ts +415 -0
  173. package/src/examples/mobile-tabs-example.component.ts +208 -0
  174. package/src/examples/post-create.page.ts +311 -0
  175. package/src/examples/post-detail.page.ts +296 -0
  176. package/src/examples/sign-in.page.ts +291 -0
  177. package/src/examples/whitelabel-demo-modal.component.ts +1094 -0
  178. package/src/examples/whitelabel-demo-modal.service.ts +77 -0
  179. package/src/models/index.ts +7 -0
  180. package/src/models/post.model.ts +41 -0
  181. package/src/pages/community.page.ts +769 -0
  182. package/src/pages/handbook.page.ts +388 -0
  183. package/src/pages/home.page.ts +303 -0
  184. package/src/pages/index.ts +11 -0
  185. package/src/pages/inquiries.example.ts +273 -0
  186. package/src/pages/inquiry-detail.example.css +189 -0
  187. package/src/pages/inquiry-detail.example.ts +415 -0
  188. package/src/pages/mobile-tabs-example.component.ts +179 -0
  189. package/src/pages/post-create.page.ts +311 -0
  190. package/src/pages/post-detail.page.ts +296 -0
  191. package/src/pages/sign-in.page.ts +291 -0
  192. package/src/pages/whitelabel-demo-modal.component.ts +1094 -0
  193. package/src/pages/whitelabel-demo-modal.service.ts +77 -0
  194. package/src/public-api.ts +6 -0
  195. package/src/services/base-modal.service.ts +101 -0
  196. package/src/services/index.ts +11 -0
  197. package/src/services/posts.service.ts +542 -0
  198. package/src/services/tracking-permission.service.ts +88 -0
  199. package/src/services/user.service.ts +60 -0
  200. package/src/services/whitelabel.service.ts +675 -0
  201. package/{styles → src/styles}/ionic.css +25 -0
  202. package/tsconfig.lib.json +17 -0
  203. package/tsconfig.lib.prod.json +9 -0
  204. package/tsconfig.spec.json +13 -0
  205. package/fesm2022/propbinder-mobile-design.mjs +0 -26136
  206. package/fesm2022/propbinder-mobile-design.mjs.map +0 -1
  207. package/index.d.ts +0 -8154
  208. /package/{assets → src/assets}/fonts/Brockmann-Bold.otf +0 -0
  209. /package/{assets → src/assets}/fonts/Brockmann-BoldItalic.otf +0 -0
  210. /package/{assets → src/assets}/fonts/Brockmann-Medium.otf +0 -0
  211. /package/{assets → src/assets}/fonts/Brockmann-MediumItalic.otf +0 -0
  212. /package/{assets → src/assets}/fonts/Brockmann-Regular.otf +0 -0
  213. /package/{assets → src/assets}/fonts/Brockmann-RegularItalic.otf +0 -0
  214. /package/{assets → src/assets}/fonts/Brockmann-SemiBold.otf +0 -0
  215. /package/{assets → src/assets}/fonts/Brockmann-SemiBoldItalic.otf +0 -0
  216. /package/{assets → src/assets}/fonts/Brockmann_desktop_license.pdf +0 -0
  217. /package/{assets → src/assets}/fonts/brockmann-medium-webfont.woff2 +0 -0
  218. /package/{assets → src/assets}/fonts/brockmann-regular-webfont.woff2 +0 -0
  219. /package/{assets → src/assets}/fonts/brockmann-semibold-webfont.woff2 +0 -0
  220. /package/{styles → src/components/shared}/mobile-common.css +0 -0
  221. /package/{styles → src/components/shared}/mobile-page-base.css +0 -0
@@ -0,0 +1,549 @@
1
+ import { Component, input, output, signal, model } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { DsIconComponent } from '@propbinder/design-system';
4
+ import { Haptics, ImpactStyle } from '@capacitor/haptics';
5
+ import { DsMobileListItemComponent } from '../list-item';
6
+ import { DsAvatarWithBadgeComponent } from '../avatar-with-badge/ds-avatar-with-badge';
7
+
8
+ /**
9
+ * DsMobileInteractiveListItemPostComponent
10
+ *
11
+ * Specialized interactive list item for displaying social media posts.
12
+ * Built on top of ds-mobile-interactive-list-item base component.
13
+ * Displays user posts with avatar, content, media, and action buttons.
14
+ * Follows Threads-inspired design with clean layout and interactions.
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <ds-mobile-interactive-list-item-post
19
+ * [authorName]="'John Doe'"
20
+ * [authorRole]="'Tenant'"
21
+ * [timestamp]="'2h ago'"
22
+ * [avatarInitials]="'JD'"
23
+ * [clickable]="true"
24
+ * [enableLongPress]="true"
25
+ * (postClick)="openPost()">
26
+ *
27
+ * <post-content>
28
+ * <post-text>This is a sample post...</post-text>
29
+ * </post-content>
30
+ *
31
+ * <post-actions>
32
+ * <action-like [active]="true" count="42" />
33
+ * <action-comment count="12" />
34
+ * </post-actions>
35
+ * </ds-mobile-interactive-list-item-post>
36
+ * ```
37
+ */
38
+ @Component({
39
+ selector: 'ds-mobile-interactive-list-item-post',
40
+ standalone: true,
41
+ imports: [CommonModule, DsAvatarWithBadgeComponent, DsMobileListItemComponent],
42
+ styles: [`
43
+ :host {
44
+ display: block;
45
+ }
46
+
47
+ /* Hide divider on last child */
48
+ :host:last-child {
49
+ --divider-display: none;
50
+ --item-padding-bottom: 0;
51
+ }
52
+
53
+ .post-header {
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: space-between;
57
+ height: 32px;
58
+ margin-bottom: 8px;
59
+ }
60
+
61
+ .menu-slot {
62
+ flex-shrink: 0;
63
+ }
64
+ `],
65
+ template: `
66
+ <ds-mobile-list-item
67
+ [leadingSize]="'32px'"
68
+ [align]="align()"
69
+ [variant]="variant()"
70
+ [interactive]="clickable()"
71
+ [enableLongPress]="enableLongPress()"
72
+ [moreActions]="moreActions()"
73
+ (itemClick)="handlePostClick()"
74
+ (longPress)="handleLongPress()"
75
+ (moreButtonClick)="handleMoreButtonClick($event)">
76
+
77
+ <div content-leading>
78
+ <ds-avatar-with-badge
79
+ [type]="avatarType()"
80
+ [initials]="avatarInitials()"
81
+ [src]="avatarSrc()"
82
+ [iconName]="avatarIconName()"
83
+ [size]="'md'"
84
+ [showBadge]="showBadge()"
85
+ [badgePosition]="'bottom-right'"
86
+ />
87
+ </div>
88
+
89
+ <div content-main>
90
+ <div class="post-header">
91
+ <div class="author-details">
92
+ <div class="author-name">{{ authorName() }}</div>
93
+ <div class="author-meta">{{ authorRole() }} · {{ timestamp() }}</div>
94
+ </div>
95
+
96
+ <div class="menu-slot">
97
+ <ng-content select="post-menu" />
98
+ </div>
99
+ </div>
100
+
101
+ <ng-content select="post-content" />
102
+ <ng-content select="post-actions" />
103
+ </div>
104
+ </ds-mobile-list-item>
105
+ `
106
+ })
107
+ export class DsMobileInteractiveListItemPostComponent {
108
+ /**
109
+ * Author's display name
110
+ */
111
+ authorName = input.required<string>();
112
+
113
+ /**
114
+ * Author's role (e.g., "Tenant", "Property Manager")
115
+ */
116
+ authorRole = input.required<string>();
117
+
118
+ /**
119
+ * Timestamp text (e.g., "2h ago", "1d ago")
120
+ */
121
+ timestamp = input.required<string>();
122
+
123
+ /**
124
+ * Avatar initials (for initials type)
125
+ */
126
+ avatarInitials = input<string>('');
127
+
128
+ /**
129
+ * Avatar type
130
+ */
131
+ avatarType = input<'initials' | 'photo' | 'icon'>('initials');
132
+
133
+ /**
134
+ * Avatar photo source (for photo type)
135
+ */
136
+ avatarSrc = input<string>('');
137
+
138
+ /**
139
+ * Icon name (for icon type avatars)
140
+ */
141
+ avatarIconName = input<string>('remixUser3Fill');
142
+
143
+ /**
144
+ * Show badge on avatar (e.g., for property managers)
145
+ */
146
+ showBadge = input<boolean>(false);
147
+
148
+ /**
149
+ * Display variant
150
+ * - undefined (default) - Standard display
151
+ * - 'compact' - Compact display for nested/related posts
152
+ */
153
+ variant = input<'compact' | undefined>(undefined);
154
+
155
+ /**
156
+ * Vertical alignment of content
157
+ * - 'top' - Align to top (default)
158
+ * - 'center' - Align to center
159
+ * - 'bottom' - Align to bottom
160
+ */
161
+ align = input<'top' | 'center' | 'bottom'>('top');
162
+
163
+ /**
164
+ * Whether the post card is clickable
165
+ */
166
+ clickable = input<boolean>(false);
167
+
168
+ /**
169
+ * Enable long-press interaction when clickable is true
170
+ * Set to false to disable long-press but keep click
171
+ * Also controls visibility of desktop "more" button
172
+ * @default true
173
+ */
174
+ enableLongPress = input<boolean>(true);
175
+
176
+ /**
177
+ * Unified toggle for contextual actions (more button + long press).
178
+ * When set, takes precedence over `enableLongPress`.
179
+ */
180
+ moreActions = input<boolean | undefined>(undefined);
181
+
182
+ /**
183
+ * Emits when the post card is clicked (if clickable)
184
+ */
185
+ postClick = output<void>();
186
+
187
+ /**
188
+ * Emits when the comment button is clicked
189
+ */
190
+ commentClick = output<void>();
191
+
192
+ /**
193
+ * Emits when the post card is long-pressed
194
+ */
195
+ longPress = output<void>();
196
+
197
+ handlePostClick(): void {
198
+ console.log('[InteractiveListItemPost] handlePostClick called, emitting postClick');
199
+ this.postClick.emit();
200
+ }
201
+
202
+ handleCommentClick(): void {
203
+ this.commentClick.emit();
204
+ }
205
+
206
+ handleLongPress(): void {
207
+ this.longPress.emit();
208
+ }
209
+
210
+ handleMoreButtonClick(event: Event): void {
211
+ // Desktop more button click - trigger the same action as long press
212
+ this.longPress.emit();
213
+ }
214
+ }
215
+
216
+ /**
217
+ * PostContentComponent
218
+ *
219
+ * Main content section of the post.
220
+ *
221
+ * Contains:
222
+ * - `<post-text>` - Text content
223
+ * - `<post-media>` - Optional images/videos
224
+ * - `<post-attachments>` - Optional file attachments
225
+ */
226
+ @Component({
227
+ selector: 'post-content',
228
+ standalone: true,
229
+ styles: [`
230
+ :host {
231
+ display: flex;
232
+ flex-direction: column;
233
+ gap: 12px;
234
+ margin-bottom: 8px;
235
+ }
236
+ `],
237
+ template: `
238
+ <ng-content select="post-text" />
239
+ <ng-content select="post-media" />
240
+ <ng-content select="ds-mobile-inline-photo" />
241
+ <ng-content select="post-attachments" />
242
+ `
243
+ })
244
+ export class PostContentComponent {}
245
+
246
+ /**
247
+ * PostTextComponent
248
+ *
249
+ * Text content of the post.
250
+ */
251
+ @Component({
252
+ selector: 'post-text',
253
+ standalone: true,
254
+ styles: [`
255
+ :host {
256
+ font-family: 'Brockmann', sans-serif;
257
+ font-size: var(--font-size-sm);
258
+ font-weight: 400;
259
+ line-height: 22px;
260
+ letter-spacing: -0.3px;
261
+ color: var(--color-text-primary, #1a1a1a);
262
+ display: block;
263
+ white-space: pre-wrap;
264
+ word-wrap: break-word;
265
+ }
266
+ `],
267
+ template: `<ng-content />`
268
+ })
269
+ export class PostTextComponent {}
270
+
271
+ /**
272
+ * PostMediaComponent
273
+ *
274
+ * Media container for images/videos.
275
+ */
276
+ @Component({
277
+ selector: 'post-media',
278
+ standalone: true,
279
+ styles: [`
280
+ :host {
281
+ display: block;
282
+ border-radius: 8px;
283
+ overflow: hidden;
284
+ }
285
+
286
+ ::ng-deep img {
287
+ width: 100%;
288
+ height: auto;
289
+ display: block;
290
+ }
291
+
292
+ ::ng-deep video {
293
+ width: 100%;
294
+ height: auto;
295
+ display: block;
296
+ }
297
+ `],
298
+ template: `<ng-content />`
299
+ })
300
+ export class PostMediaComponent {}
301
+
302
+ /**
303
+ * PostAttachmentsComponent
304
+ *
305
+ * Container for file attachments, links, etc.
306
+ */
307
+ @Component({
308
+ selector: 'post-attachments',
309
+ standalone: true,
310
+ styles: [`
311
+ :host {
312
+ display: flex;
313
+ flex-direction: column;
314
+ gap: 8px;
315
+ }
316
+ `],
317
+ template: `<ng-content />`
318
+ })
319
+ export class PostAttachmentsComponent {}
320
+
321
+ /**
322
+ * PostActionsComponent
323
+ *
324
+ * Action buttons container (like, comment, share).
325
+ *
326
+ * Contains:
327
+ * - `<action-like>` - Like button with count
328
+ * - `<action-comment>` - Comment button with count
329
+ * - `<action-share>` - Share button
330
+ */
331
+ @Component({
332
+ selector: 'post-actions',
333
+ standalone: true,
334
+ styles: [`
335
+ :host {
336
+ display: flex;
337
+ align-items: center;
338
+ gap: 16px;
339
+ padding-top: 4px;
340
+ }
341
+ `],
342
+ template: `<ng-content />`
343
+ })
344
+ export class PostActionsComponent {}
345
+
346
+ /**
347
+ * ActionLikeComponent
348
+ *
349
+ * Like action button with count display and animated heart icon.
350
+ */
351
+ @Component({
352
+ selector: 'action-like',
353
+ standalone: true,
354
+ imports: [CommonModule, DsIconComponent],
355
+ host: {
356
+ '[class.active]': 'active()',
357
+ '(click)': 'handleClick($event)'
358
+ },
359
+ styles: [`
360
+ :host {
361
+ display: flex;
362
+ align-items: center;
363
+ gap: 2px;
364
+ color: var(--color-text-secondary, #737373);
365
+ cursor: pointer;
366
+ transition: color 0.2s ease;
367
+ user-select: none;
368
+ -webkit-tap-highlight-color: transparent;
369
+ }
370
+
371
+ :host.active {
372
+ color: #f91880;
373
+ }
374
+
375
+ .icon-wrapper {
376
+ position: relative;
377
+ display: flex;
378
+ align-items: center;
379
+ justify-content: center;
380
+ }
381
+
382
+ .icon-pulse {
383
+ position: absolute;
384
+ top: 50%;
385
+ left: 50%;
386
+ transform: translate(-50%, -50%);
387
+ opacity: 0;
388
+ pointer-events: none;
389
+ }
390
+
391
+ .icon-pulse.animating {
392
+ animation: pulse 0.4s cubic-bezier(0.4, 0, 0.2, 1);
393
+ }
394
+
395
+ @keyframes pulse {
396
+ 0% {
397
+ transform: translate(-50%, -50%) scale(1);
398
+ opacity: 0.8;
399
+ }
400
+ 100% {
401
+ transform: translate(-50%, -50%) scale(2.5);
402
+ opacity: 0;
403
+ }
404
+ }
405
+
406
+ .count {
407
+ font-family: 'Brockmann', sans-serif;
408
+ font-size: var(--font-size-xs);
409
+ font-weight: 500;
410
+ line-height: 20px;
411
+ letter-spacing: -0.28px;
412
+ }
413
+ `],
414
+ template: `
415
+ <div class="icon-wrapper">
416
+ <ds-icon
417
+ #pulseIcon
418
+ class="icon-pulse"
419
+ [class.animating]="isPulsing()"
420
+ [name]="active() ? 'remixHeart3Fill' : 'remixHeart3Line'"
421
+ size="20px" />
422
+ <ds-icon
423
+ [name]="active() ? 'remixHeart3Fill' : 'remixHeart3Line'"
424
+ size="20px" />
425
+ </div>
426
+ @if (count() > 0) {
427
+ <span class="count">{{ count() }}</span>
428
+ }
429
+ `
430
+ })
431
+ export class ActionLikeComponent {
432
+ /**
433
+ * Whether the like is active (user has liked)
434
+ * Using model() for two-way binding
435
+ */
436
+ active = model<boolean>(false);
437
+
438
+ /**
439
+ * Number of likes
440
+ * Using model() for two-way binding
441
+ */
442
+ count = model<number>(0);
443
+
444
+ /**
445
+ * Emits when the like button is clicked
446
+ */
447
+ likeClick = output<{ active: boolean; count: number }>();
448
+
449
+ /**
450
+ * Signal to control pulse animation
451
+ */
452
+ isPulsing = signal(false);
453
+
454
+ async handleClick(event: Event): Promise<void> {
455
+ event.stopPropagation();
456
+
457
+ // Toggle active state
458
+ const newActive = !this.active();
459
+ this.active.set(newActive);
460
+
461
+ // Update count
462
+ const newCount = newActive ? this.count() + 1 : this.count() - 1;
463
+ this.count.set(Math.max(0, newCount));
464
+
465
+ // Trigger pulse animation only when liking
466
+ if (newActive) {
467
+ this.isPulsing.set(true);
468
+ setTimeout(() => this.isPulsing.set(false), 400);
469
+ }
470
+
471
+ // Haptic feedback for like/unlike
472
+ try {
473
+ await Haptics.impact({ style: ImpactStyle.Light });
474
+ } catch {
475
+ // Fallback to Web Vibration API if Capacitor Haptics is not available
476
+ if ('vibrate' in navigator) {
477
+ navigator.vibrate(50);
478
+ }
479
+ }
480
+
481
+ // Emit the event with the new state
482
+ this.likeClick.emit({ active: newActive, count: newCount });
483
+ }
484
+ }
485
+
486
+ /**
487
+ * ActionCommentComponent
488
+ *
489
+ * Comment action button with count display.
490
+ */
491
+ @Component({
492
+ selector: 'action-comment',
493
+ standalone: true,
494
+ imports: [CommonModule, DsIconComponent],
495
+ host: {
496
+ '(click)': 'handleClick($event)'
497
+ },
498
+ styles: [`
499
+ :host {
500
+ display: flex;
501
+ align-items: center;
502
+ gap: 2px;
503
+ color: var(--color-text-secondary, #737373);
504
+ cursor: pointer;
505
+ transition: color 0.2s ease;
506
+ user-select: none;
507
+ -webkit-tap-highlight-color: transparent;
508
+ }
509
+
510
+ :host:active {
511
+ transform: scale(0.95);
512
+ }
513
+
514
+ :host:hover {
515
+ color: var(--color-text-primary, #1a1a1a);
516
+ }
517
+
518
+ .count {
519
+ font-family: 'Brockmann', sans-serif;
520
+ font-size: var(--font-size-xs);
521
+ font-weight: 500;
522
+ line-height: 20px;
523
+ letter-spacing: -0.28px;
524
+ }
525
+ `],
526
+ template: `
527
+ <ds-icon name="remixChat3Line" size="20px" />
528
+ @if (count() > 0) {
529
+ <span class="count">{{ count() }}</span>
530
+ }
531
+ `
532
+ })
533
+ export class ActionCommentComponent {
534
+ /**
535
+ * Number of comments
536
+ */
537
+ count = input<number>(0);
538
+
539
+ /**
540
+ * Emits when the comment button is clicked
541
+ */
542
+ commentClick = output<void>();
543
+
544
+ handleClick(event: Event): void {
545
+ event.stopPropagation();
546
+ this.commentClick.emit();
547
+ }
548
+ }
549
+
@@ -0,0 +1,124 @@
1
+ import { Component, input, output } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { DsAvatarComponent } from '@propbinder/design-system';
4
+ import { DsIconComponent } from '@propbinder/design-system';
5
+
6
+ /**
7
+ * PostPdfAttachmentComponent
8
+ *
9
+ * PDF file attachment display for posts.
10
+ * Shows PDF info card with icon, filename, and file size.
11
+ * Emits click event to open PDF in viewer.
12
+ */
13
+ @Component({
14
+ selector: 'post-pdf-attachment',
15
+ standalone: true,
16
+ imports: [CommonModule, DsAvatarComponent, DsIconComponent],
17
+ host: {
18
+ '(click)': 'handleClick($event)'
19
+ },
20
+ styles: [`
21
+ :host {
22
+ display: flex;
23
+ align-items: center;
24
+ gap: 8px;
25
+ padding: 10px 12px;
26
+ background: var(--color-background-neutral-secondary, #f5f5f5);
27
+ border-radius: 16px;
28
+ cursor: pointer;
29
+ transition: all 0.2s ease;
30
+ }
31
+
32
+ :host:hover {
33
+ background: var(--color-background-neutral-secondary-hover, #ebebeb);
34
+ }
35
+
36
+ :host:active {
37
+ transform: scale(0.98);
38
+ }
39
+
40
+ .pdf-avatar {
41
+ flex-shrink: 0;
42
+ }
43
+
44
+ .pdf-avatar::ng-deep .avatar--icon {
45
+ background-color: #ff5757 !important;
46
+ }
47
+
48
+ .pdf-info {
49
+ flex: 1;
50
+ min-width: 0;
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: 2px;
54
+ }
55
+
56
+ .pdf-name {
57
+ font-family: 'Brockmann', sans-serif;
58
+ font-size: var(--font-size-sm);
59
+ font-weight: 600;
60
+ line-height: 20px;
61
+ letter-spacing: -0.3px;
62
+ color: var(--color-text-primary, #1a1a1a);
63
+ white-space: nowrap;
64
+ overflow: hidden;
65
+ text-overflow: ellipsis;
66
+ }
67
+
68
+ .pdf-meta {
69
+ font-family: 'Brockmann', sans-serif;
70
+ font-size: var(--font-size-xs);
71
+ font-weight: 400;
72
+ line-height: 1.2;
73
+ letter-spacing: -0.26px;
74
+ color: var(--color-text-tertiary, #737373);
75
+ }
76
+
77
+ .open-icon {
78
+ color: var(--color-text-tertiary, #a3a3a3);
79
+ flex-shrink: 0;
80
+ }
81
+ `],
82
+ template: `
83
+ <div class="pdf-avatar">
84
+ <ds-avatar
85
+ type="icon"
86
+ iconName="remixFileTextLine"
87
+ size="md"
88
+ />
89
+ </div>
90
+
91
+ <div class="pdf-info">
92
+ <div class="pdf-name">{{ fileName() }}</div>
93
+ <div class="pdf-meta">PDF · {{ fileSize() }}</div>
94
+ </div>
95
+
96
+ <ds-icon
97
+ name="remixArrowRightSLine"
98
+ size="24px"
99
+ class="open-icon"
100
+ />
101
+ `
102
+ })
103
+ export class PostPdfAttachmentComponent {
104
+ /**
105
+ * PDF file name
106
+ */
107
+ fileName = input<string>('Document.pdf');
108
+
109
+ /**
110
+ * File size display (e.g., "1.2 MB")
111
+ */
112
+ fileSize = input<string>('');
113
+
114
+ /**
115
+ * Emits when the PDF attachment is clicked
116
+ */
117
+ pdfClick = output<void>();
118
+
119
+ handleClick(event: Event): void {
120
+ event.stopPropagation();
121
+ this.pdfClick.emit();
122
+ }
123
+ }
124
+
@@ -0,0 +1,13 @@
1
+ // Export the main component and shared post components without the indent
2
+ export {
3
+ DsMobileInteractiveListItemPostComponent,
4
+ PostContentComponent,
5
+ PostTextComponent,
6
+ PostMediaComponent,
7
+ PostAttachmentsComponent,
8
+ PostActionsComponent,
9
+ ActionLikeComponent,
10
+ ActionCommentComponent
11
+ } from './ds-mobile-interactive-list-item-post';
12
+ export { PostPdfAttachmentComponent } from './ds-mobile-post-pdf-attachment';
13
+