@propbinder/mobile-design 0.0.1 → 0.0.2

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/ng-package.json +7 -0
  2. package/package.json +12 -39
  3. package/src/animations/page-transitions.ts +86 -0
  4. package/src/assets/fonts/Brockmann-Bold.otf +0 -0
  5. package/src/assets/fonts/Brockmann-BoldItalic.otf +0 -0
  6. package/src/assets/fonts/Brockmann-Medium.otf +0 -0
  7. package/src/assets/fonts/Brockmann-MediumItalic.otf +0 -0
  8. package/src/assets/fonts/Brockmann-Regular.otf +0 -0
  9. package/src/assets/fonts/Brockmann-RegularItalic.otf +0 -0
  10. package/src/assets/fonts/Brockmann-SemiBold.otf +0 -0
  11. package/src/assets/fonts/Brockmann-SemiBoldItalic.otf +0 -0
  12. package/src/assets/fonts/Brockmann_desktop_license.pdf +0 -0
  13. package/src/assets/fonts/brockmann-medium-webfont.woff2 +0 -0
  14. package/src/assets/fonts/brockmann-regular-webfont.woff2 +0 -0
  15. package/src/assets/fonts/brockmann-semibold-webfont.woff2 +0 -0
  16. package/src/components/action-list-item/ds-mobile-action-list-item.ts +83 -0
  17. package/src/components/action-list-item/index.ts +2 -0
  18. package/src/components/app-layout/ds-mobile-app-layout.css +343 -0
  19. package/src/components/app-layout/ds-mobile-app-layout.ts +271 -0
  20. package/src/components/app-layout/index.ts +2 -0
  21. package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +130 -0
  22. package/src/components/avatar-with-badge/index.ts +2 -0
  23. package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +273 -0
  24. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +110 -0
  25. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +167 -0
  26. package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +656 -0
  27. package/src/components/bottom-sheet/index.ts +3 -0
  28. package/src/components/comment/ds-mobile-comment.ts +516 -0
  29. package/src/components/comment/index.ts +2 -0
  30. package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +182 -0
  31. package/src/components/contact-list-item/index.ts +2 -0
  32. package/src/components/content/ds-mobile-content.ts +158 -0
  33. package/src/components/content/index.ts +2 -0
  34. package/src/components/ds-mobile-tabs.css +372 -0
  35. package/src/components/ds-mobile-tabs.ts +217 -0
  36. package/src/components/file-attachment/ds-mobile-file-attachment.ts +164 -0
  37. package/src/components/file-attachment/index.ts +2 -0
  38. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +98 -0
  39. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +514 -0
  40. package/src/components/handbook-detail-modal/index.ts +3 -0
  41. package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +130 -0
  42. package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +444 -0
  43. package/src/components/handbook-folder/index.ts +4 -0
  44. package/src/components/header-content/ds-mobile-header-content.ts +211 -0
  45. package/src/components/header-content/index.ts +2 -0
  46. package/src/components/index.ts +45 -0
  47. package/src/components/inline-photo/ds-mobile-inline-photo.ts +269 -0
  48. package/src/components/inline-photo/index.ts +1 -0
  49. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.css +60 -0
  50. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +280 -0
  51. package/src/components/interactive-list-item-inquiry/index.ts +2 -0
  52. package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +197 -0
  53. package/src/components/interactive-list-item-message/index.ts +2 -0
  54. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.css +70 -0
  55. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +594 -0
  56. package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +124 -0
  57. package/src/components/interactive-list-item-post/index.ts +13 -0
  58. package/src/components/lightbox/ds-mobile-lightbox-footer.ts +331 -0
  59. package/src/components/lightbox/ds-mobile-lightbox-header.ts +173 -0
  60. package/src/components/lightbox/ds-mobile-lightbox-image.ts +464 -0
  61. package/src/components/lightbox/ds-mobile-lightbox-pdf.css +375 -0
  62. package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +374 -0
  63. package/src/components/lightbox/ds-mobile-lightbox.css +587 -0
  64. package/src/components/lightbox/ds-mobile-lightbox.service.ts +293 -0
  65. package/src/components/lightbox/ds-mobile-lightbox.ts +529 -0
  66. package/src/components/lightbox/index.ts +22 -0
  67. package/src/components/list-item/ds-mobile-list-item.ts +499 -0
  68. package/src/components/list-item/index.ts +2 -0
  69. package/src/components/list-item-static/ds-mobile-list-item-static.ts +133 -0
  70. package/src/components/list-item-static/index.ts +2 -0
  71. package/src/components/logo/ds-logo.ts +85 -0
  72. package/src/components/logo/index.ts +2 -0
  73. package/src/components/modal/ds-mobile-modal.css +163 -0
  74. package/src/components/modal/ds-mobile-modal.service.ts +329 -0
  75. package/src/components/modal/index.ts +8 -0
  76. package/src/components/page-details/ds-mobile-page-details.css +285 -0
  77. package/src/components/page-details/ds-mobile-page-details.ts +128 -0
  78. package/src/components/page-details/index.ts +2 -0
  79. package/src/components/page-main/ds-mobile-page-main.css +346 -0
  80. package/src/components/page-main/ds-mobile-page-main.ts +331 -0
  81. package/src/components/page-main/index.ts +2 -0
  82. package/src/components/post-card/ds-mobile-post-card.ts +685 -0
  83. package/src/components/post-card/ds-mobile-post-pdf-attachment.ts +124 -0
  84. package/src/components/post-card/index.ts +11 -0
  85. package/src/components/post-composer/ds-mobile-post-composer.ts +140 -0
  86. package/src/components/post-composer/index.ts +2 -0
  87. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +104 -0
  88. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +1273 -0
  89. package/src/components/post-detail-modal/index.ts +9 -0
  90. package/src/components/shared/directives/index.ts +2 -0
  91. package/src/components/shared/directives/long-press.directive.ts +208 -0
  92. package/src/components/shared/index.ts +3 -0
  93. package/src/components/shared/mobile-common.css +94 -0
  94. package/src/components/shared/mobile-page-base.css +315 -0
  95. package/src/components/shared/mobile-page-base.ts +70 -0
  96. package/src/components/swiper/ds-mobile-swiper.ts +123 -0
  97. package/src/components/swiper/index.ts +2 -0
  98. package/src/components/tab-bar/ds-mobile-tab-bar.ts +132 -0
  99. package/src/components/tab-bar/index.ts +2 -0
  100. package/src/components/tabs/ds-mobile-tabs.css +405 -0
  101. package/src/components/tabs/ds-mobile-tabs.ts +204 -0
  102. package/src/components/tabs/index.ts +2 -0
  103. package/src/pages/community.page.ts +768 -0
  104. package/src/pages/handbook.page.ts +298 -0
  105. package/src/pages/home.page.ts +192 -0
  106. package/src/pages/index.ts +9 -0
  107. package/src/pages/inquiries.example.ts +212 -0
  108. package/src/pages/inquiry-detail.example.css +434 -0
  109. package/src/pages/inquiry-detail.example.ts +416 -0
  110. package/src/pages/mobile-tabs-example.component.ts +146 -0
  111. package/src/pages/post-create.page.ts +311 -0
  112. package/src/pages/post-detail.page.ts +295 -0
  113. package/src/pages/whitelabel-demo.page.ts +548 -0
  114. package/src/public-api.ts +5 -0
  115. package/src/services/user.service.ts +35 -0
  116. package/src/services/whitelabel.service.ts +171 -0
  117. package/src/styles/ionic.css +673 -0
  118. package/tsconfig.lib.json +17 -0
  119. package/tsconfig.lib.prod.json +9 -0
  120. package/tsconfig.spec.json +13 -0
  121. package/fesm2022/propbinder-mobile-design.mjs +0 -8294
  122. package/fesm2022/propbinder-mobile-design.mjs.map +0 -1
  123. package/index.d.ts +0 -2860
@@ -0,0 +1,514 @@
1
+ import {
2
+ Component,
3
+ signal,
4
+ Input,
5
+ CUSTOM_ELEMENTS_SCHEMA
6
+ } from '@angular/core';
7
+ import { CommonModule } from '@angular/common';
8
+ import {
9
+ IonContent,
10
+ ModalController
11
+ } from '@ionic/angular/standalone';
12
+ import { DsIconButtonComponent } from '@propbinder/design-system';
13
+ import { DsMobileHandbookFolderMiniComponent } from '../handbook-folder/ds-mobile-handbook-folder-mini';
14
+ import { DsMobileFileAttachmentComponent } from '../file-attachment';
15
+ import { DsMobileContactListItemComponent } from '../contact-list-item';
16
+ import { DsMobileSwiperComponent } from '../swiper';
17
+
18
+ /**
19
+ * Handbook detail data interface
20
+ */
21
+ export interface HandbookDetailData {
22
+ title: string;
23
+ variant: string;
24
+ iconName: string;
25
+ itemCount: number;
26
+ items?: HandbookItem[];
27
+ }
28
+
29
+ export interface HandbookItem {
30
+ title: string;
31
+ description?: string;
32
+ images?: string[];
33
+ attachments?: AttachmentItem[];
34
+ contacts?: ContactItem[];
35
+ }
36
+
37
+ export interface AttachmentItem {
38
+ name: string;
39
+ type?: string;
40
+ }
41
+
42
+ export interface ContactItem {
43
+ name: string;
44
+ initials: string;
45
+ contactPerson?: string;
46
+ phoneNumber?: string;
47
+ }
48
+
49
+ /**
50
+ * DsMobileHandbookDetailModalComponent
51
+ *
52
+ * Modal wrapper for displaying handbook folder details.
53
+ *
54
+ * Features:
55
+ * - Folder content display
56
+ * - Items list with descriptions
57
+ * - Images and attachments
58
+ * - Contact information
59
+ * - Native modal controls (close, swipe down)
60
+ * - Safe area support
61
+ *
62
+ * This component is typically not used directly - use DsMobileHandbookDetailModalService instead.
63
+ */
64
+ @Component({
65
+ selector: 'ds-mobile-handbook-detail-modal',
66
+ standalone: true,
67
+ imports: [
68
+ CommonModule,
69
+ IonContent,
70
+ DsIconButtonComponent,
71
+ DsMobileHandbookFolderMiniComponent,
72
+ DsMobileFileAttachmentComponent,
73
+ DsMobileContactListItemComponent,
74
+ DsMobileSwiperComponent
75
+ ],
76
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
77
+ template: `
78
+ <ion-content [fullscreen]="true" [scrollY]="true" class="handbook-modal-content">
79
+ <div class="handbook-modal-wrapper">
80
+ <!-- Header -->
81
+ <div class="handbook-modal-header">
82
+ <div class="header-content">
83
+ <!-- Handbook folder info -->
84
+ <div class="handbook-folder-info">
85
+ <ds-mobile-handbook-folder-mini
86
+ [variant]="handbook().variant"
87
+ [iconName]="handbook().iconName">
88
+ </ds-mobile-handbook-folder-mini>
89
+ <div class="folder-details">
90
+ <div class="folder-name">{{ handbook().title }}</div>
91
+ <div class="folder-meta">
92
+ <span>{{ handbook().itemCount }} emner</span>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- Close button -->
98
+ <ds-icon-button
99
+ icon="remixCloseLine"
100
+ variant="secondary"
101
+ size="lg"
102
+ (click)="close()"
103
+ class="close-button"
104
+ aria-label="Luk">
105
+ </ds-icon-button>
106
+ </div>
107
+ </div>
108
+
109
+ <!-- Content -->
110
+ <div class="handbook-detail-container">
111
+ @if (handbook().items && handbook().items!.length > 0) {
112
+ @for (item of getDisplayItems(); track item.title + $index; let isLast = $last) {
113
+ <div class="handbook-item" [class.last-item]="isLast">
114
+ <div class="item-text-group">
115
+ <h2 class="item-title">{{ item.title }}</h2>
116
+
117
+ @if (item.description) {
118
+ <p class="item-description">{{ item.description }}</p>
119
+ }
120
+ </div>
121
+
122
+ <!-- Images -->
123
+ @if (item.images && item.images.length > 0) {
124
+ <ds-mobile-swiper [slideWidth]="item.images.length === 1 ? '100%' : '60vw'" [gap]="16">
125
+ @for (image of item.images; track image) {
126
+ <div class="swiper-slide">
127
+ <img
128
+ [src]="image"
129
+ [alt]="item.title"
130
+ class="item-image"
131
+ />
132
+ </div>
133
+ }
134
+ </ds-mobile-swiper>
135
+ }
136
+
137
+ <!-- Contacts -->
138
+ @if (item.contacts && item.contacts.length > 0) {
139
+ <div class="contacts-list">
140
+ @for (contact of item.contacts; track contact.name) {
141
+ <ds-mobile-contact-list-item
142
+ [name]="contact.name"
143
+ [initials]="contact.initials"
144
+ [contactPerson]="contact.contactPerson || ''"
145
+ [phoneNumber]="contact.phoneNumber || ''"
146
+ [clickable]="true"
147
+ (contactClick)="handleContactClick(contact)">
148
+ </ds-mobile-contact-list-item>
149
+ }
150
+ </div>
151
+ }
152
+
153
+ <!-- Attachments -->
154
+ @if (item.attachments && item.attachments.length > 0) {
155
+ <div class="attachments-list">
156
+ @for (attachment of item.attachments; track attachment.name) {
157
+ <ds-mobile-file-attachment
158
+ [fileName]="attachment.name"
159
+ [variant]="attachment.type === 'pdf' ? 'pdf' : 'doc'"
160
+ (fileClick)="handleAttachmentClick(attachment)">
161
+ </ds-mobile-file-attachment>
162
+ }
163
+ </div>
164
+ }
165
+ </div>
166
+ }
167
+ } @else {
168
+ <!-- Empty State -->
169
+ <div class="handbook-empty-state">
170
+ <img
171
+ src="/Assets/Empty state-chat.png"
172
+ alt="No items yet"
173
+ class="empty-state-image"
174
+ />
175
+ <h3 class="empty-state-title">No items yet</h3>
176
+ <p class="empty-state-description">This folder is empty</p>
177
+ </div>
178
+ }
179
+ </div>
180
+ </div>
181
+ </ion-content>
182
+ `,
183
+ styles: [`
184
+ .handbook-modal-content {
185
+ --background: var(--color-background-neutral-primary, #ffffff);
186
+ }
187
+
188
+ .handbook-modal-wrapper {
189
+ display: flex;
190
+ flex-direction: column;
191
+ min-height: 100%;
192
+ min-height: 100dvh;
193
+ background: var(--color-background-neutral-primary, #ffffff);
194
+ }
195
+
196
+ .handbook-modal-header {
197
+ position: sticky;
198
+ top: 0;
199
+ z-index: 10;
200
+ background: var(--color-background-neutral-primary, #ffffff);
201
+ border-bottom: 1px solid var(--border-color-default);
202
+ padding: 0 16px;
203
+ }
204
+
205
+ .header-content {
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: space-between;
209
+ gap: 12px;
210
+ min-height: 72px;
211
+ }
212
+
213
+ .handbook-folder-info {
214
+ display: flex;
215
+ align-items: center;
216
+ gap: 12px;
217
+ flex: 1;
218
+ min-width: 0;
219
+ }
220
+
221
+ .folder-details {
222
+ display: flex;
223
+ flex-direction: column;
224
+ min-width: 0;
225
+ flex: 1;
226
+ }
227
+
228
+ .folder-name {
229
+ font-family: 'Brockmann', sans-serif;
230
+ font-size: var(--font-size-sm);
231
+ font-weight: 600;
232
+ line-height: 20px;
233
+ letter-spacing: -0.3px;
234
+ color: var(--color-text-primary, #1a1a1a);
235
+ white-space: nowrap;
236
+ overflow: hidden;
237
+ text-overflow: ellipsis;
238
+ }
239
+
240
+ .folder-meta {
241
+ font-family: 'Brockmann', sans-serif;
242
+ font-size: var(--font-size-xs);
243
+ font-weight: 400;
244
+ line-height: 1.2;
245
+ letter-spacing: -0.26px;
246
+ color: var(--color-text-tertiary, #737373);
247
+ display: flex;
248
+ align-items: center;
249
+ gap: 4px;
250
+ }
251
+
252
+ .close-button {
253
+ flex-shrink: 0;
254
+ border-radius: 50%;
255
+ }
256
+
257
+ .close-button::ng-deep button {
258
+ border-radius: 50% !important;
259
+ width: 36px !important;
260
+ height: 36px !important;
261
+ min-width: 36px !important;
262
+ min-height: 36px !important;
263
+ padding: 0 !important;
264
+ display: flex !important;
265
+ align-items: center !important;
266
+ justify-content: center !important;
267
+ }
268
+
269
+ .handbook-detail-container {
270
+ display: flex;
271
+ flex-direction: column;
272
+ width: 100%;
273
+ max-width: 640px;
274
+ margin: 0 auto;
275
+ flex: 1;
276
+ }
277
+
278
+ .handbook-item {
279
+ width: 100%;
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: 24px;
283
+ padding: 24px 20px 24px 20px;
284
+ border-bottom: 1px solid var(--border-color-default);
285
+ }
286
+
287
+ .handbook-item.last-item {
288
+ border-bottom: none;
289
+ }
290
+
291
+ .item-text-group {
292
+ display: flex;
293
+ flex-direction: column;
294
+ gap: 8px;
295
+ }
296
+
297
+ .item-title {
298
+ font-family: 'Brockmann', sans-serif;
299
+ font-size: 16px;
300
+ font-weight: 600;
301
+ line-height: 24px;
302
+ color: var(--color-text-primary, #1a1a1a);
303
+ margin: 0;
304
+ }
305
+
306
+ .item-description {
307
+ font-family: 'Brockmann', sans-serif;
308
+ font-size: var(--font-size-sm);
309
+ line-height: 20px;
310
+ color: var(--color-text-primary, #1a1a1a);
311
+ margin: 0;
312
+ }
313
+
314
+ .item-image {
315
+ width: 100%;
316
+ height: 280px;
317
+ object-fit: cover;
318
+ border-radius: 12px;
319
+ display: block;
320
+ }
321
+
322
+ .contacts-list {
323
+ display: flex;
324
+ flex-direction: column;
325
+ gap: 0;
326
+ }
327
+
328
+ .contacts-list ds-mobile-contact-list-item:not(:last-child) {
329
+ position: relative;
330
+ padding-bottom: 8px;
331
+ }
332
+
333
+ .contacts-list ds-mobile-contact-list-item:not(:first-child) {
334
+ padding-top: 8px;
335
+ }
336
+
337
+ .contacts-list ds-mobile-contact-list-item:not(:last-child)::after {
338
+ content: '';
339
+ position: absolute;
340
+ bottom: 0;
341
+ left: 44px;
342
+ right: 0;
343
+ height: 1px;
344
+ background: var(--border-color-default);
345
+ }
346
+
347
+
348
+ .attachments-list {
349
+ display: flex;
350
+ flex-direction: column;
351
+ gap: 4px;
352
+ }
353
+
354
+
355
+ /* Empty State */
356
+ .handbook-empty-state {
357
+ display: flex;
358
+ flex-direction: column;
359
+ align-items: center;
360
+ justify-content: center;
361
+ padding: 60px 20px;
362
+ text-align: center;
363
+ }
364
+
365
+ .empty-state-image {
366
+ width: 96px;
367
+ height: 96px;
368
+ }
369
+
370
+ .empty-state-title {
371
+ font-family: 'Brockmann', sans-serif;
372
+ font-size: var(--font-size-base);
373
+ font-weight: 600;
374
+ line-height: 1.3;
375
+ color: var(--color-text-primary, #1a1a1a);
376
+ }
377
+
378
+ .empty-state-description {
379
+ font-family: 'Brockmann', sans-serif;
380
+ font-size: var(--font-size-sm);
381
+ font-weight: 400;
382
+ line-height: 1.4;
383
+ color: var(--color-text-secondary, #737373);
384
+ }
385
+
386
+ /* Safe area support */
387
+ @supports (padding: env(safe-area-inset-bottom)) {
388
+ .handbook-detail-container {
389
+ padding-bottom: calc(20px + env(safe-area-inset-bottom));
390
+ }
391
+ }
392
+ `]
393
+ })
394
+ export class DsMobileHandbookDetailModalComponent {
395
+ // Handbook data passed from service
396
+ @Input() handbookData!: HandbookDetailData;
397
+
398
+ // Signal for reactive handbook data
399
+ handbook = signal<HandbookDetailData>({
400
+ title: '',
401
+ variant: 'light-purple',
402
+ iconName: 'remixFolder3Line',
403
+ itemCount: 0,
404
+ items: []
405
+ });
406
+
407
+ constructor(
408
+ private modalController: ModalController
409
+ ) {}
410
+
411
+ ngOnInit(): void {
412
+ // Initialize handbook data from input
413
+ if (this.handbookData) {
414
+ this.handbook.set(this.handbookData);
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Split handbook items to enforce content structure rules:
420
+ * - Never mix photos and documents (attachments) in the same section
421
+ * - Never mix contact persons and attachments together in the same section
422
+ *
423
+ * This method splits items that violate these rules into multiple display items.
424
+ * Each resulting item will have only compatible content types.
425
+ */
426
+ splitItemsByContentRules(item: HandbookItem): HandbookItem[] {
427
+ const displayItems: HandbookItem[] = [];
428
+
429
+ const hasImages = item.images && item.images.length > 0;
430
+ const hasContacts = item.contacts && item.contacts.length > 0;
431
+ const hasAttachments = item.attachments && item.attachments.length > 0;
432
+
433
+ // Case 1: Only one type of content - keep as is
434
+ const contentTypeCount = [hasImages, hasContacts, hasAttachments].filter(Boolean).length;
435
+ if (contentTypeCount <= 1) {
436
+ return [item];
437
+ }
438
+
439
+ // Case 2: Has images + contacts (allowed together) but no attachments
440
+ if (hasImages && hasContacts && !hasAttachments) {
441
+ return [item];
442
+ }
443
+
444
+ // Case 3: Violates rules - need to split
445
+
446
+ // First item: Text + Images (if present)
447
+ if (hasImages) {
448
+ displayItems.push({
449
+ title: item.title,
450
+ description: item.description,
451
+ images: item.images
452
+ });
453
+ }
454
+
455
+ // Second item: Text + Contacts (if present and no images shown yet)
456
+ if (hasContacts) {
457
+ displayItems.push({
458
+ title: item.title,
459
+ description: hasImages ? undefined : item.description, // Only show description if not shown before
460
+ contacts: item.contacts
461
+ });
462
+ }
463
+
464
+ // Third item: Text + Attachments (if present)
465
+ if (hasAttachments) {
466
+ displayItems.push({
467
+ title: item.title,
468
+ description: (!hasImages && !hasContacts) ? item.description : undefined, // Only show description if not shown before
469
+ attachments: item.attachments
470
+ });
471
+ }
472
+
473
+ return displayItems;
474
+ }
475
+
476
+ /**
477
+ * Get all display items with enforced content structure rules applied
478
+ */
479
+ getDisplayItems(): HandbookItem[] {
480
+ const items = this.handbook().items || [];
481
+ const displayItems: HandbookItem[] = [];
482
+
483
+ for (const item of items) {
484
+ const splitItems = this.splitItemsByContentRules(item);
485
+ displayItems.push(...splitItems);
486
+ }
487
+
488
+ return displayItems;
489
+ }
490
+
491
+ /**
492
+ * Close the modal
493
+ */
494
+ close(): void {
495
+ this.modalController.dismiss();
496
+ }
497
+
498
+ /**
499
+ * Handle contact click
500
+ */
501
+ handleContactClick(contact: ContactItem): void {
502
+ console.log('Contact clicked:', contact);
503
+ // Implement contact action (e.g., show contact details, call, etc.)
504
+ }
505
+
506
+ /**
507
+ * Handle attachment click
508
+ */
509
+ handleAttachmentClick(attachment: AttachmentItem): void {
510
+ console.log('Attachment clicked:', attachment);
511
+ // Implement attachment action (e.g., open file viewer, download, etc.)
512
+ }
513
+ }
514
+
@@ -0,0 +1,3 @@
1
+ export * from './ds-mobile-handbook-detail-modal';
2
+ export * from './ds-mobile-handbook-detail-modal.service';
3
+
@@ -0,0 +1,130 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { DsIconComponent } from '@propbinder/design-system';
4
+
5
+ /**
6
+ * DsMobileHandbookFolderMiniComponent
7
+ *
8
+ * A minimized folder icon component for use in headers and small spaces.
9
+ * Simplified version without animations or page sheets - just folder and icon.
10
+ *
11
+ * @example
12
+ * ```html
13
+ * <ds-mobile-handbook-folder-mini
14
+ * [variant]="'pink'"
15
+ * [iconName]="'remixLightbulbLine'">
16
+ * </ds-mobile-handbook-folder-mini>
17
+ * ```
18
+ */
19
+ @Component({
20
+ selector: 'ds-mobile-handbook-folder-mini',
21
+ standalone: true,
22
+ imports: [CommonModule, DsIconComponent],
23
+ styles: [`
24
+ :host {
25
+ display: inline-block;
26
+ width: 32px;
27
+ height: 32px;
28
+ flex-shrink: 0;
29
+ }
30
+
31
+ .mini-folder-container {
32
+ position: relative;
33
+ width: 100%;
34
+ height: 100%;
35
+ display: flex;
36
+ flex-direction: column;
37
+ }
38
+
39
+ .mini-folder-tab {
40
+ width: 50%;
41
+ height: auto;
42
+ display: block;
43
+ }
44
+
45
+ .mini-folder-back {
46
+ height: 28px;
47
+ border-radius: 0px 4px 4px 4px;
48
+ position: relative;
49
+ margin-top: -1px;
50
+ }
51
+
52
+ .mini-folder-front {
53
+ position: absolute;
54
+ bottom: 0;
55
+ left: 0;
56
+ right: 0;
57
+ height: 24px;
58
+ border-radius: 4px;
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ z-index: 2;
63
+ box-shadow: inset 0 8px 8px rgba(255, 255, 255, 0.2),
64
+ inset 0 0.5px 0.5px rgba(255, 255, 255, 0.3);
65
+ }
66
+ `],
67
+ template: `
68
+ <div class="mini-folder-container">
69
+ <!-- Folder Tab SVG -->
70
+ <svg
71
+ class="mini-folder-tab"
72
+ width="101"
73
+ height="24"
74
+ viewBox="0 0 101 24"
75
+ fill="none"
76
+ xmlns="http://www.w3.org/2000/svg">
77
+ <path
78
+ d="M100.037 23.9999L100.5 24L0 24.0001V10.7646C0 4.80853 4.91797 -0.0234985 11 -0.0196688L66.4213 -0.0322266C69.3519 -0.0115886 72.197 1.20548 74.2473 3.29947L90.6765 20.0951C93.1218 22.5925 96.5417 23.9999 100.037 23.9999Z"
79
+ [attr.fill]="getColorVar('strong')"/>
80
+ </svg>
81
+
82
+ <!-- Folder Back -->
83
+ <div class="mini-folder-back" [style.background-color]="getColorVar('strong')">
84
+ <!-- Folder Front -->
85
+ <div
86
+ class="mini-folder-front"
87
+ [style.background-color]="getColorVar('base')">
88
+ <ds-icon
89
+ [name]="iconName"
90
+ [size]="'14px'"
91
+ [style.color]="'white'" />
92
+ </div>
93
+ </div>
94
+ </div>
95
+ `
96
+ })
97
+ export class DsMobileHandbookFolderMiniComponent {
98
+ /**
99
+ * Color variant for the folder
100
+ * Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey
101
+ */
102
+ @Input() variant: string = 'light-purple';
103
+
104
+ /**
105
+ * Icon name from the design system icon library
106
+ */
107
+ @Input() iconName: string = 'remixFolder3Line';
108
+
109
+ /**
110
+ * Get the CSS variable name for the color variant
111
+ */
112
+ getColorVar(suffix: 'base' | 'strong'): string {
113
+ const variantMap: Record<string, string> = {
114
+ 'success': 'success',
115
+ 'warning': 'warning',
116
+ 'destructive': 'destructive',
117
+ 'blue': 'blue',
118
+ 'light-purple': 'light-purple',
119
+ 'pink': 'pink',
120
+ 'salmon-orange': 'salmon-orange',
121
+ 'orange': 'orange',
122
+ 'lime-green': 'lime-green',
123
+ 'grey': 'grey'
124
+ };
125
+
126
+ const colorName = variantMap[this.variant] || 'light-purple';
127
+ return `var(--color-${colorName}-${suffix})`;
128
+ }
129
+ }
130
+