@propbinder/mobile-design 0.0.2 → 0.0.21

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 (123) hide show
  1. package/fesm2022/propbinder-mobile-design.mjs +12596 -0
  2. package/fesm2022/propbinder-mobile-design.mjs.map +1 -0
  3. package/index.d.ts +3214 -0
  4. package/package.json +39 -12
  5. package/ng-package.json +0 -7
  6. package/src/animations/page-transitions.ts +0 -86
  7. package/src/assets/fonts/Brockmann-Bold.otf +0 -0
  8. package/src/assets/fonts/Brockmann-BoldItalic.otf +0 -0
  9. package/src/assets/fonts/Brockmann-Medium.otf +0 -0
  10. package/src/assets/fonts/Brockmann-MediumItalic.otf +0 -0
  11. package/src/assets/fonts/Brockmann-Regular.otf +0 -0
  12. package/src/assets/fonts/Brockmann-RegularItalic.otf +0 -0
  13. package/src/assets/fonts/Brockmann-SemiBold.otf +0 -0
  14. package/src/assets/fonts/Brockmann-SemiBoldItalic.otf +0 -0
  15. package/src/assets/fonts/Brockmann_desktop_license.pdf +0 -0
  16. package/src/assets/fonts/brockmann-medium-webfont.woff2 +0 -0
  17. package/src/assets/fonts/brockmann-regular-webfont.woff2 +0 -0
  18. package/src/assets/fonts/brockmann-semibold-webfont.woff2 +0 -0
  19. package/src/components/action-list-item/ds-mobile-action-list-item.ts +0 -83
  20. package/src/components/action-list-item/index.ts +0 -2
  21. package/src/components/app-layout/ds-mobile-app-layout.css +0 -343
  22. package/src/components/app-layout/ds-mobile-app-layout.ts +0 -271
  23. package/src/components/app-layout/index.ts +0 -2
  24. package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +0 -130
  25. package/src/components/avatar-with-badge/index.ts +0 -2
  26. package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +0 -273
  27. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +0 -110
  28. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +0 -167
  29. package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +0 -656
  30. package/src/components/bottom-sheet/index.ts +0 -3
  31. package/src/components/comment/ds-mobile-comment.ts +0 -516
  32. package/src/components/comment/index.ts +0 -2
  33. package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +0 -182
  34. package/src/components/contact-list-item/index.ts +0 -2
  35. package/src/components/content/ds-mobile-content.ts +0 -158
  36. package/src/components/content/index.ts +0 -2
  37. package/src/components/ds-mobile-tabs.css +0 -372
  38. package/src/components/ds-mobile-tabs.ts +0 -217
  39. package/src/components/file-attachment/ds-mobile-file-attachment.ts +0 -164
  40. package/src/components/file-attachment/index.ts +0 -2
  41. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +0 -98
  42. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +0 -514
  43. package/src/components/handbook-detail-modal/index.ts +0 -3
  44. package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +0 -130
  45. package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +0 -444
  46. package/src/components/handbook-folder/index.ts +0 -4
  47. package/src/components/header-content/ds-mobile-header-content.ts +0 -211
  48. package/src/components/header-content/index.ts +0 -2
  49. package/src/components/index.ts +0 -45
  50. package/src/components/inline-photo/ds-mobile-inline-photo.ts +0 -269
  51. package/src/components/inline-photo/index.ts +0 -1
  52. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.css +0 -60
  53. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +0 -280
  54. package/src/components/interactive-list-item-inquiry/index.ts +0 -2
  55. package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +0 -197
  56. package/src/components/interactive-list-item-message/index.ts +0 -2
  57. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.css +0 -70
  58. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +0 -594
  59. package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +0 -124
  60. package/src/components/interactive-list-item-post/index.ts +0 -13
  61. package/src/components/lightbox/ds-mobile-lightbox-footer.ts +0 -331
  62. package/src/components/lightbox/ds-mobile-lightbox-header.ts +0 -173
  63. package/src/components/lightbox/ds-mobile-lightbox-image.ts +0 -464
  64. package/src/components/lightbox/ds-mobile-lightbox-pdf.css +0 -375
  65. package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +0 -374
  66. package/src/components/lightbox/ds-mobile-lightbox.css +0 -587
  67. package/src/components/lightbox/ds-mobile-lightbox.service.ts +0 -293
  68. package/src/components/lightbox/ds-mobile-lightbox.ts +0 -529
  69. package/src/components/lightbox/index.ts +0 -22
  70. package/src/components/list-item/ds-mobile-list-item.ts +0 -499
  71. package/src/components/list-item/index.ts +0 -2
  72. package/src/components/list-item-static/ds-mobile-list-item-static.ts +0 -133
  73. package/src/components/list-item-static/index.ts +0 -2
  74. package/src/components/logo/ds-logo.ts +0 -85
  75. package/src/components/logo/index.ts +0 -2
  76. package/src/components/modal/ds-mobile-modal.css +0 -163
  77. package/src/components/modal/ds-mobile-modal.service.ts +0 -329
  78. package/src/components/modal/index.ts +0 -8
  79. package/src/components/page-details/ds-mobile-page-details.css +0 -285
  80. package/src/components/page-details/ds-mobile-page-details.ts +0 -128
  81. package/src/components/page-details/index.ts +0 -2
  82. package/src/components/page-main/ds-mobile-page-main.css +0 -346
  83. package/src/components/page-main/ds-mobile-page-main.ts +0 -331
  84. package/src/components/page-main/index.ts +0 -2
  85. package/src/components/post-card/ds-mobile-post-card.ts +0 -685
  86. package/src/components/post-card/ds-mobile-post-pdf-attachment.ts +0 -124
  87. package/src/components/post-card/index.ts +0 -11
  88. package/src/components/post-composer/ds-mobile-post-composer.ts +0 -140
  89. package/src/components/post-composer/index.ts +0 -2
  90. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +0 -104
  91. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +0 -1273
  92. package/src/components/post-detail-modal/index.ts +0 -9
  93. package/src/components/shared/directives/index.ts +0 -2
  94. package/src/components/shared/directives/long-press.directive.ts +0 -208
  95. package/src/components/shared/index.ts +0 -3
  96. package/src/components/shared/mobile-common.css +0 -94
  97. package/src/components/shared/mobile-page-base.css +0 -315
  98. package/src/components/shared/mobile-page-base.ts +0 -70
  99. package/src/components/swiper/ds-mobile-swiper.ts +0 -123
  100. package/src/components/swiper/index.ts +0 -2
  101. package/src/components/tab-bar/ds-mobile-tab-bar.ts +0 -132
  102. package/src/components/tab-bar/index.ts +0 -2
  103. package/src/components/tabs/ds-mobile-tabs.css +0 -405
  104. package/src/components/tabs/ds-mobile-tabs.ts +0 -204
  105. package/src/components/tabs/index.ts +0 -2
  106. package/src/pages/community.page.ts +0 -768
  107. package/src/pages/handbook.page.ts +0 -298
  108. package/src/pages/home.page.ts +0 -192
  109. package/src/pages/index.ts +0 -9
  110. package/src/pages/inquiries.example.ts +0 -212
  111. package/src/pages/inquiry-detail.example.css +0 -434
  112. package/src/pages/inquiry-detail.example.ts +0 -416
  113. package/src/pages/mobile-tabs-example.component.ts +0 -146
  114. package/src/pages/post-create.page.ts +0 -311
  115. package/src/pages/post-detail.page.ts +0 -295
  116. package/src/pages/whitelabel-demo.page.ts +0 -548
  117. package/src/public-api.ts +0 -5
  118. package/src/services/user.service.ts +0 -35
  119. package/src/services/whitelabel.service.ts +0 -171
  120. package/src/styles/ionic.css +0 -673
  121. package/tsconfig.lib.json +0 -17
  122. package/tsconfig.lib.prod.json +0 -9
  123. package/tsconfig.spec.json +0 -13
@@ -1,464 +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
- HostListener
12
- } from '@angular/core';
13
- import { CommonModule } from '@angular/common';
14
- import {
15
- IonSpinner,
16
- GestureController,
17
- Gesture
18
- } from '@ionic/angular/standalone';
19
- import { Share } from '@capacitor/share';
20
- import { Haptics, ImpactStyle } from '@capacitor/haptics';
21
- import { DsIconButtonComponent } from '@propbinder/design-system';
22
- import { DsAvatarComponent } from '@propbinder/design-system';
23
- import { DsMobileLightboxHeaderComponent } from './ds-mobile-lightbox-header';
24
- import { DsMobileLightboxFooterComponent } from './ds-mobile-lightbox-footer';
25
- import type { LightboxImage, LightboxAuthor } from './ds-mobile-lightbox.service';
26
- import Swiper from 'swiper';
27
- import type { SwiperOptions } from 'swiper/types';
28
-
29
- /**
30
- * DsMobileLightboxImageComponent
31
- *
32
- * Full-screen image lightbox component with Swiper.js navigation and pinch-zoom.
33
- *
34
- * This component is typically not used directly - use DsMobileLightboxService instead.
35
- *
36
- * Features:
37
- * - Swiper.js for smooth image navigation
38
- * - Pinch to zoom in/out
39
- * - Double-tap to toggle zoom
40
- * - Swipe down to close (when not zoomed)
41
- * - Image counter and navigation controls
42
- *
43
- * @example
44
- * ```typescript
45
- * // Don't instantiate directly - use the service:
46
- * constructor(private lightbox: DsMobileLightboxService) {}
47
- *
48
- * openImage() {
49
- * this.lightbox.openImages({
50
- * images: [{ type: 'image', src: 'image.jpg', title: 'My Image' }]
51
- * });
52
- * }
53
- * ```
54
- */
55
- @Component({
56
- selector: 'ds-mobile-lightbox-image',
57
- standalone: true,
58
- imports: [
59
- CommonModule,
60
- IonSpinner,
61
- DsIconButtonComponent,
62
- DsAvatarComponent,
63
- DsMobileLightboxHeaderComponent,
64
- DsMobileLightboxFooterComponent
65
- ],
66
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
67
- template: `
68
- <div class="lightbox-overlay"
69
- [class.zoomed]="isZoomed()">
70
-
71
- <div class="lightbox-wrapper">
72
- <!-- Header with author info and close button -->
73
- <ds-mobile-lightbox-header
74
- [author]="author"
75
- (closeClick)="close()"
76
- />
77
-
78
- <!-- Swiper container -->
79
- <div class="swiper-container" #swiperContainer>
80
- <div class="swiper-wrapper">
81
- @for (image of images; track image.src; let i = $index) {
82
- <div class="swiper-slide">
83
- <div class="image-zoom-container" [attr.data-index]="i">
84
- <img
85
- [src]="image.src"
86
- [alt]="image.alt || 'Lightbox image'"
87
- class="lightbox-image"
88
- (load)="onImageLoad(i)"
89
- (error)="onImageError(i)">
90
- </div>
91
- </div>
92
- }
93
- </div>
94
- </div>
95
-
96
- <!-- Loading indicator -->
97
- @if (isLoading()) {
98
- <div class="loading-spinner">
99
- <ion-spinner name="crescent"></ion-spinner>
100
- </div>
101
- }
102
-
103
- <!-- Footer with navigation and actions -->
104
- <ds-mobile-lightbox-footer
105
- [showNavigation]="showControls && images.length > 1"
106
- [currentIndex]="currentIndex()"
107
- [totalImages]="images.length"
108
- [isLiked]="isLiked()"
109
- [likeCount]="likeCount()"
110
- [commentCount]="commentCount()"
111
- (prevClick)="previousImage()"
112
- (nextClick)="nextImage()"
113
- (likeClick)="onLikeToggle()"
114
- (commentClick)="onReply()"
115
- (shareClick)="onShare()"
116
- />
117
- </div>
118
- </div>
119
- `,
120
- styleUrl: './ds-mobile-lightbox.css'
121
- })
122
- export class DsMobileLightboxImageComponent implements OnInit, AfterViewInit, OnDestroy {
123
- // Inputs (passed from service as regular properties, not signals)
124
- images!: LightboxImage[];
125
- author?: LightboxAuthor;
126
- initialIndex: number = 0;
127
- enableZoom: boolean = true;
128
- showControls: boolean = true;
129
- enableSwipe: boolean = true;
130
- showInfo: boolean = true;
131
- animation: 'fade' | 'zoom' | 'slide' = 'fade';
132
- onCloseRequested?: () => void;
133
-
134
- // View children
135
- @ViewChild('swiperContainer', { read: ElementRef }) swiperContainer!: ElementRef<HTMLDivElement>;
136
-
137
- // State
138
- currentIndex = signal(0);
139
- scale = signal(1);
140
- isZoomed = signal(false);
141
- isLoading = signal(true);
142
- hasError = signal(false);
143
-
144
- // Action states
145
- isLiked = signal(false);
146
- likeCount = signal(0);
147
- commentCount = signal(0);
148
-
149
- // Computed
150
- currentImage = computed(() => this.images[this.currentIndex()]);
151
-
152
- // Swiper instance
153
- private swiper?: Swiper;
154
- private zoomData: Map<number, { scale: number; x: number; y: number }> = new Map();
155
-
156
- constructor(
157
- private gestureCtrl: GestureController
158
- ) {}
159
-
160
- ngOnInit(): void {
161
- // Set initial index from the passed property
162
- if (this.initialIndex !== undefined) {
163
- this.currentIndex.set(this.initialIndex);
164
- }
165
-
166
- // Initialize action states from current image
167
- const currentImg = this.images[this.currentIndex()];
168
- if (currentImg) {
169
- this.isLiked.set(currentImg.isLiked ?? false);
170
- this.likeCount.set(currentImg.likeCount ?? 0);
171
- this.commentCount.set(currentImg.commentCount ?? 0);
172
- }
173
- }
174
-
175
- ngAfterViewInit(): void {
176
- setTimeout(() => {
177
- this.initializeSwiper();
178
- this.initializeZoomGestures();
179
- }, 100);
180
- }
181
-
182
- ngOnDestroy(): void {
183
- // Clean up Swiper
184
- if (this.swiper) {
185
- this.swiper.destroy();
186
- this.swiper = undefined;
187
- }
188
- }
189
- /**
190
- * Initialize Swiper for image navigation
191
- */
192
- private initializeSwiper(): void {
193
- if (!this.swiperContainer) {
194
- console.error('[Lightbox] Swiper container not found');
195
- return;
196
- }
197
-
198
- const swiperOptions: SwiperOptions = {
199
- initialSlide: this.initialIndex,
200
- speed: 300,
201
- resistance: true,
202
- resistanceRatio: 0.85,
203
- slidesPerView: 1,
204
- spaceBetween: 0,
205
- touchRatio: 1,
206
- longSwipesRatio: 0.5,
207
- threshold: 10,
208
- on: {
209
- slideChange: (swiper) => {
210
- this.currentIndex.set(swiper.activeIndex);
211
- this.updateActionStates();
212
-
213
- // Check if the image is already loaded
214
- const currentSlide = swiper.slides[swiper.activeIndex];
215
- const img = currentSlide?.querySelector('img');
216
- if (img && img.complete && img.naturalHeight !== 0) {
217
- // Image is already loaded
218
- this.isLoading.set(false);
219
- }
220
- },
221
- slideChangeTransitionStart: () => {
222
- // Don't show loading spinner if image is already loaded
223
- const currentSlide = this.swiper?.slides[this.swiper.activeIndex];
224
- const img = currentSlide?.querySelector('img');
225
- if (!img || !img.complete || img.naturalHeight === 0) {
226
- this.isLoading.set(true);
227
- }
228
- }
229
- }
230
- };
231
-
232
- this.swiper = new Swiper(this.swiperContainer.nativeElement, swiperOptions);
233
-
234
- // Check if the initial image is already loaded
235
- setTimeout(() => {
236
- const currentSlide = this.swiper?.slides[this.currentIndex()];
237
- const img = currentSlide?.querySelector('img');
238
- if (img && img.complete && img.naturalHeight !== 0) {
239
- this.isLoading.set(false);
240
- }
241
- }, 0);
242
- }
243
-
244
- /**
245
- * Initialize pinch-zoom gestures for all slides
246
- */
247
- private initializeZoomGestures(): void {
248
- if (!this.enableZoom) return;
249
-
250
- const slides = this.swiperContainer.nativeElement.querySelectorAll('.image-zoom-container');
251
-
252
- slides.forEach((slide, index) => {
253
- this.initializeZoomForSlide(slide as HTMLElement, index);
254
- });
255
- }
256
-
257
- /**
258
- * Initialize zoom gestures for a specific slide
259
- */
260
- private initializeZoomForSlide(container: HTMLElement, index: number): void {
261
- let initialDistance = 0;
262
- let initialScale = 1;
263
- let currentScale = 1;
264
- let lastTap = 0;
265
-
266
- // Double-tap to zoom
267
- container.addEventListener('click', (event: MouseEvent) => {
268
- const now = Date.now();
269
- const timeSinceLastTap = now - lastTap;
270
-
271
- if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {
272
- event.preventDefault();
273
- this.toggleZoom(container, index);
274
- }
275
-
276
- lastTap = now;
277
- });
278
-
279
- // Pinch to zoom
280
- const getTouchDistance = (touches: TouchList) => {
281
- const dx = touches[0].clientX - touches[1].clientX;
282
- const dy = touches[0].clientY - touches[1].clientY;
283
- return Math.sqrt(dx * dx + dy * dy);
284
- };
285
-
286
- container.addEventListener('touchstart', (event: TouchEvent) => {
287
- if (event.touches.length === 2) {
288
- event.preventDefault();
289
- initialDistance = getTouchDistance(event.touches);
290
- const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };
291
- initialScale = zoomData.scale;
292
-
293
- // Disable Swiper when zooming
294
- if (this.swiper) {
295
- this.swiper.allowTouchMove = false;
296
- }
297
- }
298
- }, { passive: false });
299
-
300
- container.addEventListener('touchmove', (event: TouchEvent) => {
301
- if (event.touches.length === 2) {
302
- event.preventDefault();
303
-
304
- const currentDistance = getTouchDistance(event.touches);
305
- const pinchScale = currentDistance / initialDistance;
306
-
307
- currentScale = Math.max(1, Math.min(initialScale * pinchScale, 4));
308
-
309
- const img = container.querySelector('img');
310
- if (img) {
311
- img.style.transform = `scale(${currentScale})`;
312
- }
313
-
314
- if (currentScale > 1) {
315
- this.isZoomed.set(true);
316
- } else {
317
- this.isZoomed.set(false);
318
- }
319
- }
320
- }, { passive: false });
321
-
322
- container.addEventListener('touchend', (event: TouchEvent) => {
323
- if (event.touches.length < 2) {
324
- // Save zoom state
325
- this.zoomData.set(index, { scale: currentScale, x: 0, y: 0 });
326
-
327
- // Re-enable Swiper if not zoomed
328
- if (this.swiper && currentScale <= 1) {
329
- this.swiper.allowTouchMove = true;
330
- }
331
- }
332
- });
333
- }
334
-
335
- /**
336
- * Toggle zoom on double-tap
337
- */
338
- private toggleZoom(container: HTMLElement, index: number): void {
339
- const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };
340
- const img = container.querySelector('img');
341
-
342
- if (!img) return;
343
-
344
- if (zoomData.scale > 1) {
345
- // Zoom out
346
- img.style.transform = 'scale(1)';
347
- this.zoomData.set(index, { scale: 1, x: 0, y: 0 });
348
- this.isZoomed.set(false);
349
- if (this.swiper) {
350
- this.swiper.allowTouchMove = true;
351
- }
352
- } else {
353
- // Zoom in
354
- img.style.transform = 'scale(2)';
355
- this.zoomData.set(index, { scale: 2, x: 0, y: 0 });
356
- this.isZoomed.set(true);
357
- if (this.swiper) {
358
- this.swiper.allowTouchMove = false;
359
- }
360
- }
361
- }
362
-
363
- /**
364
- * Update action states (like, comments) when slide changes
365
- */
366
- private updateActionStates(): void {
367
- const currentImg = this.images[this.currentIndex()];
368
- if (currentImg) {
369
- this.isLiked.set(currentImg.isLiked ?? false);
370
- this.likeCount.set(currentImg.likeCount ?? 0);
371
- this.commentCount.set(currentImg.commentCount ?? 0);
372
- }
373
- }
374
-
375
- /**
376
- * Close the lightbox
377
- */
378
- close(): void {
379
- if (this.onCloseRequested) {
380
- this.onCloseRequested();
381
- }
382
- }
383
-
384
- /**
385
- * Handle share button click
386
- */
387
- async onShare(): Promise<void> {
388
- console.log('[Lightbox] Share button clicked');
389
- const currentImg = this.currentImage();
390
-
391
- try {
392
- await Share.share({
393
- title: currentImg.title || 'Shared Image',
394
- url: currentImg.src,
395
- dialogTitle: 'Share Image',
396
- });
397
- } catch (error) {
398
- console.error('[Lightbox] Share failed:', error);
399
- }
400
- }
401
-
402
- /**
403
- * Handle like button toggle
404
- */
405
- onLikeToggle(): void {
406
- console.log('[Lightbox] Like button toggled');
407
- this.isLiked.update(liked => !liked);
408
-
409
- if (this.isLiked()) {
410
- this.likeCount.update(count => count + 1);
411
- } else {
412
- this.likeCount.update(count => Math.max(0, count - 1));
413
- }
414
- }
415
-
416
- /**
417
- * Handle reply/comment button click
418
- */
419
- onReply(): void {
420
- console.log('[Lightbox] Reply button clicked');
421
- if (this.onCloseRequested) {
422
- this.onCloseRequested();
423
- }
424
- }
425
-
426
- /**
427
- * Navigate to the next image
428
- */
429
- nextImage(): void {
430
- if (this.swiper && this.currentIndex() < this.images.length - 1) {
431
- this.swiper.slideNext();
432
- }
433
- }
434
-
435
- /**
436
- * Navigate to the previous image
437
- */
438
- previousImage(): void {
439
- if (this.swiper && this.currentIndex() > 0) {
440
- this.swiper.slidePrev();
441
- }
442
- }
443
-
444
- /**
445
- * Handle image load success
446
- */
447
- onImageLoad(index: number): void {
448
- if (index === this.currentIndex()) {
449
- this.isLoading.set(false);
450
- }
451
- }
452
-
453
- /**
454
- * Handle image load error
455
- */
456
- onImageError(index: number): void {
457
- if (index === this.currentIndex()) {
458
- console.error(`[Lightbox] Image ${index} failed to load`);
459
- this.isLoading.set(false);
460
- this.hasError.set(true);
461
- }
462
- }
463
- }
464
-