@propbinder/mobile-design 0.2.15 → 0.2.16
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 +1483 -1374
- package/fesm2022/propbinder-mobile-design.mjs.map +1 -1
- package/index.d.ts +219 -76
- package/package.json +1 -1
|
@@ -17,12 +17,12 @@ import { Camera, CameraSource, CameraResultType } from '@capacitor/camera';
|
|
|
17
17
|
import { Subject } from 'rxjs';
|
|
18
18
|
import { createAnimation } from '@ionic/core';
|
|
19
19
|
import { filter } from 'rxjs/operators';
|
|
20
|
-
import { Share } from '@capacitor/share';
|
|
21
20
|
import Swiper from 'swiper';
|
|
21
|
+
import { Pagination } from 'swiper/modules';
|
|
22
|
+
import { Share } from '@capacitor/share';
|
|
22
23
|
import { Filesystem, Directory } from '@capacitor/filesystem';
|
|
23
24
|
import { Browser } from '@capacitor/browser';
|
|
24
25
|
import { Capacitor } from '@capacitor/core';
|
|
25
|
-
import { Pagination } from 'swiper/modules';
|
|
26
26
|
import * as i1$3 from '@angular/platform-browser';
|
|
27
27
|
|
|
28
28
|
const DEFAULT_CONFIG = {
|
|
@@ -9479,902 +9479,1211 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9479
9479
|
}] } });
|
|
9480
9480
|
|
|
9481
9481
|
/**
|
|
9482
|
-
*
|
|
9482
|
+
* DsMobileSwiperComponent
|
|
9483
9483
|
*
|
|
9484
|
-
*
|
|
9485
|
-
* Displays author information and close button with consistent styling.
|
|
9486
|
-
*/
|
|
9487
|
-
class DsMobileLightboxHeaderComponent {
|
|
9488
|
-
/**
|
|
9489
|
-
* Author information to display
|
|
9490
|
-
*/
|
|
9491
|
-
author = input(...(ngDevMode ? [undefined, { debugName: "author" }] : []));
|
|
9492
|
-
/**
|
|
9493
|
-
* Emitted when close button is clicked
|
|
9494
|
-
*/
|
|
9495
|
-
closeClick = output();
|
|
9496
|
-
/**
|
|
9497
|
-
* Emitted when share button is clicked
|
|
9498
|
-
*/
|
|
9499
|
-
shareClick = output();
|
|
9500
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9501
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileLightboxHeaderComponent, isStandalone: true, selector: "ds-mobile-lightbox-header", inputs: { author: { classPropertyName: "author", publicName: "author", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeClick: "closeClick", shareClick: "shareClick" }, ngImport: i0, template: `
|
|
9502
|
-
<div class="lightbox-header lightbox-context">
|
|
9503
|
-
<div class="header-content">
|
|
9504
|
-
<!-- Post author info -->
|
|
9505
|
-
@if (author()) {
|
|
9506
|
-
<div class="post-author-info">
|
|
9507
|
-
<ds-avatar
|
|
9508
|
-
[initials]="author()!.avatarInitials ?? ''"
|
|
9509
|
-
[type]="author()!.avatarType ?? 'initials'"
|
|
9510
|
-
[src]="author()!.avatarSrc ?? ''"
|
|
9511
|
-
size="md"
|
|
9512
|
-
/>
|
|
9513
|
-
<div class="author-details">
|
|
9514
|
-
<div class="author-name">{{ author()!.name }}</div>
|
|
9515
|
-
<div class="author-meta">
|
|
9516
|
-
@if (author()!.role) {
|
|
9517
|
-
<span>{{ author()!.role }}</span>
|
|
9518
|
-
}
|
|
9519
|
-
@if (author()!.role && author()!.timestamp) {
|
|
9520
|
-
<span class="separator">·</span>
|
|
9521
|
-
}
|
|
9522
|
-
@if (author()!.timestamp) {
|
|
9523
|
-
<span>{{ author()!.timestamp }}</span>
|
|
9524
|
-
}
|
|
9525
|
-
</div>
|
|
9526
|
-
</div>
|
|
9527
|
-
</div>
|
|
9528
|
-
}
|
|
9529
|
-
|
|
9530
|
-
<!-- Action buttons - always visible -->
|
|
9531
|
-
<div class="header-actions">
|
|
9532
|
-
<ds-icon-button
|
|
9533
|
-
icon="remixShare2Line"
|
|
9534
|
-
variant="ghost"
|
|
9535
|
-
size="md"
|
|
9536
|
-
(clicked)="shareClick.emit()"
|
|
9537
|
-
class="share-button"
|
|
9538
|
-
[ariaLabel]="'Share'">
|
|
9539
|
-
</ds-icon-button>
|
|
9540
|
-
|
|
9541
|
-
<ds-icon-button
|
|
9542
|
-
icon="remixCloseLine"
|
|
9543
|
-
variant="ghost"
|
|
9544
|
-
size="md"
|
|
9545
|
-
(clicked)="closeClick.emit()"
|
|
9546
|
-
class="close-button"
|
|
9547
|
-
[ariaLabel]="'Close'">
|
|
9548
|
-
</ds-icon-button>
|
|
9549
|
-
</div>
|
|
9550
|
-
</div>
|
|
9551
|
-
</div>
|
|
9552
|
-
`, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ".lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:flex-end;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0;margin-right:auto}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.close-button,.share-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button,.share-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover,.share-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active,.share-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg,.share-button::ng-deep svg{color:#fff!important;fill:#fff!important}@supports (padding-top: env(safe-area-inset-top)){.lightbox-header{padding-top:calc(16px + env(safe-area-inset-top))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }] });
|
|
9553
|
-
}
|
|
9554
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxHeaderComponent, decorators: [{
|
|
9555
|
-
type: Component,
|
|
9556
|
-
args: [{ selector: 'ds-mobile-lightbox-header', standalone: true, imports: [CommonModule, DsIconButtonComponent, DsAvatarComponent], template: `
|
|
9557
|
-
<div class="lightbox-header lightbox-context">
|
|
9558
|
-
<div class="header-content">
|
|
9559
|
-
<!-- Post author info -->
|
|
9560
|
-
@if (author()) {
|
|
9561
|
-
<div class="post-author-info">
|
|
9562
|
-
<ds-avatar
|
|
9563
|
-
[initials]="author()!.avatarInitials ?? ''"
|
|
9564
|
-
[type]="author()!.avatarType ?? 'initials'"
|
|
9565
|
-
[src]="author()!.avatarSrc ?? ''"
|
|
9566
|
-
size="md"
|
|
9567
|
-
/>
|
|
9568
|
-
<div class="author-details">
|
|
9569
|
-
<div class="author-name">{{ author()!.name }}</div>
|
|
9570
|
-
<div class="author-meta">
|
|
9571
|
-
@if (author()!.role) {
|
|
9572
|
-
<span>{{ author()!.role }}</span>
|
|
9573
|
-
}
|
|
9574
|
-
@if (author()!.role && author()!.timestamp) {
|
|
9575
|
-
<span class="separator">·</span>
|
|
9576
|
-
}
|
|
9577
|
-
@if (author()!.timestamp) {
|
|
9578
|
-
<span>{{ author()!.timestamp }}</span>
|
|
9579
|
-
}
|
|
9580
|
-
</div>
|
|
9581
|
-
</div>
|
|
9582
|
-
</div>
|
|
9583
|
-
}
|
|
9584
|
-
|
|
9585
|
-
<!-- Action buttons - always visible -->
|
|
9586
|
-
<div class="header-actions">
|
|
9587
|
-
<ds-icon-button
|
|
9588
|
-
icon="remixShare2Line"
|
|
9589
|
-
variant="ghost"
|
|
9590
|
-
size="md"
|
|
9591
|
-
(clicked)="shareClick.emit()"
|
|
9592
|
-
class="share-button"
|
|
9593
|
-
[ariaLabel]="'Share'">
|
|
9594
|
-
</ds-icon-button>
|
|
9595
|
-
|
|
9596
|
-
<ds-icon-button
|
|
9597
|
-
icon="remixCloseLine"
|
|
9598
|
-
variant="ghost"
|
|
9599
|
-
size="md"
|
|
9600
|
-
(clicked)="closeClick.emit()"
|
|
9601
|
-
class="close-button"
|
|
9602
|
-
[ariaLabel]="'Close'">
|
|
9603
|
-
</ds-icon-button>
|
|
9604
|
-
</div>
|
|
9605
|
-
</div>
|
|
9606
|
-
</div>
|
|
9607
|
-
`, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ".lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:flex-end;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0;margin-right:auto}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.close-button,.share-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button,.share-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover,.share-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active,.share-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg,.share-button::ng-deep svg{color:#fff!important;fill:#fff!important}@supports (padding-top: env(safe-area-inset-top)){.lightbox-header{padding-top:calc(16px + env(safe-area-inset-top))}}\n"] }]
|
|
9608
|
-
}], propDecorators: { author: [{ type: i0.Input, args: [{ isSignal: true, alias: "author", required: false }] }], closeClick: [{ type: i0.Output, args: ["closeClick"] }], shareClick: [{ type: i0.Output, args: ["shareClick"] }] } });
|
|
9609
|
-
|
|
9610
|
-
/**
|
|
9611
|
-
* DsMobileLightboxFooterComponent
|
|
9484
|
+
* A reusable swiper/carousel component with configurable child width and spacing.
|
|
9612
9485
|
*
|
|
9613
|
-
*
|
|
9614
|
-
*
|
|
9486
|
+
* Features:
|
|
9487
|
+
* - First slide is left-aligned
|
|
9488
|
+
* - Middle slides are centered when active
|
|
9489
|
+
* - Last slide is right-aligned
|
|
9490
|
+
* - Configurable slide width and gap
|
|
9491
|
+
* - Content projection via ng-content
|
|
9492
|
+
*
|
|
9493
|
+
* Usage:
|
|
9494
|
+
* ```html
|
|
9495
|
+
* <ds-mobile-swiper [slideWidth]="'75vw'" [gap]="16">
|
|
9496
|
+
* <div class="swiper-slide">Slide 1</div>
|
|
9497
|
+
* <div class="swiper-slide">Slide 2</div>
|
|
9498
|
+
* <div class="swiper-slide">Slide 3</div>
|
|
9499
|
+
* </ds-mobile-swiper>
|
|
9500
|
+
* ```
|
|
9615
9501
|
*/
|
|
9616
|
-
class
|
|
9617
|
-
|
|
9618
|
-
* Whether to show navigation controls
|
|
9619
|
-
*/
|
|
9620
|
-
showNavigation = input(false, ...(ngDevMode ? [{ debugName: "showNavigation" }] : []));
|
|
9621
|
-
/**
|
|
9622
|
-
* Current image index (0-based)
|
|
9623
|
-
*/
|
|
9624
|
-
currentIndex = input(0, ...(ngDevMode ? [{ debugName: "currentIndex" }] : []));
|
|
9625
|
-
/**
|
|
9626
|
-
* Total number of images
|
|
9627
|
-
*/
|
|
9628
|
-
totalImages = input(1, ...(ngDevMode ? [{ debugName: "totalImages" }] : []));
|
|
9629
|
-
/**
|
|
9630
|
-
* Whether to show like & comment action buttons
|
|
9631
|
-
* @default false
|
|
9632
|
-
*/
|
|
9633
|
-
showActions = input(false, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
|
|
9634
|
-
/**
|
|
9635
|
-
* Whether the content is liked
|
|
9636
|
-
*/
|
|
9637
|
-
isLiked = input(false, ...(ngDevMode ? [{ debugName: "isLiked" }] : []));
|
|
9502
|
+
class DsMobileSwiperComponent {
|
|
9503
|
+
elementRef;
|
|
9638
9504
|
/**
|
|
9639
|
-
*
|
|
9505
|
+
* Width of each slide (e.g., '75vw', '300px', '80%')
|
|
9640
9506
|
*/
|
|
9641
|
-
|
|
9507
|
+
slideWidth = input('75vw', ...(ngDevMode ? [{ debugName: "slideWidth" }] : []));
|
|
9642
9508
|
/**
|
|
9643
|
-
*
|
|
9509
|
+
* Gap between slides in pixels
|
|
9644
9510
|
*/
|
|
9645
|
-
|
|
9511
|
+
gap = input(16, ...(ngDevMode ? [{ debugName: "gap" }] : []));
|
|
9646
9512
|
/**
|
|
9647
|
-
*
|
|
9513
|
+
* Enable pagination dots
|
|
9648
9514
|
*/
|
|
9649
|
-
|
|
9515
|
+
pagination = input(false, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
|
|
9650
9516
|
/**
|
|
9651
|
-
*
|
|
9517
|
+
* Enable auto height - container adapts to active slide's height
|
|
9652
9518
|
*/
|
|
9653
|
-
|
|
9519
|
+
autoHeight = input(false, ...(ngDevMode ? [{ debugName: "autoHeight" }] : []));
|
|
9654
9520
|
/**
|
|
9655
|
-
*
|
|
9521
|
+
* Enable progressive opacity based on slide position
|
|
9522
|
+
* Slides fade in/out smoothly as they move toward/away from center
|
|
9656
9523
|
*/
|
|
9657
|
-
|
|
9524
|
+
progressiveOpacity = input(false, ...(ngDevMode ? [{ debugName: "progressiveOpacity" }] : []));
|
|
9658
9525
|
/**
|
|
9659
|
-
*
|
|
9526
|
+
* Enable progressive scale based on slide position
|
|
9527
|
+
* Slides scale down smoothly as they move away from center
|
|
9660
9528
|
*/
|
|
9661
|
-
|
|
9662
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9663
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileLightboxFooterComponent, isStandalone: true, selector: "ds-mobile-lightbox-footer", inputs: { showNavigation: { classPropertyName: "showNavigation", publicName: "showNavigation", isSignal: true, isRequired: false, transformFunction: null }, currentIndex: { classPropertyName: "currentIndex", publicName: "currentIndex", isSignal: true, isRequired: false, transformFunction: null }, totalImages: { classPropertyName: "totalImages", publicName: "totalImages", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, isLiked: { classPropertyName: "isLiked", publicName: "isLiked", isSignal: true, isRequired: false, transformFunction: null }, likeCount: { classPropertyName: "likeCount", publicName: "likeCount", isSignal: true, isRequired: false, transformFunction: null }, commentCount: { classPropertyName: "commentCount", publicName: "commentCount", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { prevClick: "prevClick", nextClick: "nextClick", likeClick: "likeClick", commentClick: "commentClick" }, ngImport: i0, template: `
|
|
9664
|
-
<div class="lightbox-footer">
|
|
9665
|
-
<!-- Navigation controls (only shown for multiple images) -->
|
|
9666
|
-
@if (showNavigation() && totalImages() > 1) {
|
|
9667
|
-
<div class="footer-navigation">
|
|
9668
|
-
<button
|
|
9669
|
-
class="nav-button prev"
|
|
9670
|
-
(click)="prevClick.emit()"
|
|
9671
|
-
[disabled]="currentIndex() === 0"
|
|
9672
|
-
aria-label="Previous image">
|
|
9673
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
9674
|
-
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9675
|
-
</svg>
|
|
9676
|
-
</button>
|
|
9677
|
-
|
|
9678
|
-
<div class="counter">
|
|
9679
|
-
{{ currentIndex() + 1 }} / {{ totalImages() }}
|
|
9680
|
-
</div>
|
|
9681
|
-
|
|
9682
|
-
<button
|
|
9683
|
-
class="nav-button next"
|
|
9684
|
-
(click)="nextClick.emit()"
|
|
9685
|
-
[disabled]="currentIndex() === totalImages() - 1"
|
|
9686
|
-
aria-label="Next image">
|
|
9687
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
9688
|
-
<path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9689
|
-
</svg>
|
|
9690
|
-
</button>
|
|
9691
|
-
</div>
|
|
9692
|
-
}
|
|
9693
|
-
|
|
9694
|
-
<!-- Action buttons -->
|
|
9695
|
-
@if (showActions()) {
|
|
9696
|
-
<div class="footer-actions">
|
|
9697
|
-
<div class="action-buttons-left">
|
|
9698
|
-
<!-- Like button -->
|
|
9699
|
-
<ds-icon-button
|
|
9700
|
-
[icon]="isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'"
|
|
9701
|
-
variant="ghost"
|
|
9702
|
-
size="md"
|
|
9703
|
-
(click)="likeClick.emit()"
|
|
9704
|
-
[attr.data-liked]="isLiked()"
|
|
9705
|
-
class="action-button-like"
|
|
9706
|
-
[ariaLabel]="'Like'">
|
|
9707
|
-
</ds-icon-button>
|
|
9708
|
-
|
|
9709
|
-
<!-- Comment button -->
|
|
9710
|
-
<ds-icon-button
|
|
9711
|
-
icon="remixChat3Line"
|
|
9712
|
-
variant="ghost"
|
|
9713
|
-
size="md"
|
|
9714
|
-
(click)="commentClick.emit()"
|
|
9715
|
-
class="action-button-comment"
|
|
9716
|
-
[ariaLabel]="'Comment'">
|
|
9717
|
-
</ds-icon-button>
|
|
9718
|
-
</div>
|
|
9719
|
-
</div>
|
|
9720
|
-
}
|
|
9721
|
-
</div>
|
|
9722
|
-
`, isInline: true, styles: [".lightbox-footer{position:fixed;bottom:0;left:0;right:0;z-index:100;padding:16px 20px 20px;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none;display:flex;flex-direction:column;gap:12px}.footer-navigation{display:flex;align-items:center;justify-content:center;gap:24px;pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);border-radius:50%;color:#fff;width:40px;height:40px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);padding:0}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px;flex-shrink:0}.counter{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-radius:100px;padding:8px 16px;color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;letter-spacing:-.3px;pointer-events:auto;-webkit-user-select:none;user-select:none}.footer-actions{display:flex;align-items:center;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-footer{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
|
|
9723
|
-
}
|
|
9724
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxFooterComponent, decorators: [{
|
|
9725
|
-
type: Component,
|
|
9726
|
-
args: [{ selector: 'ds-mobile-lightbox-footer', standalone: true, imports: [CommonModule, DsIconButtonComponent], template: `
|
|
9727
|
-
<div class="lightbox-footer">
|
|
9728
|
-
<!-- Navigation controls (only shown for multiple images) -->
|
|
9729
|
-
@if (showNavigation() && totalImages() > 1) {
|
|
9730
|
-
<div class="footer-navigation">
|
|
9731
|
-
<button
|
|
9732
|
-
class="nav-button prev"
|
|
9733
|
-
(click)="prevClick.emit()"
|
|
9734
|
-
[disabled]="currentIndex() === 0"
|
|
9735
|
-
aria-label="Previous image">
|
|
9736
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
9737
|
-
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9738
|
-
</svg>
|
|
9739
|
-
</button>
|
|
9740
|
-
|
|
9741
|
-
<div class="counter">
|
|
9742
|
-
{{ currentIndex() + 1 }} / {{ totalImages() }}
|
|
9743
|
-
</div>
|
|
9744
|
-
|
|
9745
|
-
<button
|
|
9746
|
-
class="nav-button next"
|
|
9747
|
-
(click)="nextClick.emit()"
|
|
9748
|
-
[disabled]="currentIndex() === totalImages() - 1"
|
|
9749
|
-
aria-label="Next image">
|
|
9750
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
9751
|
-
<path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9752
|
-
</svg>
|
|
9753
|
-
</button>
|
|
9754
|
-
</div>
|
|
9755
|
-
}
|
|
9756
|
-
|
|
9757
|
-
<!-- Action buttons -->
|
|
9758
|
-
@if (showActions()) {
|
|
9759
|
-
<div class="footer-actions">
|
|
9760
|
-
<div class="action-buttons-left">
|
|
9761
|
-
<!-- Like button -->
|
|
9762
|
-
<ds-icon-button
|
|
9763
|
-
[icon]="isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'"
|
|
9764
|
-
variant="ghost"
|
|
9765
|
-
size="md"
|
|
9766
|
-
(click)="likeClick.emit()"
|
|
9767
|
-
[attr.data-liked]="isLiked()"
|
|
9768
|
-
class="action-button-like"
|
|
9769
|
-
[ariaLabel]="'Like'">
|
|
9770
|
-
</ds-icon-button>
|
|
9771
|
-
|
|
9772
|
-
<!-- Comment button -->
|
|
9773
|
-
<ds-icon-button
|
|
9774
|
-
icon="remixChat3Line"
|
|
9775
|
-
variant="ghost"
|
|
9776
|
-
size="md"
|
|
9777
|
-
(click)="commentClick.emit()"
|
|
9778
|
-
class="action-button-comment"
|
|
9779
|
-
[ariaLabel]="'Comment'">
|
|
9780
|
-
</ds-icon-button>
|
|
9781
|
-
</div>
|
|
9782
|
-
</div>
|
|
9783
|
-
}
|
|
9784
|
-
</div>
|
|
9785
|
-
`, styles: [".lightbox-footer{position:fixed;bottom:0;left:0;right:0;z-index:100;padding:16px 20px 20px;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none;display:flex;flex-direction:column;gap:12px}.footer-navigation{display:flex;align-items:center;justify-content:center;gap:24px;pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);border-radius:50%;color:#fff;width:40px;height:40px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);padding:0}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px;flex-shrink:0}.counter{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-radius:100px;padding:8px 16px;color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;letter-spacing:-.3px;pointer-events:auto;-webkit-user-select:none;user-select:none}.footer-actions{display:flex;align-items:center;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-footer{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"] }]
|
|
9786
|
-
}], propDecorators: { showNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNavigation", required: false }] }], currentIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentIndex", required: false }] }], totalImages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalImages", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], isLiked: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLiked", required: false }] }], likeCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "likeCount", required: false }] }], commentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentCount", required: false }] }], prevClick: [{ type: i0.Output, args: ["prevClick"] }], nextClick: [{ type: i0.Output, args: ["nextClick"] }], likeClick: [{ type: i0.Output, args: ["likeClick"] }], commentClick: [{ type: i0.Output, args: ["commentClick"] }] } });
|
|
9787
|
-
|
|
9788
|
-
/**
|
|
9789
|
-
* DsMobileLightboxImageComponent
|
|
9790
|
-
*
|
|
9791
|
-
* Full-screen image lightbox component with Swiper.js navigation and pinch-zoom.
|
|
9792
|
-
*
|
|
9793
|
-
* This component is typically not used directly - use DsMobileLightboxService instead.
|
|
9794
|
-
*
|
|
9795
|
-
* Features:
|
|
9796
|
-
* - Swiper.js for smooth image navigation
|
|
9797
|
-
* - Pinch to zoom in/out
|
|
9798
|
-
* - Double-tap to toggle zoom
|
|
9799
|
-
* - Swipe down to close (when not zoomed)
|
|
9800
|
-
* - Image counter and navigation controls
|
|
9801
|
-
*
|
|
9802
|
-
* @example
|
|
9803
|
-
* ```typescript
|
|
9804
|
-
* // Don't instantiate directly - use the service:
|
|
9805
|
-
* constructor(private lightbox: DsMobileLightboxService) {}
|
|
9806
|
-
*
|
|
9807
|
-
* openImage() {
|
|
9808
|
-
* this.lightbox.openImages({
|
|
9809
|
-
* images: [{ type: 'image', src: 'image.jpg', title: 'My Image' }]
|
|
9810
|
-
* });
|
|
9811
|
-
* }
|
|
9812
|
-
* ```
|
|
9813
|
-
*/
|
|
9814
|
-
class DsMobileLightboxImageComponent {
|
|
9815
|
-
gestureCtrl;
|
|
9816
|
-
// Inputs (passed from service as regular properties, not signals)
|
|
9817
|
-
images;
|
|
9818
|
-
author;
|
|
9819
|
-
initialIndex = 0;
|
|
9820
|
-
enableZoom = true;
|
|
9821
|
-
showControls = true;
|
|
9822
|
-
enableSwipe = true;
|
|
9823
|
-
showInfo = true;
|
|
9824
|
-
showActions = false;
|
|
9825
|
-
animation = 'fade';
|
|
9826
|
-
onCloseRequested;
|
|
9827
|
-
// View children
|
|
9529
|
+
progressiveScale = input(false, ...(ngDevMode ? [{ debugName: "progressiveScale" }] : []));
|
|
9828
9530
|
swiperContainer;
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
isZoomed = signal(false, ...(ngDevMode ? [{ debugName: "isZoomed" }] : []));
|
|
9833
|
-
isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
9834
|
-
hasError = signal(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
|
|
9835
|
-
// Action states
|
|
9836
|
-
isLiked = signal(false, ...(ngDevMode ? [{ debugName: "isLiked" }] : []));
|
|
9837
|
-
likeCount = signal(0, ...(ngDevMode ? [{ debugName: "likeCount" }] : []));
|
|
9838
|
-
commentCount = signal(0, ...(ngDevMode ? [{ debugName: "commentCount" }] : []));
|
|
9839
|
-
// Computed
|
|
9840
|
-
currentImage = computed(() => this.images[this.currentIndex()], ...(ngDevMode ? [{ debugName: "currentImage" }] : []));
|
|
9841
|
-
// Swiper instance
|
|
9842
|
-
swiper;
|
|
9843
|
-
zoomData = new Map();
|
|
9844
|
-
constructor(gestureCtrl) {
|
|
9845
|
-
this.gestureCtrl = gestureCtrl;
|
|
9846
|
-
}
|
|
9847
|
-
ngOnInit() {
|
|
9848
|
-
// Set initial index from the passed property
|
|
9849
|
-
if (this.initialIndex !== undefined) {
|
|
9850
|
-
this.currentIndex.set(this.initialIndex);
|
|
9851
|
-
}
|
|
9852
|
-
// Initialize action states from current image
|
|
9853
|
-
const currentImg = this.images[this.currentIndex()];
|
|
9854
|
-
if (currentImg) {
|
|
9855
|
-
this.isLiked.set(currentImg.isLiked ?? false);
|
|
9856
|
-
this.likeCount.set(currentImg.likeCount ?? 0);
|
|
9857
|
-
this.commentCount.set(currentImg.commentCount ?? 0);
|
|
9858
|
-
}
|
|
9531
|
+
swiperInstance = null;
|
|
9532
|
+
constructor(elementRef) {
|
|
9533
|
+
this.elementRef = elementRef;
|
|
9859
9534
|
}
|
|
9860
9535
|
ngAfterViewInit() {
|
|
9536
|
+
// Add progressive-opacity class to host if enabled
|
|
9537
|
+
if (this.progressiveOpacity()) {
|
|
9538
|
+
this.elementRef.nativeElement.classList.add('progressive-opacity');
|
|
9539
|
+
}
|
|
9861
9540
|
setTimeout(() => {
|
|
9862
9541
|
this.initializeSwiper();
|
|
9863
|
-
this.initializeZoomGestures();
|
|
9864
9542
|
}, 100);
|
|
9865
9543
|
}
|
|
9866
|
-
ngOnDestroy() {
|
|
9867
|
-
// Clean up Swiper
|
|
9868
|
-
if (this.swiper) {
|
|
9869
|
-
this.swiper.destroy();
|
|
9870
|
-
this.swiper = undefined;
|
|
9871
|
-
}
|
|
9872
|
-
}
|
|
9873
|
-
/**
|
|
9874
|
-
* Initialize Swiper for image navigation
|
|
9875
|
-
*/
|
|
9876
9544
|
initializeSwiper() {
|
|
9877
|
-
if (!this.swiperContainer)
|
|
9878
|
-
console.error('[Lightbox] Swiper container not found');
|
|
9545
|
+
if (!this.swiperContainer)
|
|
9879
9546
|
return;
|
|
9880
|
-
|
|
9881
|
-
const
|
|
9882
|
-
|
|
9547
|
+
// Apply slide width to all slides
|
|
9548
|
+
const slides = this.swiperContainer.nativeElement.querySelectorAll('.swiper-slide');
|
|
9549
|
+
slides.forEach((slide, index) => {
|
|
9550
|
+
slide.style.width = this.slideWidth();
|
|
9551
|
+
// Set initial opacity BEFORE Swiper initializes to prevent flash of inactive slides
|
|
9552
|
+
if (this.progressiveOpacity()) {
|
|
9553
|
+
// Hide all slides except the first one (active slide)
|
|
9554
|
+
slide.style.opacity = index === 0 ? '1' : '0';
|
|
9555
|
+
}
|
|
9556
|
+
});
|
|
9557
|
+
const config = {
|
|
9558
|
+
slidesPerView: 'auto',
|
|
9559
|
+
spaceBetween: this.gap(),
|
|
9560
|
+
centeredSlides: true,
|
|
9561
|
+
centeredSlidesBounds: true,
|
|
9883
9562
|
speed: 300,
|
|
9884
9563
|
resistance: true,
|
|
9885
9564
|
resistanceRatio: 0.85,
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9565
|
+
autoHeight: this.autoHeight(),
|
|
9566
|
+
watchSlidesProgress: this.progressiveOpacity() || this.progressiveScale(), // Enable progress tracking
|
|
9567
|
+
};
|
|
9568
|
+
// Configure event handlers
|
|
9569
|
+
config.on = {};
|
|
9570
|
+
// Configure autoHeight animation
|
|
9571
|
+
if (this.autoHeight()) {
|
|
9572
|
+
config.autoHeight = true;
|
|
9573
|
+
// The height transition will use the speed value (300ms)
|
|
9574
|
+
config.on.slideChangeTransitionStart = () => {
|
|
9575
|
+
// Height transition happens automatically
|
|
9576
|
+
};
|
|
9577
|
+
}
|
|
9578
|
+
// Configure progressive effects (opacity and/or scale)
|
|
9579
|
+
if (this.progressiveOpacity() || this.progressiveScale()) {
|
|
9580
|
+
config.on.setTranslate = () => {
|
|
9581
|
+
if (!this.swiperInstance)
|
|
9582
|
+
return;
|
|
9583
|
+
this.swiperInstance.slides.forEach((slideEl) => {
|
|
9584
|
+
const progress = slideEl.progress || 0;
|
|
9585
|
+
const absProgress = Math.abs(progress);
|
|
9586
|
+
// Progressive opacity with sharper cutoff
|
|
9587
|
+
if (this.progressiveOpacity()) {
|
|
9588
|
+
// Make opacity drop off more aggressively
|
|
9589
|
+
// Slides with absProgress > 0.5 will be completely hidden
|
|
9590
|
+
let opacity;
|
|
9591
|
+
if (absProgress > 0.5) {
|
|
9592
|
+
opacity = 0;
|
|
9593
|
+
}
|
|
9594
|
+
else {
|
|
9595
|
+
opacity = 1 - (absProgress * 2); // 2x multiplier for faster fade
|
|
9596
|
+
}
|
|
9597
|
+
slideEl.style.opacity = Math.max(opacity, 0).toString();
|
|
9901
9598
|
}
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
this.isLoading.set(true);
|
|
9599
|
+
// Progressive scale
|
|
9600
|
+
if (this.progressiveScale()) {
|
|
9601
|
+
// Scale from 1 (center) to 0.9 (edges)
|
|
9602
|
+
const minScale = 0.9;
|
|
9603
|
+
const scale = 1 - (absProgress * (1 - minScale));
|
|
9604
|
+
slideEl.style.transform = `scale(${Math.max(scale, minScale)})`;
|
|
9909
9605
|
}
|
|
9910
|
-
}
|
|
9911
|
-
}
|
|
9912
|
-
};
|
|
9913
|
-
this.swiper = new Swiper(this.swiperContainer.nativeElement, swiperOptions);
|
|
9914
|
-
// Check if the initial image is already loaded
|
|
9915
|
-
setTimeout(() => {
|
|
9916
|
-
const currentSlide = this.swiper?.slides[this.currentIndex()];
|
|
9917
|
-
const img = currentSlide?.querySelector('img');
|
|
9918
|
-
if (img && img.complete && img.naturalHeight !== 0) {
|
|
9919
|
-
this.isLoading.set(false);
|
|
9920
|
-
}
|
|
9921
|
-
}, 0);
|
|
9922
|
-
}
|
|
9923
|
-
/**
|
|
9924
|
-
* Initialize pinch-zoom gestures for all slides
|
|
9925
|
-
*/
|
|
9926
|
-
initializeZoomGestures() {
|
|
9927
|
-
if (!this.enableZoom)
|
|
9928
|
-
return;
|
|
9929
|
-
const slides = this.swiperContainer.nativeElement.querySelectorAll('.image-zoom-container');
|
|
9930
|
-
slides.forEach((slide, index) => {
|
|
9931
|
-
this.initializeZoomForSlide(slide, index);
|
|
9932
|
-
});
|
|
9933
|
-
}
|
|
9934
|
-
/**
|
|
9935
|
-
* Initialize zoom gestures for a specific slide
|
|
9936
|
-
*/
|
|
9937
|
-
initializeZoomForSlide(container, index) {
|
|
9938
|
-
let initialDistance = 0;
|
|
9939
|
-
let initialScale = 1;
|
|
9940
|
-
let currentScale = 1;
|
|
9941
|
-
let lastTap = 0;
|
|
9942
|
-
// Double-tap to zoom
|
|
9943
|
-
container.addEventListener('click', (event) => {
|
|
9944
|
-
const now = Date.now();
|
|
9945
|
-
const timeSinceLastTap = now - lastTap;
|
|
9946
|
-
if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {
|
|
9947
|
-
event.preventDefault();
|
|
9948
|
-
this.toggleZoom(container, index);
|
|
9949
|
-
}
|
|
9950
|
-
lastTap = now;
|
|
9951
|
-
});
|
|
9952
|
-
// Pinch to zoom
|
|
9953
|
-
const getTouchDistance = (touches) => {
|
|
9954
|
-
const dx = touches[0].clientX - touches[1].clientX;
|
|
9955
|
-
const dy = touches[0].clientY - touches[1].clientY;
|
|
9956
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
9957
|
-
};
|
|
9958
|
-
container.addEventListener('touchstart', (event) => {
|
|
9959
|
-
if (event.touches.length === 2) {
|
|
9960
|
-
event.preventDefault();
|
|
9961
|
-
initialDistance = getTouchDistance(event.touches);
|
|
9962
|
-
const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };
|
|
9963
|
-
initialScale = zoomData.scale;
|
|
9964
|
-
// Disable Swiper when zooming
|
|
9965
|
-
if (this.swiper) {
|
|
9966
|
-
this.swiper.allowTouchMove = false;
|
|
9967
|
-
}
|
|
9968
|
-
}
|
|
9969
|
-
}, { passive: false });
|
|
9970
|
-
container.addEventListener('touchmove', (event) => {
|
|
9971
|
-
if (event.touches.length === 2) {
|
|
9972
|
-
event.preventDefault();
|
|
9973
|
-
const currentDistance = getTouchDistance(event.touches);
|
|
9974
|
-
const pinchScale = currentDistance / initialDistance;
|
|
9975
|
-
currentScale = Math.max(1, Math.min(initialScale * pinchScale, 4));
|
|
9976
|
-
const img = container.querySelector('img');
|
|
9977
|
-
if (img) {
|
|
9978
|
-
img.style.transform = `scale(${currentScale})`;
|
|
9979
|
-
}
|
|
9980
|
-
if (currentScale > 1) {
|
|
9981
|
-
this.isZoomed.set(true);
|
|
9982
|
-
}
|
|
9983
|
-
else {
|
|
9984
|
-
this.isZoomed.set(false);
|
|
9985
|
-
}
|
|
9986
|
-
}
|
|
9987
|
-
}, { passive: false });
|
|
9988
|
-
container.addEventListener('touchend', (event) => {
|
|
9989
|
-
if (event.touches.length < 2) {
|
|
9990
|
-
// Save zoom state
|
|
9991
|
-
this.zoomData.set(index, { scale: currentScale, x: 0, y: 0 });
|
|
9992
|
-
// Re-enable Swiper if not zoomed
|
|
9993
|
-
if (this.swiper && currentScale <= 1) {
|
|
9994
|
-
this.swiper.allowTouchMove = true;
|
|
9995
|
-
}
|
|
9996
|
-
}
|
|
9997
|
-
});
|
|
9998
|
-
}
|
|
9999
|
-
/**
|
|
10000
|
-
* Toggle zoom on double-tap
|
|
10001
|
-
*/
|
|
10002
|
-
toggleZoom(container, index) {
|
|
10003
|
-
const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };
|
|
10004
|
-
const img = container.querySelector('img');
|
|
10005
|
-
if (!img)
|
|
10006
|
-
return;
|
|
10007
|
-
if (zoomData.scale > 1) {
|
|
10008
|
-
// Zoom out
|
|
10009
|
-
img.style.transform = 'scale(1)';
|
|
10010
|
-
this.zoomData.set(index, { scale: 1, x: 0, y: 0 });
|
|
10011
|
-
this.isZoomed.set(false);
|
|
10012
|
-
if (this.swiper) {
|
|
10013
|
-
this.swiper.allowTouchMove = true;
|
|
10014
|
-
}
|
|
10015
|
-
}
|
|
10016
|
-
else {
|
|
10017
|
-
// Zoom in
|
|
10018
|
-
img.style.transform = 'scale(2)';
|
|
10019
|
-
this.zoomData.set(index, { scale: 2, x: 0, y: 0 });
|
|
10020
|
-
this.isZoomed.set(true);
|
|
10021
|
-
if (this.swiper) {
|
|
10022
|
-
this.swiper.allowTouchMove = false;
|
|
10023
|
-
}
|
|
10024
|
-
}
|
|
10025
|
-
}
|
|
10026
|
-
/**
|
|
10027
|
-
* Update action states (like, comments) when slide changes
|
|
10028
|
-
*/
|
|
10029
|
-
updateActionStates() {
|
|
10030
|
-
const currentImg = this.images[this.currentIndex()];
|
|
10031
|
-
if (currentImg) {
|
|
10032
|
-
this.isLiked.set(currentImg.isLiked ?? false);
|
|
10033
|
-
this.likeCount.set(currentImg.likeCount ?? 0);
|
|
10034
|
-
this.commentCount.set(currentImg.commentCount ?? 0);
|
|
10035
|
-
}
|
|
10036
|
-
}
|
|
10037
|
-
/**
|
|
10038
|
-
* Close the lightbox
|
|
10039
|
-
*/
|
|
10040
|
-
close() {
|
|
10041
|
-
if (this.onCloseRequested) {
|
|
10042
|
-
this.onCloseRequested();
|
|
10043
|
-
}
|
|
10044
|
-
}
|
|
10045
|
-
/**
|
|
10046
|
-
* Handle share button click
|
|
10047
|
-
*/
|
|
10048
|
-
async onShare() {
|
|
10049
|
-
console.log('[Lightbox] Share button clicked');
|
|
10050
|
-
const currentImg = this.currentImage();
|
|
10051
|
-
if (!currentImg?.src) {
|
|
10052
|
-
console.warn('[Lightbox] No image to share');
|
|
10053
|
-
return;
|
|
10054
|
-
}
|
|
10055
|
-
try {
|
|
10056
|
-
// Check if Web Share API is available (for browser)
|
|
10057
|
-
if (navigator.share) {
|
|
10058
|
-
await navigator.share({
|
|
10059
|
-
title: currentImg.title || 'Shared Image',
|
|
10060
|
-
text: currentImg.description || '',
|
|
10061
|
-
url: currentImg.src,
|
|
10062
9606
|
});
|
|
10063
|
-
|
|
10064
|
-
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10069
|
-
|
|
10070
|
-
|
|
9607
|
+
};
|
|
9608
|
+
// Also update on init
|
|
9609
|
+
config.on.init = () => {
|
|
9610
|
+
if (!this.swiperInstance)
|
|
9611
|
+
return;
|
|
9612
|
+
this.swiperInstance.slides.forEach((slideEl) => {
|
|
9613
|
+
const progress = slideEl.progress || 0;
|
|
9614
|
+
const absProgress = Math.abs(progress);
|
|
9615
|
+
// Set initial opacity with sharper cutoff
|
|
9616
|
+
if (this.progressiveOpacity()) {
|
|
9617
|
+
let opacity;
|
|
9618
|
+
if (absProgress > 0.5) {
|
|
9619
|
+
opacity = 0;
|
|
9620
|
+
}
|
|
9621
|
+
else {
|
|
9622
|
+
opacity = 1 - (absProgress * 2);
|
|
9623
|
+
}
|
|
9624
|
+
slideEl.style.opacity = Math.max(opacity, 0).toString();
|
|
9625
|
+
}
|
|
9626
|
+
// Set initial scale
|
|
9627
|
+
if (this.progressiveScale()) {
|
|
9628
|
+
const minScale = 0.9;
|
|
9629
|
+
const scale = 1 - (absProgress * (1 - minScale));
|
|
9630
|
+
slideEl.style.transform = `scale(${Math.max(scale, minScale)})`;
|
|
9631
|
+
}
|
|
10071
9632
|
});
|
|
10072
|
-
|
|
10073
|
-
}
|
|
10074
|
-
}
|
|
10075
|
-
catch (error) {
|
|
10076
|
-
// User cancellation is expected and not an error
|
|
10077
|
-
if (error?.message?.includes('cancel') || error?.code === 'USER_CANCELLED') {
|
|
10078
|
-
console.log('[Lightbox] Share cancelled by user');
|
|
10079
|
-
return;
|
|
10080
|
-
}
|
|
10081
|
-
console.error('[Lightbox] Share failed:', error);
|
|
10082
|
-
}
|
|
10083
|
-
}
|
|
10084
|
-
/**
|
|
10085
|
-
* Handle like button toggle
|
|
10086
|
-
*/
|
|
10087
|
-
onLikeToggle() {
|
|
10088
|
-
console.log('[Lightbox] Like button toggled');
|
|
10089
|
-
this.isLiked.update(liked => !liked);
|
|
10090
|
-
if (this.isLiked()) {
|
|
10091
|
-
this.likeCount.update(count => count + 1);
|
|
9633
|
+
};
|
|
10092
9634
|
}
|
|
10093
|
-
|
|
10094
|
-
|
|
9635
|
+
// Add pagination if enabled
|
|
9636
|
+
if (this.pagination()) {
|
|
9637
|
+
config.modules = [Pagination];
|
|
9638
|
+
config.pagination = {
|
|
9639
|
+
el: '.swiper-pagination',
|
|
9640
|
+
clickable: true,
|
|
9641
|
+
dynamicBullets: false,
|
|
9642
|
+
};
|
|
10095
9643
|
}
|
|
9644
|
+
this.swiperInstance = new Swiper(this.swiperContainer.nativeElement, config);
|
|
10096
9645
|
}
|
|
10097
9646
|
/**
|
|
10098
|
-
*
|
|
9647
|
+
* Navigate to previous slide
|
|
10099
9648
|
*/
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
if (this.onCloseRequested) {
|
|
10103
|
-
this.onCloseRequested();
|
|
10104
|
-
}
|
|
9649
|
+
slidePrev() {
|
|
9650
|
+
this.swiperInstance?.slidePrev();
|
|
10105
9651
|
}
|
|
10106
9652
|
/**
|
|
10107
|
-
* Navigate to
|
|
9653
|
+
* Navigate to next slide
|
|
10108
9654
|
*/
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
this.swiper.slideNext();
|
|
10112
|
-
}
|
|
9655
|
+
slideNext() {
|
|
9656
|
+
this.swiperInstance?.slideNext();
|
|
10113
9657
|
}
|
|
10114
9658
|
/**
|
|
10115
|
-
*
|
|
9659
|
+
* Check if at the beginning
|
|
10116
9660
|
*/
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
this.swiper.slidePrev();
|
|
10120
|
-
}
|
|
9661
|
+
isBeginning() {
|
|
9662
|
+
return this.swiperInstance?.isBeginning ?? true;
|
|
10121
9663
|
}
|
|
10122
9664
|
/**
|
|
10123
|
-
*
|
|
9665
|
+
* Check if at the end
|
|
10124
9666
|
*/
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
this.isLoading.set(false);
|
|
10128
|
-
}
|
|
9667
|
+
isEnd() {
|
|
9668
|
+
return this.swiperInstance?.isEnd ?? true;
|
|
10129
9669
|
}
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
|
|
10134
|
-
if (index === this.currentIndex()) {
|
|
10135
|
-
console.error(`[Lightbox] Image ${index} failed to load`);
|
|
10136
|
-
this.isLoading.set(false);
|
|
10137
|
-
this.hasError.set(true);
|
|
9670
|
+
ngOnDestroy() {
|
|
9671
|
+
if (this.swiperInstance) {
|
|
9672
|
+
this.swiperInstance.destroy();
|
|
9673
|
+
this.swiperInstance = null;
|
|
10138
9674
|
}
|
|
10139
9675
|
}
|
|
10140
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
10141
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type:
|
|
10142
|
-
<div class="
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
<div class="lightbox-wrapper">
|
|
10146
|
-
<!-- Header with author info and action buttons -->
|
|
10147
|
-
<ds-mobile-lightbox-header
|
|
10148
|
-
[author]="author"
|
|
10149
|
-
(closeClick)="close()"
|
|
10150
|
-
(shareClick)="onShare()"
|
|
10151
|
-
/>
|
|
10152
|
-
|
|
10153
|
-
<!-- Swiper container -->
|
|
10154
|
-
<div class="swiper-container" #swiperContainer>
|
|
10155
|
-
<div class="swiper-wrapper">
|
|
10156
|
-
@for (image of images; track image.src; let i = $index) {
|
|
10157
|
-
<div class="swiper-slide">
|
|
10158
|
-
<div class="image-zoom-container" [attr.data-index]="i">
|
|
10159
|
-
<img
|
|
10160
|
-
[src]="image.src"
|
|
10161
|
-
[alt]="image.alt || 'Lightbox image'"
|
|
10162
|
-
class="lightbox-image"
|
|
10163
|
-
(load)="onImageLoad(i)"
|
|
10164
|
-
(error)="onImageError(i)">
|
|
10165
|
-
</div>
|
|
10166
|
-
</div>
|
|
10167
|
-
}
|
|
10168
|
-
</div>
|
|
10169
|
-
</div>
|
|
10170
|
-
|
|
10171
|
-
<!-- Loading indicator -->
|
|
10172
|
-
@if (isLoading()) {
|
|
10173
|
-
<div class="loading-spinner">
|
|
10174
|
-
<ion-spinner name="crescent"></ion-spinner>
|
|
10175
|
-
</div>
|
|
10176
|
-
}
|
|
10177
|
-
|
|
10178
|
-
<!-- Footer with navigation and actions -->
|
|
10179
|
-
<ds-mobile-lightbox-footer
|
|
10180
|
-
[showNavigation]="showControls && images.length > 1"
|
|
10181
|
-
[showActions]="showActions"
|
|
10182
|
-
[currentIndex]="currentIndex()"
|
|
10183
|
-
[totalImages]="images.length"
|
|
10184
|
-
[isLiked]="isLiked()"
|
|
10185
|
-
[likeCount]="likeCount()"
|
|
10186
|
-
[commentCount]="commentCount()"
|
|
10187
|
-
(prevClick)="previousImage()"
|
|
10188
|
-
(nextClick)="nextImage()"
|
|
10189
|
-
(likeClick)="onLikeToggle()"
|
|
10190
|
-
(commentClick)="onReply()"
|
|
10191
|
-
/>
|
|
9676
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSwiperComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
9677
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileSwiperComponent, isStandalone: true, selector: "ds-mobile-swiper", inputs: { slideWidth: { classPropertyName: "slideWidth", publicName: "slideWidth", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, autoHeight: { classPropertyName: "autoHeight", publicName: "autoHeight", isSignal: true, isRequired: false, transformFunction: null }, progressiveOpacity: { classPropertyName: "progressiveOpacity", publicName: "progressiveOpacity", isSignal: true, isRequired: false, transformFunction: null }, progressiveScale: { classPropertyName: "progressiveScale", publicName: "progressiveScale", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "swiperContainer", first: true, predicate: ["swiperContainer"], descendants: true }], ngImport: i0, template: `
|
|
9678
|
+
<div class="swiper-container" #swiperContainer>
|
|
9679
|
+
<div class="swiper-wrapper">
|
|
9680
|
+
<ng-content></ng-content>
|
|
10192
9681
|
</div>
|
|
9682
|
+
@if (pagination()) {
|
|
9683
|
+
<div class="swiper-pagination"></div>
|
|
9684
|
+
}
|
|
10193
9685
|
</div>
|
|
10194
|
-
`, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}:host{display:block;position:fixed;inset:0;width:100vw;height:100vh;z-index:10000}.lightbox-overlay{position:fixed;inset:0;width:100vw;height:100vh;background:#000000fa;z-index:10000;display:flex;flex-direction:column;touch-action:none;animation:fadeIn .2s ease-out}.lightbox-overlay.zoomed{overflow:hidden}.lightbox-content{display:block;height:100vh;width:100vw;position:absolute;inset:0}.lightbox-content::part(scroll){display:flex;flex-direction:column;height:100%;overflow:hidden}.lightbox-wrapper{position:absolute;inset:0;display:flex;flex-direction:column;width:100%;height:100%}.lightbox-content.zoomed{overflow:hidden}.lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.close-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg{color:#fff!important;fill:#fff!important}.swiper-container{position:absolute;inset:0;width:100%;height:100%;z-index:1}.swiper-wrapper{width:100%;height:100%}.swiper-slide{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.image-zoom-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden}.lightbox-image{max-width:min(640px,100%);max-height:100%;width:auto;height:auto;-o-object-fit:contain;object-fit:contain;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none;transition:transform .3s ease-out;transform-origin:center center}.lightbox-overlay.zoomed .swiper-container{touch-action:none}.loading-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.loading-spinner ion-spinner{--color: rgba(255, 255, 255, .8);width:48px;height:48px}.error-message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10;text-align:center;color:#fffc;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:500;padding:20px;background:#00000080;border-radius:12px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.lightbox-bottom-section{position:fixed;bottom:0;left:0;right:0;z-index:100;display:flex;flex-direction:column;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none}.lightbox-controls{display:flex;align-items:center;justify-content:center;gap:24px;padding:16px 20px 12px;pointer-events:none}.nav-button,.counter{pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);color:#fff;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease;padding:0;margin:0;outline:none}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px}.counter{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;padding:10px 16px;background:#00000080;border-radius:100px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);white-space:nowrap}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-bottom-section{padding-bottom:env(safe-area-inset-bottom)}}.lightbox-footer{display:flex;padding:12px 20px 20px;pointer-events:none}.footer-actions{display:flex;align-items:center;justify-content:space-between;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-with-count::ng-deep button,.action-button-share::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover,.action-button-with-count::ng-deep button:hover,.action-button-share::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active,.action-button-with-count::ng-deep button:active,.action-button-share::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-with-count::ng-deep button svg,.action-button-share::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content,.action-button-with-count::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg,.action-button-with-count::ng-deep button .btn__icon svg,.action-button-share::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment,.action-button-share{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-share::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@media (min-width: 768px){.lightbox-header{padding:24px}.close-button{width:48px;height:48px}.lightbox-controls{padding:20px 24px 16px}.nav-button{width:48px;height:48px}.counter{font-size:var(--font-size-base);padding:12px 20px}.lightbox-footer{padding:16px 24px 24px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{height:48px;padding:0 20px}.action-button-share::ng-deep button{width:48px!important;height:48px!important;min-width:48px!important;min-height:48px!important}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion: reduce){.image-wrapper,.nav-button,.lightbox-caption{transition:none}}.nav-button:focus-visible{outline:2px solid white;outline-offset:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: DsMobileLightboxHeaderComponent, selector: "ds-mobile-lightbox-header", inputs: ["author"], outputs: ["closeClick", "shareClick"] }, { kind: "component", type: DsMobileLightboxFooterComponent, selector: "ds-mobile-lightbox-footer", inputs: ["showNavigation", "currentIndex", "totalImages", "showActions", "isLiked", "likeCount", "commentCount"], outputs: ["prevClick", "nextClick", "likeClick", "commentClick"] }] });
|
|
9686
|
+
`, isInline: true, styles: [":host{display:block;width:100%}.swiper-container{width:100%;position:relative;overflow:visible}.swiper-wrapper{display:flex;box-sizing:content-box}:host ::ng-deep .swiper-slide{flex-shrink:0;height:auto;position:relative;display:flex;align-items:flex-start;justify-content:center;transition:opacity .3s ease,transform .3s ease}:host(.progressive-opacity) ::ng-deep .swiper-slide{opacity:0}:host(.progressive-opacity) ::ng-deep .swiper-slide:first-child{opacity:1}.swiper-pagination{position:relative;text-align:center;display:flex;justify-content:center;margin-top:20px;margin-bottom:-16px}:host ::ng-deep .swiper-pagination-bullet{width:6px;height:6px;border-radius:50%;background:var(--color-accent);opacity:.25;transition:all .3s ease;cursor:pointer}:host ::ng-deep .swiper-pagination-bullet-active{opacity:1;background:var(--color-accent);width:20px;border-radius:3px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
10195
9687
|
}
|
|
10196
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
9688
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSwiperComponent, decorators: [{
|
|
10197
9689
|
type: Component,
|
|
10198
|
-
args: [{ selector: 'ds-mobile-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
DsMobileLightboxFooterComponent
|
|
10203
|
-
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
|
|
10204
|
-
<div class="lightbox-overlay"
|
|
10205
|
-
[class.zoomed]="isZoomed()">
|
|
10206
|
-
|
|
10207
|
-
<div class="lightbox-wrapper">
|
|
10208
|
-
<!-- Header with author info and action buttons -->
|
|
10209
|
-
<ds-mobile-lightbox-header
|
|
10210
|
-
[author]="author"
|
|
10211
|
-
(closeClick)="close()"
|
|
10212
|
-
(shareClick)="onShare()"
|
|
10213
|
-
/>
|
|
10214
|
-
|
|
10215
|
-
<!-- Swiper container -->
|
|
10216
|
-
<div class="swiper-container" #swiperContainer>
|
|
10217
|
-
<div class="swiper-wrapper">
|
|
10218
|
-
@for (image of images; track image.src; let i = $index) {
|
|
10219
|
-
<div class="swiper-slide">
|
|
10220
|
-
<div class="image-zoom-container" [attr.data-index]="i">
|
|
10221
|
-
<img
|
|
10222
|
-
[src]="image.src"
|
|
10223
|
-
[alt]="image.alt || 'Lightbox image'"
|
|
10224
|
-
class="lightbox-image"
|
|
10225
|
-
(load)="onImageLoad(i)"
|
|
10226
|
-
(error)="onImageError(i)">
|
|
10227
|
-
</div>
|
|
10228
|
-
</div>
|
|
10229
|
-
}
|
|
10230
|
-
</div>
|
|
10231
|
-
</div>
|
|
10232
|
-
|
|
10233
|
-
<!-- Loading indicator -->
|
|
10234
|
-
@if (isLoading()) {
|
|
10235
|
-
<div class="loading-spinner">
|
|
10236
|
-
<ion-spinner name="crescent"></ion-spinner>
|
|
10237
|
-
</div>
|
|
10238
|
-
}
|
|
10239
|
-
|
|
10240
|
-
<!-- Footer with navigation and actions -->
|
|
10241
|
-
<ds-mobile-lightbox-footer
|
|
10242
|
-
[showNavigation]="showControls && images.length > 1"
|
|
10243
|
-
[showActions]="showActions"
|
|
10244
|
-
[currentIndex]="currentIndex()"
|
|
10245
|
-
[totalImages]="images.length"
|
|
10246
|
-
[isLiked]="isLiked()"
|
|
10247
|
-
[likeCount]="likeCount()"
|
|
10248
|
-
[commentCount]="commentCount()"
|
|
10249
|
-
(prevClick)="previousImage()"
|
|
10250
|
-
(nextClick)="nextImage()"
|
|
10251
|
-
(likeClick)="onLikeToggle()"
|
|
10252
|
-
(commentClick)="onReply()"
|
|
10253
|
-
/>
|
|
9690
|
+
args: [{ selector: 'ds-mobile-swiper', standalone: true, imports: [CommonModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
|
|
9691
|
+
<div class="swiper-container" #swiperContainer>
|
|
9692
|
+
<div class="swiper-wrapper">
|
|
9693
|
+
<ng-content></ng-content>
|
|
10254
9694
|
</div>
|
|
9695
|
+
@if (pagination()) {
|
|
9696
|
+
<div class="swiper-pagination"></div>
|
|
9697
|
+
}
|
|
10255
9698
|
</div>
|
|
10256
|
-
`, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}:host{display:block;position:fixed;inset:0;width:100vw;height:100vh;z-index:10000}.lightbox-overlay{position:fixed;inset:0;width:100vw;height:100vh;background:#000000fa;z-index:10000;display:flex;flex-direction:column;touch-action:none;animation:fadeIn .2s ease-out}.lightbox-overlay.zoomed{overflow:hidden}.lightbox-content{display:block;height:100vh;width:100vw;position:absolute;inset:0}.lightbox-content::part(scroll){display:flex;flex-direction:column;height:100%;overflow:hidden}.lightbox-wrapper{position:absolute;inset:0;display:flex;flex-direction:column;width:100%;height:100%}.lightbox-content.zoomed{overflow:hidden}.lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.close-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg{color:#fff!important;fill:#fff!important}.swiper-container{position:absolute;inset:0;width:100%;height:100%;z-index:1}.swiper-wrapper{width:100%;height:100%}.swiper-slide{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.image-zoom-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden}.lightbox-image{max-width:min(640px,100%);max-height:100%;width:auto;height:auto;-o-object-fit:contain;object-fit:contain;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none;transition:transform .3s ease-out;transform-origin:center center}.lightbox-overlay.zoomed .swiper-container{touch-action:none}.loading-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.loading-spinner ion-spinner{--color: rgba(255, 255, 255, .8);width:48px;height:48px}.error-message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10;text-align:center;color:#fffc;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:500;padding:20px;background:#00000080;border-radius:12px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.lightbox-bottom-section{position:fixed;bottom:0;left:0;right:0;z-index:100;display:flex;flex-direction:column;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none}.lightbox-controls{display:flex;align-items:center;justify-content:center;gap:24px;padding:16px 20px 12px;pointer-events:none}.nav-button,.counter{pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);color:#fff;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease;padding:0;margin:0;outline:none}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px}.counter{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;padding:10px 16px;background:#00000080;border-radius:100px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);white-space:nowrap}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-bottom-section{padding-bottom:env(safe-area-inset-bottom)}}.lightbox-footer{display:flex;padding:12px 20px 20px;pointer-events:none}.footer-actions{display:flex;align-items:center;justify-content:space-between;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-with-count::ng-deep button,.action-button-share::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover,.action-button-with-count::ng-deep button:hover,.action-button-share::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active,.action-button-with-count::ng-deep button:active,.action-button-share::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-with-count::ng-deep button svg,.action-button-share::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content,.action-button-with-count::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg,.action-button-with-count::ng-deep button .btn__icon svg,.action-button-share::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment,.action-button-share{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-share::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@media (min-width: 768px){.lightbox-header{padding:24px}.close-button{width:48px;height:48px}.lightbox-controls{padding:20px 24px 16px}.nav-button{width:48px;height:48px}.counter{font-size:var(--font-size-base);padding:12px 20px}.lightbox-footer{padding:16px 24px 24px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{height:48px;padding:0 20px}.action-button-share::ng-deep button{width:48px!important;height:48px!important;min-width:48px!important;min-height:48px!important}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion: reduce){.image-wrapper,.nav-button,.lightbox-caption{transition:none}}.nav-button:focus-visible{outline:2px solid white;outline-offset:2px}\n"] }]
|
|
10257
|
-
}], ctorParameters: () => [{ type:
|
|
9699
|
+
`, styles: [":host{display:block;width:100%}.swiper-container{width:100%;position:relative;overflow:visible}.swiper-wrapper{display:flex;box-sizing:content-box}:host ::ng-deep .swiper-slide{flex-shrink:0;height:auto;position:relative;display:flex;align-items:flex-start;justify-content:center;transition:opacity .3s ease,transform .3s ease}:host(.progressive-opacity) ::ng-deep .swiper-slide{opacity:0}:host(.progressive-opacity) ::ng-deep .swiper-slide:first-child{opacity:1}.swiper-pagination{position:relative;text-align:center;display:flex;justify-content:center;margin-top:20px;margin-bottom:-16px}:host ::ng-deep .swiper-pagination-bullet{width:6px;height:6px;border-radius:50%;background:var(--color-accent);opacity:.25;transition:all .3s ease;cursor:pointer}:host ::ng-deep .swiper-pagination-bullet-active{opacity:1;background:var(--color-accent);width:20px;border-radius:3px}\n"] }]
|
|
9700
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { slideWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideWidth", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], autoHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoHeight", required: false }] }], progressiveOpacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "progressiveOpacity", required: false }] }], progressiveScale: [{ type: i0.Input, args: [{ isSignal: true, alias: "progressiveScale", required: false }] }], swiperContainer: [{
|
|
10258
9701
|
type: ViewChild,
|
|
10259
|
-
args: ['swiperContainer', {
|
|
9702
|
+
args: ['swiperContainer', { static: false }]
|
|
10260
9703
|
}] } });
|
|
10261
9704
|
|
|
10262
9705
|
/**
|
|
10263
|
-
*
|
|
10264
|
-
*
|
|
10265
|
-
* PDF viewer component that displays PDF info and allows users to open PDFs in the native device viewer.
|
|
10266
|
-
* Shows a lightbox with PDF details first, then user can choose to open in native viewer.
|
|
9706
|
+
* DsMobileSystemMessageBannerComponent
|
|
10267
9707
|
*
|
|
10268
|
-
*
|
|
9708
|
+
* Full-width centered banner component for displaying system messages in chat conversations.
|
|
9709
|
+
* Uses the same text styling as message bubbles for consistency.
|
|
10269
9710
|
*
|
|
10270
9711
|
* Features:
|
|
10271
|
-
* -
|
|
10272
|
-
* -
|
|
10273
|
-
* -
|
|
10274
|
-
* -
|
|
10275
|
-
*
|
|
9712
|
+
* - Full-width centered layout
|
|
9713
|
+
* - Subtle background with theming support
|
|
9714
|
+
* - Same typography as message bubbles
|
|
9715
|
+
* - Optional icon support
|
|
9716
|
+
*
|
|
9717
|
+
* Common use cases:
|
|
9718
|
+
* - Inquiry status updates ("Your inquiry has been assigned to...")
|
|
9719
|
+
* - System notifications ("This inquiry is marked as resolved")
|
|
9720
|
+
* - Auto-replies ("We aim to respond within 24 hours...")
|
|
9721
|
+
* - Time/date separators
|
|
10276
9722
|
*
|
|
10277
9723
|
* @example
|
|
10278
|
-
* ```
|
|
10279
|
-
*
|
|
10280
|
-
*
|
|
9724
|
+
* ```html
|
|
9725
|
+
* <!-- Simple system message -->
|
|
9726
|
+
* <ds-mobile-system-message-banner
|
|
9727
|
+
* [message]="'Ricki Meihlen har overtaget din henvendelse og vil kontakte dig snart.'">
|
|
9728
|
+
* </ds-mobile-system-message-banner>
|
|
10281
9729
|
*
|
|
10282
|
-
*
|
|
10283
|
-
*
|
|
10284
|
-
*
|
|
10285
|
-
*
|
|
10286
|
-
*
|
|
9730
|
+
* <!-- With icon -->
|
|
9731
|
+
* <ds-mobile-system-message-banner
|
|
9732
|
+
* [message]="'Vi bestræber os på at svare inden for 24 timer på hverdage.'"
|
|
9733
|
+
* [iconName]="'remixInformationLine'">
|
|
9734
|
+
* </ds-mobile-system-message-banner>
|
|
10287
9735
|
* ```
|
|
10288
9736
|
*/
|
|
10289
|
-
class
|
|
10290
|
-
// Inputs (passed from service as regular properties)
|
|
10291
|
-
pdf;
|
|
10292
|
-
author;
|
|
10293
|
-
onCloseRequested;
|
|
10294
|
-
// State
|
|
10295
|
-
isLoading = false;
|
|
10296
|
-
hasError = false;
|
|
10297
|
-
errorMessage = '';
|
|
10298
|
-
cachedFilePath;
|
|
10299
|
-
constructor() { }
|
|
10300
|
-
ngOnInit() {
|
|
10301
|
-
console.log('[PDF Lightbox] Initializing with PDF:', this.pdf);
|
|
10302
|
-
// Don't automatically open - let user click the "Open" button
|
|
10303
|
-
// this.openPdfInNativeViewer();
|
|
10304
|
-
}
|
|
9737
|
+
class DsMobileSystemMessageBannerComponent {
|
|
10305
9738
|
/**
|
|
10306
|
-
*
|
|
9739
|
+
* System message text to display
|
|
10307
9740
|
*/
|
|
10308
|
-
|
|
10309
|
-
if (!this.pdf?.src) {
|
|
10310
|
-
console.error('[PDF Lightbox] No PDF source provided');
|
|
10311
|
-
this.hasError = true;
|
|
10312
|
-
this.errorMessage = 'No PDF file provided';
|
|
10313
|
-
return;
|
|
10314
|
-
}
|
|
10315
|
-
this.isLoading = true;
|
|
10316
|
-
this.hasError = false;
|
|
10317
|
-
this.errorMessage = '';
|
|
10318
|
-
try {
|
|
10319
|
-
console.log('[PDF Lightbox] Opening PDF:', this.pdf.src);
|
|
10320
|
-
// Check if it's already a full URL
|
|
10321
|
-
let pdfUrl;
|
|
10322
|
-
if (this.pdf.src.startsWith('http://') || this.pdf.src.startsWith('https://')) {
|
|
10323
|
-
// Already a full URL
|
|
10324
|
-
pdfUrl = this.pdf.src;
|
|
10325
|
-
}
|
|
10326
|
-
else {
|
|
10327
|
-
// Relative path - construct full URL
|
|
10328
|
-
// Use current origin (which includes the dev server URL in Capacitor)
|
|
10329
|
-
// Remove leading slash if present to avoid double slashes
|
|
10330
|
-
const cleanPath = this.pdf.src.startsWith('/') ? this.pdf.src.slice(1) : this.pdf.src;
|
|
10331
|
-
pdfUrl = `${window.location.origin}/${cleanPath}`;
|
|
10332
|
-
}
|
|
10333
|
-
console.log('[PDF Lightbox] Opening PDF at URL:', pdfUrl);
|
|
10334
|
-
// Use Browser to open the PDF
|
|
10335
|
-
await Browser.open({
|
|
10336
|
-
url: pdfUrl,
|
|
10337
|
-
presentationStyle: 'fullscreen'
|
|
10338
|
-
});
|
|
10339
|
-
this.isLoading = false;
|
|
10340
|
-
// Close the modal after opening browser
|
|
10341
|
-
setTimeout(() => {
|
|
10342
|
-
this.close();
|
|
10343
|
-
}, 500);
|
|
10344
|
-
}
|
|
10345
|
-
catch (error) {
|
|
10346
|
-
console.error('[PDF Lightbox] Error opening PDF:', error);
|
|
10347
|
-
this.isLoading = false;
|
|
10348
|
-
this.hasError = true;
|
|
10349
|
-
this.errorMessage = error?.message || 'Failed to open PDF';
|
|
10350
|
-
}
|
|
10351
|
-
}
|
|
9741
|
+
message = input.required(...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
10352
9742
|
/**
|
|
10353
|
-
*
|
|
9743
|
+
* Optional icon name (currently using inline SVG for info icon)
|
|
9744
|
+
* Can be extended to support full icon library integration
|
|
10354
9745
|
*/
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
9746
|
+
iconName = input('', ...(ngDevMode ? [{ debugName: "iconName" }] : []));
|
|
9747
|
+
/**
|
|
9748
|
+
* Whether this system message appears directly after a timestamp
|
|
9749
|
+
* When true, removes top padding to reduce spacing
|
|
9750
|
+
*/
|
|
9751
|
+
afterTimestamp = input(false, ...(ngDevMode ? [{ debugName: "afterTimestamp" }] : []));
|
|
9752
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9753
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileSystemMessageBannerComponent, isStandalone: true, selector: "ds-mobile-system-message-banner", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, afterTimestamp: { classPropertyName: "afterTimestamp", publicName: "afterTimestamp", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.after-timestamp": "afterTimestamp()" } }, ngImport: i0, template: `
|
|
9754
|
+
<div class="system-message-container">
|
|
9755
|
+
<div class="system-message-content">
|
|
9756
|
+
@if (iconName()) {
|
|
9757
|
+
<span class="system-message-icon">
|
|
9758
|
+
<!-- Icon slot - you can add ds-icon component here if needed -->
|
|
9759
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
9760
|
+
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
|
|
9761
|
+
</svg>
|
|
9762
|
+
</span>
|
|
9763
|
+
}
|
|
9764
|
+
<p class="system-message-text">{{ message() }}</p>
|
|
9765
|
+
</div>
|
|
9766
|
+
</div>
|
|
9767
|
+
`, isInline: true, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
9768
|
+
}
|
|
9769
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, decorators: [{
|
|
9770
|
+
type: Component,
|
|
9771
|
+
args: [{ selector: 'ds-mobile-system-message-banner', standalone: true, imports: [CommonModule], host: {
|
|
9772
|
+
'[class.after-timestamp]': 'afterTimestamp()'
|
|
9773
|
+
}, template: `
|
|
9774
|
+
<div class="system-message-container">
|
|
9775
|
+
<div class="system-message-content">
|
|
9776
|
+
@if (iconName()) {
|
|
9777
|
+
<span class="system-message-icon">
|
|
9778
|
+
<!-- Icon slot - you can add ds-icon component here if needed -->
|
|
9779
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
9780
|
+
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
|
|
9781
|
+
</svg>
|
|
9782
|
+
</span>
|
|
9783
|
+
}
|
|
9784
|
+
<p class="system-message-text">{{ message() }}</p>
|
|
9785
|
+
</div>
|
|
9786
|
+
</div>
|
|
9787
|
+
`, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"] }]
|
|
9788
|
+
}], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], afterTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterTimestamp", required: false }] }] } });
|
|
9789
|
+
|
|
9790
|
+
/**
|
|
9791
|
+
* DsMobileLightboxHeaderComponent
|
|
9792
|
+
*
|
|
9793
|
+
* Shared header component for all lightbox types (image, PDF, etc.)
|
|
9794
|
+
* Displays author information and close button with consistent styling.
|
|
9795
|
+
*/
|
|
9796
|
+
class DsMobileLightboxHeaderComponent {
|
|
9797
|
+
/**
|
|
9798
|
+
* Author information to display
|
|
9799
|
+
*/
|
|
9800
|
+
author = input(...(ngDevMode ? [undefined, { debugName: "author" }] : []));
|
|
9801
|
+
/**
|
|
9802
|
+
* Emitted when close button is clicked
|
|
9803
|
+
*/
|
|
9804
|
+
closeClick = output();
|
|
9805
|
+
/**
|
|
9806
|
+
* Emitted when share button is clicked
|
|
9807
|
+
*/
|
|
9808
|
+
shareClick = output();
|
|
9809
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9810
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileLightboxHeaderComponent, isStandalone: true, selector: "ds-mobile-lightbox-header", inputs: { author: { classPropertyName: "author", publicName: "author", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeClick: "closeClick", shareClick: "shareClick" }, ngImport: i0, template: `
|
|
9811
|
+
<div class="lightbox-header lightbox-context">
|
|
9812
|
+
<div class="header-content">
|
|
9813
|
+
<!-- Post author info -->
|
|
9814
|
+
@if (author()) {
|
|
9815
|
+
<div class="post-author-info">
|
|
9816
|
+
<ds-avatar
|
|
9817
|
+
[initials]="author()!.avatarInitials ?? ''"
|
|
9818
|
+
[type]="author()!.avatarType ?? 'initials'"
|
|
9819
|
+
[src]="author()!.avatarSrc ?? ''"
|
|
9820
|
+
size="md"
|
|
9821
|
+
/>
|
|
9822
|
+
<div class="author-details">
|
|
9823
|
+
<div class="author-name">{{ author()!.name }}</div>
|
|
9824
|
+
<div class="author-meta">
|
|
9825
|
+
@if (author()!.role) {
|
|
9826
|
+
<span>{{ author()!.role }}</span>
|
|
9827
|
+
}
|
|
9828
|
+
@if (author()!.role && author()!.timestamp) {
|
|
9829
|
+
<span class="separator">·</span>
|
|
9830
|
+
}
|
|
9831
|
+
@if (author()!.timestamp) {
|
|
9832
|
+
<span>{{ author()!.timestamp }}</span>
|
|
9833
|
+
}
|
|
9834
|
+
</div>
|
|
9835
|
+
</div>
|
|
9836
|
+
</div>
|
|
9837
|
+
}
|
|
9838
|
+
|
|
9839
|
+
<!-- Action buttons - always visible -->
|
|
9840
|
+
<div class="header-actions">
|
|
9841
|
+
<ds-icon-button
|
|
9842
|
+
icon="remixShare2Line"
|
|
9843
|
+
variant="ghost"
|
|
9844
|
+
size="md"
|
|
9845
|
+
(clicked)="shareClick.emit()"
|
|
9846
|
+
class="share-button"
|
|
9847
|
+
[ariaLabel]="'Share'">
|
|
9848
|
+
</ds-icon-button>
|
|
9849
|
+
|
|
9850
|
+
<ds-icon-button
|
|
9851
|
+
icon="remixCloseLine"
|
|
9852
|
+
variant="ghost"
|
|
9853
|
+
size="md"
|
|
9854
|
+
(clicked)="closeClick.emit()"
|
|
9855
|
+
class="close-button"
|
|
9856
|
+
[ariaLabel]="'Close'">
|
|
9857
|
+
</ds-icon-button>
|
|
9858
|
+
</div>
|
|
9859
|
+
</div>
|
|
9860
|
+
</div>
|
|
9861
|
+
`, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ".lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:flex-end;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0;margin-right:auto}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.close-button,.share-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button,.share-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover,.share-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active,.share-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg,.share-button::ng-deep svg{color:#fff!important;fill:#fff!important}@supports (padding-top: env(safe-area-inset-top)){.lightbox-header{padding-top:calc(16px + env(safe-area-inset-top))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }] });
|
|
9862
|
+
}
|
|
9863
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxHeaderComponent, decorators: [{
|
|
9864
|
+
type: Component,
|
|
9865
|
+
args: [{ selector: 'ds-mobile-lightbox-header', standalone: true, imports: [CommonModule, DsIconButtonComponent, DsAvatarComponent], template: `
|
|
9866
|
+
<div class="lightbox-header lightbox-context">
|
|
9867
|
+
<div class="header-content">
|
|
9868
|
+
<!-- Post author info -->
|
|
9869
|
+
@if (author()) {
|
|
9870
|
+
<div class="post-author-info">
|
|
9871
|
+
<ds-avatar
|
|
9872
|
+
[initials]="author()!.avatarInitials ?? ''"
|
|
9873
|
+
[type]="author()!.avatarType ?? 'initials'"
|
|
9874
|
+
[src]="author()!.avatarSrc ?? ''"
|
|
9875
|
+
size="md"
|
|
9876
|
+
/>
|
|
9877
|
+
<div class="author-details">
|
|
9878
|
+
<div class="author-name">{{ author()!.name }}</div>
|
|
9879
|
+
<div class="author-meta">
|
|
9880
|
+
@if (author()!.role) {
|
|
9881
|
+
<span>{{ author()!.role }}</span>
|
|
9882
|
+
}
|
|
9883
|
+
@if (author()!.role && author()!.timestamp) {
|
|
9884
|
+
<span class="separator">·</span>
|
|
9885
|
+
}
|
|
9886
|
+
@if (author()!.timestamp) {
|
|
9887
|
+
<span>{{ author()!.timestamp }}</span>
|
|
9888
|
+
}
|
|
9889
|
+
</div>
|
|
9890
|
+
</div>
|
|
9891
|
+
</div>
|
|
9892
|
+
}
|
|
9893
|
+
|
|
9894
|
+
<!-- Action buttons - always visible -->
|
|
9895
|
+
<div class="header-actions">
|
|
9896
|
+
<ds-icon-button
|
|
9897
|
+
icon="remixShare2Line"
|
|
9898
|
+
variant="ghost"
|
|
9899
|
+
size="md"
|
|
9900
|
+
(clicked)="shareClick.emit()"
|
|
9901
|
+
class="share-button"
|
|
9902
|
+
[ariaLabel]="'Share'">
|
|
9903
|
+
</ds-icon-button>
|
|
9904
|
+
|
|
9905
|
+
<ds-icon-button
|
|
9906
|
+
icon="remixCloseLine"
|
|
9907
|
+
variant="ghost"
|
|
9908
|
+
size="md"
|
|
9909
|
+
(clicked)="closeClick.emit()"
|
|
9910
|
+
class="close-button"
|
|
9911
|
+
[ariaLabel]="'Close'">
|
|
9912
|
+
</ds-icon-button>
|
|
9913
|
+
</div>
|
|
9914
|
+
</div>
|
|
9915
|
+
</div>
|
|
9916
|
+
`, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ".lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:flex-end;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0;margin-right:auto}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.close-button,.share-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button,.share-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover,.share-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active,.share-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg,.share-button::ng-deep svg{color:#fff!important;fill:#fff!important}@supports (padding-top: env(safe-area-inset-top)){.lightbox-header{padding-top:calc(16px + env(safe-area-inset-top))}}\n"] }]
|
|
9917
|
+
}], propDecorators: { author: [{ type: i0.Input, args: [{ isSignal: true, alias: "author", required: false }] }], closeClick: [{ type: i0.Output, args: ["closeClick"] }], shareClick: [{ type: i0.Output, args: ["shareClick"] }] } });
|
|
9918
|
+
|
|
9919
|
+
/**
|
|
9920
|
+
* DsMobileLightboxFooterComponent
|
|
9921
|
+
*
|
|
9922
|
+
* Shared footer component for all lightbox types (image, PDF, etc.)
|
|
9923
|
+
* Displays navigation controls (for multiple images) and action buttons.
|
|
9924
|
+
*/
|
|
9925
|
+
class DsMobileLightboxFooterComponent {
|
|
9926
|
+
/**
|
|
9927
|
+
* Whether to show navigation controls
|
|
9928
|
+
*/
|
|
9929
|
+
showNavigation = input(false, ...(ngDevMode ? [{ debugName: "showNavigation" }] : []));
|
|
9930
|
+
/**
|
|
9931
|
+
* Current image index (0-based)
|
|
9932
|
+
*/
|
|
9933
|
+
currentIndex = input(0, ...(ngDevMode ? [{ debugName: "currentIndex" }] : []));
|
|
9934
|
+
/**
|
|
9935
|
+
* Total number of images
|
|
9936
|
+
*/
|
|
9937
|
+
totalImages = input(1, ...(ngDevMode ? [{ debugName: "totalImages" }] : []));
|
|
9938
|
+
/**
|
|
9939
|
+
* Whether to show like & comment action buttons
|
|
9940
|
+
* @default false
|
|
9941
|
+
*/
|
|
9942
|
+
showActions = input(false, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
|
|
9943
|
+
/**
|
|
9944
|
+
* Whether the content is liked
|
|
9945
|
+
*/
|
|
9946
|
+
isLiked = input(false, ...(ngDevMode ? [{ debugName: "isLiked" }] : []));
|
|
9947
|
+
/**
|
|
9948
|
+
* Number of likes
|
|
9949
|
+
*/
|
|
9950
|
+
likeCount = input(0, ...(ngDevMode ? [{ debugName: "likeCount" }] : []));
|
|
9951
|
+
/**
|
|
9952
|
+
* Number of comments
|
|
9953
|
+
*/
|
|
9954
|
+
commentCount = input(0, ...(ngDevMode ? [{ debugName: "commentCount" }] : []));
|
|
9955
|
+
/**
|
|
9956
|
+
* Emitted when previous button is clicked
|
|
9957
|
+
*/
|
|
9958
|
+
prevClick = output();
|
|
9959
|
+
/**
|
|
9960
|
+
* Emitted when next button is clicked
|
|
9961
|
+
*/
|
|
9962
|
+
nextClick = output();
|
|
9963
|
+
/**
|
|
9964
|
+
* Emitted when like button is clicked
|
|
9965
|
+
*/
|
|
9966
|
+
likeClick = output();
|
|
9967
|
+
/**
|
|
9968
|
+
* Emitted when comment button is clicked
|
|
9969
|
+
*/
|
|
9970
|
+
commentClick = output();
|
|
9971
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9972
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileLightboxFooterComponent, isStandalone: true, selector: "ds-mobile-lightbox-footer", inputs: { showNavigation: { classPropertyName: "showNavigation", publicName: "showNavigation", isSignal: true, isRequired: false, transformFunction: null }, currentIndex: { classPropertyName: "currentIndex", publicName: "currentIndex", isSignal: true, isRequired: false, transformFunction: null }, totalImages: { classPropertyName: "totalImages", publicName: "totalImages", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, isLiked: { classPropertyName: "isLiked", publicName: "isLiked", isSignal: true, isRequired: false, transformFunction: null }, likeCount: { classPropertyName: "likeCount", publicName: "likeCount", isSignal: true, isRequired: false, transformFunction: null }, commentCount: { classPropertyName: "commentCount", publicName: "commentCount", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { prevClick: "prevClick", nextClick: "nextClick", likeClick: "likeClick", commentClick: "commentClick" }, ngImport: i0, template: `
|
|
9973
|
+
<div class="lightbox-footer">
|
|
9974
|
+
<!-- Navigation controls (only shown for multiple images) -->
|
|
9975
|
+
@if (showNavigation() && totalImages() > 1) {
|
|
9976
|
+
<div class="footer-navigation">
|
|
9977
|
+
<button
|
|
9978
|
+
class="nav-button prev"
|
|
9979
|
+
(click)="prevClick.emit()"
|
|
9980
|
+
[disabled]="currentIndex() === 0"
|
|
9981
|
+
aria-label="Previous image">
|
|
9982
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
9983
|
+
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9984
|
+
</svg>
|
|
9985
|
+
</button>
|
|
9986
|
+
|
|
9987
|
+
<div class="counter">
|
|
9988
|
+
{{ currentIndex() + 1 }} / {{ totalImages() }}
|
|
9989
|
+
</div>
|
|
9990
|
+
|
|
9991
|
+
<button
|
|
9992
|
+
class="nav-button next"
|
|
9993
|
+
(click)="nextClick.emit()"
|
|
9994
|
+
[disabled]="currentIndex() === totalImages() - 1"
|
|
9995
|
+
aria-label="Next image">
|
|
9996
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
9997
|
+
<path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9998
|
+
</svg>
|
|
9999
|
+
</button>
|
|
10000
|
+
</div>
|
|
10001
|
+
}
|
|
10002
|
+
|
|
10003
|
+
<!-- Action buttons -->
|
|
10004
|
+
@if (showActions()) {
|
|
10005
|
+
<div class="footer-actions">
|
|
10006
|
+
<div class="action-buttons-left">
|
|
10007
|
+
<!-- Like button -->
|
|
10008
|
+
<ds-icon-button
|
|
10009
|
+
[icon]="isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'"
|
|
10010
|
+
variant="ghost"
|
|
10011
|
+
size="md"
|
|
10012
|
+
(click)="likeClick.emit()"
|
|
10013
|
+
[attr.data-liked]="isLiked()"
|
|
10014
|
+
class="action-button-like"
|
|
10015
|
+
[ariaLabel]="'Like'">
|
|
10016
|
+
</ds-icon-button>
|
|
10017
|
+
|
|
10018
|
+
<!-- Comment button -->
|
|
10019
|
+
<ds-icon-button
|
|
10020
|
+
icon="remixChat3Line"
|
|
10021
|
+
variant="ghost"
|
|
10022
|
+
size="md"
|
|
10023
|
+
(click)="commentClick.emit()"
|
|
10024
|
+
class="action-button-comment"
|
|
10025
|
+
[ariaLabel]="'Comment'">
|
|
10026
|
+
</ds-icon-button>
|
|
10027
|
+
</div>
|
|
10028
|
+
</div>
|
|
10029
|
+
}
|
|
10030
|
+
</div>
|
|
10031
|
+
`, isInline: true, styles: [".lightbox-footer{position:fixed;bottom:0;left:0;right:0;z-index:100;padding:16px 20px 20px;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none;display:flex;flex-direction:column;gap:12px}.footer-navigation{display:flex;align-items:center;justify-content:center;gap:24px;pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);border-radius:50%;color:#fff;width:40px;height:40px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);padding:0}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px;flex-shrink:0}.counter{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-radius:100px;padding:8px 16px;color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;letter-spacing:-.3px;pointer-events:auto;-webkit-user-select:none;user-select:none}.footer-actions{display:flex;align-items:center;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-footer{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
|
|
10032
|
+
}
|
|
10033
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxFooterComponent, decorators: [{
|
|
10034
|
+
type: Component,
|
|
10035
|
+
args: [{ selector: 'ds-mobile-lightbox-footer', standalone: true, imports: [CommonModule, DsIconButtonComponent], template: `
|
|
10036
|
+
<div class="lightbox-footer">
|
|
10037
|
+
<!-- Navigation controls (only shown for multiple images) -->
|
|
10038
|
+
@if (showNavigation() && totalImages() > 1) {
|
|
10039
|
+
<div class="footer-navigation">
|
|
10040
|
+
<button
|
|
10041
|
+
class="nav-button prev"
|
|
10042
|
+
(click)="prevClick.emit()"
|
|
10043
|
+
[disabled]="currentIndex() === 0"
|
|
10044
|
+
aria-label="Previous image">
|
|
10045
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
10046
|
+
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
10047
|
+
</svg>
|
|
10048
|
+
</button>
|
|
10049
|
+
|
|
10050
|
+
<div class="counter">
|
|
10051
|
+
{{ currentIndex() + 1 }} / {{ totalImages() }}
|
|
10052
|
+
</div>
|
|
10053
|
+
|
|
10054
|
+
<button
|
|
10055
|
+
class="nav-button next"
|
|
10056
|
+
(click)="nextClick.emit()"
|
|
10057
|
+
[disabled]="currentIndex() === totalImages() - 1"
|
|
10058
|
+
aria-label="Next image">
|
|
10059
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
10060
|
+
<path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
10061
|
+
</svg>
|
|
10062
|
+
</button>
|
|
10063
|
+
</div>
|
|
10064
|
+
}
|
|
10065
|
+
|
|
10066
|
+
<!-- Action buttons -->
|
|
10067
|
+
@if (showActions()) {
|
|
10068
|
+
<div class="footer-actions">
|
|
10069
|
+
<div class="action-buttons-left">
|
|
10070
|
+
<!-- Like button -->
|
|
10071
|
+
<ds-icon-button
|
|
10072
|
+
[icon]="isLiked() ? 'remixHeart3Fill' : 'remixHeart3Line'"
|
|
10073
|
+
variant="ghost"
|
|
10074
|
+
size="md"
|
|
10075
|
+
(click)="likeClick.emit()"
|
|
10076
|
+
[attr.data-liked]="isLiked()"
|
|
10077
|
+
class="action-button-like"
|
|
10078
|
+
[ariaLabel]="'Like'">
|
|
10079
|
+
</ds-icon-button>
|
|
10080
|
+
|
|
10081
|
+
<!-- Comment button -->
|
|
10082
|
+
<ds-icon-button
|
|
10083
|
+
icon="remixChat3Line"
|
|
10084
|
+
variant="ghost"
|
|
10085
|
+
size="md"
|
|
10086
|
+
(click)="commentClick.emit()"
|
|
10087
|
+
class="action-button-comment"
|
|
10088
|
+
[ariaLabel]="'Comment'">
|
|
10089
|
+
</ds-icon-button>
|
|
10090
|
+
</div>
|
|
10091
|
+
</div>
|
|
10092
|
+
}
|
|
10093
|
+
</div>
|
|
10094
|
+
`, styles: [".lightbox-footer{position:fixed;bottom:0;left:0;right:0;z-index:100;padding:16px 20px 20px;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none;display:flex;flex-direction:column;gap:12px}.footer-navigation{display:flex;align-items:center;justify-content:center;gap:24px;pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);border-radius:50%;color:#fff;width:40px;height:40px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);padding:0}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px;flex-shrink:0}.counter{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-radius:100px;padding:8px 16px;color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;letter-spacing:-.3px;pointer-events:auto;-webkit-user-select:none;user-select:none}.footer-actions{display:flex;align-items:center;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-footer{padding-bottom:calc(20px + env(safe-area-inset-bottom))}}\n"] }]
|
|
10095
|
+
}], propDecorators: { showNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNavigation", required: false }] }], currentIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentIndex", required: false }] }], totalImages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalImages", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], isLiked: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLiked", required: false }] }], likeCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "likeCount", required: false }] }], commentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentCount", required: false }] }], prevClick: [{ type: i0.Output, args: ["prevClick"] }], nextClick: [{ type: i0.Output, args: ["nextClick"] }], likeClick: [{ type: i0.Output, args: ["likeClick"] }], commentClick: [{ type: i0.Output, args: ["commentClick"] }] } });
|
|
10096
|
+
|
|
10097
|
+
/**
|
|
10098
|
+
* DsMobileLightboxImageComponent
|
|
10099
|
+
*
|
|
10100
|
+
* Full-screen image lightbox component with Swiper.js navigation and pinch-zoom.
|
|
10101
|
+
*
|
|
10102
|
+
* This component is typically not used directly - use DsMobileLightboxService instead.
|
|
10103
|
+
*
|
|
10104
|
+
* Features:
|
|
10105
|
+
* - Swiper.js for smooth image navigation
|
|
10106
|
+
* - Pinch to zoom in/out
|
|
10107
|
+
* - Double-tap to toggle zoom
|
|
10108
|
+
* - Swipe down to close (when not zoomed)
|
|
10109
|
+
* - Image counter and navigation controls
|
|
10110
|
+
*
|
|
10111
|
+
* @example
|
|
10112
|
+
* ```typescript
|
|
10113
|
+
* // Don't instantiate directly - use the service:
|
|
10114
|
+
* constructor(private lightbox: DsMobileLightboxService) {}
|
|
10115
|
+
*
|
|
10116
|
+
* openImage() {
|
|
10117
|
+
* this.lightbox.openImages({
|
|
10118
|
+
* images: [{ type: 'image', src: 'image.jpg', title: 'My Image' }]
|
|
10119
|
+
* });
|
|
10120
|
+
* }
|
|
10121
|
+
* ```
|
|
10122
|
+
*/
|
|
10123
|
+
class DsMobileLightboxImageComponent {
|
|
10124
|
+
gestureCtrl;
|
|
10125
|
+
// Inputs (passed from service as regular properties, not signals)
|
|
10126
|
+
images;
|
|
10127
|
+
author;
|
|
10128
|
+
initialIndex = 0;
|
|
10129
|
+
enableZoom = true;
|
|
10130
|
+
showControls = true;
|
|
10131
|
+
enableSwipe = true;
|
|
10132
|
+
showInfo = true;
|
|
10133
|
+
showActions = false;
|
|
10134
|
+
animation = 'fade';
|
|
10135
|
+
onCloseRequested;
|
|
10136
|
+
// View children
|
|
10137
|
+
swiperContainer;
|
|
10138
|
+
// State
|
|
10139
|
+
currentIndex = signal(0, ...(ngDevMode ? [{ debugName: "currentIndex" }] : []));
|
|
10140
|
+
scale = signal(1, ...(ngDevMode ? [{ debugName: "scale" }] : []));
|
|
10141
|
+
isZoomed = signal(false, ...(ngDevMode ? [{ debugName: "isZoomed" }] : []));
|
|
10142
|
+
isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
10143
|
+
hasError = signal(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
|
|
10144
|
+
// Action states
|
|
10145
|
+
isLiked = signal(false, ...(ngDevMode ? [{ debugName: "isLiked" }] : []));
|
|
10146
|
+
likeCount = signal(0, ...(ngDevMode ? [{ debugName: "likeCount" }] : []));
|
|
10147
|
+
commentCount = signal(0, ...(ngDevMode ? [{ debugName: "commentCount" }] : []));
|
|
10148
|
+
// Computed
|
|
10149
|
+
currentImage = computed(() => this.images[this.currentIndex()], ...(ngDevMode ? [{ debugName: "currentImage" }] : []));
|
|
10150
|
+
// Swiper instance
|
|
10151
|
+
swiper;
|
|
10152
|
+
zoomData = new Map();
|
|
10153
|
+
constructor(gestureCtrl) {
|
|
10154
|
+
this.gestureCtrl = gestureCtrl;
|
|
10155
|
+
}
|
|
10156
|
+
ngOnInit() {
|
|
10157
|
+
// Set initial index from the passed property
|
|
10158
|
+
if (this.initialIndex !== undefined) {
|
|
10159
|
+
this.currentIndex.set(this.initialIndex);
|
|
10160
|
+
}
|
|
10161
|
+
// Initialize action states from current image
|
|
10162
|
+
const currentImg = this.images[this.currentIndex()];
|
|
10163
|
+
if (currentImg) {
|
|
10164
|
+
this.isLiked.set(currentImg.isLiked ?? false);
|
|
10165
|
+
this.likeCount.set(currentImg.likeCount ?? 0);
|
|
10166
|
+
this.commentCount.set(currentImg.commentCount ?? 0);
|
|
10167
|
+
}
|
|
10168
|
+
}
|
|
10169
|
+
ngAfterViewInit() {
|
|
10170
|
+
setTimeout(() => {
|
|
10171
|
+
this.initializeSwiper();
|
|
10172
|
+
this.initializeZoomGestures();
|
|
10173
|
+
}, 100);
|
|
10174
|
+
}
|
|
10175
|
+
ngOnDestroy() {
|
|
10176
|
+
// Clean up Swiper
|
|
10177
|
+
if (this.swiper) {
|
|
10178
|
+
this.swiper.destroy();
|
|
10179
|
+
this.swiper = undefined;
|
|
10180
|
+
}
|
|
10181
|
+
}
|
|
10182
|
+
/**
|
|
10183
|
+
* Initialize Swiper for image navigation
|
|
10184
|
+
*/
|
|
10185
|
+
initializeSwiper() {
|
|
10186
|
+
if (!this.swiperContainer) {
|
|
10187
|
+
console.error('[Lightbox] Swiper container not found');
|
|
10188
|
+
return;
|
|
10189
|
+
}
|
|
10190
|
+
const swiperOptions = {
|
|
10191
|
+
initialSlide: this.initialIndex,
|
|
10192
|
+
speed: 300,
|
|
10193
|
+
resistance: true,
|
|
10194
|
+
resistanceRatio: 0.85,
|
|
10195
|
+
slidesPerView: 1,
|
|
10196
|
+
spaceBetween: 0,
|
|
10197
|
+
touchRatio: 1,
|
|
10198
|
+
longSwipesRatio: 0.5,
|
|
10199
|
+
threshold: 10,
|
|
10200
|
+
on: {
|
|
10201
|
+
slideChange: (swiper) => {
|
|
10202
|
+
this.currentIndex.set(swiper.activeIndex);
|
|
10203
|
+
this.updateActionStates();
|
|
10204
|
+
// Check if the image is already loaded
|
|
10205
|
+
const currentSlide = swiper.slides[swiper.activeIndex];
|
|
10206
|
+
const img = currentSlide?.querySelector('img');
|
|
10207
|
+
if (img && img.complete && img.naturalHeight !== 0) {
|
|
10208
|
+
// Image is already loaded
|
|
10209
|
+
this.isLoading.set(false);
|
|
10210
|
+
}
|
|
10211
|
+
},
|
|
10212
|
+
slideChangeTransitionStart: () => {
|
|
10213
|
+
// Don't show loading spinner if image is already loaded
|
|
10214
|
+
const currentSlide = this.swiper?.slides[this.swiper.activeIndex];
|
|
10215
|
+
const img = currentSlide?.querySelector('img');
|
|
10216
|
+
if (!img || !img.complete || img.naturalHeight === 0) {
|
|
10217
|
+
this.isLoading.set(true);
|
|
10218
|
+
}
|
|
10219
|
+
}
|
|
10220
|
+
}
|
|
10221
|
+
};
|
|
10222
|
+
this.swiper = new Swiper(this.swiperContainer.nativeElement, swiperOptions);
|
|
10223
|
+
// Check if the initial image is already loaded
|
|
10224
|
+
setTimeout(() => {
|
|
10225
|
+
const currentSlide = this.swiper?.slides[this.currentIndex()];
|
|
10226
|
+
const img = currentSlide?.querySelector('img');
|
|
10227
|
+
if (img && img.complete && img.naturalHeight !== 0) {
|
|
10228
|
+
this.isLoading.set(false);
|
|
10229
|
+
}
|
|
10230
|
+
}, 0);
|
|
10231
|
+
}
|
|
10232
|
+
/**
|
|
10233
|
+
* Initialize pinch-zoom gestures for all slides
|
|
10234
|
+
*/
|
|
10235
|
+
initializeZoomGestures() {
|
|
10236
|
+
if (!this.enableZoom)
|
|
10237
|
+
return;
|
|
10238
|
+
const slides = this.swiperContainer.nativeElement.querySelectorAll('.image-zoom-container');
|
|
10239
|
+
slides.forEach((slide, index) => {
|
|
10240
|
+
this.initializeZoomForSlide(slide, index);
|
|
10241
|
+
});
|
|
10242
|
+
}
|
|
10243
|
+
/**
|
|
10244
|
+
* Initialize zoom gestures for a specific slide
|
|
10245
|
+
*/
|
|
10246
|
+
initializeZoomForSlide(container, index) {
|
|
10247
|
+
let initialDistance = 0;
|
|
10248
|
+
let initialScale = 1;
|
|
10249
|
+
let currentScale = 1;
|
|
10250
|
+
let lastTap = 0;
|
|
10251
|
+
// Double-tap to zoom
|
|
10252
|
+
container.addEventListener('click', (event) => {
|
|
10253
|
+
const now = Date.now();
|
|
10254
|
+
const timeSinceLastTap = now - lastTap;
|
|
10255
|
+
if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {
|
|
10256
|
+
event.preventDefault();
|
|
10257
|
+
this.toggleZoom(container, index);
|
|
10258
|
+
}
|
|
10259
|
+
lastTap = now;
|
|
10260
|
+
});
|
|
10261
|
+
// Pinch to zoom
|
|
10262
|
+
const getTouchDistance = (touches) => {
|
|
10263
|
+
const dx = touches[0].clientX - touches[1].clientX;
|
|
10264
|
+
const dy = touches[0].clientY - touches[1].clientY;
|
|
10265
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
10266
|
+
};
|
|
10267
|
+
container.addEventListener('touchstart', (event) => {
|
|
10268
|
+
if (event.touches.length === 2) {
|
|
10269
|
+
event.preventDefault();
|
|
10270
|
+
initialDistance = getTouchDistance(event.touches);
|
|
10271
|
+
const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };
|
|
10272
|
+
initialScale = zoomData.scale;
|
|
10273
|
+
// Disable Swiper when zooming
|
|
10274
|
+
if (this.swiper) {
|
|
10275
|
+
this.swiper.allowTouchMove = false;
|
|
10276
|
+
}
|
|
10277
|
+
}
|
|
10278
|
+
}, { passive: false });
|
|
10279
|
+
container.addEventListener('touchmove', (event) => {
|
|
10280
|
+
if (event.touches.length === 2) {
|
|
10281
|
+
event.preventDefault();
|
|
10282
|
+
const currentDistance = getTouchDistance(event.touches);
|
|
10283
|
+
const pinchScale = currentDistance / initialDistance;
|
|
10284
|
+
currentScale = Math.max(1, Math.min(initialScale * pinchScale, 4));
|
|
10285
|
+
const img = container.querySelector('img');
|
|
10286
|
+
if (img) {
|
|
10287
|
+
img.style.transform = `scale(${currentScale})`;
|
|
10288
|
+
}
|
|
10289
|
+
if (currentScale > 1) {
|
|
10290
|
+
this.isZoomed.set(true);
|
|
10291
|
+
}
|
|
10292
|
+
else {
|
|
10293
|
+
this.isZoomed.set(false);
|
|
10294
|
+
}
|
|
10295
|
+
}
|
|
10296
|
+
}, { passive: false });
|
|
10297
|
+
container.addEventListener('touchend', (event) => {
|
|
10298
|
+
if (event.touches.length < 2) {
|
|
10299
|
+
// Save zoom state
|
|
10300
|
+
this.zoomData.set(index, { scale: currentScale, x: 0, y: 0 });
|
|
10301
|
+
// Re-enable Swiper if not zoomed
|
|
10302
|
+
if (this.swiper && currentScale <= 1) {
|
|
10303
|
+
this.swiper.allowTouchMove = true;
|
|
10304
|
+
}
|
|
10305
|
+
}
|
|
10306
|
+
});
|
|
10307
|
+
}
|
|
10308
|
+
/**
|
|
10309
|
+
* Toggle zoom on double-tap
|
|
10310
|
+
*/
|
|
10311
|
+
toggleZoom(container, index) {
|
|
10312
|
+
const zoomData = this.zoomData.get(index) || { scale: 1, x: 0, y: 0 };
|
|
10313
|
+
const img = container.querySelector('img');
|
|
10314
|
+
if (!img)
|
|
10315
|
+
return;
|
|
10316
|
+
if (zoomData.scale > 1) {
|
|
10317
|
+
// Zoom out
|
|
10318
|
+
img.style.transform = 'scale(1)';
|
|
10319
|
+
this.zoomData.set(index, { scale: 1, x: 0, y: 0 });
|
|
10320
|
+
this.isZoomed.set(false);
|
|
10321
|
+
if (this.swiper) {
|
|
10322
|
+
this.swiper.allowTouchMove = true;
|
|
10323
|
+
}
|
|
10324
|
+
}
|
|
10325
|
+
else {
|
|
10326
|
+
// Zoom in
|
|
10327
|
+
img.style.transform = 'scale(2)';
|
|
10328
|
+
this.zoomData.set(index, { scale: 2, x: 0, y: 0 });
|
|
10329
|
+
this.isZoomed.set(true);
|
|
10330
|
+
if (this.swiper) {
|
|
10331
|
+
this.swiper.allowTouchMove = false;
|
|
10332
|
+
}
|
|
10333
|
+
}
|
|
10334
|
+
}
|
|
10335
|
+
/**
|
|
10336
|
+
* Update action states (like, comments) when slide changes
|
|
10337
|
+
*/
|
|
10338
|
+
updateActionStates() {
|
|
10339
|
+
const currentImg = this.images[this.currentIndex()];
|
|
10340
|
+
if (currentImg) {
|
|
10341
|
+
this.isLiked.set(currentImg.isLiked ?? false);
|
|
10342
|
+
this.likeCount.set(currentImg.likeCount ?? 0);
|
|
10343
|
+
this.commentCount.set(currentImg.commentCount ?? 0);
|
|
10344
|
+
}
|
|
10345
|
+
}
|
|
10346
|
+
/**
|
|
10347
|
+
* Close the lightbox
|
|
10348
|
+
*/
|
|
10349
|
+
close() {
|
|
10350
|
+
if (this.onCloseRequested) {
|
|
10351
|
+
this.onCloseRequested();
|
|
10352
|
+
}
|
|
10353
|
+
}
|
|
10354
|
+
/**
|
|
10355
|
+
* Handle share button click
|
|
10356
|
+
*/
|
|
10357
|
+
async onShare() {
|
|
10358
|
+
console.log('[Lightbox] Share button clicked');
|
|
10359
|
+
const currentImg = this.currentImage();
|
|
10360
|
+
if (!currentImg?.src) {
|
|
10361
|
+
console.warn('[Lightbox] No image to share');
|
|
10362
|
+
return;
|
|
10363
|
+
}
|
|
10364
|
+
try {
|
|
10365
|
+
// Check if Web Share API is available (for browser)
|
|
10366
|
+
if (navigator.share) {
|
|
10367
|
+
await navigator.share({
|
|
10368
|
+
title: currentImg.title || 'Shared Image',
|
|
10369
|
+
text: currentImg.description || '',
|
|
10370
|
+
url: currentImg.src,
|
|
10371
|
+
});
|
|
10372
|
+
console.log('[Lightbox] Shared via Web Share API');
|
|
10373
|
+
}
|
|
10374
|
+
else {
|
|
10375
|
+
// Fallback to Capacitor Share API (for native apps)
|
|
10376
|
+
await Share.share({
|
|
10377
|
+
title: currentImg.title || 'Shared Image',
|
|
10378
|
+
url: currentImg.src,
|
|
10379
|
+
dialogTitle: 'Share Image',
|
|
10380
|
+
});
|
|
10381
|
+
console.log('[Lightbox] Shared via Capacitor Share API');
|
|
10382
|
+
}
|
|
10383
|
+
}
|
|
10384
|
+
catch (error) {
|
|
10385
|
+
// User cancellation is expected and not an error
|
|
10386
|
+
if (error?.message?.includes('cancel') || error?.code === 'USER_CANCELLED') {
|
|
10387
|
+
console.log('[Lightbox] Share cancelled by user');
|
|
10388
|
+
return;
|
|
10389
|
+
}
|
|
10390
|
+
console.error('[Lightbox] Share failed:', error);
|
|
10391
|
+
}
|
|
10392
|
+
}
|
|
10393
|
+
/**
|
|
10394
|
+
* Handle like button toggle
|
|
10395
|
+
*/
|
|
10396
|
+
onLikeToggle() {
|
|
10397
|
+
console.log('[Lightbox] Like button toggled');
|
|
10398
|
+
this.isLiked.update(liked => !liked);
|
|
10399
|
+
if (this.isLiked()) {
|
|
10400
|
+
this.likeCount.update(count => count + 1);
|
|
10401
|
+
}
|
|
10402
|
+
else {
|
|
10403
|
+
this.likeCount.update(count => Math.max(0, count - 1));
|
|
10404
|
+
}
|
|
10405
|
+
}
|
|
10406
|
+
/**
|
|
10407
|
+
* Handle reply/comment button click
|
|
10408
|
+
*/
|
|
10409
|
+
onReply() {
|
|
10410
|
+
console.log('[Lightbox] Reply button clicked');
|
|
10411
|
+
if (this.onCloseRequested) {
|
|
10412
|
+
this.onCloseRequested();
|
|
10413
|
+
}
|
|
10414
|
+
}
|
|
10415
|
+
/**
|
|
10416
|
+
* Navigate to the next image
|
|
10417
|
+
*/
|
|
10418
|
+
nextImage() {
|
|
10419
|
+
if (this.swiper && this.currentIndex() < this.images.length - 1) {
|
|
10420
|
+
this.swiper.slideNext();
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10423
|
+
/**
|
|
10424
|
+
* Navigate to the previous image
|
|
10425
|
+
*/
|
|
10426
|
+
previousImage() {
|
|
10427
|
+
if (this.swiper && this.currentIndex() > 0) {
|
|
10428
|
+
this.swiper.slidePrev();
|
|
10429
|
+
}
|
|
10430
|
+
}
|
|
10431
|
+
/**
|
|
10432
|
+
* Handle image load success
|
|
10433
|
+
*/
|
|
10434
|
+
onImageLoad(index) {
|
|
10435
|
+
if (index === this.currentIndex()) {
|
|
10436
|
+
this.isLoading.set(false);
|
|
10437
|
+
}
|
|
10438
|
+
}
|
|
10439
|
+
/**
|
|
10440
|
+
* Handle image load error
|
|
10441
|
+
*/
|
|
10442
|
+
onImageError(index) {
|
|
10443
|
+
if (index === this.currentIndex()) {
|
|
10444
|
+
console.error(`[Lightbox] Image ${index} failed to load`);
|
|
10445
|
+
this.isLoading.set(false);
|
|
10446
|
+
this.hasError.set(true);
|
|
10447
|
+
}
|
|
10448
|
+
}
|
|
10449
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxImageComponent, deps: [{ token: i1.GestureController }], target: i0.ɵɵFactoryTarget.Component });
|
|
10450
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileLightboxImageComponent, isStandalone: true, selector: "ds-mobile-lightbox-image", viewQueries: [{ propertyName: "swiperContainer", first: true, predicate: ["swiperContainer"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
10451
|
+
<div class="lightbox-overlay"
|
|
10452
|
+
[class.zoomed]="isZoomed()">
|
|
10453
|
+
|
|
10454
|
+
<div class="lightbox-wrapper">
|
|
10455
|
+
<!-- Header with author info and action buttons -->
|
|
10456
|
+
<ds-mobile-lightbox-header
|
|
10457
|
+
[author]="author"
|
|
10458
|
+
(closeClick)="close()"
|
|
10459
|
+
(shareClick)="onShare()"
|
|
10460
|
+
/>
|
|
10461
|
+
|
|
10462
|
+
<!-- Swiper container -->
|
|
10463
|
+
<div class="swiper-container" #swiperContainer>
|
|
10464
|
+
<div class="swiper-wrapper">
|
|
10465
|
+
@for (image of images; track image.src; let i = $index) {
|
|
10466
|
+
<div class="swiper-slide">
|
|
10467
|
+
<div class="image-zoom-container" [attr.data-index]="i">
|
|
10468
|
+
<img
|
|
10469
|
+
[src]="image.src"
|
|
10470
|
+
[alt]="image.alt || 'Lightbox image'"
|
|
10471
|
+
class="lightbox-image"
|
|
10472
|
+
(load)="onImageLoad(i)"
|
|
10473
|
+
(error)="onImageError(i)">
|
|
10474
|
+
</div>
|
|
10475
|
+
</div>
|
|
10476
|
+
}
|
|
10477
|
+
</div>
|
|
10478
|
+
</div>
|
|
10479
|
+
|
|
10480
|
+
<!-- Loading indicator -->
|
|
10481
|
+
@if (isLoading()) {
|
|
10482
|
+
<div class="loading-spinner">
|
|
10483
|
+
<ion-spinner name="crescent"></ion-spinner>
|
|
10484
|
+
</div>
|
|
10485
|
+
}
|
|
10486
|
+
|
|
10487
|
+
<!-- Footer with navigation and actions -->
|
|
10488
|
+
<ds-mobile-lightbox-footer
|
|
10489
|
+
[showNavigation]="showControls && images.length > 1"
|
|
10490
|
+
[showActions]="showActions"
|
|
10491
|
+
[currentIndex]="currentIndex()"
|
|
10492
|
+
[totalImages]="images.length"
|
|
10493
|
+
[isLiked]="isLiked()"
|
|
10494
|
+
[likeCount]="likeCount()"
|
|
10495
|
+
[commentCount]="commentCount()"
|
|
10496
|
+
(prevClick)="previousImage()"
|
|
10497
|
+
(nextClick)="nextImage()"
|
|
10498
|
+
(likeClick)="onLikeToggle()"
|
|
10499
|
+
(commentClick)="onReply()"
|
|
10500
|
+
/>
|
|
10501
|
+
</div>
|
|
10502
|
+
</div>
|
|
10503
|
+
`, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}:host{display:block;position:fixed;inset:0;width:100vw;height:100vh;z-index:10000}.lightbox-overlay{position:fixed;inset:0;width:100vw;height:100vh;background:#000000fa;z-index:10000;display:flex;flex-direction:column;touch-action:none;animation:fadeIn .2s ease-out}.lightbox-overlay.zoomed{overflow:hidden}.lightbox-content{display:block;height:100vh;width:100vw;position:absolute;inset:0}.lightbox-content::part(scroll){display:flex;flex-direction:column;height:100%;overflow:hidden}.lightbox-wrapper{position:absolute;inset:0;display:flex;flex-direction:column;width:100%;height:100%}.lightbox-content.zoomed{overflow:hidden}.lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.close-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg{color:#fff!important;fill:#fff!important}.swiper-container{position:absolute;inset:0;width:100%;height:100%;z-index:1}.swiper-wrapper{width:100%;height:100%}.swiper-slide{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.image-zoom-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden}.lightbox-image{max-width:min(640px,100%);max-height:100%;width:auto;height:auto;-o-object-fit:contain;object-fit:contain;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none;transition:transform .3s ease-out;transform-origin:center center}.lightbox-overlay.zoomed .swiper-container{touch-action:none}.loading-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.loading-spinner ion-spinner{--color: rgba(255, 255, 255, .8);width:48px;height:48px}.error-message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10;text-align:center;color:#fffc;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:500;padding:20px;background:#00000080;border-radius:12px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.lightbox-bottom-section{position:fixed;bottom:0;left:0;right:0;z-index:100;display:flex;flex-direction:column;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none}.lightbox-controls{display:flex;align-items:center;justify-content:center;gap:24px;padding:16px 20px 12px;pointer-events:none}.nav-button,.counter{pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);color:#fff;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease;padding:0;margin:0;outline:none}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px}.counter{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;padding:10px 16px;background:#00000080;border-radius:100px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);white-space:nowrap}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-bottom-section{padding-bottom:env(safe-area-inset-bottom)}}.lightbox-footer{display:flex;padding:12px 20px 20px;pointer-events:none}.footer-actions{display:flex;align-items:center;justify-content:space-between;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-with-count::ng-deep button,.action-button-share::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover,.action-button-with-count::ng-deep button:hover,.action-button-share::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active,.action-button-with-count::ng-deep button:active,.action-button-share::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-with-count::ng-deep button svg,.action-button-share::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content,.action-button-with-count::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg,.action-button-with-count::ng-deep button .btn__icon svg,.action-button-share::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment,.action-button-share{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-share::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@media (min-width: 768px){.lightbox-header{padding:24px}.close-button{width:48px;height:48px}.lightbox-controls{padding:20px 24px 16px}.nav-button{width:48px;height:48px}.counter{font-size:var(--font-size-base);padding:12px 20px}.lightbox-footer{padding:16px 24px 24px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{height:48px;padding:0 20px}.action-button-share::ng-deep button{width:48px!important;height:48px!important;min-width:48px!important;min-height:48px!important}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion: reduce){.image-wrapper,.nav-button,.lightbox-caption{transition:none}}.nav-button:focus-visible{outline:2px solid white;outline-offset:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: DsMobileLightboxHeaderComponent, selector: "ds-mobile-lightbox-header", inputs: ["author"], outputs: ["closeClick", "shareClick"] }, { kind: "component", type: DsMobileLightboxFooterComponent, selector: "ds-mobile-lightbox-footer", inputs: ["showNavigation", "currentIndex", "totalImages", "showActions", "isLiked", "likeCount", "commentCount"], outputs: ["prevClick", "nextClick", "likeClick", "commentClick"] }] });
|
|
10504
|
+
}
|
|
10505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileLightboxImageComponent, decorators: [{
|
|
10506
|
+
type: Component,
|
|
10507
|
+
args: [{ selector: 'ds-mobile-lightbox-image', standalone: true, imports: [
|
|
10508
|
+
CommonModule,
|
|
10509
|
+
IonSpinner,
|
|
10510
|
+
DsMobileLightboxHeaderComponent,
|
|
10511
|
+
DsMobileLightboxFooterComponent
|
|
10512
|
+
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
|
|
10513
|
+
<div class="lightbox-overlay"
|
|
10514
|
+
[class.zoomed]="isZoomed()">
|
|
10515
|
+
|
|
10516
|
+
<div class="lightbox-wrapper">
|
|
10517
|
+
<!-- Header with author info and action buttons -->
|
|
10518
|
+
<ds-mobile-lightbox-header
|
|
10519
|
+
[author]="author"
|
|
10520
|
+
(closeClick)="close()"
|
|
10521
|
+
(shareClick)="onShare()"
|
|
10522
|
+
/>
|
|
10523
|
+
|
|
10524
|
+
<!-- Swiper container -->
|
|
10525
|
+
<div class="swiper-container" #swiperContainer>
|
|
10526
|
+
<div class="swiper-wrapper">
|
|
10527
|
+
@for (image of images; track image.src; let i = $index) {
|
|
10528
|
+
<div class="swiper-slide">
|
|
10529
|
+
<div class="image-zoom-container" [attr.data-index]="i">
|
|
10530
|
+
<img
|
|
10531
|
+
[src]="image.src"
|
|
10532
|
+
[alt]="image.alt || 'Lightbox image'"
|
|
10533
|
+
class="lightbox-image"
|
|
10534
|
+
(load)="onImageLoad(i)"
|
|
10535
|
+
(error)="onImageError(i)">
|
|
10536
|
+
</div>
|
|
10537
|
+
</div>
|
|
10538
|
+
}
|
|
10539
|
+
</div>
|
|
10540
|
+
</div>
|
|
10541
|
+
|
|
10542
|
+
<!-- Loading indicator -->
|
|
10543
|
+
@if (isLoading()) {
|
|
10544
|
+
<div class="loading-spinner">
|
|
10545
|
+
<ion-spinner name="crescent"></ion-spinner>
|
|
10546
|
+
</div>
|
|
10547
|
+
}
|
|
10548
|
+
|
|
10549
|
+
<!-- Footer with navigation and actions -->
|
|
10550
|
+
<ds-mobile-lightbox-footer
|
|
10551
|
+
[showNavigation]="showControls && images.length > 1"
|
|
10552
|
+
[showActions]="showActions"
|
|
10553
|
+
[currentIndex]="currentIndex()"
|
|
10554
|
+
[totalImages]="images.length"
|
|
10555
|
+
[isLiked]="isLiked()"
|
|
10556
|
+
[likeCount]="likeCount()"
|
|
10557
|
+
[commentCount]="commentCount()"
|
|
10558
|
+
(prevClick)="previousImage()"
|
|
10559
|
+
(nextClick)="nextImage()"
|
|
10560
|
+
(likeClick)="onLikeToggle()"
|
|
10561
|
+
(commentClick)="onReply()"
|
|
10562
|
+
/>
|
|
10563
|
+
</div>
|
|
10564
|
+
</div>
|
|
10565
|
+
`, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}:host{display:block;position:fixed;inset:0;width:100vw;height:100vh;z-index:10000}.lightbox-overlay{position:fixed;inset:0;width:100vw;height:100vh;background:#000000fa;z-index:10000;display:flex;flex-direction:column;touch-action:none;animation:fadeIn .2s ease-out}.lightbox-overlay.zoomed{overflow:hidden}.lightbox-content{display:block;height:100vh;width:100vw;position:absolute;inset:0}.lightbox-content::part(scroll){display:flex;flex-direction:column;height:100%;overflow:hidden}.lightbox-wrapper{position:absolute;inset:0;display:flex;flex-direction:column;width:100%;height:100%}.lightbox-content.zoomed{overflow:hidden}.lightbox-header{position:fixed;top:0;left:0;right:0;z-index:1000;padding:0 16px;background:linear-gradient(to bottom,rgba(0,0,0,.8) 0%,rgba(0,0,0,.4) 80%,transparent 100%);pointer-events:none}.header-content{display:flex;align-items:center;justify-content:space-between;gap:12px;pointer-events:auto}.post-author-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.author-details{display:flex;flex-direction:column;min-width:0;flex:1}.author-name{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px}.author-meta{color:#ffffffb3;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;display:flex;align-items:center;gap:6px}.author-meta .separator{color:#ffffff80}.close-button{pointer-events:auto;flex-shrink:0;border-radius:50%}.close-button::ng-deep button{color:#fff!important;background:#ffffff1a!important;border-radius:50%;transition:background .2s ease;border:none;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}.close-button::ng-deep button:hover{background:#ffffff26!important}.close-button::ng-deep button:active{background:#ffffff26!important}.close-button::ng-deep svg{color:#fff!important;fill:#fff!important}.swiper-container{position:absolute;inset:0;width:100%;height:100%;z-index:1}.swiper-wrapper{width:100%;height:100%}.swiper-slide{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.image-zoom-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden}.lightbox-image{max-width:min(640px,100%);max-height:100%;width:auto;height:auto;-o-object-fit:contain;object-fit:contain;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none;transition:transform .3s ease-out;transform-origin:center center}.lightbox-overlay.zoomed .swiper-container{touch-action:none}.loading-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.loading-spinner ion-spinner{--color: rgba(255, 255, 255, .8);width:48px;height:48px}.error-message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10;text-align:center;color:#fffc;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:500;padding:20px;background:#00000080;border-radius:12px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.lightbox-bottom-section{position:fixed;bottom:0;left:0;right:0;z-index:100;display:flex;flex-direction:column;background:linear-gradient(to top,rgba(0,0,0,.8) 0%,rgba(0,0,0,.6) 50%,rgba(0,0,0,.4) 75%,transparent 100%);pointer-events:none}.lightbox-controls{display:flex;align-items:center;justify-content:center;gap:24px;padding:16px 20px 12px;pointer-events:none}.nav-button,.counter{pointer-events:auto}.nav-button{background:#ffffff1a;border:1px solid rgba(255,255,255,.2);color:#fff;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease;padding:0;margin:0;outline:none}.nav-button:hover:not(:disabled){background:#fff3;transform:scale(1.05)}.nav-button:active:not(:disabled){transform:scale(.95)}.nav-button:disabled{opacity:.3;cursor:not-allowed}.nav-button svg{width:24px;height:24px}.counter{color:#fff;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:1;padding:10px 16px;background:#00000080;border-radius:100px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);white-space:nowrap}@supports (padding-bottom: env(safe-area-inset-bottom)){.lightbox-bottom-section{padding-bottom:env(safe-area-inset-bottom)}}.lightbox-footer{display:flex;padding:12px 20px 20px;pointer-events:none}.footer-actions{display:flex;align-items:center;justify-content:space-between;gap:16px;pointer-events:auto}.action-buttons-left{display:flex;align-items:center;gap:16px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-with-count::ng-deep button,.action-button-share::ng-deep button{background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)!important;color:#fff!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:all .2s ease}.action-button-like::ng-deep button:hover,.action-button-comment::ng-deep button:hover,.action-button-with-count::ng-deep button:hover,.action-button-share::ng-deep button:hover{background:#fff3!important;transform:scale(1.02)}.action-button-like::ng-deep button:active,.action-button-comment::ng-deep button:active,.action-button-with-count::ng-deep button:active,.action-button-share::ng-deep button:active{transform:scale(.98)}.action-button-like::ng-deep button svg,.action-button-comment::ng-deep button svg,.action-button-with-count::ng-deep button svg,.action-button-share::ng-deep button svg,.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon,.action-button-like::ng-deep button .btn__content,.action-button-comment::ng-deep button .btn__content,.action-button-with-count::ng-deep button .btn__content{color:#fff!important;fill:#fff!important}.action-button-like::ng-deep button .btn__icon svg,.action-button-comment::ng-deep button .btn__icon svg,.action-button-with-count::ng-deep button .btn__icon svg,.action-button-share::ng-deep button .btn__icon svg{color:#fff!important;fill:#fff!important;display:block!important;opacity:1!important;visibility:visible!important;width:20px!important;height:20px!important}.action-button-like::ng-deep button .btn__icon,.action-button-comment::ng-deep button .btn__icon,.action-button-with-count::ng-deep button .btn__icon,.action-button-share::ng-deep button .btn__icon{display:flex!important;align-items:center!important;justify-content:center!important;flex-shrink:0!important}.action-button-like[data-liked=true]::ng-deep button svg{fill:#f91880!important;color:#f91880!important}.action-button-like[data-liked=true]::ng-deep button{border-color:#f918804d!important}.action-button-like,.action-button-comment,.action-button-share{flex-shrink:0;border-radius:50%}.action-button-like::ng-deep button,.action-button-comment::ng-deep button,.action-button-share::ng-deep button{border-radius:50%!important;width:44px!important;height:44px!important;min-width:44px!important;min-height:44px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}@media (min-width: 768px){.lightbox-header{padding:24px}.close-button{width:48px;height:48px}.lightbox-controls{padding:20px 24px 16px}.nav-button{width:48px;height:48px}.counter{font-size:var(--font-size-base);padding:12px 20px}.lightbox-footer{padding:16px 24px 24px}.action-button-like::ng-deep button,.action-button-comment::ng-deep button{height:48px;padding:0 20px}.action-button-share::ng-deep button{width:48px!important;height:48px!important;min-width:48px!important;min-height:48px!important}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion: reduce){.image-wrapper,.nav-button,.lightbox-caption{transition:none}}.nav-button:focus-visible{outline:2px solid white;outline-offset:2px}\n"] }]
|
|
10566
|
+
}], ctorParameters: () => [{ type: i1.GestureController }], propDecorators: { swiperContainer: [{
|
|
10567
|
+
type: ViewChild,
|
|
10568
|
+
args: ['swiperContainer', { read: ElementRef }]
|
|
10569
|
+
}] } });
|
|
10570
|
+
|
|
10571
|
+
/**
|
|
10572
|
+
* DsMobileLightboxPdfComponent
|
|
10573
|
+
*
|
|
10574
|
+
* PDF viewer component that displays PDF info and allows users to open PDFs in the native device viewer.
|
|
10575
|
+
* Shows a lightbox with PDF details first, then user can choose to open in native viewer.
|
|
10576
|
+
*
|
|
10577
|
+
* This component is typically not used directly - use DsMobileLightboxService instead.
|
|
10578
|
+
*
|
|
10579
|
+
* Features:
|
|
10580
|
+
* - PDF info preview (title, size, icon)
|
|
10581
|
+
* - User-initiated native PDF viewing (iOS/Android)
|
|
10582
|
+
* - Download and cache support
|
|
10583
|
+
* - Share functionality
|
|
10584
|
+
* - Loading states
|
|
10585
|
+
*
|
|
10586
|
+
* @example
|
|
10587
|
+
* ```typescript
|
|
10588
|
+
* // Don't instantiate directly - use the service:
|
|
10589
|
+
* constructor(private lightbox: DsMobileLightboxService) {}
|
|
10590
|
+
*
|
|
10591
|
+
* openPdf() {
|
|
10592
|
+
* this.lightbox.openPdf({
|
|
10593
|
+
* pdf: { type: 'pdf', src: 'document.pdf', title: 'My Document' }
|
|
10594
|
+
* });
|
|
10595
|
+
* }
|
|
10596
|
+
* ```
|
|
10597
|
+
*/
|
|
10598
|
+
class DsMobileLightboxPdfComponent {
|
|
10599
|
+
// Inputs (passed from service as regular properties)
|
|
10600
|
+
pdf;
|
|
10601
|
+
author;
|
|
10602
|
+
onCloseRequested;
|
|
10603
|
+
// State
|
|
10604
|
+
isLoading = false;
|
|
10605
|
+
hasError = false;
|
|
10606
|
+
errorMessage = '';
|
|
10607
|
+
cachedFilePath;
|
|
10608
|
+
constructor() { }
|
|
10609
|
+
ngOnInit() {
|
|
10610
|
+
console.log('[PDF Lightbox] Initializing with PDF:', this.pdf);
|
|
10611
|
+
// Don't automatically open - let user click the "Open" button
|
|
10612
|
+
// this.openPdfInNativeViewer();
|
|
10613
|
+
}
|
|
10614
|
+
/**
|
|
10615
|
+
* Open the PDF in the native device viewer
|
|
10616
|
+
*/
|
|
10617
|
+
async openPdfInNativeViewer() {
|
|
10618
|
+
if (!this.pdf?.src) {
|
|
10619
|
+
console.error('[PDF Lightbox] No PDF source provided');
|
|
10620
|
+
this.hasError = true;
|
|
10621
|
+
this.errorMessage = 'No PDF file provided';
|
|
10622
|
+
return;
|
|
10623
|
+
}
|
|
10624
|
+
this.isLoading = true;
|
|
10625
|
+
this.hasError = false;
|
|
10626
|
+
this.errorMessage = '';
|
|
10627
|
+
try {
|
|
10628
|
+
console.log('[PDF Lightbox] Opening PDF:', this.pdf.src);
|
|
10629
|
+
// Check if it's already a full URL
|
|
10630
|
+
let pdfUrl;
|
|
10631
|
+
if (this.pdf.src.startsWith('http://') || this.pdf.src.startsWith('https://')) {
|
|
10632
|
+
// Already a full URL
|
|
10633
|
+
pdfUrl = this.pdf.src;
|
|
10634
|
+
}
|
|
10635
|
+
else {
|
|
10636
|
+
// Relative path - construct full URL
|
|
10637
|
+
// Use current origin (which includes the dev server URL in Capacitor)
|
|
10638
|
+
// Remove leading slash if present to avoid double slashes
|
|
10639
|
+
const cleanPath = this.pdf.src.startsWith('/') ? this.pdf.src.slice(1) : this.pdf.src;
|
|
10640
|
+
pdfUrl = `${window.location.origin}/${cleanPath}`;
|
|
10641
|
+
}
|
|
10642
|
+
console.log('[PDF Lightbox] Opening PDF at URL:', pdfUrl);
|
|
10643
|
+
// Use Browser to open the PDF
|
|
10644
|
+
await Browser.open({
|
|
10645
|
+
url: pdfUrl,
|
|
10646
|
+
presentationStyle: 'fullscreen'
|
|
10647
|
+
});
|
|
10648
|
+
this.isLoading = false;
|
|
10649
|
+
// Close the modal after opening browser
|
|
10650
|
+
setTimeout(() => {
|
|
10651
|
+
this.close();
|
|
10652
|
+
}, 500);
|
|
10653
|
+
}
|
|
10654
|
+
catch (error) {
|
|
10655
|
+
console.error('[PDF Lightbox] Error opening PDF:', error);
|
|
10656
|
+
this.isLoading = false;
|
|
10657
|
+
this.hasError = true;
|
|
10658
|
+
this.errorMessage = error?.message || 'Failed to open PDF';
|
|
10659
|
+
}
|
|
10660
|
+
}
|
|
10661
|
+
/**
|
|
10662
|
+
* Download a remote PDF and open it
|
|
10663
|
+
*/
|
|
10664
|
+
async downloadAndOpenPdf() {
|
|
10665
|
+
try {
|
|
10666
|
+
console.log('[PDF Lightbox] Downloading PDF from:', this.pdf.src);
|
|
10667
|
+
// Fetch the PDF
|
|
10668
|
+
const response = await fetch(this.pdf.src);
|
|
10669
|
+
if (!response.ok) {
|
|
10670
|
+
throw new Error(`Failed to download PDF: ${response.statusText}`);
|
|
10671
|
+
}
|
|
10672
|
+
const blob = await response.blob();
|
|
10673
|
+
const base64Data = await this.blobToBase64(blob);
|
|
10674
|
+
// Generate a filename
|
|
10675
|
+
const fileName = this.pdf.title
|
|
10676
|
+
? `${this.pdf.title.replace(/[^a-z0-9]/gi, '_')}.pdf`
|
|
10677
|
+
: 'document.pdf';
|
|
10678
|
+
// Save to cache directory
|
|
10679
|
+
const result = await Filesystem.writeFile({
|
|
10680
|
+
path: fileName,
|
|
10681
|
+
data: base64Data,
|
|
10682
|
+
directory: Directory.Cache
|
|
10683
|
+
});
|
|
10684
|
+
console.log('[PDF Lightbox] PDF saved to cache:', result.uri);
|
|
10685
|
+
this.cachedFilePath = result.uri;
|
|
10686
|
+
// Open using Browser
|
|
10378
10687
|
await Browser.open({
|
|
10379
10688
|
url: result.uri,
|
|
10380
10689
|
presentationStyle: 'fullscreen'
|
|
@@ -13496,98 +13805,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
13496
13805
|
|
|
13497
13806
|
<ds-icon
|
|
13498
13807
|
content-trailing
|
|
13499
|
-
name="remixArrowRightSLine"
|
|
13500
|
-
size="20px"
|
|
13501
|
-
class="item-trailing"
|
|
13502
|
-
/>
|
|
13503
|
-
</ds-mobile-card-inline>
|
|
13504
|
-
`, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3b82f6)!important}\n"] }]
|
|
13505
|
-
}], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], fileUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileUrl", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
|
|
13506
|
-
|
|
13507
|
-
/**
|
|
13508
|
-
* DsMobileSystemMessageBannerComponent
|
|
13509
|
-
*
|
|
13510
|
-
* Full-width centered banner component for displaying system messages in chat conversations.
|
|
13511
|
-
* Uses the same text styling as message bubbles for consistency.
|
|
13512
|
-
*
|
|
13513
|
-
* Features:
|
|
13514
|
-
* - Full-width centered layout
|
|
13515
|
-
* - Subtle background with theming support
|
|
13516
|
-
* - Same typography as message bubbles
|
|
13517
|
-
* - Optional icon support
|
|
13518
|
-
*
|
|
13519
|
-
* Common use cases:
|
|
13520
|
-
* - Inquiry status updates ("Your inquiry has been assigned to...")
|
|
13521
|
-
* - System notifications ("This inquiry is marked as resolved")
|
|
13522
|
-
* - Auto-replies ("We aim to respond within 24 hours...")
|
|
13523
|
-
* - Time/date separators
|
|
13524
|
-
*
|
|
13525
|
-
* @example
|
|
13526
|
-
* ```html
|
|
13527
|
-
* <!-- Simple system message -->
|
|
13528
|
-
* <ds-mobile-system-message-banner
|
|
13529
|
-
* [message]="'Ricki Meihlen har overtaget din henvendelse og vil kontakte dig snart.'">
|
|
13530
|
-
* </ds-mobile-system-message-banner>
|
|
13531
|
-
*
|
|
13532
|
-
* <!-- With icon -->
|
|
13533
|
-
* <ds-mobile-system-message-banner
|
|
13534
|
-
* [message]="'Vi bestræber os på at svare inden for 24 timer på hverdage.'"
|
|
13535
|
-
* [iconName]="'remixInformationLine'">
|
|
13536
|
-
* </ds-mobile-system-message-banner>
|
|
13537
|
-
* ```
|
|
13538
|
-
*/
|
|
13539
|
-
class DsMobileSystemMessageBannerComponent {
|
|
13540
|
-
/**
|
|
13541
|
-
* System message text to display
|
|
13542
|
-
*/
|
|
13543
|
-
message = input.required(...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
13544
|
-
/**
|
|
13545
|
-
* Optional icon name (currently using inline SVG for info icon)
|
|
13546
|
-
* Can be extended to support full icon library integration
|
|
13547
|
-
*/
|
|
13548
|
-
iconName = input('', ...(ngDevMode ? [{ debugName: "iconName" }] : []));
|
|
13549
|
-
/**
|
|
13550
|
-
* Whether this system message appears directly after a timestamp
|
|
13551
|
-
* When true, removes top padding to reduce spacing
|
|
13552
|
-
*/
|
|
13553
|
-
afterTimestamp = input(false, ...(ngDevMode ? [{ debugName: "afterTimestamp" }] : []));
|
|
13554
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13555
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileSystemMessageBannerComponent, isStandalone: true, selector: "ds-mobile-system-message-banner", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, afterTimestamp: { classPropertyName: "afterTimestamp", publicName: "afterTimestamp", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.after-timestamp": "afterTimestamp()" } }, ngImport: i0, template: `
|
|
13556
|
-
<div class="system-message-container">
|
|
13557
|
-
<div class="system-message-content">
|
|
13558
|
-
@if (iconName()) {
|
|
13559
|
-
<span class="system-message-icon">
|
|
13560
|
-
<!-- Icon slot - you can add ds-icon component here if needed -->
|
|
13561
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
13562
|
-
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
|
|
13563
|
-
</svg>
|
|
13564
|
-
</span>
|
|
13565
|
-
}
|
|
13566
|
-
<p class="system-message-text">{{ message() }}</p>
|
|
13567
|
-
</div>
|
|
13568
|
-
</div>
|
|
13569
|
-
`, isInline: true, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
13570
|
-
}
|
|
13571
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileSystemMessageBannerComponent, decorators: [{
|
|
13572
|
-
type: Component,
|
|
13573
|
-
args: [{ selector: 'ds-mobile-system-message-banner', standalone: true, imports: [CommonModule], host: {
|
|
13574
|
-
'[class.after-timestamp]': 'afterTimestamp()'
|
|
13575
|
-
}, template: `
|
|
13576
|
-
<div class="system-message-container">
|
|
13577
|
-
<div class="system-message-content">
|
|
13578
|
-
@if (iconName()) {
|
|
13579
|
-
<span class="system-message-icon">
|
|
13580
|
-
<!-- Icon slot - you can add ds-icon component here if needed -->
|
|
13581
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
13582
|
-
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM11 7h2v2h-2V7zm0 4h2v6h-2v-6z"/>
|
|
13583
|
-
</svg>
|
|
13584
|
-
</span>
|
|
13585
|
-
}
|
|
13586
|
-
<p class="system-message-text">{{ message() }}</p>
|
|
13587
|
-
</div>
|
|
13588
|
-
</div>
|
|
13589
|
-
`, styles: [":host{display:block;width:100%;padding:12px 0}:host(.after-timestamp){padding-top:0}.system-message-container{display:flex;justify-content:center;align-items:center;width:100%;padding:0 16px}.system-message-content{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;max-width:85%;text-align:center}.system-message-icon{flex-shrink:0;width:16px;height:16px;color:var(--color-text-tertiary, #a0a0a0)}.system-message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--color-text-secondary, #666666);margin:0}\n"] }]
|
|
13590
|
-
}], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], afterTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterTimestamp", required: false }] }] } });
|
|
13808
|
+
name="remixArrowRightSLine"
|
|
13809
|
+
size="20px"
|
|
13810
|
+
class="item-trailing"
|
|
13811
|
+
/>
|
|
13812
|
+
</ds-mobile-card-inline>
|
|
13813
|
+
`, styles: [".item-avatar.pdf ::ng-deep .avatar--icon{background-color:#ff5757!important}.item-avatar.doc ::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3b82f6)!important}\n"] }]
|
|
13814
|
+
}], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], fileUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileUrl", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
|
|
13591
13815
|
|
|
13592
13816
|
/**
|
|
13593
13817
|
* DsMobileChatModalComponent
|
|
@@ -14934,487 +15158,263 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14934
15158
|
[rows]="1"
|
|
14935
15159
|
placeholder="Tell us what this inquiry is about..."
|
|
14936
15160
|
class="inquiry-description-input ghost-input-clean"
|
|
14937
|
-
(valueChange)="validateForm()"
|
|
14938
|
-
/>
|
|
14939
|
-
</ds-mobile-section>
|
|
14940
|
-
|
|
14941
|
-
<!-- Fixed Bottom Container (Slides with keyboard) -->
|
|
14942
|
-
<div footer class="fixed-bottom-container">
|
|
14943
|
-
<!-- Attachment Previews (if any) -->
|
|
14944
|
-
@if (attachments().length > 0) {
|
|
14945
|
-
<div class="attachment-previews-section">
|
|
14946
|
-
<div class="image-previews">
|
|
14947
|
-
@for (attachment of attachments(); track attachment.id) {
|
|
14948
|
-
<ds-mobile-attachment-preview
|
|
14949
|
-
[attachment]="attachment"
|
|
14950
|
-
(remove)="removeAttachment($event)"
|
|
14951
|
-
/>
|
|
14952
|
-
}
|
|
14953
|
-
</div>
|
|
14954
|
-
</div>
|
|
14955
|
-
}
|
|
14956
|
-
|
|
14957
|
-
<!-- Submit Actions Container -->
|
|
14958
|
-
<div class="submit-container">
|
|
14959
|
-
<div class="submit-content">
|
|
14960
|
-
<!-- Upload Actions (Left) -->
|
|
14961
|
-
<div class="upload-actions">
|
|
14962
|
-
<ds-icon-button
|
|
14963
|
-
icon="remixImageLine"
|
|
14964
|
-
variant="secondary"
|
|
14965
|
-
size="md"
|
|
14966
|
-
(clicked)="addPhoto()"
|
|
14967
|
-
[disabled]="attachments().length >= 6"
|
|
14968
|
-
aria-label="Add photo">
|
|
14969
|
-
</ds-icon-button>
|
|
14970
|
-
<ds-icon-button
|
|
14971
|
-
icon="remixAttachmentLine"
|
|
14972
|
-
variant="secondary"
|
|
14973
|
-
size="md"
|
|
14974
|
-
(clicked)="handleAddAttachment()"
|
|
14975
|
-
[disabled]="attachments().length >= 6"
|
|
14976
|
-
aria-label="Add attachment">
|
|
14977
|
-
</ds-icon-button>
|
|
14978
|
-
|
|
14979
|
-
<!-- Hidden file input for file selection -->
|
|
14980
|
-
<input
|
|
14981
|
-
#fileInput
|
|
14982
|
-
type="file"
|
|
14983
|
-
accept="*/*"
|
|
14984
|
-
multiple
|
|
14985
|
-
(change)="handleFileSelect($event)"
|
|
14986
|
-
style="display: none;"
|
|
14987
|
-
aria-hidden="true"
|
|
14988
|
-
/>
|
|
14989
|
-
</div>
|
|
14990
|
-
|
|
14991
|
-
<!-- Submit Button (Right) -->
|
|
14992
|
-
<ds-button
|
|
14993
|
-
variant="primary"
|
|
14994
|
-
size="lg"
|
|
14995
|
-
[disabled]="!isFormValid() || isSubmitting()"
|
|
14996
|
-
(clicked)="handleSubmit()">
|
|
14997
|
-
Submit
|
|
14998
|
-
</ds-button>
|
|
14999
|
-
</div>
|
|
15000
|
-
</div>
|
|
15001
|
-
</div>
|
|
15002
|
-
</ds-mobile-modal-base>
|
|
15003
|
-
`, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ".inquiry-title-input{flex:0 0 auto}.inquiry-title-input ::ng-deep textarea{font-size:var(--font-size-2xl);font-weight:400;line-height:1.2;max-height:200px;overflow-y:auto;resize:none;box-sizing:border-box;padding-right:52px}.fixed-bottom-container{background:var(--color-background-neutral-primary);border-top:1px solid var(--border-color-default)}.attachment-previews-section{padding:16px 20px;border-bottom:1px solid var(--border-color-default)}.image-previews{display:flex;flex-wrap:wrap;gap:8px}.submit-container{padding:16px 20px}.submit-content{display:flex;align-items:center;justify-content:space-between;gap:16px}.upload-actions{display:flex;align-items:center;gap:8px}.upload-actions ds-icon-button::ng-deep button{width:44px;height:44px;border-radius:50%}.submit-content ds-button::ng-deep button{border-radius:100px}.inquiry-description-input{display:flex;flex:1;min-height:0}.inquiry-description-input ::ng-deep .textarea-container{display:flex;flex:1;min-height:0}.inquiry-description-input ::ng-deep textarea{flex:1;min-height:200px;resize:none}@media (min-width: 768px){.submit-container{padding:20px 32px}}\n"] }]
|
|
15004
|
-
}], propDecorators: { titleInputRef: [{
|
|
15005
|
-
type: ViewChild,
|
|
15006
|
-
args: ['titleInput', { read: ElementRef }]
|
|
15007
|
-
}], titleInput: [{
|
|
15008
|
-
type: ViewChild,
|
|
15009
|
-
args: ['titleInput']
|
|
15010
|
-
}], fileInput: [{
|
|
15011
|
-
type: ViewChild,
|
|
15012
|
-
args: ['fileInput']
|
|
15013
|
-
}], loading: [{
|
|
15014
|
-
type: Input
|
|
15015
|
-
}], error: [{
|
|
15016
|
-
type: Input
|
|
15017
|
-
}], onSubmit: [{
|
|
15018
|
-
type: Input
|
|
15019
|
-
}] } });
|
|
15020
|
-
|
|
15021
|
-
/**
|
|
15022
|
-
* DsMobileNewInquiryModalService
|
|
15023
|
-
*
|
|
15024
|
-
* Service for displaying the new inquiry creation modal.
|
|
15025
|
-
* Built on Ionic's modal system with native gestures and animations.
|
|
15026
|
-
*
|
|
15027
|
-
* Features:
|
|
15028
|
-
* - Full-screen modal with form
|
|
15029
|
-
* - Title and description inputs
|
|
15030
|
-
* - Photo upload with camera/gallery
|
|
15031
|
-
* - Form validation
|
|
15032
|
-
* - Submit handling
|
|
15033
|
-
* - Loading and error states
|
|
15034
|
-
*
|
|
15035
|
-
* @example
|
|
15036
|
-
* ```typescript
|
|
15037
|
-
* constructor(private inquiryModal: DsMobileNewInquiryModalService) {}
|
|
15038
|
-
*
|
|
15039
|
-
* async createNewInquiry() {
|
|
15040
|
-
* await this.inquiryModal.open({
|
|
15041
|
-
* onSubmit: async (data) => {
|
|
15042
|
-
* console.log('Creating inquiry:', data);
|
|
15043
|
-
* // Call your API to create the inquiry
|
|
15044
|
-
* await this.apiService.createInquiry(data);
|
|
15045
|
-
* // Close the modal
|
|
15046
|
-
* await this.inquiryModal.close();
|
|
15047
|
-
* }
|
|
15048
|
-
* });
|
|
15049
|
-
* }
|
|
15050
|
-
* ```
|
|
15051
|
-
*/
|
|
15052
|
-
class DsMobileNewInquiryModalService extends BaseModalService {
|
|
15053
|
-
constructor(modalController) {
|
|
15054
|
-
super(modalController);
|
|
15055
|
-
}
|
|
15056
|
-
/**
|
|
15057
|
-
* Open the new inquiry modal
|
|
15058
|
-
*
|
|
15059
|
-
* @param options Modal options including onSubmit callback
|
|
15060
|
-
* @returns Promise that resolves when the modal is presented
|
|
15061
|
-
*/
|
|
15062
|
-
async open(options) {
|
|
15063
|
-
// console.log('[NewInquiryModal] Opening modal with options:', options);
|
|
15064
|
-
const modal = await this.createModal(DsMobileNewInquiryModalComponent, {
|
|
15065
|
-
onSubmit: options?.onSubmit,
|
|
15066
|
-
loading: options?.loading ?? false,
|
|
15067
|
-
error: options?.error,
|
|
15068
|
-
}, {
|
|
15069
|
-
keyboardClose: false, // Don't close on keyboard hide for this modal
|
|
15070
|
-
});
|
|
15071
|
-
// console.log('[NewInquiryModal] Modal created, presenting...');
|
|
15072
|
-
await modal.present();
|
|
15073
|
-
// console.log('[NewInquiryModal] Modal presented');
|
|
15074
|
-
}
|
|
15075
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
15076
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalService, providedIn: 'root' });
|
|
15077
|
-
}
|
|
15078
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalService, decorators: [{
|
|
15079
|
-
type: Injectable,
|
|
15080
|
-
args: [{
|
|
15081
|
-
providedIn: 'root',
|
|
15082
|
-
}]
|
|
15083
|
-
}], ctorParameters: () => [{ type: i1.ModalController }] });
|
|
15084
|
-
|
|
15085
|
-
/**
|
|
15086
|
-
* DsMobileHandbookFolderMiniComponent
|
|
15087
|
-
*
|
|
15088
|
-
* A minimized folder icon component for use in headers and small spaces.
|
|
15089
|
-
* Simplified version without animations or page sheets - just folder and icon.
|
|
15090
|
-
*
|
|
15091
|
-
* @example
|
|
15092
|
-
* ```html
|
|
15093
|
-
* <ds-mobile-handbook-folder-mini
|
|
15094
|
-
* [variant]="'pink'"
|
|
15095
|
-
* [iconName]="'remixLightbulbLine'">
|
|
15096
|
-
* </ds-mobile-handbook-folder-mini>
|
|
15097
|
-
* ```
|
|
15098
|
-
*/
|
|
15099
|
-
class DsMobileHandbookFolderMiniComponent {
|
|
15100
|
-
/**
|
|
15101
|
-
* Color variant for the folder
|
|
15102
|
-
* Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey
|
|
15103
|
-
*/
|
|
15104
|
-
variant = 'light-purple';
|
|
15105
|
-
/**
|
|
15106
|
-
* Icon name from the design system icon library
|
|
15107
|
-
*/
|
|
15108
|
-
iconName = 'remixFolder3Line';
|
|
15109
|
-
/**
|
|
15110
|
-
* Get the CSS variable name for the color variant
|
|
15111
|
-
*/
|
|
15112
|
-
getColorVar(suffix) {
|
|
15113
|
-
const variantMap = {
|
|
15114
|
-
'success': 'success',
|
|
15115
|
-
'warning': 'warning',
|
|
15116
|
-
'destructive': 'destructive',
|
|
15117
|
-
'blue': 'blue',
|
|
15118
|
-
'light-purple': 'light-purple',
|
|
15119
|
-
'pink': 'pink',
|
|
15120
|
-
'salmon-orange': 'salmon-orange',
|
|
15121
|
-
'orange': 'orange',
|
|
15122
|
-
'lime-green': 'lime-green',
|
|
15123
|
-
'grey': 'grey'
|
|
15124
|
-
};
|
|
15125
|
-
const colorName = variantMap[this.variant] || 'light-purple';
|
|
15126
|
-
return `var(--color-${colorName}-${suffix})`;
|
|
15127
|
-
}
|
|
15128
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookFolderMiniComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15129
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DsMobileHandbookFolderMiniComponent, isStandalone: true, selector: "ds-mobile-handbook-folder-mini", inputs: { variant: "variant", iconName: "iconName" }, ngImport: i0, template: `
|
|
15130
|
-
<div class="mini-folder-container">
|
|
15131
|
-
<!-- Folder Tab SVG -->
|
|
15132
|
-
<svg
|
|
15133
|
-
class="mini-folder-tab"
|
|
15134
|
-
width="101"
|
|
15135
|
-
height="24"
|
|
15136
|
-
viewBox="0 0 101 24"
|
|
15137
|
-
fill="none"
|
|
15138
|
-
xmlns="http://www.w3.org/2000/svg">
|
|
15139
|
-
<path
|
|
15140
|
-
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"
|
|
15141
|
-
[attr.fill]="getColorVar('strong')"/>
|
|
15142
|
-
</svg>
|
|
15143
|
-
|
|
15144
|
-
<!-- Folder Back -->
|
|
15145
|
-
<div class="mini-folder-back" [style.background-color]="getColorVar('strong')">
|
|
15146
|
-
<!-- Folder Front -->
|
|
15147
|
-
<div
|
|
15148
|
-
class="mini-folder-front"
|
|
15149
|
-
[style.background-color]="getColorVar('base')">
|
|
15150
|
-
<ds-icon
|
|
15151
|
-
[name]="iconName"
|
|
15152
|
-
[size]="'14px'"
|
|
15153
|
-
[style.color]="'white'" />
|
|
15154
|
-
</div>
|
|
15155
|
-
</div>
|
|
15156
|
-
</div>
|
|
15157
|
-
`, isInline: true, styles: [":host{display:inline-block;width:32px;height:32px;flex-shrink:0}.mini-folder-container{position:relative;width:100%;height:100%;display:flex;flex-direction:column}.mini-folder-tab{width:50%;height:auto;display:block}.mini-folder-back{height:28px;border-radius:0 4px 4px;position:relative;margin-top:-1px}.mini-folder-front{position:absolute;bottom:0;left:0;right:0;height:24px;border-radius:4px;display:flex;align-items:center;justify-content:center;z-index:2;box-shadow:inset 0 8px 8px #fff3,inset 0 .5px .5px #ffffff4d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
|
|
15158
|
-
}
|
|
15159
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookFolderMiniComponent, decorators: [{
|
|
15160
|
-
type: Component,
|
|
15161
|
-
args: [{ selector: 'ds-mobile-handbook-folder-mini', standalone: true, imports: [CommonModule, DsIconComponent], template: `
|
|
15162
|
-
<div class="mini-folder-container">
|
|
15163
|
-
<!-- Folder Tab SVG -->
|
|
15164
|
-
<svg
|
|
15165
|
-
class="mini-folder-tab"
|
|
15166
|
-
width="101"
|
|
15167
|
-
height="24"
|
|
15168
|
-
viewBox="0 0 101 24"
|
|
15169
|
-
fill="none"
|
|
15170
|
-
xmlns="http://www.w3.org/2000/svg">
|
|
15171
|
-
<path
|
|
15172
|
-
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"
|
|
15173
|
-
[attr.fill]="getColorVar('strong')"/>
|
|
15174
|
-
</svg>
|
|
15175
|
-
|
|
15176
|
-
<!-- Folder Back -->
|
|
15177
|
-
<div class="mini-folder-back" [style.background-color]="getColorVar('strong')">
|
|
15178
|
-
<!-- Folder Front -->
|
|
15179
|
-
<div
|
|
15180
|
-
class="mini-folder-front"
|
|
15181
|
-
[style.background-color]="getColorVar('base')">
|
|
15182
|
-
<ds-icon
|
|
15183
|
-
[name]="iconName"
|
|
15184
|
-
[size]="'14px'"
|
|
15185
|
-
[style.color]="'white'" />
|
|
15161
|
+
(valueChange)="validateForm()"
|
|
15162
|
+
/>
|
|
15163
|
+
</ds-mobile-section>
|
|
15164
|
+
|
|
15165
|
+
<!-- Fixed Bottom Container (Slides with keyboard) -->
|
|
15166
|
+
<div footer class="fixed-bottom-container">
|
|
15167
|
+
<!-- Attachment Previews (if any) -->
|
|
15168
|
+
@if (attachments().length > 0) {
|
|
15169
|
+
<div class="attachment-previews-section">
|
|
15170
|
+
<div class="image-previews">
|
|
15171
|
+
@for (attachment of attachments(); track attachment.id) {
|
|
15172
|
+
<ds-mobile-attachment-preview
|
|
15173
|
+
[attachment]="attachment"
|
|
15174
|
+
(remove)="removeAttachment($event)"
|
|
15175
|
+
/>
|
|
15176
|
+
}
|
|
15177
|
+
</div>
|
|
15178
|
+
</div>
|
|
15179
|
+
}
|
|
15180
|
+
|
|
15181
|
+
<!-- Submit Actions Container -->
|
|
15182
|
+
<div class="submit-container">
|
|
15183
|
+
<div class="submit-content">
|
|
15184
|
+
<!-- Upload Actions (Left) -->
|
|
15185
|
+
<div class="upload-actions">
|
|
15186
|
+
<ds-icon-button
|
|
15187
|
+
icon="remixImageLine"
|
|
15188
|
+
variant="secondary"
|
|
15189
|
+
size="md"
|
|
15190
|
+
(clicked)="addPhoto()"
|
|
15191
|
+
[disabled]="attachments().length >= 6"
|
|
15192
|
+
aria-label="Add photo">
|
|
15193
|
+
</ds-icon-button>
|
|
15194
|
+
<ds-icon-button
|
|
15195
|
+
icon="remixAttachmentLine"
|
|
15196
|
+
variant="secondary"
|
|
15197
|
+
size="md"
|
|
15198
|
+
(clicked)="handleAddAttachment()"
|
|
15199
|
+
[disabled]="attachments().length >= 6"
|
|
15200
|
+
aria-label="Add attachment">
|
|
15201
|
+
</ds-icon-button>
|
|
15202
|
+
|
|
15203
|
+
<!-- Hidden file input for file selection -->
|
|
15204
|
+
<input
|
|
15205
|
+
#fileInput
|
|
15206
|
+
type="file"
|
|
15207
|
+
accept="*/*"
|
|
15208
|
+
multiple
|
|
15209
|
+
(change)="handleFileSelect($event)"
|
|
15210
|
+
style="display: none;"
|
|
15211
|
+
aria-hidden="true"
|
|
15212
|
+
/>
|
|
15213
|
+
</div>
|
|
15214
|
+
|
|
15215
|
+
<!-- Submit Button (Right) -->
|
|
15216
|
+
<ds-button
|
|
15217
|
+
variant="primary"
|
|
15218
|
+
size="lg"
|
|
15219
|
+
[disabled]="!isFormValid() || isSubmitting()"
|
|
15220
|
+
(clicked)="handleSubmit()">
|
|
15221
|
+
Submit
|
|
15222
|
+
</ds-button>
|
|
15223
|
+
</div>
|
|
15186
15224
|
</div>
|
|
15187
15225
|
</div>
|
|
15188
|
-
</
|
|
15189
|
-
`, styles: ["
|
|
15190
|
-
}], propDecorators: {
|
|
15226
|
+
</ds-mobile-modal-base>
|
|
15227
|
+
`, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ".inquiry-title-input{flex:0 0 auto}.inquiry-title-input ::ng-deep textarea{font-size:var(--font-size-2xl);font-weight:400;line-height:1.2;max-height:200px;overflow-y:auto;resize:none;box-sizing:border-box;padding-right:52px}.fixed-bottom-container{background:var(--color-background-neutral-primary);border-top:1px solid var(--border-color-default)}.attachment-previews-section{padding:16px 20px;border-bottom:1px solid var(--border-color-default)}.image-previews{display:flex;flex-wrap:wrap;gap:8px}.submit-container{padding:16px 20px}.submit-content{display:flex;align-items:center;justify-content:space-between;gap:16px}.upload-actions{display:flex;align-items:center;gap:8px}.upload-actions ds-icon-button::ng-deep button{width:44px;height:44px;border-radius:50%}.submit-content ds-button::ng-deep button{border-radius:100px}.inquiry-description-input{display:flex;flex:1;min-height:0}.inquiry-description-input ::ng-deep .textarea-container{display:flex;flex:1;min-height:0}.inquiry-description-input ::ng-deep textarea{flex:1;min-height:200px;resize:none}@media (min-width: 768px){.submit-container{padding:20px 32px}}\n"] }]
|
|
15228
|
+
}], propDecorators: { titleInputRef: [{
|
|
15229
|
+
type: ViewChild,
|
|
15230
|
+
args: ['titleInput', { read: ElementRef }]
|
|
15231
|
+
}], titleInput: [{
|
|
15232
|
+
type: ViewChild,
|
|
15233
|
+
args: ['titleInput']
|
|
15234
|
+
}], fileInput: [{
|
|
15235
|
+
type: ViewChild,
|
|
15236
|
+
args: ['fileInput']
|
|
15237
|
+
}], loading: [{
|
|
15191
15238
|
type: Input
|
|
15192
|
-
}],
|
|
15239
|
+
}], error: [{
|
|
15240
|
+
type: Input
|
|
15241
|
+
}], onSubmit: [{
|
|
15193
15242
|
type: Input
|
|
15194
15243
|
}] } });
|
|
15195
15244
|
|
|
15196
15245
|
/**
|
|
15197
|
-
*
|
|
15246
|
+
* DsMobileNewInquiryModalService
|
|
15198
15247
|
*
|
|
15199
|
-
*
|
|
15248
|
+
* Service for displaying the new inquiry creation modal.
|
|
15249
|
+
* Built on Ionic's modal system with native gestures and animations.
|
|
15200
15250
|
*
|
|
15201
15251
|
* Features:
|
|
15202
|
-
* -
|
|
15203
|
-
* -
|
|
15204
|
-
* -
|
|
15205
|
-
* -
|
|
15206
|
-
* -
|
|
15252
|
+
* - Full-screen modal with form
|
|
15253
|
+
* - Title and description inputs
|
|
15254
|
+
* - Photo upload with camera/gallery
|
|
15255
|
+
* - Form validation
|
|
15256
|
+
* - Submit handling
|
|
15257
|
+
* - Loading and error states
|
|
15207
15258
|
*
|
|
15208
|
-
*
|
|
15209
|
-
* ```
|
|
15210
|
-
*
|
|
15211
|
-
*
|
|
15212
|
-
*
|
|
15213
|
-
*
|
|
15214
|
-
*
|
|
15215
|
-
*
|
|
15216
|
-
|
|
15217
|
-
|
|
15218
|
-
|
|
15219
|
-
|
|
15220
|
-
|
|
15221
|
-
|
|
15222
|
-
|
|
15223
|
-
|
|
15224
|
-
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
* Enable pagination dots
|
|
15229
|
-
*/
|
|
15230
|
-
pagination = input(false, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
|
|
15231
|
-
/**
|
|
15232
|
-
* Enable auto height - container adapts to active slide's height
|
|
15233
|
-
*/
|
|
15234
|
-
autoHeight = input(false, ...(ngDevMode ? [{ debugName: "autoHeight" }] : []));
|
|
15235
|
-
/**
|
|
15236
|
-
* Enable progressive opacity based on slide position
|
|
15237
|
-
* Slides fade in/out smoothly as they move toward/away from center
|
|
15238
|
-
*/
|
|
15239
|
-
progressiveOpacity = input(false, ...(ngDevMode ? [{ debugName: "progressiveOpacity" }] : []));
|
|
15240
|
-
/**
|
|
15241
|
-
* Enable progressive scale based on slide position
|
|
15242
|
-
* Slides scale down smoothly as they move away from center
|
|
15243
|
-
*/
|
|
15244
|
-
progressiveScale = input(false, ...(ngDevMode ? [{ debugName: "progressiveScale" }] : []));
|
|
15245
|
-
swiperContainer;
|
|
15246
|
-
swiperInstance = null;
|
|
15247
|
-
constructor(elementRef) {
|
|
15248
|
-
this.elementRef = elementRef;
|
|
15249
|
-
}
|
|
15250
|
-
ngAfterViewInit() {
|
|
15251
|
-
// Add progressive-opacity class to host if enabled
|
|
15252
|
-
if (this.progressiveOpacity()) {
|
|
15253
|
-
this.elementRef.nativeElement.classList.add('progressive-opacity');
|
|
15254
|
-
}
|
|
15255
|
-
setTimeout(() => {
|
|
15256
|
-
this.initializeSwiper();
|
|
15257
|
-
}, 100);
|
|
15258
|
-
}
|
|
15259
|
-
initializeSwiper() {
|
|
15260
|
-
if (!this.swiperContainer)
|
|
15261
|
-
return;
|
|
15262
|
-
// Apply slide width to all slides
|
|
15263
|
-
const slides = this.swiperContainer.nativeElement.querySelectorAll('.swiper-slide');
|
|
15264
|
-
slides.forEach((slide, index) => {
|
|
15265
|
-
slide.style.width = this.slideWidth();
|
|
15266
|
-
// Set initial opacity BEFORE Swiper initializes to prevent flash of inactive slides
|
|
15267
|
-
if (this.progressiveOpacity()) {
|
|
15268
|
-
// Hide all slides except the first one (active slide)
|
|
15269
|
-
slide.style.opacity = index === 0 ? '1' : '0';
|
|
15270
|
-
}
|
|
15271
|
-
});
|
|
15272
|
-
const config = {
|
|
15273
|
-
slidesPerView: 'auto',
|
|
15274
|
-
spaceBetween: this.gap(),
|
|
15275
|
-
centeredSlides: true,
|
|
15276
|
-
centeredSlidesBounds: true,
|
|
15277
|
-
speed: 300,
|
|
15278
|
-
resistance: true,
|
|
15279
|
-
resistanceRatio: 0.85,
|
|
15280
|
-
autoHeight: this.autoHeight(),
|
|
15281
|
-
watchSlidesProgress: this.progressiveOpacity() || this.progressiveScale(), // Enable progress tracking
|
|
15282
|
-
};
|
|
15283
|
-
// Configure event handlers
|
|
15284
|
-
config.on = {};
|
|
15285
|
-
// Configure autoHeight animation
|
|
15286
|
-
if (this.autoHeight()) {
|
|
15287
|
-
config.autoHeight = true;
|
|
15288
|
-
// The height transition will use the speed value (300ms)
|
|
15289
|
-
config.on.slideChangeTransitionStart = () => {
|
|
15290
|
-
// Height transition happens automatically
|
|
15291
|
-
};
|
|
15292
|
-
}
|
|
15293
|
-
// Configure progressive effects (opacity and/or scale)
|
|
15294
|
-
if (this.progressiveOpacity() || this.progressiveScale()) {
|
|
15295
|
-
config.on.setTranslate = () => {
|
|
15296
|
-
if (!this.swiperInstance)
|
|
15297
|
-
return;
|
|
15298
|
-
this.swiperInstance.slides.forEach((slideEl) => {
|
|
15299
|
-
const progress = slideEl.progress || 0;
|
|
15300
|
-
const absProgress = Math.abs(progress);
|
|
15301
|
-
// Progressive opacity with sharper cutoff
|
|
15302
|
-
if (this.progressiveOpacity()) {
|
|
15303
|
-
// Make opacity drop off more aggressively
|
|
15304
|
-
// Slides with absProgress > 0.5 will be completely hidden
|
|
15305
|
-
let opacity;
|
|
15306
|
-
if (absProgress > 0.5) {
|
|
15307
|
-
opacity = 0;
|
|
15308
|
-
}
|
|
15309
|
-
else {
|
|
15310
|
-
opacity = 1 - (absProgress * 2); // 2x multiplier for faster fade
|
|
15311
|
-
}
|
|
15312
|
-
slideEl.style.opacity = Math.max(opacity, 0).toString();
|
|
15313
|
-
}
|
|
15314
|
-
// Progressive scale
|
|
15315
|
-
if (this.progressiveScale()) {
|
|
15316
|
-
// Scale from 1 (center) to 0.9 (edges)
|
|
15317
|
-
const minScale = 0.9;
|
|
15318
|
-
const scale = 1 - (absProgress * (1 - minScale));
|
|
15319
|
-
slideEl.style.transform = `scale(${Math.max(scale, minScale)})`;
|
|
15320
|
-
}
|
|
15321
|
-
});
|
|
15322
|
-
};
|
|
15323
|
-
// Also update on init
|
|
15324
|
-
config.on.init = () => {
|
|
15325
|
-
if (!this.swiperInstance)
|
|
15326
|
-
return;
|
|
15327
|
-
this.swiperInstance.slides.forEach((slideEl) => {
|
|
15328
|
-
const progress = slideEl.progress || 0;
|
|
15329
|
-
const absProgress = Math.abs(progress);
|
|
15330
|
-
// Set initial opacity with sharper cutoff
|
|
15331
|
-
if (this.progressiveOpacity()) {
|
|
15332
|
-
let opacity;
|
|
15333
|
-
if (absProgress > 0.5) {
|
|
15334
|
-
opacity = 0;
|
|
15335
|
-
}
|
|
15336
|
-
else {
|
|
15337
|
-
opacity = 1 - (absProgress * 2);
|
|
15338
|
-
}
|
|
15339
|
-
slideEl.style.opacity = Math.max(opacity, 0).toString();
|
|
15340
|
-
}
|
|
15341
|
-
// Set initial scale
|
|
15342
|
-
if (this.progressiveScale()) {
|
|
15343
|
-
const minScale = 0.9;
|
|
15344
|
-
const scale = 1 - (absProgress * (1 - minScale));
|
|
15345
|
-
slideEl.style.transform = `scale(${Math.max(scale, minScale)})`;
|
|
15346
|
-
}
|
|
15347
|
-
});
|
|
15348
|
-
};
|
|
15349
|
-
}
|
|
15350
|
-
// Add pagination if enabled
|
|
15351
|
-
if (this.pagination()) {
|
|
15352
|
-
config.modules = [Pagination];
|
|
15353
|
-
config.pagination = {
|
|
15354
|
-
el: '.swiper-pagination',
|
|
15355
|
-
clickable: true,
|
|
15356
|
-
dynamicBullets: false,
|
|
15357
|
-
};
|
|
15358
|
-
}
|
|
15359
|
-
this.swiperInstance = new Swiper(this.swiperContainer.nativeElement, config);
|
|
15259
|
+
* @example
|
|
15260
|
+
* ```typescript
|
|
15261
|
+
* constructor(private inquiryModal: DsMobileNewInquiryModalService) {}
|
|
15262
|
+
*
|
|
15263
|
+
* async createNewInquiry() {
|
|
15264
|
+
* await this.inquiryModal.open({
|
|
15265
|
+
* onSubmit: async (data) => {
|
|
15266
|
+
* console.log('Creating inquiry:', data);
|
|
15267
|
+
* // Call your API to create the inquiry
|
|
15268
|
+
* await this.apiService.createInquiry(data);
|
|
15269
|
+
* // Close the modal
|
|
15270
|
+
* await this.inquiryModal.close();
|
|
15271
|
+
* }
|
|
15272
|
+
* });
|
|
15273
|
+
* }
|
|
15274
|
+
* ```
|
|
15275
|
+
*/
|
|
15276
|
+
class DsMobileNewInquiryModalService extends BaseModalService {
|
|
15277
|
+
constructor(modalController) {
|
|
15278
|
+
super(modalController);
|
|
15360
15279
|
}
|
|
15361
15280
|
/**
|
|
15362
|
-
*
|
|
15281
|
+
* Open the new inquiry modal
|
|
15282
|
+
*
|
|
15283
|
+
* @param options Modal options including onSubmit callback
|
|
15284
|
+
* @returns Promise that resolves when the modal is presented
|
|
15363
15285
|
*/
|
|
15364
|
-
|
|
15365
|
-
|
|
15286
|
+
async open(options) {
|
|
15287
|
+
// console.log('[NewInquiryModal] Opening modal with options:', options);
|
|
15288
|
+
const modal = await this.createModal(DsMobileNewInquiryModalComponent, {
|
|
15289
|
+
onSubmit: options?.onSubmit,
|
|
15290
|
+
loading: options?.loading ?? false,
|
|
15291
|
+
error: options?.error,
|
|
15292
|
+
}, {
|
|
15293
|
+
keyboardClose: false, // Don't close on keyboard hide for this modal
|
|
15294
|
+
});
|
|
15295
|
+
// console.log('[NewInquiryModal] Modal created, presenting...');
|
|
15296
|
+
await modal.present();
|
|
15297
|
+
// console.log('[NewInquiryModal] Modal presented');
|
|
15366
15298
|
}
|
|
15299
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
15300
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalService, providedIn: 'root' });
|
|
15301
|
+
}
|
|
15302
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalService, decorators: [{
|
|
15303
|
+
type: Injectable,
|
|
15304
|
+
args: [{
|
|
15305
|
+
providedIn: 'root',
|
|
15306
|
+
}]
|
|
15307
|
+
}], ctorParameters: () => [{ type: i1.ModalController }] });
|
|
15308
|
+
|
|
15309
|
+
/**
|
|
15310
|
+
* DsMobileHandbookFolderMiniComponent
|
|
15311
|
+
*
|
|
15312
|
+
* A minimized folder icon component for use in headers and small spaces.
|
|
15313
|
+
* Simplified version without animations or page sheets - just folder and icon.
|
|
15314
|
+
*
|
|
15315
|
+
* @example
|
|
15316
|
+
* ```html
|
|
15317
|
+
* <ds-mobile-handbook-folder-mini
|
|
15318
|
+
* [variant]="'pink'"
|
|
15319
|
+
* [iconName]="'remixLightbulbLine'">
|
|
15320
|
+
* </ds-mobile-handbook-folder-mini>
|
|
15321
|
+
* ```
|
|
15322
|
+
*/
|
|
15323
|
+
class DsMobileHandbookFolderMiniComponent {
|
|
15367
15324
|
/**
|
|
15368
|
-
*
|
|
15325
|
+
* Color variant for the folder
|
|
15326
|
+
* Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey
|
|
15369
15327
|
*/
|
|
15370
|
-
|
|
15371
|
-
this.swiperInstance?.slideNext();
|
|
15372
|
-
}
|
|
15328
|
+
variant = 'light-purple';
|
|
15373
15329
|
/**
|
|
15374
|
-
*
|
|
15330
|
+
* Icon name from the design system icon library
|
|
15375
15331
|
*/
|
|
15376
|
-
|
|
15377
|
-
return this.swiperInstance?.isBeginning ?? true;
|
|
15378
|
-
}
|
|
15332
|
+
iconName = 'remixFolder3Line';
|
|
15379
15333
|
/**
|
|
15380
|
-
*
|
|
15334
|
+
* Get the CSS variable name for the color variant
|
|
15381
15335
|
*/
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
|
|
15387
|
-
|
|
15388
|
-
|
|
15389
|
-
|
|
15336
|
+
getColorVar(suffix) {
|
|
15337
|
+
const variantMap = {
|
|
15338
|
+
'success': 'success',
|
|
15339
|
+
'warning': 'warning',
|
|
15340
|
+
'destructive': 'destructive',
|
|
15341
|
+
'blue': 'blue',
|
|
15342
|
+
'light-purple': 'light-purple',
|
|
15343
|
+
'pink': 'pink',
|
|
15344
|
+
'salmon-orange': 'salmon-orange',
|
|
15345
|
+
'orange': 'orange',
|
|
15346
|
+
'lime-green': 'lime-green',
|
|
15347
|
+
'grey': 'grey'
|
|
15348
|
+
};
|
|
15349
|
+
const colorName = variantMap[this.variant] || 'light-purple';
|
|
15350
|
+
return `var(--color-${colorName}-${suffix})`;
|
|
15390
15351
|
}
|
|
15391
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
15392
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
15393
|
-
<div class="
|
|
15394
|
-
|
|
15395
|
-
|
|
15352
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookFolderMiniComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15353
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DsMobileHandbookFolderMiniComponent, isStandalone: true, selector: "ds-mobile-handbook-folder-mini", inputs: { variant: "variant", iconName: "iconName" }, ngImport: i0, template: `
|
|
15354
|
+
<div class="mini-folder-container">
|
|
15355
|
+
<!-- Folder Tab SVG -->
|
|
15356
|
+
<svg
|
|
15357
|
+
class="mini-folder-tab"
|
|
15358
|
+
width="101"
|
|
15359
|
+
height="24"
|
|
15360
|
+
viewBox="0 0 101 24"
|
|
15361
|
+
fill="none"
|
|
15362
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
15363
|
+
<path
|
|
15364
|
+
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"
|
|
15365
|
+
[attr.fill]="getColorVar('strong')"/>
|
|
15366
|
+
</svg>
|
|
15367
|
+
|
|
15368
|
+
<!-- Folder Back -->
|
|
15369
|
+
<div class="mini-folder-back" [style.background-color]="getColorVar('strong')">
|
|
15370
|
+
<!-- Folder Front -->
|
|
15371
|
+
<div
|
|
15372
|
+
class="mini-folder-front"
|
|
15373
|
+
[style.background-color]="getColorVar('base')">
|
|
15374
|
+
<ds-icon
|
|
15375
|
+
[name]="iconName"
|
|
15376
|
+
[size]="'14px'"
|
|
15377
|
+
[style.color]="'white'" />
|
|
15378
|
+
</div>
|
|
15396
15379
|
</div>
|
|
15397
|
-
@if (pagination()) {
|
|
15398
|
-
<div class="swiper-pagination"></div>
|
|
15399
|
-
}
|
|
15400
15380
|
</div>
|
|
15401
|
-
`, isInline: true, styles: [":host{display:block;width:
|
|
15381
|
+
`, isInline: true, styles: [":host{display:inline-block;width:32px;height:32px;flex-shrink:0}.mini-folder-container{position:relative;width:100%;height:100%;display:flex;flex-direction:column}.mini-folder-tab{width:50%;height:auto;display:block}.mini-folder-back{height:28px;border-radius:0 4px 4px;position:relative;margin-top:-1px}.mini-folder-front{position:absolute;bottom:0;left:0;right:0;height:24px;border-radius:4px;display:flex;align-items:center;justify-content:center;z-index:2;box-shadow:inset 0 8px 8px #fff3,inset 0 .5px .5px #ffffff4d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
|
|
15402
15382
|
}
|
|
15403
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
15383
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookFolderMiniComponent, decorators: [{
|
|
15404
15384
|
type: Component,
|
|
15405
|
-
args: [{ selector: 'ds-mobile-
|
|
15406
|
-
<div class="
|
|
15407
|
-
|
|
15408
|
-
|
|
15385
|
+
args: [{ selector: 'ds-mobile-handbook-folder-mini', standalone: true, imports: [CommonModule, DsIconComponent], template: `
|
|
15386
|
+
<div class="mini-folder-container">
|
|
15387
|
+
<!-- Folder Tab SVG -->
|
|
15388
|
+
<svg
|
|
15389
|
+
class="mini-folder-tab"
|
|
15390
|
+
width="101"
|
|
15391
|
+
height="24"
|
|
15392
|
+
viewBox="0 0 101 24"
|
|
15393
|
+
fill="none"
|
|
15394
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
15395
|
+
<path
|
|
15396
|
+
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"
|
|
15397
|
+
[attr.fill]="getColorVar('strong')"/>
|
|
15398
|
+
</svg>
|
|
15399
|
+
|
|
15400
|
+
<!-- Folder Back -->
|
|
15401
|
+
<div class="mini-folder-back" [style.background-color]="getColorVar('strong')">
|
|
15402
|
+
<!-- Folder Front -->
|
|
15403
|
+
<div
|
|
15404
|
+
class="mini-folder-front"
|
|
15405
|
+
[style.background-color]="getColorVar('base')">
|
|
15406
|
+
<ds-icon
|
|
15407
|
+
[name]="iconName"
|
|
15408
|
+
[size]="'14px'"
|
|
15409
|
+
[style.color]="'white'" />
|
|
15410
|
+
</div>
|
|
15409
15411
|
</div>
|
|
15410
|
-
@if (pagination()) {
|
|
15411
|
-
<div class="swiper-pagination"></div>
|
|
15412
|
-
}
|
|
15413
15412
|
</div>
|
|
15414
|
-
`, styles: [":host{display:block;width:
|
|
15415
|
-
}],
|
|
15416
|
-
type:
|
|
15417
|
-
|
|
15413
|
+
`, styles: [":host{display:inline-block;width:32px;height:32px;flex-shrink:0}.mini-folder-container{position:relative;width:100%;height:100%;display:flex;flex-direction:column}.mini-folder-tab{width:50%;height:auto;display:block}.mini-folder-back{height:28px;border-radius:0 4px 4px;position:relative;margin-top:-1px}.mini-folder-front{position:absolute;bottom:0;left:0;right:0;height:24px;border-radius:4px;display:flex;align-items:center;justify-content:center;z-index:2;box-shadow:inset 0 8px 8px #fff3,inset 0 .5px .5px #ffffff4d}\n"] }]
|
|
15414
|
+
}], propDecorators: { variant: [{
|
|
15415
|
+
type: Input
|
|
15416
|
+
}], iconName: [{
|
|
15417
|
+
type: Input
|
|
15418
15418
|
}] } });
|
|
15419
15419
|
|
|
15420
15420
|
/**
|
|
@@ -16351,6 +16351,115 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
16351
16351
|
`, styles: [":host{display:block;width:100%}.text-input-wrapper{position:relative;width:100%}.text-input{width:100%;height:48px;padding:0 16px;box-sizing:border-box;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-base);font-weight:400;line-height:1.4;color:var(--text-color-default-primary);background-color:var(--color-background-neutral-primary);border:1px solid var(--border-color-default);border-radius:8px;transition:border-color var(--transition-duration-fast) var(--ease-smooth),background-color var(--transition-duration-fast) var(--ease-smooth),box-shadow var(--transition-duration-fast) var(--ease-smooth);outline:none;-webkit-appearance:none;appearance:none}.text-input::placeholder{color:var(--text-color-default-tertiary)}.text-input:hover:not(:disabled):not(:focus){border-color:var(--border-color-default);background-color:var(--color-background-neutral-primary-hover)}.text-input:focus{border-color:var(--color-accent);background-color:var(--color-background-neutral-primary);box-shadow:0 0 0 3px var(--outline-color-default)}.text-input.error{border-color:var(--color-destructive-base)}.text-input.error:focus{border-color:var(--color-destructive-base);box-shadow:0 0 0 3px #dc26261a}.text-input:disabled{background-color:var(--color-background-neutral-disabled);border-color:var(--border-color-default);color:var(--text-color-default-disabled);cursor:not-allowed}.text-input:disabled::placeholder{color:var(--text-color-default-disabled)}.error-message{margin-top:8px;font-family:Brockmann,system-ui,-apple-system,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--color-destructive-base)}\n"] }]
|
|
16352
16352
|
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], inputmode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputmode", required: false }] }], autoClearError: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClearError", required: false }] }], validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "validator", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], blur: [{ type: i0.Output, args: ["blur"] }], focus: [{ type: i0.Output, args: ["focus"] }], errorCleared: [{ type: i0.Output, args: ["errorCleared"] }] } });
|
|
16353
16353
|
|
|
16354
|
+
/**
|
|
16355
|
+
* DsMobileFileAttachmentComponent
|
|
16356
|
+
*
|
|
16357
|
+
* File attachment display for various document types.
|
|
16358
|
+
* Shows file info card with icon, filename, and file size.
|
|
16359
|
+
* Supports PDF and generic document formats.
|
|
16360
|
+
* Emits click event to open file in viewer.
|
|
16361
|
+
*
|
|
16362
|
+
* @example
|
|
16363
|
+
* ```html
|
|
16364
|
+
* <ds-mobile-file-attachment
|
|
16365
|
+
* [fileName]="'Document.pdf'"
|
|
16366
|
+
* [fileSize]="'1.2 MB'"
|
|
16367
|
+
* [variant]="'pdf'"
|
|
16368
|
+
* (fileClick)="openFile()">
|
|
16369
|
+
* </ds-mobile-file-attachment>
|
|
16370
|
+
* ```
|
|
16371
|
+
*/
|
|
16372
|
+
class DsMobileFileAttachmentComponent {
|
|
16373
|
+
/**
|
|
16374
|
+
* File name
|
|
16375
|
+
*/
|
|
16376
|
+
fileName = input('Document', ...(ngDevMode ? [{ debugName: "fileName" }] : []));
|
|
16377
|
+
/**
|
|
16378
|
+
* File size display (e.g., "1.2 MB")
|
|
16379
|
+
*/
|
|
16380
|
+
fileSize = input('', ...(ngDevMode ? [{ debugName: "fileSize" }] : []));
|
|
16381
|
+
/**
|
|
16382
|
+
* File type variant
|
|
16383
|
+
* - 'pdf' - PDF document (red icon)
|
|
16384
|
+
* - 'doc' - Generic document (blue icon)
|
|
16385
|
+
*/
|
|
16386
|
+
variant = input('doc', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
16387
|
+
/**
|
|
16388
|
+
* Emits when the file attachment is clicked
|
|
16389
|
+
*/
|
|
16390
|
+
fileClick = output();
|
|
16391
|
+
/**
|
|
16392
|
+
* Get the appropriate icon name based on variant
|
|
16393
|
+
*/
|
|
16394
|
+
getIconName() {
|
|
16395
|
+
return this.variant() === 'pdf' ? 'remixFileTextLine' : 'remixAttachmentLine';
|
|
16396
|
+
}
|
|
16397
|
+
/**
|
|
16398
|
+
* Get the file type label based on variant
|
|
16399
|
+
*/
|
|
16400
|
+
getFileTypeLabel() {
|
|
16401
|
+
return this.variant() === 'pdf' ? 'PDF' : 'DOC';
|
|
16402
|
+
}
|
|
16403
|
+
handleClick(event) {
|
|
16404
|
+
event.stopPropagation();
|
|
16405
|
+
this.fileClick.emit();
|
|
16406
|
+
}
|
|
16407
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileFileAttachmentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16408
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileFileAttachmentComponent, isStandalone: true, selector: "ds-mobile-file-attachment", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fileSize: { classPropertyName: "fileSize", publicName: "fileSize", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileClick: "fileClick" }, host: { listeners: { "click": "handleClick($event)" } }, ngImport: i0, template: `
|
|
16409
|
+
<div class="file-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
|
|
16410
|
+
<ds-avatar
|
|
16411
|
+
type="icon"
|
|
16412
|
+
[iconName]="getIconName()"
|
|
16413
|
+
size="lg"
|
|
16414
|
+
/>
|
|
16415
|
+
</div>
|
|
16416
|
+
|
|
16417
|
+
<div class="file-info">
|
|
16418
|
+
<div class="file-name">{{ fileName() }}</div>
|
|
16419
|
+
@if (fileSize()) {
|
|
16420
|
+
<div class="file-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
|
|
16421
|
+
} @else {
|
|
16422
|
+
<div class="file-meta">{{ getFileTypeLabel() }}</div>
|
|
16423
|
+
}
|
|
16424
|
+
</div>
|
|
16425
|
+
|
|
16426
|
+
<ds-icon
|
|
16427
|
+
name="remixArrowRightSLine"
|
|
16428
|
+
size="20px"
|
|
16429
|
+
class="open-icon"
|
|
16430
|
+
/>
|
|
16431
|
+
`, isInline: true, styles: [":host{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease}:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host:active{transform:scale(.98)}.file-avatar{flex-shrink:0}.file-avatar.pdf::ng-deep .avatar--icon{background-color:#ff5757!important}.file-avatar.doc::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}.file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.file-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.open-icon{color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
|
|
16432
|
+
}
|
|
16433
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileFileAttachmentComponent, decorators: [{
|
|
16434
|
+
type: Component,
|
|
16435
|
+
args: [{ selector: 'ds-mobile-file-attachment', standalone: true, imports: [CommonModule, DsAvatarComponent, DsIconComponent], host: {
|
|
16436
|
+
'(click)': 'handleClick($event)'
|
|
16437
|
+
}, template: `
|
|
16438
|
+
<div class="file-avatar" [class.pdf]="variant() === 'pdf'" [class.doc]="variant() === 'doc'">
|
|
16439
|
+
<ds-avatar
|
|
16440
|
+
type="icon"
|
|
16441
|
+
[iconName]="getIconName()"
|
|
16442
|
+
size="lg"
|
|
16443
|
+
/>
|
|
16444
|
+
</div>
|
|
16445
|
+
|
|
16446
|
+
<div class="file-info">
|
|
16447
|
+
<div class="file-name">{{ fileName() }}</div>
|
|
16448
|
+
@if (fileSize()) {
|
|
16449
|
+
<div class="file-meta">{{ getFileTypeLabel() }} · {{ fileSize() }}</div>
|
|
16450
|
+
} @else {
|
|
16451
|
+
<div class="file-meta">{{ getFileTypeLabel() }}</div>
|
|
16452
|
+
}
|
|
16453
|
+
</div>
|
|
16454
|
+
|
|
16455
|
+
<ds-icon
|
|
16456
|
+
name="remixArrowRightSLine"
|
|
16457
|
+
size="20px"
|
|
16458
|
+
class="open-icon"
|
|
16459
|
+
/>
|
|
16460
|
+
`, styles: [":host{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:16px;cursor:pointer;transition:all .2s ease}:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host:active{transform:scale(.98)}.file-avatar{flex-shrink:0}.file-avatar.pdf::ng-deep .avatar--icon{background-color:#ff5757!important}.file-avatar.doc::ng-deep .avatar--icon{background-color:var(--color-blue-base, #3B82F6)!important}.file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.file-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.open-icon{color:var(--color-text-tertiary, #a3a3a3);flex-shrink:0}\n"] }]
|
|
16461
|
+
}], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSize", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], fileClick: [{ type: i0.Output, args: ["fileClick"] }] } });
|
|
16462
|
+
|
|
16354
16463
|
/**
|
|
16355
16464
|
* DsMobileFabComponent
|
|
16356
16465
|
*
|
|
@@ -20606,5 +20715,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
20606
20715
|
* Generated bundle index. Do not edit.
|
|
20607
20716
|
*/
|
|
20608
20717
|
|
|
20609
|
-
export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsAppIconComponent, DsAvatarWithBadgeComponent, DsLogoComponent, DsMobileActionsBottomSheetComponent, DsMobileAttachmentPreviewComponent, DsMobileBottomSheetService, DsMobileBottomSheetWrapperComponent, DsMobileCardInlineBannerComponent, DsMobileCardInlineComponent, DsMobileCardInlineContactComponent, DsMobileCardInlineFileComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileDropdownComponent, DsMobileEmptyStateComponent, DsMobileFabComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileIllustrationComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLoaderOverlayComponent, DsMobileLongPressDirective, DsMobileMessageBubbleComponent, DsMobileMessageComposerComponent, DsMobileModalBaseComponent, DsMobileModalService, DsMobileNewInquiryModalComponent, DsMobileNewInquiryModalService, DsMobileOfflineBannerComponent, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileProfileActionsSheetComponent, DsMobilePropertyBannerComponent, DsMobileSectionComponent, DsMobileTabBarComponent, DsMobileTabsComponent, DsTextInputComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobileModalBase, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, SignInPageComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoModalComponent, WhitelabelDemoModalService, WhitelabelService, customBackTransition, customPageTransition };
|
|
20718
|
+
export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsAppIconComponent, DsAvatarWithBadgeComponent, DsLogoComponent, DsMobileActionListItemComponent, DsMobileActionsBottomSheetComponent, DsMobileAttachmentPreviewComponent, DsMobileBottomSheetService, DsMobileBottomSheetWrapperComponent, DsMobileCardInlineBannerComponent, DsMobileCardInlineComponent, DsMobileCardInlineContactComponent, DsMobileCardInlineFileComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileDropdownComponent, DsMobileEmptyStateComponent, DsMobileFabComponent, DsMobileFileAttachmentComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileIllustrationComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileLoaderOverlayComponent, DsMobileLongPressDirective, DsMobileMessageBubbleComponent, DsMobileMessageComposerComponent, DsMobileModalBaseComponent, DsMobileModalService, DsMobileNewInquiryModalComponent, DsMobileNewInquiryModalService, DsMobileOfflineBannerComponent, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileProfileActionsSheetComponent, DsMobilePropertyBannerComponent, DsMobileSectionComponent, DsMobileSwiperComponent, DsMobileSystemMessageBannerComponent, DsMobileTabBarComponent, DsMobileTabsComponent, DsTextInputComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobileModalBase, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, SignInPageComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, UserService, WhitelabelDemoModalComponent, WhitelabelDemoModalService, WhitelabelService, customBackTransition, customPageTransition };
|
|
20610
20719
|
//# sourceMappingURL=propbinder-mobile-design.mjs.map
|