@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.
- package/fesm2022/propbinder-mobile-design.mjs +26206 -0
- package/fesm2022/propbinder-mobile-design.mjs.map +1 -0
- package/index.d.ts +8193 -0
- package/package.json +39 -3
- package/ng-package.json +0 -24
- package/src/animations/page-transitions.ts +0 -165
- package/src/components/action-list-item/ds-mobile-action-list-item.ts +0 -102
- package/src/components/action-list-item/index.ts +0 -2
- package/src/components/app-icon/ds-app-icon.ts +0 -133
- package/src/components/app-icon/index.ts +0 -2
- package/src/components/attachment-preview/ds-mobile-attachment-preview.css +0 -139
- package/src/components/attachment-preview/ds-mobile-attachment-preview.ts +0 -164
- package/src/components/attachment-preview/index.ts +0 -1
- package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +0 -142
- package/src/components/avatar-with-badge/index.ts +0 -2
- package/src/components/booking-modal/ds-mobile-booking-confirmation-wrapper.ts +0 -71
- package/src/components/booking-modal/ds-mobile-booking-modal.service.ts +0 -121
- package/src/components/booking-modal/ds-mobile-booking-modal.ts +0 -598
- package/src/components/booking-modal/ds-mobile-booking-summary.ts +0 -161
- package/src/components/booking-modal/index.ts +0 -4
- package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +0 -266
- package/src/components/bottom-sheet/ds-mobile-bottom-sheet-header.ts +0 -146
- package/src/components/bottom-sheet/ds-mobile-bottom-sheet-wrapper.ts +0 -156
- package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +0 -101
- package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +0 -169
- package/src/components/bottom-sheet/ds-mobile-confirmation-sheet.ts +0 -211
- package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +0 -578
- package/src/components/bottom-sheet/ds-mobile-profile-actions-sheet.ts +0 -614
- package/src/components/bottom-sheet/index.ts +0 -8
- package/src/components/bottom-sheet/modal-shadow-fix.ts +0 -42
- package/src/components/card-inline/ds-mobile-card-inline.ts +0 -301
- package/src/components/card-inline/index.ts +0 -2
- package/src/components/card-inline-banner/ds-mobile-card-inline-banner.ts +0 -118
- package/src/components/card-inline-banner/index.ts +0 -1
- package/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts +0 -120
- package/src/components/card-inline-contact/index.ts +0 -1
- package/src/components/card-inline-file/ds-mobile-card-inline-file.ts +0 -141
- package/src/components/card-inline-file/index.ts +0 -1
- package/src/components/chat-modal/ds-mobile-chat-modal.css +0 -159
- package/src/components/chat-modal/ds-mobile-chat-modal.service.ts +0 -105
- package/src/components/chat-modal/ds-mobile-chat-modal.ts +0 -918
- package/src/components/chat-modal/index.ts +0 -8
- package/src/components/comment/ds-mobile-comment.ts +0 -568
- package/src/components/comment/index.ts +0 -2
- package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +0 -182
- package/src/components/contact-list-item/index.ts +0 -2
- package/src/components/content/ds-mobile-content.ts +0 -139
- package/src/components/content/index.ts +0 -2
- package/src/components/dropdown/ds-mobile-dropdown.css +0 -199
- package/src/components/dropdown/ds-mobile-dropdown.ts +0 -340
- package/src/components/dropdown/index.ts +0 -2
- package/src/components/ds-mobile-tabs.css +0 -407
- package/src/components/ds-mobile-tabs.ts +0 -216
- package/src/components/empty-state/ds-mobile-empty-state.ts +0 -120
- package/src/components/empty-state/index.ts +0 -2
- package/src/components/fab/ds-mobile-fab.ts +0 -315
- package/src/components/fab/index.ts +0 -1
- package/src/components/facility-creation-modal/ds-mobile-facility-creation-confirmation-wrapper.ts +0 -121
- package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.css +0 -189
- package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.service.ts +0 -135
- package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.ts +0 -656
- package/src/components/facility-creation-modal/index.ts +0 -9
- package/src/components/facility-creation-modal/sheets/ds-mobile-access-sheet.ts +0 -105
- package/src/components/facility-creation-modal/sheets/ds-mobile-price-sheet.ts +0 -188
- package/src/components/facility-creation-modal/sheets/ds-mobile-when-can-book-sheet.ts +0 -460
- package/src/components/facility-creation-modal/sheets/ds-mobile-who-can-book-sheet.ts +0 -134
- package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.service.ts +0 -69
- package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.ts +0 -379
- package/src/components/facility-detail-modal/index.ts +0 -2
- package/src/components/file-attachment/ds-mobile-file-attachment.ts +0 -164
- package/src/components/file-attachment/index.ts +0 -2
- package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.css +0 -214
- package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +0 -84
- package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +0 -424
- package/src/components/handbook-detail-modal/index.ts +0 -3
- package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +0 -175
- package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +0 -533
- package/src/components/handbook-folder/index.ts +0 -4
- package/src/components/header-content/ds-mobile-header-content.ts +0 -222
- package/src/components/header-content/index.ts +0 -2
- package/src/components/illustration/ds-mobile-illustration.ts +0 -124
- package/src/components/illustration/index.ts +0 -2
- package/src/components/index.ts +0 -124
- package/src/components/inline-photo/ds-mobile-inline-photo.ts +0 -361
- package/src/components/inline-photo/index.ts +0 -1
- package/src/components/inline-tabs/ds-mobile-inline-tabs.ts +0 -132
- package/src/components/inline-tabs/index.ts +0 -2
- package/src/components/interactive-list-item-booking/ds-mobile-interactive-list-item-booking.ts +0 -350
- package/src/components/interactive-list-item-booking/index.ts +0 -1
- package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +0 -321
- package/src/components/interactive-list-item-inquiry/index.ts +0 -2
- package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +0 -237
- package/src/components/interactive-list-item-message/index.ts +0 -2
- package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +0 -549
- package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +0 -124
- package/src/components/interactive-list-item-post/index.ts +0 -13
- package/src/components/lightbox/ds-mobile-lightbox-footer.ts +0 -315
- package/src/components/lightbox/ds-mobile-lightbox-header.ts +0 -202
- package/src/components/lightbox/ds-mobile-lightbox-image.ts +0 -484
- package/src/components/lightbox/ds-mobile-lightbox-pdf.css +0 -377
- package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +0 -374
- package/src/components/lightbox/ds-mobile-lightbox.css +0 -587
- package/src/components/lightbox/ds-mobile-lightbox.service.ts +0 -296
- package/src/components/lightbox/ds-mobile-lightbox.ts +0 -529
- package/src/components/lightbox/index.ts +0 -22
- package/src/components/list-item/ds-mobile-list-item.ts +0 -603
- package/src/components/list-item/index.ts +0 -2
- package/src/components/list-item-static/ds-mobile-list-item-static.ts +0 -133
- package/src/components/list-item-static/index.ts +0 -2
- package/src/components/loader-overlay/ds-mobile-loader-overlay.css +0 -49
- package/src/components/loader-overlay/ds-mobile-loader-overlay.ts +0 -77
- package/src/components/loader-overlay/index.ts +0 -1
- package/src/components/logo/ds-logo.ts +0 -95
- package/src/components/logo/index.ts +0 -2
- package/src/components/message-bubble/ds-mobile-message-bubble.ts +0 -633
- package/src/components/message-bubble/index.ts +0 -7
- package/src/components/message-composer/ds-mobile-message-composer.ts +0 -1146
- package/src/components/message-composer/index.ts +0 -7
- package/src/components/modal/ds-mobile-modal.css +0 -163
- package/src/components/modal/ds-mobile-modal.service.ts +0 -329
- package/src/components/modal/index.ts +0 -8
- package/src/components/modal-base/ds-mobile-modal-base.css +0 -378
- package/src/components/modal-base/ds-mobile-modal-base.ts +0 -261
- package/src/components/modal-base/index.ts +0 -2
- package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.css +0 -112
- package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.service.ts +0 -93
- package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.ts +0 -442
- package/src/components/new-inquiry-modal/index.ts +0 -4
- package/src/components/offline-banner/ds-mobile-offline-banner.ts +0 -135
- package/src/components/offline-banner/index.ts +0 -1
- package/src/components/page-details/ds-mobile-page-details.css +0 -83
- package/src/components/page-details/ds-mobile-page-details.ts +0 -282
- package/src/components/page-details/index.ts +0 -2
- package/src/components/page-main/ds-mobile-page-main.css +0 -68
- package/src/components/page-main/ds-mobile-page-main.ts +0 -421
- package/src/components/page-main/index.ts +0 -2
- package/src/components/post-composer/ds-mobile-post-composer.ts +0 -140
- package/src/components/post-composer/index.ts +0 -2
- package/src/components/post-detail-modal/ds-mobile-post-detail-modal.css +0 -390
- package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +0 -108
- package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +0 -722
- package/src/components/post-detail-modal/index.ts +0 -9
- package/src/components/property-banner/ds-mobile-property-banner.ts +0 -95
- package/src/components/property-banner/index.ts +0 -2
- package/src/components/section/ds-mobile-section.ts +0 -263
- package/src/components/section/index.ts +0 -2
- package/src/components/shared/directives/index.ts +0 -2
- package/src/components/shared/directives/long-press.directive.ts +0 -212
- package/src/components/shared/index.ts +0 -3
- package/src/components/shared/mobile-modal-base.ts +0 -457
- package/src/components/shared/mobile-page-base.ts +0 -204
- package/src/components/swiper/ds-mobile-swiper-with-nav.ts +0 -160
- package/src/components/swiper/ds-mobile-swiper.ts +0 -327
- package/src/components/swiper/index.ts +0 -3
- package/src/components/system-message-banner/ds-mobile-system-message-banner.ts +0 -129
- package/src/components/system-message-banner/index.ts +0 -2
- package/src/components/tab-bar/ds-mobile-tab-bar.css +0 -533
- package/src/components/tab-bar/ds-mobile-tab-bar.ts +0 -735
- package/src/components/tab-bar/index.ts +0 -2
- package/src/components/tabs/ds-mobile-tabs.css +0 -25
- package/src/components/tabs/ds-mobile-tabs.ts +0 -89
- package/src/components/tabs/index.ts +0 -2
- package/src/components/text-input/ds-text-input.ts +0 -287
- package/src/components/text-input/index.ts +0 -2
- package/src/examples/booking.page.ts +0 -434
- package/src/examples/community.page.ts +0 -776
- package/src/examples/handbook.page.ts +0 -324
- package/src/examples/home.page.ts +0 -347
- package/src/examples/index.ts +0 -12
- package/src/examples/inquiries.example.ts +0 -273
- package/src/examples/inquiry-detail.example.css +0 -189
- package/src/examples/inquiry-detail.example.ts +0 -415
- package/src/examples/mobile-tabs-example.component.ts +0 -208
- package/src/examples/post-create.page.ts +0 -311
- package/src/examples/post-detail.page.ts +0 -296
- package/src/examples/sign-in.page.ts +0 -291
- package/src/examples/whitelabel-demo-modal.component.ts +0 -1094
- package/src/examples/whitelabel-demo-modal.service.ts +0 -77
- package/src/models/index.ts +0 -7
- package/src/models/post.model.ts +0 -41
- package/src/pages/community.page.ts +0 -769
- package/src/pages/handbook.page.ts +0 -388
- package/src/pages/home.page.ts +0 -303
- package/src/pages/index.ts +0 -11
- package/src/pages/inquiries.example.ts +0 -273
- package/src/pages/inquiry-detail.example.css +0 -189
- package/src/pages/inquiry-detail.example.ts +0 -415
- package/src/pages/mobile-tabs-example.component.ts +0 -179
- package/src/pages/post-create.page.ts +0 -311
- package/src/pages/post-detail.page.ts +0 -296
- package/src/pages/sign-in.page.ts +0 -291
- package/src/pages/whitelabel-demo-modal.component.ts +0 -1094
- package/src/pages/whitelabel-demo-modal.service.ts +0 -77
- package/src/public-api.ts +0 -6
- package/src/services/base-modal.service.ts +0 -101
- package/src/services/index.ts +0 -11
- package/src/services/posts.service.ts +0 -542
- package/src/services/tracking-permission.service.ts +0 -88
- package/src/services/user.service.ts +0 -60
- package/src/services/whitelabel.service.ts +0 -675
- package/tsconfig.lib.json +0 -17
- package/tsconfig.lib.prod.json +0 -9
- package/tsconfig.spec.json +0 -13
- /package/{src/assets → assets}/fonts/Brockmann-Bold.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-BoldItalic.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-Medium.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-MediumItalic.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-Regular.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-RegularItalic.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-SemiBold.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann-SemiBoldItalic.otf +0 -0
- /package/{src/assets → assets}/fonts/Brockmann_desktop_license.pdf +0 -0
- /package/{src/assets → assets}/fonts/brockmann-medium-webfont.woff2 +0 -0
- /package/{src/assets → assets}/fonts/brockmann-mediumitalic-webfont.woff2 +0 -0
- /package/{src/assets → assets}/fonts/brockmann-regular-webfont.woff2 +0 -0
- /package/{src/assets → assets}/fonts/brockmann-regularitalic-webfont.woff2 +0 -0
- /package/{src/assets → assets}/fonts/brockmann-semibold-webfont.woff2 +0 -0
- /package/{src/assets → assets}/fonts/brockmann-semibolditalic-webfont.woff2 +0 -0
- /package/{src/styles → styles}/ionic.css +0 -0
- /package/{src/components/shared → styles}/mobile-common.css +0 -0
- /package/{src/components/shared → styles}/mobile-page-base.css +0 -0
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Component, input } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* DsMobilePropertyBannerComponent
|
|
6
|
-
*
|
|
7
|
-
* Compact banner displaying property photo and address.
|
|
8
|
-
* Designed for use in page headers to show current property context.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```html
|
|
12
|
-
* <ds-mobile-property-banner
|
|
13
|
-
* address="Toftegårds Allé 5A, 2. tv."
|
|
14
|
-
* photoUrl="/Assets/building.jpg">
|
|
15
|
-
* </ds-mobile-property-banner>
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
@Component({
|
|
19
|
-
selector: 'ds-mobile-property-banner',
|
|
20
|
-
standalone: true,
|
|
21
|
-
imports: [CommonModule],
|
|
22
|
-
styles: [`
|
|
23
|
-
:host {
|
|
24
|
-
display: block;
|
|
25
|
-
width: 100%;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.property-banner {
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
gap: 8px;
|
|
32
|
-
height: 40px;
|
|
33
|
-
padding: 0 8px;
|
|
34
|
-
background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.1);
|
|
35
|
-
border: none;
|
|
36
|
-
backdrop-filter: blur(10px);
|
|
37
|
-
border-radius: 12px;
|
|
38
|
-
cursor: pointer;
|
|
39
|
-
transition: background 0.2s ease;
|
|
40
|
-
-webkit-tap-highlight-color: transparent;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.property-banner:hover {
|
|
44
|
-
background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.12);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.property-banner:active {
|
|
48
|
-
background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.15);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.property-photo {
|
|
52
|
-
width: 24px;
|
|
53
|
-
height: 24px;
|
|
54
|
-
border-radius: 6px;
|
|
55
|
-
object-fit: cover;
|
|
56
|
-
flex-shrink: 0;
|
|
57
|
-
background: rgba(var(--header-content-color-rgb, 255, 255, 255), 0.1);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.property-address {
|
|
61
|
-
font-family: 'Brockmann', sans-serif;
|
|
62
|
-
font-size: var(--font-size-sm);
|
|
63
|
-
font-weight: 500;
|
|
64
|
-
color: var(--header-content-color, white);
|
|
65
|
-
line-height: 1.4;
|
|
66
|
-
flex: 1;
|
|
67
|
-
min-width: 0;
|
|
68
|
-
white-space: nowrap;
|
|
69
|
-
overflow: hidden;
|
|
70
|
-
text-overflow: ellipsis;
|
|
71
|
-
}
|
|
72
|
-
`],
|
|
73
|
-
template: `
|
|
74
|
-
<div class="property-banner">
|
|
75
|
-
<img
|
|
76
|
-
[src]="photoUrl()"
|
|
77
|
-
[alt]="address()"
|
|
78
|
-
class="property-photo"
|
|
79
|
-
/>
|
|
80
|
-
<span class="property-address">{{ address() }}</span>
|
|
81
|
-
</div>
|
|
82
|
-
`
|
|
83
|
-
})
|
|
84
|
-
export class DsMobilePropertyBannerComponent {
|
|
85
|
-
/**
|
|
86
|
-
* Property address text
|
|
87
|
-
*/
|
|
88
|
-
address = input.required<string>();
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* URL to property photo
|
|
92
|
-
*/
|
|
93
|
-
photoUrl = input.required<string>();
|
|
94
|
-
}
|
|
95
|
-
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { Component, input, output } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { DsIconComponent } from '@propbinder/design-system';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* DsMobileSectionComponent
|
|
7
|
-
*
|
|
8
|
-
* Universal section component for mobile pages, modals, and content containers.
|
|
9
|
-
* Provides consistent layout with optional headlines, action links, flexible padding, and borders.
|
|
10
|
-
*
|
|
11
|
-
* **Features:**
|
|
12
|
-
* - Optional section headline with icon support
|
|
13
|
-
* - Optional action link with click handler
|
|
14
|
-
* - Flexible padding control
|
|
15
|
-
* - Border management (bottom border by default)
|
|
16
|
-
* - Works in pages, modals, and any content container
|
|
17
|
-
*
|
|
18
|
-
* **Usage Patterns:**
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```html
|
|
22
|
-
* <!-- Section with headline and link -->
|
|
23
|
-
* <ds-mobile-section
|
|
24
|
-
* headline="Recent Posts"
|
|
25
|
-
* linkText="See all"
|
|
26
|
-
* (linkClick)="navigate()">
|
|
27
|
-
* <div class="posts-list">...</div>
|
|
28
|
-
* </ds-mobile-section>
|
|
29
|
-
*
|
|
30
|
-
* <!-- Section with icon in headline -->
|
|
31
|
-
* <ds-mobile-section
|
|
32
|
-
* headline="Messages"
|
|
33
|
-
* icon="remixChat3Line"
|
|
34
|
-
* linkText="View all"
|
|
35
|
-
* (linkClick)="viewMessages()">
|
|
36
|
-
* <div class="messages">...</div>
|
|
37
|
-
* </ds-mobile-section>
|
|
38
|
-
*
|
|
39
|
-
* <!-- Empty state section (no headline) -->
|
|
40
|
-
* <ds-mobile-section>
|
|
41
|
-
* <div class="empty-state">
|
|
42
|
-
* <ds-avatar type="icon" iconName="remixInboxLine" />
|
|
43
|
-
* <h3>No messages yet</h3>
|
|
44
|
-
* </div>
|
|
45
|
-
* </ds-mobile-section>
|
|
46
|
-
*
|
|
47
|
-
* <!-- Last section without border -->
|
|
48
|
-
* <ds-mobile-section
|
|
49
|
-
* headline="Contact"
|
|
50
|
-
* [showBorder]="false">
|
|
51
|
-
* <div class="contact-form">...</div>
|
|
52
|
-
* </ds-mobile-section>
|
|
53
|
-
*
|
|
54
|
-
* <!-- Section with custom padding -->
|
|
55
|
-
* <ds-mobile-section
|
|
56
|
-
* headline="Photos"
|
|
57
|
-
* padding="20px 0">
|
|
58
|
-
* <div class="photo-grid">...</div>
|
|
59
|
-
* </ds-mobile-section>
|
|
60
|
-
*
|
|
61
|
-
* <!-- Full-width section in page (default behavior) -->
|
|
62
|
-
* <ds-mobile-page-main title="Home">
|
|
63
|
-
* <ds-mobile-section headline="Posts">
|
|
64
|
-
* <div class="posts">...</div>
|
|
65
|
-
* </ds-mobile-section>
|
|
66
|
-
* </ds-mobile-page-main>
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
@Component({
|
|
70
|
-
selector: 'ds-mobile-section',
|
|
71
|
-
standalone: true,
|
|
72
|
-
imports: [CommonModule, DsIconComponent],
|
|
73
|
-
host: {
|
|
74
|
-
'[class.has-border]': 'showBorder()'
|
|
75
|
-
},
|
|
76
|
-
styles: [`
|
|
77
|
-
:host {
|
|
78
|
-
display: block;
|
|
79
|
-
width: 100%;
|
|
80
|
-
border-bottom: 1px solid transparent;
|
|
81
|
-
transition: border-color 0.2s ease;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
:host(.has-border) {
|
|
85
|
-
border-bottom-color: var(--border-color-default);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/* Automatically hide border on last section */
|
|
89
|
-
:host(.has-border):last-child {
|
|
90
|
-
border-bottom-color: transparent;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.section {
|
|
94
|
-
width: 100%;
|
|
95
|
-
display: flex;
|
|
96
|
-
flex-direction: column;
|
|
97
|
-
padding: var(--section-padding, 20px);
|
|
98
|
-
gap: var(--section-gap, 12px);
|
|
99
|
-
overflow: var(--section-overflow);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/* Increase padding on desktop breakpoints */
|
|
103
|
-
@media (min-width: 768px) {
|
|
104
|
-
.section {
|
|
105
|
-
padding: var(--section-padding, 32px);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/* Remove horizontal padding on desktop when inside page components */
|
|
109
|
-
ds-mobile-page-main :host .section,
|
|
110
|
-
ds-mobile-page-details :host .section {
|
|
111
|
-
padding-left: 0;
|
|
112
|
-
padding-right: 0;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.section-header {
|
|
117
|
-
display: flex;
|
|
118
|
-
align-items: center;
|
|
119
|
-
justify-content: space-between;
|
|
120
|
-
gap: 12px;
|
|
121
|
-
min-height: 24px;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.section-headline {
|
|
125
|
-
font-family: 'Brockmann', sans-serif;
|
|
126
|
-
font-size: var(--font-size-base);
|
|
127
|
-
font-weight: 600;
|
|
128
|
-
color: var(--text-color-default-primary);
|
|
129
|
-
margin: 0;
|
|
130
|
-
padding: 0;
|
|
131
|
-
letter-spacing: -0.2px;
|
|
132
|
-
display: flex;
|
|
133
|
-
align-items: center;
|
|
134
|
-
gap: 6px;
|
|
135
|
-
line-height: 1.4;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.section-link {
|
|
139
|
-
font-family: 'Brockmann', sans-serif;
|
|
140
|
-
font-size: var(--font-size-sm);
|
|
141
|
-
font-weight: 500;
|
|
142
|
-
color: var(--color-accent, #5d5fef);
|
|
143
|
-
text-decoration: none;
|
|
144
|
-
cursor: pointer;
|
|
145
|
-
white-space: nowrap;
|
|
146
|
-
transition: opacity 0.2s ease;
|
|
147
|
-
-webkit-tap-highlight-color: transparent;
|
|
148
|
-
display: flex;
|
|
149
|
-
align-items: center;
|
|
150
|
-
gap: 2px;
|
|
151
|
-
line-height: 1;
|
|
152
|
-
user-select: none;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.section-link:hover {
|
|
156
|
-
opacity: 0.8;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
.section-link:active {
|
|
160
|
-
opacity: 0.6;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.section-content {
|
|
164
|
-
display: flex;
|
|
165
|
-
flex-direction: column;
|
|
166
|
-
gap: var(--section-content-gap);
|
|
167
|
-
}
|
|
168
|
-
`],
|
|
169
|
-
template: `
|
|
170
|
-
<section class="section" [style.--section-padding]="padding()" [style.--section-gap]="gap()" [style.--section-content-gap]="contentGap()" [style.--section-overflow]="overflow()">
|
|
171
|
-
@if (headline() || linkText()) {
|
|
172
|
-
<header class="section-header">
|
|
173
|
-
@if (headline()) {
|
|
174
|
-
<h2 class="section-headline">
|
|
175
|
-
@if (icon()) {
|
|
176
|
-
<ds-icon [name]="icon()!" size="20px" />
|
|
177
|
-
}
|
|
178
|
-
{{ headline() }}
|
|
179
|
-
</h2>
|
|
180
|
-
}
|
|
181
|
-
@if (linkText()) {
|
|
182
|
-
<a class="section-link" (click)="handleLinkClick()" [attr.role]="'button'" [attr.tabindex]="0">
|
|
183
|
-
{{ linkText() }}
|
|
184
|
-
<ds-icon name="remixArrowRightSLine" size="16px" />
|
|
185
|
-
</a>
|
|
186
|
-
}
|
|
187
|
-
<ng-content select="[header-action]" />
|
|
188
|
-
</header>
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
<div class="section-content">
|
|
192
|
-
<ng-content />
|
|
193
|
-
</div>
|
|
194
|
-
</section>
|
|
195
|
-
`
|
|
196
|
-
})
|
|
197
|
-
export class DsMobileSectionComponent {
|
|
198
|
-
/**
|
|
199
|
-
* Section headline text
|
|
200
|
-
* @default ''
|
|
201
|
-
*/
|
|
202
|
-
headline = input<string>('');
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Optional icon to display before headline
|
|
206
|
-
* @default ''
|
|
207
|
-
*/
|
|
208
|
-
icon = input<string>('');
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Link text (e.g., "See all", "View more")
|
|
212
|
-
* When provided, displays a clickable link in the section header
|
|
213
|
-
* @default ''
|
|
214
|
-
*/
|
|
215
|
-
linkText = input<string>('');
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Section padding
|
|
219
|
-
* Accepts any valid CSS padding value
|
|
220
|
-
* When not set, defaults to 20px on mobile and 32px on desktop
|
|
221
|
-
* @default ''
|
|
222
|
-
*/
|
|
223
|
-
padding = input<string>('');
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Gap between section header and content
|
|
227
|
-
* Accepts any valid CSS gap value
|
|
228
|
-
* @default '12px'
|
|
229
|
-
*/
|
|
230
|
-
gap = input<string>('12px');
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Gap between child elements within section-content
|
|
234
|
-
* Accepts any valid CSS gap value
|
|
235
|
-
* @default '12px'
|
|
236
|
-
*/
|
|
237
|
-
contentGap = input<string>('12px');
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Whether to show bottom border
|
|
241
|
-
* @default true
|
|
242
|
-
*/
|
|
243
|
-
showBorder = input<boolean>(true);
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* CSS overflow property for the section
|
|
247
|
-
* @default 'visible'
|
|
248
|
-
*/
|
|
249
|
-
overflow = input<string>('visible');
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Emitted when section link is clicked
|
|
253
|
-
*/
|
|
254
|
-
linkClick = output<void>();
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Handle link click event
|
|
258
|
-
*/
|
|
259
|
-
handleLinkClick(): void {
|
|
260
|
-
this.linkClick.emit();
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Directive,
|
|
3
|
-
Output,
|
|
4
|
-
EventEmitter,
|
|
5
|
-
HostListener,
|
|
6
|
-
Input,
|
|
7
|
-
OnDestroy
|
|
8
|
-
} from '@angular/core';
|
|
9
|
-
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* DsMobileLongPressDirective
|
|
13
|
-
*
|
|
14
|
-
* A reusable directive for handling long press interactions on mobile devices.
|
|
15
|
-
* Provides haptic feedback and prevents long press when touching interactive elements.
|
|
16
|
-
*
|
|
17
|
-
* Features:
|
|
18
|
-
* - Configurable duration and movement threshold
|
|
19
|
-
* - Automatic haptic feedback (with fallback to navigator.vibrate)
|
|
20
|
-
* - Excludes interactive elements (buttons, links, inputs)
|
|
21
|
-
* - Handles touchmove cancellation
|
|
22
|
-
* - Context menu support (right-click on desktop)
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```html
|
|
26
|
-
* <!-- Basic usage -->
|
|
27
|
-
* <div dsMobileLongPress (longPress)="handleLongPress()">
|
|
28
|
-
* Long press me
|
|
29
|
-
* </div>
|
|
30
|
-
*
|
|
31
|
-
* <!-- Custom duration and threshold -->
|
|
32
|
-
* <div
|
|
33
|
-
* dsMobileLongPress
|
|
34
|
-
* [longPressDuration]="800"
|
|
35
|
-
* [moveThreshold]="15"
|
|
36
|
-
* [excludeSelectors]="'button, a, .no-longpress'"
|
|
37
|
-
* (longPress)="showContextMenu()">
|
|
38
|
-
* Custom long press
|
|
39
|
-
* </div>
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
@Directive({
|
|
43
|
-
selector: '[dsMobileLongPress]',
|
|
44
|
-
standalone: true
|
|
45
|
-
})
|
|
46
|
-
export class DsMobileLongPressDirective implements OnDestroy {
|
|
47
|
-
/**
|
|
48
|
-
* Duration in milliseconds to trigger long press
|
|
49
|
-
* @default 500
|
|
50
|
-
*/
|
|
51
|
-
@Input() longPressDuration = 500;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Maximum movement in pixels before canceling long press
|
|
55
|
-
* @default 10
|
|
56
|
-
*/
|
|
57
|
-
@Input() moveThreshold = 10;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* CSS selectors to exclude from long press detection
|
|
61
|
-
* @default 'button, a, input, select, textarea, [role="button"]'
|
|
62
|
-
*/
|
|
63
|
-
@Input() excludeSelectors = 'button, a, input, select, textarea, [role="button"]';
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Haptic feedback style (Light, Medium, Heavy)
|
|
67
|
-
* @default ImpactStyle.Medium
|
|
68
|
-
*/
|
|
69
|
-
@Input() hapticStyle: ImpactStyle = ImpactStyle.Medium;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Enable/disable haptic feedback
|
|
73
|
-
* @default true
|
|
74
|
-
*/
|
|
75
|
-
@Input() enableHaptics = true;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Emits when long press is triggered
|
|
79
|
-
*/
|
|
80
|
-
@Output() longPress = new EventEmitter<void>();
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Emits when long press starts (timer begins)
|
|
84
|
-
*/
|
|
85
|
-
@Output() longPressStart = new EventEmitter<void>();
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Emits when long press is cancelled
|
|
89
|
-
*/
|
|
90
|
-
@Output() longPressCancel = new EventEmitter<void>();
|
|
91
|
-
|
|
92
|
-
private longPressTimer: any = null;
|
|
93
|
-
private longPressTriggered = false;
|
|
94
|
-
private touchStartX = 0;
|
|
95
|
-
private touchStartY = 0;
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Handle touch start for long press detection
|
|
99
|
-
*/
|
|
100
|
-
@HostListener('touchstart', ['$event'])
|
|
101
|
-
handleTouchStart(event: TouchEvent): void {
|
|
102
|
-
// Don't start long press if touching interactive child elements
|
|
103
|
-
// But allow if the closest match is the host element itself (where the directive is attached)
|
|
104
|
-
const target = event.target as HTMLElement;
|
|
105
|
-
const closestExcluded = target.closest(this.excludeSelectors);
|
|
106
|
-
const hostElement = (event.currentTarget as HTMLElement);
|
|
107
|
-
|
|
108
|
-
// Only exclude if we found an excluded element AND it's not the host itself
|
|
109
|
-
if (closestExcluded && closestExcluded !== hostElement) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
this.longPressTriggered = false;
|
|
114
|
-
this.touchStartX = event.touches[0].clientX;
|
|
115
|
-
this.touchStartY = event.touches[0].clientY;
|
|
116
|
-
|
|
117
|
-
// Emit start event
|
|
118
|
-
this.longPressStart.emit();
|
|
119
|
-
|
|
120
|
-
// Start long press timer
|
|
121
|
-
this.longPressTimer = setTimeout(async () => {
|
|
122
|
-
this.longPressTriggered = true;
|
|
123
|
-
this.longPress.emit();
|
|
124
|
-
|
|
125
|
-
// Haptic feedback for long press
|
|
126
|
-
if (this.enableHaptics) {
|
|
127
|
-
await this.triggerHaptics();
|
|
128
|
-
}
|
|
129
|
-
}, this.longPressDuration);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Handle touch end to clear long press timer
|
|
134
|
-
*/
|
|
135
|
-
@HostListener('touchend', ['$event'])
|
|
136
|
-
handleTouchEnd(event: TouchEvent): void {
|
|
137
|
-
if (this.longPressTimer) {
|
|
138
|
-
clearTimeout(this.longPressTimer);
|
|
139
|
-
this.longPressTimer = null;
|
|
140
|
-
|
|
141
|
-
if (!this.longPressTriggered) {
|
|
142
|
-
this.longPressCancel.emit();
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Prevent normal click if long press was triggered
|
|
147
|
-
if (this.longPressTriggered) {
|
|
148
|
-
event.preventDefault();
|
|
149
|
-
event.stopPropagation();
|
|
150
|
-
this.longPressTriggered = false;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Handle touch move to cancel long press if moved too much
|
|
156
|
-
*/
|
|
157
|
-
@HostListener('touchmove', ['$event'])
|
|
158
|
-
handleTouchMove(event: TouchEvent): void {
|
|
159
|
-
if (!this.longPressTimer) return;
|
|
160
|
-
|
|
161
|
-
const touch = event.touches[0];
|
|
162
|
-
const deltaX = Math.abs(touch.clientX - this.touchStartX);
|
|
163
|
-
const deltaY = Math.abs(touch.clientY - this.touchStartY);
|
|
164
|
-
|
|
165
|
-
// Cancel long press if moved too far
|
|
166
|
-
if (deltaX > this.moveThreshold || deltaY > this.moveThreshold) {
|
|
167
|
-
clearTimeout(this.longPressTimer);
|
|
168
|
-
this.longPressTimer = null;
|
|
169
|
-
this.longPressTriggered = false;
|
|
170
|
-
this.longPressCancel.emit();
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Handle context menu (right-click on desktop) to trigger long press action
|
|
176
|
-
*/
|
|
177
|
-
@HostListener('contextmenu', ['$event'])
|
|
178
|
-
handleContextMenu(event: Event): void {
|
|
179
|
-
event.preventDefault();
|
|
180
|
-
this.longPress.emit();
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Trigger haptic feedback
|
|
185
|
-
*/
|
|
186
|
-
private async triggerHaptics(): Promise<void> {
|
|
187
|
-
try {
|
|
188
|
-
await Haptics.impact({ style: this.hapticStyle });
|
|
189
|
-
} catch {
|
|
190
|
-
// Fallback to Web Vibration API if Capacitor Haptics is not available
|
|
191
|
-
if ('vibrate' in navigator) {
|
|
192
|
-
// Map haptic styles to vibration durations
|
|
193
|
-
const vibrationMap = {
|
|
194
|
-
[ImpactStyle.Light]: 30,
|
|
195
|
-
[ImpactStyle.Medium]: 50,
|
|
196
|
-
[ImpactStyle.Heavy]: 80
|
|
197
|
-
};
|
|
198
|
-
navigator.vibrate(vibrationMap[this.hapticStyle] || 50);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Cleanup on destroy
|
|
205
|
-
*/
|
|
206
|
-
ngOnDestroy(): void {
|
|
207
|
-
if (this.longPressTimer) {
|
|
208
|
-
clearTimeout(this.longPressTimer);
|
|
209
|
-
this.longPressTimer = null;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|