@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,533 @@
1
+ import { Component, Input, signal, HostListener } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { DsIconComponent } from '@propbinder/design-system';
4
+ import { DsMobileHandbookDetailModalService, HandbookDetailData, HandbookItem } from '../handbook-detail-modal';
5
+
6
+ /**
7
+ * DsMobileHandbookFolderComponent
8
+ *
9
+ * A visually rich folder component for displaying handbook categories or sections.
10
+ * Features a two-layer folder design with customizable colors, icon, item count, and label.
11
+ *
12
+ * Design Details:
13
+ * - Folder back: 72px height with a decorative notch
14
+ * - Folder front: 64px height overlaying the back
15
+ * - Item count displayed in bottom-left corner
16
+ * - Icon displayed in bottom-right corner
17
+ * - Label text centered below the folder
18
+ *
19
+ * @example
20
+ * ```html
21
+ * <ds-mobile-handbook-folder
22
+ * [colorBase]="'#d244cf'"
23
+ * [colorWeak]="'#f9e6f9'"
24
+ * [iconName]="'remixLightbulbLine'"
25
+ * [itemCount]="8"
26
+ * [label]="'Utilities'">
27
+ * </ds-mobile-handbook-folder>
28
+ * ```
29
+ */
30
+ @Component({
31
+ selector: 'ds-mobile-handbook-folder',
32
+ standalone: true,
33
+ imports: [CommonModule, DsIconComponent],
34
+ styles: [
35
+ `
36
+ :host {
37
+ display: inline-flex;
38
+ flex-direction: column;
39
+ align-items: center;
40
+ gap: 16px;
41
+ width: 100%;
42
+ min-width: 0;
43
+ cursor: pointer;
44
+ user-select: none;
45
+ -webkit-tap-highlight-color: transparent;
46
+ padding: 16px;
47
+ border-radius: 16px;
48
+ background: var(--color-background-neutral-secondary, #f0f0f0);
49
+ transition: background 0.2s ease;
50
+ }
51
+
52
+ :host:active {
53
+ background: var(--color-background-neutral-secondary-hover, #ebebeb);
54
+ }
55
+
56
+ @media (hover: hover) {
57
+ :host:hover {
58
+ background: var(--color-background-neutral-secondary-hover, #ebebeb);
59
+ }
60
+ }
61
+
62
+ /* Native support for extended API colors */
63
+ :host {
64
+ --color-red-base: #dc3545;
65
+ --color-red-strong: #ae1d3b;
66
+ --color-green-base: #28a745;
67
+ --color-green-strong: #058057;
68
+ --color-yellow-base: #ffc107;
69
+ --color-yellow-strong: #e4b200;
70
+ --color-purple-base: #6f42c1;
71
+ --color-purple-strong: #4204c5;
72
+ --color-indigo-base: #6610f2;
73
+ --color-indigo-strong: #a527a2;
74
+ --color-lime-base: #82c91e;
75
+ --color-lime-strong: #58a503;
76
+ --color-teal-base: #20c997;
77
+ --color-teal-strong: #0ca678;
78
+ --color-cyan-base: #17a2b8;
79
+ --color-cyan-strong: #1098ad;
80
+ --color-brown-base: #795548;
81
+ --color-brown-strong: #5c4033;
82
+ --color-light-blue-base: #add8e6;
83
+ --color-light-blue-strong: #87ceeb;
84
+ --color-light-green-base: #90ee90;
85
+ --color-light-green-strong: #32cd32;
86
+ --color-coral-base: #f08080;
87
+ --color-coral-strong: #cd5c5c;
88
+ --color-salmon-base: #ffa07a;
89
+ --color-salmon-strong: #fa8072;
90
+ --color-seagreen-base: #20b2aa;
91
+ --color-seagreen-strong: #2e8b57;
92
+ }
93
+
94
+ .folder-container {
95
+ position: relative;
96
+ width: 100%;
97
+ display: flex;
98
+ flex-direction: column;
99
+ perspective: 800px;
100
+ -webkit-perspective: 800px;
101
+ max-width: 160px;
102
+ /* Safari optimization: Ensure proper 3D rendering context */
103
+ transform-style: preserve-3d;
104
+ -webkit-transform-style: preserve-3d;
105
+ }
106
+
107
+ .folder-container.open .page-sheet {
108
+ -webkit-transform: translateY(-8px);
109
+ transform: translateY(-8px);
110
+ transition-delay: 0.2s;
111
+ }
112
+
113
+ .folder-container.open .page-sheet:nth-child(1) {
114
+ -webkit-transform: scale(1) translateY(-8px) rotateX(-45deg) translateZ(0.1px);
115
+ transform: scale(1) translateY(-8px) rotateX(-45deg) translateZ(0.1px);
116
+ }
117
+
118
+ .folder-container.open .page-sheet:nth-child(2) {
119
+ -webkit-transform: scale(0.98) translateY(-12px) rotateX(-36deg) translateZ(0.1px);
120
+ transform: scale(0.98) translateY(-12px) rotateX(-36deg) translateZ(0.1px);
121
+ }
122
+
123
+ .folder-container.open .page-sheet:nth-child(3) {
124
+ -webkit-transform: scale(0.96) translateY(-16px) rotateX(-27deg) translateZ(0.1px);
125
+ transform: scale(0.96) translateY(-16px) rotateX(-27deg) translateZ(0.1px);
126
+ }
127
+
128
+ .folder-container.open .page-sheet:nth-child(4) {
129
+ -webkit-transform: scale(0.94) translateY(-20px) rotateX(-18deg) translateZ(0.1px);
130
+ transform: scale(0.94) translateY(-20px) rotateX(-18deg) translateZ(0.1px);
131
+ }
132
+
133
+ .folder-container.open .page-sheet:nth-child(5) {
134
+ -webkit-transform: scale(0.92) translateY(-24px) rotateX(-9deg) translateZ(0.1px);
135
+ transform: scale(0.92) translateY(-24px) rotateX(-9deg) translateZ(0.1px);
136
+ }
137
+
138
+ .folder-container.open .page-sheet:nth-child(6) {
139
+ -webkit-transform: scale(0.9) translateY(-28px) rotateX(0deg) translateZ(0.1px);
140
+ transform: scale(0.9) translateY(-28px) rotateX(0.1px);
141
+ }
142
+
143
+ .folder-container.open .folder-front {
144
+ -webkit-transform: translate3d(0, 0, 0) rotateX(-45deg);
145
+ transform: translate3d(0, 0, 0) rotateX(-45deg);
146
+ }
147
+
148
+ .folder-tab {
149
+ width: 50%;
150
+ height: auto;
151
+ display: block;
152
+ }
153
+
154
+ .folder-back {
155
+ height: 128px;
156
+ border-radius: 0px 12px 12px 12px;
157
+ position: relative;
158
+ margin-top: -1px;
159
+ transform-style: preserve-3d;
160
+ -webkit-transform-style: preserve-3d;
161
+ backface-visibility: hidden;
162
+ -webkit-backface-visibility: hidden;
163
+ /* Safari optimization: Force GPU acceleration */
164
+ -webkit-transform: translateZ(0);
165
+ transform: translateZ(0);
166
+ }
167
+
168
+ .page-sheet {
169
+ position: absolute;
170
+ width: 80%;
171
+ height: 120px;
172
+ background: #ffffff;
173
+ border-radius: 8px;
174
+ box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);
175
+ border: 1px solid var(--border-color-default);
176
+ transition: transform 0.3s ease-out;
177
+ -webkit-transition: -webkit-transform 0.3s ease-out;
178
+ left: 10%;
179
+ /* Safari optimization: Force hardware acceleration and proper 3D rendering */
180
+ -webkit-transform: translateZ(0);
181
+ transform: translateZ(0);
182
+ transform-style: preserve-3d;
183
+ -webkit-transform-style: preserve-3d;
184
+ backface-visibility: hidden;
185
+ -webkit-backface-visibility: hidden;
186
+ /* Safari optimization: Prevent subpixel rendering issues */
187
+ -webkit-font-smoothing: antialiased;
188
+ /* Safari optimization: Ensure proper layer creation */
189
+ will-change: transform;
190
+ }
191
+
192
+ .page-sheet:nth-child(1) {
193
+ bottom: 2px;
194
+ z-index: 6;
195
+ transform-origin: bottom center;
196
+ -webkit-transform-origin: bottom center;
197
+ -webkit-transform: scale(1) translateZ(0.1px);
198
+ transform: scale(1) translateZ(0.1px);
199
+ }
200
+
201
+ .page-sheet:nth-child(2) {
202
+ bottom: 8px;
203
+ z-index: 5;
204
+ transform-origin: bottom center;
205
+ -webkit-transform-origin: bottom center;
206
+ -webkit-transform: scale(0.98) translateZ(0.1px);
207
+ transform: scale(0.98) translateZ(0.1px);
208
+ }
209
+
210
+ .page-sheet:nth-child(3) {
211
+ bottom: 14px;
212
+ z-index: 4;
213
+ transform-origin: bottom center;
214
+ -webkit-transform-origin: bottom center;
215
+ -webkit-transform: scale(0.96) translateZ(0.1px);
216
+ transform: scale(0.96) translateZ(0.1px);
217
+ }
218
+
219
+ .page-sheet:nth-child(4) {
220
+ bottom: 20px;
221
+ z-index: 3;
222
+ transform-origin: bottom center;
223
+ -webkit-transform-origin: bottom center;
224
+ -webkit-transform: scale(0.94) translateZ(0.1px);
225
+ transform: scale(0.94) translateZ(0.1px);
226
+ }
227
+
228
+ .page-sheet:nth-child(5) {
229
+ bottom: 26px;
230
+ z-index: 2;
231
+ transform-origin: bottom center;
232
+ -webkit-transform-origin: bottom center;
233
+ -webkit-transform: scale(0.92) translateZ(0.1px);
234
+ transform: scale(0.92) translateZ(0.1px);
235
+ }
236
+
237
+ .page-sheet:nth-child(6) {
238
+ bottom: 32px;
239
+ z-index: 1;
240
+ transform-origin: bottom center;
241
+ -webkit-transform-origin: bottom center;
242
+ -webkit-transform: scale(0.9) translateZ(0.1px);
243
+ transform: scale(0.9) translateZ(0.1px);
244
+ }
245
+
246
+ .folder-front {
247
+ position: absolute;
248
+ bottom: 0;
249
+ left: 0;
250
+ right: 0;
251
+ height: 116px;
252
+ border-radius: 12px;
253
+ display: flex;
254
+ align-items: center;
255
+ justify-content: center;
256
+ padding: 8px;
257
+ z-index: 2;
258
+ transform-origin: bottom center;
259
+ -webkit-transform-origin: bottom center;
260
+ transform-style: preserve-3d;
261
+ -webkit-transform-style: preserve-3d;
262
+ transition:
263
+ transform 0.4s ease-in-out,
264
+ -webkit-transform 0.4s ease-in-out;
265
+ -webkit-transition: -webkit-transform 0.4s ease-in-out;
266
+ will-change: transform;
267
+ backface-visibility: hidden;
268
+ -webkit-backface-visibility: hidden;
269
+ -webkit-font-smoothing: antialiased;
270
+ /* Safari optimization: Use more specific transform to avoid render glitches */
271
+ -webkit-transform: rotateX(-20deg) translateZ(0.1px);
272
+ transform: rotateX(-20deg) translateZ(0.1px);
273
+ /* Safari optimization: Force layer creation for smoother animations */
274
+ -webkit-transform: translate3d(0, 0, 0) rotateX(-20deg);
275
+ transform: translate3d(0, 0, 0) rotateX(-20deg);
276
+ box-shadow:
277
+ inset 0 64px 48px rgba(255, 255, 255, 0.2),
278
+ inset 0 2px 4px rgba(255, 255, 255, 0.3),
279
+ inset 0 1px 1px rgba(255, 255, 255, 0.3);
280
+ }
281
+
282
+ .item-count {
283
+ display: flex;
284
+ align-items: center;
285
+ gap: 4px;
286
+ }
287
+
288
+ .item-count-label {
289
+ letter-spacing: 0.5px;
290
+ }
291
+
292
+ .folder-icon {
293
+ display: flex;
294
+ align-items: center;
295
+ justify-content: center;
296
+ }
297
+
298
+ .folder-label-container {
299
+ display: flex;
300
+ flex-direction: column;
301
+ align-items: center;
302
+ gap: 4px;
303
+ width: 100%;
304
+ min-width: 0;
305
+ }
306
+
307
+ .folder-label {
308
+ text-align: center;
309
+ width: 100%;
310
+ min-width: 0;
311
+ overflow: hidden;
312
+ text-overflow: ellipsis;
313
+ white-space: nowrap;
314
+ }
315
+
316
+ .loading-indicator,
317
+ .error-indicator {
318
+ font-size: var(--font-size-xs);
319
+ }
320
+ `,
321
+ ],
322
+ template: `
323
+ <div class="folder-container" [class.open]="isOpen()">
324
+ <!-- Folder Tab SVG -->
325
+ <svg class="folder-tab" width="101" height="24" viewBox="0 0 101 24" fill="none" xmlns="http://www.w3.org/2000/svg">
326
+ <path
327
+ 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"
328
+ [attr.fill]="customColor || getColorVar('strong')"
329
+ />
330
+ </svg>
331
+
332
+ <!-- Folder Back -->
333
+ <div class="folder-back" [style.background-color]="customColor || getColorVar('strong')">
334
+ <!-- Page Sheets -->
335
+ @for (sheet of getPageSheets(); track $index) {
336
+ <div class="page-sheet"></div>
337
+ }
338
+
339
+ <!-- Folder Front -->
340
+ <div class="folder-front" [style.--border-color]="customColor || getColorVar('strong')" [style.background-color]="customColor || getColorVar('base')">
341
+ <!-- Icon (Centered) -->
342
+ <div class="folder-icon">
343
+ <ds-icon [name]="iconName" [size]="'32px'" [style.color]="'white'" />
344
+ </div>
345
+ </div>
346
+ </div>
347
+ </div>
348
+
349
+ <!-- Label and Item Count -->
350
+ <div class="folder-label-container">
351
+ <div class="folder-label ui-sm-semiBold">{{ label }}</div>
352
+ <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
353
+ @if (loading) {
354
+ <span class="loading-indicator">Loading...</span>
355
+ } @else if (error) {
356
+ <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">Error</span>
357
+ } @else {
358
+ <span>{{ itemCount }}</span>
359
+ <span class="item-count-label">emner</span>
360
+ }
361
+ </div>
362
+ </div>
363
+ `,
364
+ })
365
+ export class DsMobileHandbookFolderComponent {
366
+ /**
367
+ * Color variant for the folder
368
+ * Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey
369
+ * Example: 'pink', 'success', 'blue'
370
+ */
371
+ @Input() variant: string = 'light-purple';
372
+
373
+ /**
374
+ * Optional custom hex color for the folder.
375
+ * If provided, overrides the variant color completely.
376
+ */
377
+ @Input() customColor?: string;
378
+
379
+ /**
380
+ * Icon name from the design system icon library
381
+ * Example: 'remixLightbulbLine', 'remixFolder3Line'
382
+ */
383
+ @Input() iconName: string = 'remixFolder3Line';
384
+
385
+ /**
386
+ * Number of items in the folder
387
+ * This should match the length of the items array when data is loaded
388
+ */
389
+ @Input() itemCount: number = 0;
390
+
391
+ /**
392
+ * Label text displayed below the folder (category name)
393
+ */
394
+ @Input() label: string = 'Folder';
395
+
396
+ /**
397
+ * Optional items data for the handbook folder
398
+ * Pass the HandbookItem[] array from your API response here
399
+ */
400
+ @Input() items?: HandbookItem[];
401
+
402
+ /**
403
+ * Loading state - when true, shows "Loading..." indicator instead of item count
404
+ * Set this to true while fetching data from your API
405
+ */
406
+ @Input() loading: boolean = false;
407
+
408
+ /**
409
+ * Error state - when set, shows "Error" indicator instead of item count
410
+ * Set this to an error message string if API call fails
411
+ */
412
+ @Input() error?: string;
413
+
414
+ /**
415
+ * Track open/closed state for animation
416
+ */
417
+ isOpen = signal(false);
418
+
419
+ /**
420
+ * Get the CSS variable name for the color variant
421
+ */
422
+ getColorVar(suffix: 'base' | 'strong'): string {
423
+ const variantMap: Record<string, string> = {
424
+ // Core design system variants
425
+ success: 'success',
426
+ warning: 'warning',
427
+ destructive: 'destructive',
428
+ blue: 'blue',
429
+ 'light-purple': 'light-purple',
430
+ pink: 'pink',
431
+ 'salmon-orange': 'salmon-orange',
432
+ orange: 'orange',
433
+ 'lime-green': 'lime-green',
434
+ grey: 'grey',
435
+
436
+ // Extended API colors mapping to their native exact counterparts now
437
+ red: 'red',
438
+ green: 'green',
439
+ yellow: 'yellow',
440
+ purple: 'purple',
441
+ indigo: 'indigo',
442
+ lime: 'lime',
443
+ teal: 'teal',
444
+ cyan: 'cyan',
445
+ brown: 'brown',
446
+ 'light-blue': 'light-blue',
447
+ 'light-green': 'light-green',
448
+ coral: 'coral',
449
+ salmon: 'salmon',
450
+ seagreen: 'seagreen',
451
+ };
452
+
453
+ const colorName = variantMap[this.variant] || 'light-purple';
454
+ return `var(--color-${colorName}-${suffix})`;
455
+ }
456
+
457
+ /**
458
+ * Open folder animation
459
+ */
460
+ @HostListener('mouseenter')
461
+ open(): void {
462
+ this.isOpen.set(true);
463
+ }
464
+
465
+ /**
466
+ * Close folder animation
467
+ */
468
+ @HostListener('mouseleave')
469
+ close(): void {
470
+ this.isOpen.set(false);
471
+ }
472
+
473
+ /**
474
+ * Handle touch start - open animation
475
+ */
476
+ @HostListener('touchstart', ['$event'])
477
+ onTouchStart(event: TouchEvent): void {
478
+ this.isOpen.set(true);
479
+ }
480
+
481
+ /**
482
+ * Handle touch end - close animation
483
+ */
484
+ @HostListener('touchend')
485
+ onTouchEnd(): void {
486
+ this.isOpen.set(false);
487
+ }
488
+
489
+ /**
490
+ * Handle touch cancel - close animation
491
+ */
492
+ @HostListener('touchcancel')
493
+ onTouchCancel(): void {
494
+ this.isOpen.set(false);
495
+ }
496
+
497
+ /**
498
+ * Handle click - open modal
499
+ * Only opens modal if not in loading or error state
500
+ */
501
+ @HostListener('click')
502
+ async onClick(): Promise<void> {
503
+ // Don't open modal if loading or in error state
504
+ if (this.loading || this.error) {
505
+ return;
506
+ }
507
+
508
+ const handbookData: HandbookDetailData = {
509
+ title: this.label,
510
+ variant: this.variant,
511
+ customColor: this.customColor,
512
+ iconName: this.iconName,
513
+ itemCount: this.itemCount,
514
+ items: this.items,
515
+ };
516
+
517
+ await this.handbookModal.open(handbookData, {
518
+ loading: this.loading,
519
+ error: this.error,
520
+ });
521
+ }
522
+
523
+ /**
524
+ * Calculate the number of page sheets to display
525
+ * Max 6 sheets regardless of item count
526
+ */
527
+ getPageSheets(): number[] {
528
+ const count = Math.min(this.itemCount, 6);
529
+ return Array(count).fill(0);
530
+ }
531
+
532
+ constructor(private handbookModal: DsMobileHandbookDetailModalService) {}
533
+ }
@@ -0,0 +1,4 @@
1
+ export { DsMobileHandbookFolderComponent } from './ds-mobile-handbook-folder';
2
+ export { DsMobileHandbookFolderMiniComponent } from './ds-mobile-handbook-folder-mini';
3
+
4
+