@propbinder/mobile-design 0.2.50 → 0.2.52

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/fesm2022/propbinder-mobile-design.mjs +26206 -0
  2. package/fesm2022/propbinder-mobile-design.mjs.map +1 -0
  3. package/index.d.ts +8193 -0
  4. package/package.json +39 -3
  5. package/ng-package.json +0 -24
  6. package/src/animations/page-transitions.ts +0 -165
  7. package/src/components/action-list-item/ds-mobile-action-list-item.ts +0 -102
  8. package/src/components/action-list-item/index.ts +0 -2
  9. package/src/components/app-icon/ds-app-icon.ts +0 -133
  10. package/src/components/app-icon/index.ts +0 -2
  11. package/src/components/attachment-preview/ds-mobile-attachment-preview.css +0 -139
  12. package/src/components/attachment-preview/ds-mobile-attachment-preview.ts +0 -164
  13. package/src/components/attachment-preview/index.ts +0 -1
  14. package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +0 -142
  15. package/src/components/avatar-with-badge/index.ts +0 -2
  16. package/src/components/booking-modal/ds-mobile-booking-confirmation-wrapper.ts +0 -71
  17. package/src/components/booking-modal/ds-mobile-booking-modal.service.ts +0 -121
  18. package/src/components/booking-modal/ds-mobile-booking-modal.ts +0 -598
  19. package/src/components/booking-modal/ds-mobile-booking-summary.ts +0 -161
  20. package/src/components/booking-modal/index.ts +0 -4
  21. package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +0 -266
  22. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-header.ts +0 -146
  23. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-wrapper.ts +0 -156
  24. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +0 -101
  25. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +0 -169
  26. package/src/components/bottom-sheet/ds-mobile-confirmation-sheet.ts +0 -211
  27. package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +0 -578
  28. package/src/components/bottom-sheet/ds-mobile-profile-actions-sheet.ts +0 -614
  29. package/src/components/bottom-sheet/index.ts +0 -8
  30. package/src/components/bottom-sheet/modal-shadow-fix.ts +0 -42
  31. package/src/components/card-inline/ds-mobile-card-inline.ts +0 -301
  32. package/src/components/card-inline/index.ts +0 -2
  33. package/src/components/card-inline-banner/ds-mobile-card-inline-banner.ts +0 -118
  34. package/src/components/card-inline-banner/index.ts +0 -1
  35. package/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts +0 -120
  36. package/src/components/card-inline-contact/index.ts +0 -1
  37. package/src/components/card-inline-file/ds-mobile-card-inline-file.ts +0 -141
  38. package/src/components/card-inline-file/index.ts +0 -1
  39. package/src/components/chat-modal/ds-mobile-chat-modal.css +0 -159
  40. package/src/components/chat-modal/ds-mobile-chat-modal.service.ts +0 -105
  41. package/src/components/chat-modal/ds-mobile-chat-modal.ts +0 -918
  42. package/src/components/chat-modal/index.ts +0 -8
  43. package/src/components/comment/ds-mobile-comment.ts +0 -568
  44. package/src/components/comment/index.ts +0 -2
  45. package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +0 -182
  46. package/src/components/contact-list-item/index.ts +0 -2
  47. package/src/components/content/ds-mobile-content.ts +0 -139
  48. package/src/components/content/index.ts +0 -2
  49. package/src/components/dropdown/ds-mobile-dropdown.css +0 -199
  50. package/src/components/dropdown/ds-mobile-dropdown.ts +0 -340
  51. package/src/components/dropdown/index.ts +0 -2
  52. package/src/components/ds-mobile-tabs.css +0 -407
  53. package/src/components/ds-mobile-tabs.ts +0 -216
  54. package/src/components/empty-state/ds-mobile-empty-state.ts +0 -120
  55. package/src/components/empty-state/index.ts +0 -2
  56. package/src/components/fab/ds-mobile-fab.ts +0 -315
  57. package/src/components/fab/index.ts +0 -1
  58. package/src/components/facility-creation-modal/ds-mobile-facility-creation-confirmation-wrapper.ts +0 -121
  59. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.css +0 -189
  60. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.service.ts +0 -135
  61. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.ts +0 -656
  62. package/src/components/facility-creation-modal/index.ts +0 -9
  63. package/src/components/facility-creation-modal/sheets/ds-mobile-access-sheet.ts +0 -105
  64. package/src/components/facility-creation-modal/sheets/ds-mobile-price-sheet.ts +0 -188
  65. package/src/components/facility-creation-modal/sheets/ds-mobile-when-can-book-sheet.ts +0 -460
  66. package/src/components/facility-creation-modal/sheets/ds-mobile-who-can-book-sheet.ts +0 -134
  67. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.service.ts +0 -69
  68. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.ts +0 -379
  69. package/src/components/facility-detail-modal/index.ts +0 -2
  70. package/src/components/file-attachment/ds-mobile-file-attachment.ts +0 -164
  71. package/src/components/file-attachment/index.ts +0 -2
  72. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.css +0 -214
  73. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +0 -84
  74. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +0 -424
  75. package/src/components/handbook-detail-modal/index.ts +0 -3
  76. package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +0 -175
  77. package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +0 -533
  78. package/src/components/handbook-folder/index.ts +0 -4
  79. package/src/components/header-content/ds-mobile-header-content.ts +0 -222
  80. package/src/components/header-content/index.ts +0 -2
  81. package/src/components/illustration/ds-mobile-illustration.ts +0 -124
  82. package/src/components/illustration/index.ts +0 -2
  83. package/src/components/index.ts +0 -124
  84. package/src/components/inline-photo/ds-mobile-inline-photo.ts +0 -361
  85. package/src/components/inline-photo/index.ts +0 -1
  86. package/src/components/inline-tabs/ds-mobile-inline-tabs.ts +0 -132
  87. package/src/components/inline-tabs/index.ts +0 -2
  88. package/src/components/interactive-list-item-booking/ds-mobile-interactive-list-item-booking.ts +0 -350
  89. package/src/components/interactive-list-item-booking/index.ts +0 -1
  90. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +0 -321
  91. package/src/components/interactive-list-item-inquiry/index.ts +0 -2
  92. package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +0 -237
  93. package/src/components/interactive-list-item-message/index.ts +0 -2
  94. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +0 -549
  95. package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +0 -124
  96. package/src/components/interactive-list-item-post/index.ts +0 -13
  97. package/src/components/lightbox/ds-mobile-lightbox-footer.ts +0 -315
  98. package/src/components/lightbox/ds-mobile-lightbox-header.ts +0 -202
  99. package/src/components/lightbox/ds-mobile-lightbox-image.ts +0 -484
  100. package/src/components/lightbox/ds-mobile-lightbox-pdf.css +0 -377
  101. package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +0 -374
  102. package/src/components/lightbox/ds-mobile-lightbox.css +0 -587
  103. package/src/components/lightbox/ds-mobile-lightbox.service.ts +0 -296
  104. package/src/components/lightbox/ds-mobile-lightbox.ts +0 -529
  105. package/src/components/lightbox/index.ts +0 -22
  106. package/src/components/list-item/ds-mobile-list-item.ts +0 -603
  107. package/src/components/list-item/index.ts +0 -2
  108. package/src/components/list-item-static/ds-mobile-list-item-static.ts +0 -133
  109. package/src/components/list-item-static/index.ts +0 -2
  110. package/src/components/loader-overlay/ds-mobile-loader-overlay.css +0 -49
  111. package/src/components/loader-overlay/ds-mobile-loader-overlay.ts +0 -77
  112. package/src/components/loader-overlay/index.ts +0 -1
  113. package/src/components/logo/ds-logo.ts +0 -95
  114. package/src/components/logo/index.ts +0 -2
  115. package/src/components/message-bubble/ds-mobile-message-bubble.ts +0 -633
  116. package/src/components/message-bubble/index.ts +0 -7
  117. package/src/components/message-composer/ds-mobile-message-composer.ts +0 -1146
  118. package/src/components/message-composer/index.ts +0 -7
  119. package/src/components/modal/ds-mobile-modal.css +0 -163
  120. package/src/components/modal/ds-mobile-modal.service.ts +0 -329
  121. package/src/components/modal/index.ts +0 -8
  122. package/src/components/modal-base/ds-mobile-modal-base.css +0 -378
  123. package/src/components/modal-base/ds-mobile-modal-base.ts +0 -261
  124. package/src/components/modal-base/index.ts +0 -2
  125. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.css +0 -112
  126. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.service.ts +0 -93
  127. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.ts +0 -442
  128. package/src/components/new-inquiry-modal/index.ts +0 -4
  129. package/src/components/offline-banner/ds-mobile-offline-banner.ts +0 -135
  130. package/src/components/offline-banner/index.ts +0 -1
  131. package/src/components/page-details/ds-mobile-page-details.css +0 -83
  132. package/src/components/page-details/ds-mobile-page-details.ts +0 -282
  133. package/src/components/page-details/index.ts +0 -2
  134. package/src/components/page-main/ds-mobile-page-main.css +0 -68
  135. package/src/components/page-main/ds-mobile-page-main.ts +0 -421
  136. package/src/components/page-main/index.ts +0 -2
  137. package/src/components/post-composer/ds-mobile-post-composer.ts +0 -140
  138. package/src/components/post-composer/index.ts +0 -2
  139. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.css +0 -390
  140. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +0 -108
  141. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +0 -722
  142. package/src/components/post-detail-modal/index.ts +0 -9
  143. package/src/components/property-banner/ds-mobile-property-banner.ts +0 -95
  144. package/src/components/property-banner/index.ts +0 -2
  145. package/src/components/section/ds-mobile-section.ts +0 -263
  146. package/src/components/section/index.ts +0 -2
  147. package/src/components/shared/directives/index.ts +0 -2
  148. package/src/components/shared/directives/long-press.directive.ts +0 -212
  149. package/src/components/shared/index.ts +0 -3
  150. package/src/components/shared/mobile-modal-base.ts +0 -457
  151. package/src/components/shared/mobile-page-base.ts +0 -204
  152. package/src/components/swiper/ds-mobile-swiper-with-nav.ts +0 -160
  153. package/src/components/swiper/ds-mobile-swiper.ts +0 -327
  154. package/src/components/swiper/index.ts +0 -3
  155. package/src/components/system-message-banner/ds-mobile-system-message-banner.ts +0 -129
  156. package/src/components/system-message-banner/index.ts +0 -2
  157. package/src/components/tab-bar/ds-mobile-tab-bar.css +0 -533
  158. package/src/components/tab-bar/ds-mobile-tab-bar.ts +0 -735
  159. package/src/components/tab-bar/index.ts +0 -2
  160. package/src/components/tabs/ds-mobile-tabs.css +0 -25
  161. package/src/components/tabs/ds-mobile-tabs.ts +0 -89
  162. package/src/components/tabs/index.ts +0 -2
  163. package/src/components/text-input/ds-text-input.ts +0 -287
  164. package/src/components/text-input/index.ts +0 -2
  165. package/src/examples/booking.page.ts +0 -434
  166. package/src/examples/community.page.ts +0 -776
  167. package/src/examples/handbook.page.ts +0 -324
  168. package/src/examples/home.page.ts +0 -347
  169. package/src/examples/index.ts +0 -12
  170. package/src/examples/inquiries.example.ts +0 -273
  171. package/src/examples/inquiry-detail.example.css +0 -189
  172. package/src/examples/inquiry-detail.example.ts +0 -415
  173. package/src/examples/mobile-tabs-example.component.ts +0 -208
  174. package/src/examples/post-create.page.ts +0 -311
  175. package/src/examples/post-detail.page.ts +0 -296
  176. package/src/examples/sign-in.page.ts +0 -291
  177. package/src/examples/whitelabel-demo-modal.component.ts +0 -1094
  178. package/src/examples/whitelabel-demo-modal.service.ts +0 -77
  179. package/src/models/index.ts +0 -7
  180. package/src/models/post.model.ts +0 -41
  181. package/src/pages/community.page.ts +0 -769
  182. package/src/pages/handbook.page.ts +0 -388
  183. package/src/pages/home.page.ts +0 -303
  184. package/src/pages/index.ts +0 -11
  185. package/src/pages/inquiries.example.ts +0 -273
  186. package/src/pages/inquiry-detail.example.css +0 -189
  187. package/src/pages/inquiry-detail.example.ts +0 -415
  188. package/src/pages/mobile-tabs-example.component.ts +0 -179
  189. package/src/pages/post-create.page.ts +0 -311
  190. package/src/pages/post-detail.page.ts +0 -296
  191. package/src/pages/sign-in.page.ts +0 -291
  192. package/src/pages/whitelabel-demo-modal.component.ts +0 -1094
  193. package/src/pages/whitelabel-demo-modal.service.ts +0 -77
  194. package/src/public-api.ts +0 -6
  195. package/src/services/base-modal.service.ts +0 -101
  196. package/src/services/index.ts +0 -11
  197. package/src/services/posts.service.ts +0 -542
  198. package/src/services/tracking-permission.service.ts +0 -88
  199. package/src/services/user.service.ts +0 -60
  200. package/src/services/whitelabel.service.ts +0 -675
  201. package/tsconfig.lib.json +0 -17
  202. package/tsconfig.lib.prod.json +0 -9
  203. package/tsconfig.spec.json +0 -13
  204. /package/{src/assets → assets}/fonts/Brockmann-Bold.otf +0 -0
  205. /package/{src/assets → assets}/fonts/Brockmann-BoldItalic.otf +0 -0
  206. /package/{src/assets → assets}/fonts/Brockmann-Medium.otf +0 -0
  207. /package/{src/assets → assets}/fonts/Brockmann-MediumItalic.otf +0 -0
  208. /package/{src/assets → assets}/fonts/Brockmann-Regular.otf +0 -0
  209. /package/{src/assets → assets}/fonts/Brockmann-RegularItalic.otf +0 -0
  210. /package/{src/assets → assets}/fonts/Brockmann-SemiBold.otf +0 -0
  211. /package/{src/assets → assets}/fonts/Brockmann-SemiBoldItalic.otf +0 -0
  212. /package/{src/assets → assets}/fonts/Brockmann_desktop_license.pdf +0 -0
  213. /package/{src/assets → assets}/fonts/brockmann-medium-webfont.woff2 +0 -0
  214. /package/{src/assets → assets}/fonts/brockmann-mediumitalic-webfont.woff2 +0 -0
  215. /package/{src/assets → assets}/fonts/brockmann-regular-webfont.woff2 +0 -0
  216. /package/{src/assets → assets}/fonts/brockmann-regularitalic-webfont.woff2 +0 -0
  217. /package/{src/assets → assets}/fonts/brockmann-semibold-webfont.woff2 +0 -0
  218. /package/{src/assets → assets}/fonts/brockmann-semibolditalic-webfont.woff2 +0 -0
  219. /package/{src/styles → styles}/ionic.css +0 -0
  220. /package/{src/components/shared → styles}/mobile-common.css +0 -0
  221. /package/{src/components/shared → styles}/mobile-page-base.css +0 -0
@@ -1,529 +0,0 @@
1
- import {
2
- Component,
3
- signal,
4
- computed,
5
- ViewChild,
6
- ElementRef,
7
- AfterViewInit,
8
- OnDestroy,
9
- OnInit,
10
- CUSTOM_ELEMENTS_SCHEMA
11
- } from '@angular/core';
12
- import { CommonModule } from '@angular/common';
13
- import {
14
- IonContent,
15
- IonSpinner,
16
- ModalController,
17
- GestureController,
18
- Gesture
19
- } from '@ionic/angular/standalone';
20
- import { Share } from '@capacitor/share';
21
- import { DsIconButtonComponent } from '@propbinder/design-system';
22
- import { DsAvatarComponent } from '@propbinder/design-system';
23
- import type { LightboxImage, LightboxAuthor } from './ds-mobile-lightbox.service';
24
-
25
- /**
26
- * DsMobileLightboxComponent
27
- *
28
- * Full-screen image lightbox component with native mobile gestures.
29
- * Supports swipe navigation, pinch-to-zoom, and double-tap zoom.
30
- *
31
- * This component is typically not used directly - use DsMobileLightboxService instead.
32
- *
33
- * Features:
34
- * - Swipe left/right to navigate between images
35
- * - Pinch to zoom in/out
36
- * - Double-tap to toggle zoom
37
- * - Swipe down to close (when not zoomed)
38
- * - Image counter and navigation controls
39
- * - Optional title and description display
40
- *
41
- * @example
42
- * ```typescript
43
- * // Don't instantiate directly - use the service:
44
- * constructor(private lightbox: DsMobileLightboxService) {}
45
- *
46
- * openImage() {
47
- * this.lightbox.open({
48
- * images: [{ src: 'image.jpg', title: 'My Image' }]
49
- * });
50
- * }
51
- * ```
52
- */
53
- @Component({
54
- selector: 'ds-mobile-lightbox',
55
- standalone: true,
56
- imports: [
57
- CommonModule,
58
- IonContent,
59
- IonSpinner,
60
- DsIconButtonComponent,
61
- DsAvatarComponent
62
- ],
63
- styleUrls: ['../shared/mobile-common.css', './ds-mobile-lightbox.css'],
64
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
65
- template: `
66
- <ion-content
67
- [fullscreen]="true"
68
- [scrollY]="false"
69
- [scrollX]="false"
70
- class="lightbox-content"
71
- [class.zoomed]="isZoomed()">
72
-
73
- <div class="lightbox-wrapper">
74
- <!-- Header with action buttons -->
75
- <div class="lightbox-header">
76
- <!-- Action buttons row -->
77
- <div class="header-actions">
78
- <ds-icon-button
79
- icon="remixCloseLine"
80
- variant="ghost"
81
- size="md"
82
- (click)="close()"
83
- class="close-button"
84
- aria-label="Luk lyskasse">
85
- </ds-icon-button>
86
-
87
- <ds-icon-button
88
- icon="remixShare2Line"
89
- variant="ghost"
90
- size="md"
91
- (click)="onShare()"
92
- class="share-button"
93
- aria-label="Del billede">
94
- </ds-icon-button>
95
- </div>
96
- </div>
97
-
98
- <!-- Image container with gesture support -->
99
- <div class="lightbox-container" #container>
100
- <div
101
- class="image-wrapper"
102
- #imageWrapper
103
- [style.transform]="transform()">
104
- <img
105
- #image
106
- [src]="currentImage().src"
107
- [alt]="currentImage().alt || 'Lightbox image'"
108
- class="lightbox-image"
109
- (load)="onImageLoad()"
110
- (error)="onImageError()">
111
- </div>
112
-
113
- <!-- Loading indicator -->
114
- @if (isLoading()) {
115
- <div class="loading-spinner">
116
- <ion-spinner name="crescent"></ion-spinner>
117
- </div>
118
- }
119
-
120
- <!-- Error message -->
121
- @if (hasError()) {
122
- <div class="error-message">
123
- <p>Failed to load image</p>
124
- </div>
125
- }
126
- </div>
127
-
128
- <!-- Navigation controls -->
129
- @if (showControls && images.length > 1) {
130
- <div class="lightbox-controls">
131
- <button
132
- class="nav-button prev"
133
- (click)="previousImage()"
134
- [disabled]="currentIndex() === 0"
135
- aria-label="Forrige billede">
136
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
137
- <path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
138
- </svg>
139
- </button>
140
-
141
- <div class="counter">
142
- {{ currentIndex() + 1 }} / {{ images.length }}
143
- </div>
144
-
145
- <button
146
- class="nav-button next"
147
- (click)="nextImage()"
148
- [disabled]="currentIndex() === images.length - 1"
149
- aria-label="Næste billede">
150
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
151
- <path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
152
- </svg>
153
- </button>
154
- </div>
155
- }
156
-
157
- <!-- Caption at bottom -->
158
- @if (showInfo && author) {
159
- <div class="lightbox-caption" [class.with-controls]="showControls && images.length > 1">
160
- <!-- Author meta -->
161
- <div class="author-details">
162
- <ds-avatar
163
- [initials]="author.avatarInitials ?? ''"
164
- [type]="author.avatarType ?? 'initials'"
165
- [src]="author.avatarSrc ?? ''"
166
- size="md"
167
- />
168
- <div class="author-details">
169
- <div class="author-name">{{ author.name }}</div>
170
- @if (author.role || author.timestamp) {
171
- <div class="author-meta">
172
- @if (author.role) {
173
- <span>{{ author.role }}</span>
174
- }
175
- @if (author.role && author.timestamp) {
176
- <span class="separator">·</span>
177
- }
178
- @if (author.timestamp) {
179
- <span>{{ author.timestamp }}</span>
180
- }
181
- </div>
182
- }
183
- </div>
184
- </div>
185
- </div>
186
- }
187
- </div>
188
- </ion-content>
189
- `
190
- })
191
- export class DsMobileLightboxComponent implements OnInit, AfterViewInit, OnDestroy {
192
- // Inputs (passed from service as regular properties, not signals)
193
- images!: LightboxImage[];
194
- author?: LightboxAuthor;
195
- initialIndex: number = 0;
196
- enableZoom: boolean = true;
197
- showControls: boolean = true;
198
- enableSwipe: boolean = true;
199
- showInfo: boolean = true;
200
- animation: 'fade' | 'zoom' | 'slide' = 'fade';
201
-
202
- // View children
203
- @ViewChild('container', { read: ElementRef }) containerRef!: ElementRef<HTMLDivElement>;
204
- @ViewChild('imageWrapper', { read: ElementRef }) imageWrapperRef!: ElementRef<HTMLDivElement>;
205
- @ViewChild('image', { read: ElementRef }) imageRef!: ElementRef<HTMLImageElement>;
206
-
207
- // State
208
- currentIndex = signal(0);
209
- scale = signal(1);
210
- translateX = signal(0);
211
- translateY = signal(0);
212
- isZoomed = signal(false);
213
- isLoading = signal(true);
214
- hasError = signal(false);
215
-
216
- // Action states
217
- isLiked = signal(false);
218
- likeCount = signal(0);
219
- commentCount = signal(0);
220
-
221
- // Computed
222
- currentImage = computed(() => this.images[this.currentIndex()]);
223
- transform = computed(() => {
224
- const s = this.scale();
225
- const x = this.translateX();
226
- const y = this.translateY();
227
- return `scale(${s}) translate(${x}px, ${y}px)`;
228
- });
229
-
230
- // Gesture tracking
231
- private gesture?: Gesture;
232
- private swipeGesture?: Gesture;
233
- private pinchGesture?: Gesture;
234
- private initialScale = 1;
235
- private initialTranslateX = 0;
236
- private initialTranslateY = 0;
237
- private lastPinchScale = 1;
238
-
239
- constructor(
240
- private modalController: ModalController,
241
- private gestureCtrl: GestureController
242
- ) {}
243
-
244
- ngOnInit(): void {
245
- // Set initial index from the passed property
246
- if (this.initialIndex !== undefined) {
247
- this.currentIndex.set(this.initialIndex);
248
- }
249
-
250
- // Initialize action states from current image
251
- const currentImg = this.images[this.currentIndex()];
252
- if (currentImg) {
253
- this.isLiked.set(currentImg.isLiked ?? false);
254
- this.likeCount.set(currentImg.likeCount ?? 0);
255
- this.commentCount.set(currentImg.commentCount ?? 0);
256
- }
257
- }
258
-
259
- ngAfterViewInit(): void {
260
- console.log('[Lightbox] ngAfterViewInit called');
261
- console.log('[Lightbox] Current image:', this.currentImage());
262
- console.log('[Lightbox] Images array:', this.images);
263
- console.log('[Lightbox] Container ref:', this.containerRef?.nativeElement);
264
- console.log('[Lightbox] Image wrapper ref:', this.imageWrapperRef?.nativeElement);
265
- console.log('[Lightbox] Image ref:', this.imageRef?.nativeElement);
266
-
267
- // Initialize gestures after view is ready
268
- if (this.enableZoom) {
269
- this.initializeZoomGesture();
270
- this.initializePinchZoom();
271
- }
272
- if (this.enableSwipe) {
273
- this.initializeSwipeGesture();
274
- }
275
- }
276
-
277
- ngOnDestroy(): void {
278
- // Clean up gestures
279
- this.gesture?.destroy();
280
- this.swipeGesture?.destroy();
281
- this.pinchGesture?.destroy();
282
- }
283
-
284
- /**
285
- * Initialize double-tap zoom gesture
286
- */
287
- private initializeZoomGesture(): void {
288
- if (!this.imageWrapperRef) return;
289
-
290
- let lastTap = 0;
291
- const element = this.imageWrapperRef.nativeElement;
292
-
293
- element.addEventListener('click', (event: MouseEvent) => {
294
- const now = Date.now();
295
- const timeSinceLastTap = now - lastTap;
296
-
297
- if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {
298
- // Double tap detected
299
- event.preventDefault();
300
- this.onDoubleTap();
301
- }
302
-
303
- lastTap = now;
304
- });
305
- }
306
-
307
- /**
308
- * Initialize pinch-to-zoom gesture
309
- */
310
- private initializePinchZoom(): void {
311
- if (!this.imageWrapperRef) return;
312
-
313
- const element = this.imageWrapperRef.nativeElement;
314
- let initialDistance = 0;
315
- let initialCenterX = 0;
316
- let initialCenterY = 0;
317
-
318
- const getTouchDistance = (touches: TouchList) => {
319
- const dx = touches[0].clientX - touches[1].clientX;
320
- const dy = touches[0].clientY - touches[1].clientY;
321
- return Math.sqrt(dx * dx + dy * dy);
322
- };
323
-
324
- const getTouchCenter = (touches: TouchList) => {
325
- return {
326
- x: (touches[0].clientX + touches[1].clientX) / 2,
327
- y: (touches[0].clientY + touches[1].clientY) / 2
328
- };
329
- };
330
-
331
- element.addEventListener('touchstart', (event: TouchEvent) => {
332
- if (event.touches.length === 2) {
333
- event.preventDefault();
334
- initialDistance = getTouchDistance(event.touches);
335
- const center = getTouchCenter(event.touches);
336
- initialCenterX = center.x;
337
- initialCenterY = center.y;
338
- this.initialScale = this.scale();
339
- this.lastPinchScale = 1;
340
- }
341
- }, { passive: false });
342
-
343
- element.addEventListener('touchmove', (event: TouchEvent) => {
344
- if (event.touches.length === 2) {
345
- event.preventDefault();
346
-
347
- const currentDistance = getTouchDistance(event.touches);
348
- const pinchScale = currentDistance / initialDistance;
349
-
350
- // Calculate new scale
351
- let newScale = this.initialScale * pinchScale;
352
- newScale = Math.max(1, Math.min(newScale, 4)); // Clamp between 1x and 4x
353
-
354
- this.scale.set(newScale);
355
-
356
- if (newScale > 1) {
357
- this.isZoomed.set(true);
358
- } else {
359
- this.isZoomed.set(false);
360
- this.translateX.set(0);
361
- this.translateY.set(0);
362
- }
363
-
364
- this.lastPinchScale = pinchScale;
365
- }
366
- }, { passive: false });
367
-
368
- element.addEventListener('touchend', (event: TouchEvent) => {
369
- if (event.touches.length < 2) {
370
- // Reset to 1x if we're close to it
371
- if (this.scale() < 1.1) {
372
- this.resetZoom();
373
- }
374
- }
375
- });
376
- }
377
-
378
- /**
379
- * Initialize swipe gesture for navigation
380
- */
381
- private initializeSwipeGesture(): void {
382
- if (!this.containerRef) return;
383
-
384
- this.swipeGesture = this.gestureCtrl.create({
385
- el: this.containerRef.nativeElement,
386
- gestureName: 'swipe-navigate',
387
- direction: 'x',
388
- threshold: 50,
389
- onStart: () => {
390
- this.initialTranslateX = this.translateX();
391
- },
392
- onMove: (detail) => {
393
- // Only allow swipe if not zoomed
394
- if (!this.isZoomed() && detail.deltaX !== undefined) {
395
- this.translateX.set(this.initialTranslateX + detail.deltaX / 2);
396
- }
397
- },
398
- onEnd: (detail) => {
399
- if (!this.isZoomed() && detail.deltaX !== undefined) {
400
- const threshold = 100;
401
-
402
- if (detail.deltaX > threshold) {
403
- // Swipe right - previous image
404
- this.previousImage();
405
- } else if (detail.deltaX < -threshold) {
406
- // Swipe left - next image
407
- this.nextImage();
408
- } else {
409
- // Reset position
410
- this.translateX.set(0);
411
- }
412
- }
413
- }
414
- }, true);
415
-
416
- this.swipeGesture.enable();
417
- }
418
-
419
- /**
420
- * Close the lightbox
421
- */
422
- close(): void {
423
- this.modalController.dismiss();
424
- }
425
-
426
- async onShare(): Promise<void> {
427
- console.log('[Lightbox] Share button clicked');
428
- const currentImg = this.currentImage();
429
-
430
- if (!currentImg?.src) return;
431
-
432
- try {
433
- // Use Capacitor Share API for native share sheet
434
- await Share.share({
435
- title: currentImg.title || 'Image',
436
- text: currentImg.description || '',
437
- url: currentImg.src,
438
- dialogTitle: 'Share Image'
439
- });
440
-
441
- console.log('[Lightbox] Image shared successfully');
442
- } catch (error) {
443
- console.error('[Lightbox] Error sharing image:', error);
444
- // If share fails or is cancelled, do nothing
445
- // Note: User canceling the share dialog will throw an error, which is expected
446
- }
447
- }
448
-
449
- onLike(event: { active: boolean; count: number }): void {
450
- console.log('[Lightbox] Like toggled:', event);
451
- this.isLiked.set(event.active);
452
- this.likeCount.set(event.count);
453
- // You can emit an event or call a service here to persist the like
454
- }
455
-
456
- onReply(): void {
457
- console.log('[Lightbox] Reply button clicked');
458
- // Close the lightbox and navigate to reply/comment interface
459
- // Or open a bottom sheet for quick reply
460
- this.modalController.dismiss({ action: 'reply' });
461
- }
462
-
463
- /**
464
- * Navigate to the next image
465
- */
466
- nextImage(): void {
467
- if (this.currentIndex() < this.images.length - 1) {
468
- this.resetZoom();
469
- this.currentIndex.update(i => i + 1);
470
- this.isLoading.set(true);
471
- this.hasError.set(false);
472
- }
473
- }
474
-
475
- /**
476
- * Navigate to the previous image
477
- */
478
- previousImage(): void {
479
- if (this.currentIndex() > 0) {
480
- this.resetZoom();
481
- this.currentIndex.update(i => i - 1);
482
- this.isLoading.set(true);
483
- this.hasError.set(false);
484
- }
485
- }
486
-
487
- /**
488
- * Handle double-tap to toggle zoom
489
- */
490
- onDoubleTap(): void {
491
- if (!this.enableZoom) return;
492
-
493
- if (this.isZoomed()) {
494
- this.resetZoom();
495
- } else {
496
- this.scale.set(2);
497
- this.isZoomed.set(true);
498
- }
499
- }
500
-
501
- /**
502
- * Reset zoom and pan to default state
503
- */
504
- resetZoom(): void {
505
- this.scale.set(1);
506
- this.translateX.set(0);
507
- this.translateY.set(0);
508
- this.isZoomed.set(false);
509
- }
510
-
511
- /**
512
- * Handle image load success
513
- */
514
- onImageLoad(): void {
515
- console.log('[Lightbox] Image loaded successfully');
516
- this.isLoading.set(false);
517
- this.hasError.set(false);
518
- }
519
-
520
- /**
521
- * Handle image load error
522
- */
523
- onImageError(): void {
524
- console.error('[Lightbox] Image failed to load');
525
- this.isLoading.set(false);
526
- this.hasError.set(true);
527
- }
528
- }
529
-
@@ -1,22 +0,0 @@
1
- // Components
2
- export { DsMobileLightboxImageComponent } from './ds-mobile-lightbox-image';
3
- export { DsMobileLightboxPdfComponent } from './ds-mobile-lightbox-pdf';
4
- export { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';
5
- export { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';
6
-
7
- // Service and Types
8
- export {
9
- DsMobileLightboxService,
10
- type LightboxImage,
11
- type LightboxPdf,
12
- type LightboxMediaFile,
13
- type LightboxMediaType,
14
- type LightboxAuthor,
15
- type LightboxOptions,
16
- type LightboxImageOptions,
17
- type LightboxPdfOptions
18
- } from './ds-mobile-lightbox.service';
19
-
20
- // Legacy export for backward compatibility
21
- export { DsMobileLightboxImageComponent as DsMobileLightboxComponent } from './ds-mobile-lightbox-image';
22
-