mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
#1896 Weitere Medien werden über Rand angezeigt
This commit is contained in:
@@ -157,7 +157,7 @@
|
||||
<div class="product-formats" *ngIf="item.family?.length > 0">
|
||||
<span class="label">Auch verfügbar als</span>
|
||||
|
||||
<ui-slider [scrollDistance]="200">
|
||||
<ui-slider [scrollDistance]="250">
|
||||
<a class="product-family" *ngFor="let format of item.family" [routerLink]="['/product', 'details', 'ean', format.product.ean]">
|
||||
<span class="format-detail">
|
||||
<img [src]="'/assets/images/OF_Icon_' + format.product?.format + '.svg'" alt="format icon" />
|
||||
|
||||
@@ -191,22 +191,17 @@
|
||||
}
|
||||
|
||||
.product-formats {
|
||||
@apply flex flex-row whitespace-nowrap items-center px-5 h-px-40 mb-16 pb-8;
|
||||
@apply grid whitespace-nowrap items-center px-5 h-px-40 mb-16 pb-8;
|
||||
grid-template-rows: auto;
|
||||
grid-template-columns: auto 1fr;
|
||||
max-width: 100%;
|
||||
|
||||
.label {
|
||||
@apply mr-2;
|
||||
}
|
||||
|
||||
ui-slider {
|
||||
width: 735px;
|
||||
|
||||
::ng-deep button {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.product-family {
|
||||
@apply mr-4 text-active-customer font-bold no-underline mt-4;
|
||||
@apply mr-4 text-active-customer font-bold no-underline px-2;
|
||||
|
||||
.format-detail {
|
||||
@apply flex items-center;
|
||||
|
||||
@@ -31,11 +31,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
return this.ssoService.isAuthenticated();
|
||||
}
|
||||
|
||||
@HostBinding('class.desktop')
|
||||
get isDesktop() {
|
||||
return this.deviceDetectorService.isDesktop();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private config: AppConfiguration,
|
||||
private ssoService: SsoService,
|
||||
@@ -84,6 +79,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
if (this.includeGoogleAnalytics) {
|
||||
this.initGoogleAnalytics();
|
||||
}
|
||||
|
||||
this.renderer.addClass(this.document.body, this.deviceDetectorService.deviceType);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
<div class="slider-wrapper" (mouseenter)="calcVisibility()">
|
||||
<div
|
||||
class="cta-prev-wrapper"
|
||||
*ngIf="!startReached"
|
||||
(mouseenter)="changeVisibility(false, true)"
|
||||
(mouseleave)="changeVisibility(false, false)"
|
||||
>
|
||||
<button class="cta-slider-prev" (click)="prev()" *ngIf="showPrevSliderButtons$ | async">
|
||||
<ui-icon class="slider-icon" rotate="180deg" icon="arrow" size="15px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="slider-container" #sliderContainer>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<div
|
||||
class="cta-next-wrapper"
|
||||
*ngIf="!endReached"
|
||||
(mouseenter)="changeVisibility(true, false)"
|
||||
(mouseleave)="changeVisibility(false, false)"
|
||||
>
|
||||
<button class="cta-slider-next" (click)="next()" *ngIf="showNextSliderButtons$ | async">
|
||||
<ui-icon class="slider-icon" icon="arrow" size="15px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="prev-wrapper" *ngIf="!isStartVisible">
|
||||
<button type="button" (click)="scrollLeft()">
|
||||
<ui-icon class="slider-icon" rotate="180deg" icon="arrow" size="15px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div #sliderWrapper class="ui-slider-wrapper">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<div class="next-wrapper" *ngIf="!isEndVisible">
|
||||
<button type="button" (click)="scrollRight()">
|
||||
<ui-icon class="slider-icon" icon="arrow" size="15px"></ui-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,31 +1,73 @@
|
||||
.slider-wrapper {
|
||||
@apply relative flex flex-row items-center px-2;
|
||||
.cta-slider-next,
|
||||
.cta-slider-prev {
|
||||
@apply outline-none border-none bg-white rounded-card h-full opacity-80;
|
||||
width: 55px;
|
||||
box-shadow: 3px 0 14px 8px white;
|
||||
// .slider-wrapper {
|
||||
// @apply relative flex flex-row items-center px-2;
|
||||
// .cta-slider-next,
|
||||
// .cta-slider-prev {
|
||||
// @apply outline-none border-none bg-white rounded-card h-full opacity-80;
|
||||
// width: 55px;
|
||||
// box-shadow: 3px 0 14px 8px white;
|
||||
// }
|
||||
|
||||
// .cta-next-wrapper {
|
||||
// @apply flex absolute right-0 w-14 h-full pl-4 items-center justify-center;
|
||||
// }
|
||||
|
||||
// .cta-prev-wrapper {
|
||||
// @apply flex absolute left-0 w-14 h-full pr-4 items-center justify-center;
|
||||
// }
|
||||
|
||||
// .slider-icon {
|
||||
// @apply items-center justify-center;
|
||||
// width: 40px;
|
||||
// height: 40px;
|
||||
// border-radius: 50%;
|
||||
// background-color: #e9f0f8;
|
||||
// color: #0f1542;
|
||||
// }
|
||||
// .slider-container {
|
||||
// @apply flex flex-row overflow-scroll;
|
||||
// scroll-behavior: smooth;
|
||||
// width: calc(100% + 1rem);
|
||||
// }
|
||||
// }
|
||||
.ui-slider {
|
||||
@apply grid relative;
|
||||
min-height: 40px;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
|
||||
.ui-slider-wrapper {
|
||||
@apply flex overflow-scroll items-center;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cta-next-wrapper {
|
||||
@apply flex absolute right-0 w-14 h-full pl-4 items-center justify-center;
|
||||
.prev-wrapper,
|
||||
.next-wrapper {
|
||||
@apply absolute hidden justify-center items-center;
|
||||
|
||||
button {
|
||||
@apply rounded-full grid content-center justify-center bg-glitter text-ucla-blue border-none outline-none;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.cta-prev-wrapper {
|
||||
@apply flex absolute left-0 w-14 h-full pr-4 items-center justify-center;
|
||||
.prev-wrapper {
|
||||
@apply top-0 left-0 bottom-0;
|
||||
background: rgb(0, 0, 0);
|
||||
background: linear-gradient(270deg, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 0.7) 50%);
|
||||
}
|
||||
|
||||
.slider-icon {
|
||||
@apply items-center justify-center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background-color: #e9f0f8;
|
||||
color: #0f1542;
|
||||
}
|
||||
.slider-container {
|
||||
@apply flex flex-row overflow-scroll;
|
||||
scroll-behavior: smooth;
|
||||
width: calc(100% + 1rem);
|
||||
.next-wrapper {
|
||||
@apply top-0 right-0 bottom-0;
|
||||
background: rgb(0, 0, 0);
|
||||
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 0.7) 50%);
|
||||
}
|
||||
}
|
||||
|
||||
.desktop .ui-slider:hover .prev-wrapper,
|
||||
.desktop .ui-slider:hover .next-wrapper {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
@@ -1,67 +1,69 @@
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { NativeContainerService } from 'native-container';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { fromEvent, Subscription } from 'rxjs';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'ui-slider',
|
||||
templateUrl: 'slider.component.html',
|
||||
styleUrls: ['slider.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class SliderComponent implements AfterViewInit {
|
||||
@ViewChild('sliderContainer', { static: false }) sliderContainer: ElementRef<HTMLDivElement>;
|
||||
export class UiSliderComponent implements AfterViewInit, OnDestroy {
|
||||
@HostBinding('class') clazz = 'ui-slider';
|
||||
|
||||
/* @internal */
|
||||
showPrevSliderButtons$ = new BehaviorSubject<boolean>(false);
|
||||
@Input() scrollDistance = 200;
|
||||
|
||||
/* @internal */
|
||||
showNextSliderButtons$ = new BehaviorSubject<boolean>(false);
|
||||
@ViewChild('sliderWrapper', { read: ElementRef, static: true })
|
||||
slideWrapper: ElementRef;
|
||||
|
||||
/* @internal */
|
||||
scrollDistance$ = new BehaviorSubject<number>(100);
|
||||
|
||||
hideButtons: boolean;
|
||||
startReached: boolean;
|
||||
endReached: boolean;
|
||||
|
||||
@Input()
|
||||
get scrollDistance(): number {
|
||||
return this.scrollDistance$.value;
|
||||
get slideWrapperNativeElement(): HTMLElement {
|
||||
return this.slideWrapper?.nativeElement;
|
||||
}
|
||||
|
||||
set scrollDistance(value) {
|
||||
if (this.scrollDistance !== value) {
|
||||
this.scrollDistance$.next(value);
|
||||
}
|
||||
get isStartVisible() {
|
||||
const { scrollLeft } = this.slideWrapperNativeElement;
|
||||
return scrollLeft === 0;
|
||||
}
|
||||
|
||||
constructor(private nativeContainer: NativeContainerService) {}
|
||||
get isEndVisible() {
|
||||
const { scrollLeft, clientWidth, scrollWidth } = this.slideWrapperNativeElement;
|
||||
return scrollLeft + clientWidth === scrollWidth;
|
||||
}
|
||||
|
||||
private subscriptions = new Subscription();
|
||||
|
||||
constructor(private cdr: ChangeDetectorRef) {}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.hideButtons = this.nativeContainer.isUiWebview()?.isNative;
|
||||
this.changeVisibility(false, false);
|
||||
this.cdr.markForCheck();
|
||||
this.subscriptions.add(
|
||||
fromEvent(this.slideWrapperNativeElement, 'scroll')
|
||||
.pipe(debounceTime(100))
|
||||
.subscribe(() => this.cdr.markForCheck())
|
||||
);
|
||||
}
|
||||
|
||||
prev() {
|
||||
this.sliderContainer.nativeElement.scrollLeft -= this.scrollDistance;
|
||||
this.changeVisibility(false, true);
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.unsubscribe();
|
||||
}
|
||||
|
||||
calcVisibility() {
|
||||
this.startReached = this.sliderContainer.nativeElement.scrollLeft === 0;
|
||||
this.endReached =
|
||||
this.sliderContainer.nativeElement.scrollWidth - this.sliderContainer.nativeElement.offsetWidth ===
|
||||
this.sliderContainer.nativeElement.scrollLeft;
|
||||
scrollLeft() {
|
||||
this.slideWrapperNativeElement.scrollTo({ left: this.slideWrapperNativeElement.scrollLeft - this.scrollDistance, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
changeVisibility(next: boolean, prev: boolean) {
|
||||
this.calcVisibility();
|
||||
this.showPrevSliderButtons$.next(!this.hideButtons && prev && !this.startReached);
|
||||
this.showNextSliderButtons$.next(!this.hideButtons && next && !this.endReached);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.sliderContainer.nativeElement.scrollLeft += this.scrollDistance;
|
||||
this.changeVisibility(true, false);
|
||||
scrollRight() {
|
||||
this.slideWrapperNativeElement.scrollTo({ left: this.slideWrapperNativeElement.scrollLeft + this.scrollDistance, behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { UiIconModule } from '@ui/icon';
|
||||
import { SliderComponent } from './slider.component';
|
||||
import { UiSliderComponent } from './slider.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SliderComponent],
|
||||
declarations: [UiSliderComponent],
|
||||
imports: [CommonModule, UiIconModule],
|
||||
exports: [SliderComponent],
|
||||
exports: [UiSliderComponent],
|
||||
})
|
||||
export class UiSliderModule {}
|
||||
|
||||
Reference in New Issue
Block a user