@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,140 lines • 121 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { CommonModule } from '@angular/common';
import { Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, NgModule, OnDestroy, Output, ContentChildren, QueryList, IterableDiffer, IterableDiffers, AfterContentInit, IterableChangeRecord, TemplateRef, ViewChild, ContentChild, Injectable } from '@angular/core';
import { IgxIconModule } from '../icon/index';
import { IBaseEventArgs, PlatformUtil } from '../core/utils';
import { Subject, merge } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { IgxCarouselIndicatorDirective, IgxCarouselNextButtonDirective, IgxCarouselPrevButtonDirective } from './carousel.directives';
import { useAnimation, AnimationBuilder, AnimationPlayer, AnimationReferenceMetadata } from '@angular/animations';
import { slideInLeft, fadeIn } from '../animations/main';
import { IgxSlideComponent, Direction } from './slide.component';
import { CurrentResourceStrings } from '../core/i18n/resources';
import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
let NEXT_ID = 0;
export var CarouselIndicatorsOrientation;
(function (CarouselIndicatorsOrientation) {
CarouselIndicatorsOrientation["bottom"] = "bottom";
CarouselIndicatorsOrientation["top"] = "top";
})(CarouselIndicatorsOrientation || (CarouselIndicatorsOrientation = {}));
export var CarouselAnimationType;
(function (CarouselAnimationType) {
CarouselAnimationType["none"] = "none";
CarouselAnimationType["slide"] = "slide";
CarouselAnimationType["fade"] = "fade";
})(CarouselAnimationType || (CarouselAnimationType = {}));
let CarouselHammerConfig = class CarouselHammerConfig extends HammerGestureConfig {
constructor() {
super(...arguments);
this.overrides = {
pan: { direction: Hammer.DIRECTION_HORIZONTAL }
};
}
};
CarouselHammerConfig = __decorate([
Injectable()
], CarouselHammerConfig);
export { CarouselHammerConfig };
/**
* **Ignite UI for Angular Carousel** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/carousel.html)
*
* The Ignite UI Carousel is used to browse or navigate through a collection of slides. Slides can contain custom
* content such as images or cards and be used for things such as on-boarding tutorials or page-based interfaces.
* It can be used as a separate fullscreen element or inside another component.
*
* Example:
* ```html
* <igx-carousel>
* <igx-slide>
* <h3>First Slide Header</h3>
* <p>First slide Content</p>
* <igx-slide>
* <igx-slide>
* <h3>Second Slide Header</h3>
* <p>Second Slide Content</p>
* </igx-carousel>
* ```
*/
let IgxCarouselComponent = class IgxCarouselComponent {
constructor(element, iterableDiffers, builder, platformUtil) {
this.element = element;
this.iterableDiffers = iterableDiffers;
this.builder = builder;
this.platformUtil = platformUtil;
/**
* Returns the `role` attribute of the carousel.
* ```typescript
* let carouselRole = this.carousel.role;
* ```
* @memberof IgxCarouselComponent
*/
this.role = 'region';
/**
* Sets the `id` of the carousel.
* If not set, the `id` of the first carousel component will be `"igx-carousel-0"`.
* ```html
* <igx-carousel id="my-first-carousel"></igx-carousel>
* ```
* @memberof IgxCarouselComponent
*/
this.id = `igx-carousel-${NEXT_ID++}`;
/**
* Returns the `aria-label` of the carousel.
*
* ```typescript
* let carousel = this.carousel.ariaLabel;
* ```
*
*/
this.ariaLabel = 'carousel';
/**
* Returns the class of the carousel component.
* ```typescript
* let class = this.carousel.cssClass;
* ```
* @memberof IgxCarouselComponent
*/
this.cssClass = 'igx-carousel';
/**
* Sets whether the carousel should `loop` back to the first slide after reaching the last slide.
* Default value is `true`.
* ```html
* <igx-carousel [loop]="false"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.loop = true;
/**
* Sets whether the carousel will `pause` the slide transitions on user interactions.
* Default value is `true`.
* ```html
* <igx-carousel [pause]="false"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.pause = true;
/**
* Controls whether the carousel should render the left/right `navigation` buttons.
* Default value is `true`.
* ```html
* <igx-carousel [navigation] = "false"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.navigation = true;
/**
* Controls whether the carousel should support keyboard navigation.
* Default value is `true`.
* ```html
* <igx-carousel [keyboardSupport] = "false"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.keyboardSupport = true;
/**
* Controls whether the carousel should support gestures.
* Default value is `true`.
* ```html
* <igx-carousel [gesturesSupport] = "false"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.gesturesSupport = true;
/**
* Controls the maximum indexes that can be shown.
* Default value is `5`.
* ```html
* <igx-carousel [maximumIndicatorsCount] = "10"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.maximumIndicatorsCount = 5;
/**
* Gets/sets the display mode of carousel indicators. It can be top or bottom.
* Default value is `bottom`.
* ```html
* <igx-carousel indicatorsOrientation='top'>
* <igx-carousel>
* ```
* @memberOf IgxSlideComponent
*/
this.indicatorsOrientation = CarouselIndicatorsOrientation.bottom;
/**
* Gets/sets the animation type of carousel.
* Default value is `slide`.
* ```html
* <igx-carousel animationType='none'>
* <igx-carousel>
* ```
* @memberOf IgxSlideComponent
*/
this.animationType = CarouselAnimationType.slide;
/**
* The custom template, if any, that should be used when rendering carousel indicators
*
* ```typescript
* // Set in typescript
* const myCustomTemplate: TemplateRef<any> = myComponent.customTemplate;
* myComponent.carousel.indicatorTemplate = myCustomTemplate;
* ```
* ```html
* <!-- Set in markup -->
* <igx-carousel #carousel>
* ...
* <ng-template igxCarouselIndicator let-slide>
* <igx-icon *ngIf="slide.active" fontSet="material">brightness_7</igx-icon>
* <igx-icon *ngIf="!slide.active" fontSet="material">brightness_5</igx-icon>
* </ng-template>
* </igx-carousel>
* ```
*/
this.indicatorTemplate = null;
/**
* The custom template, if any, that should be used when rendering carousel next button
*
* ```typescript
* // Set in typescript
* const myCustomTemplate: TemplateRef<any> = myComponent.customTemplate;
* myComponent.carousel.nextButtonTemplate = myCustomTemplate;
* ```
* ```html
* <!-- Set in markup -->
* <igx-carousel #carousel>
* ...
* <ng-template igxCarouselNextButton let-disabled>
* <button igxButton="fab" igxRipple="white" [disabled]="disabled">
* <igx-icon fontSet="material">add</igx-icon>
* </button>
* </ng-template>
* </igx-carousel>
* ```
*/
this.nextButtonTemplate = null;
/**
* The custom template, if any, that should be used when rendering carousel previous button
*
* ```typescript
* // Set in typescript
* const myCustomTemplate: TemplateRef<any> = myComponent.customTemplate;
* myComponent.carousel.nextButtonTemplate = myCustomTemplate;
* ```
* ```html
* <!-- Set in markup -->
* <igx-carousel #carousel>
* ...
* <ng-template igxCarouselPrevButton let-disabled>
* <button igxButton="fab" igxRipple="white" [disabled]="disabled">
* <igx-icon fontSet="material">remove</igx-icon>
* </button>
* </ng-template>
* </igx-carousel>
* ```
*/
this.prevButtonTemplate = null;
/**
* An event that is emitted after a slide transition has happened.
* Provides references to the `IgxCarouselComponent` and `IgxSlideComponent` as event arguments.
* ```html
* <igx-carousel (onSlideChanged)="onSlideChanged($event)"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.onSlideChanged = new EventEmitter();
/**
* An event that is emitted after a slide has been added to the carousel.
* Provides references to the `IgxCarouselComponent` and `IgxSlideComponent` as event arguments.
* ```html
* <igx-carousel (onSlideAdded)="onSlideAdded($event)"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.onSlideAdded = new EventEmitter();
/**
* An event that is emitted after a slide has been removed from the carousel.
* Provides references to the `IgxCarouselComponent` and `IgxSlideComponent` as event arguments.
* ```html
* <igx-carousel (onSlideRemoved)="onSlideRemoved($event)"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.onSlideRemoved = new EventEmitter();
/**
* An event that is emitted after the carousel has been paused.
* Provides a reference to the `IgxCarouselComponent` as an event argument.
* ```html
* <igx-carousel (onCarouselPaused)="onCarouselPaused($event)"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.onCarouselPaused = new EventEmitter();
/**
* An event that is emitted after the carousel has resumed transitioning between `slides`.
* Provides a reference to the `IgxCarouselComponent` as an event argument.
* ```html
* <igx-carousel (onCarouselPlaying)="onCarouselPlaying($event)"></igx-carousel>
* ```
* @memberOf IgxCarouselComponent
*/
this.onCarouselPlaying = new EventEmitter();
this._resourceStrings = CurrentResourceStrings.CarouselResStrings;
this.destroy$ = new Subject();
this.differ = null;
this.animationDuration = 320;
this.animationPosition = 0;
this.newDuration = 0;
this.differ = this.iterableDiffers.find([]).create(null);
}
/**
* Returns the `tabIndex` of the carousel component.
* ```typescript
* let tabIndex = this.carousel.tabIndex;
* ```
* @memberof IgxCarouselComponent
*/
get tabIndex() {
return 0;
}
/**
* Gets the `touch-action` style of the `list item`.
* ```typescript
* let touchAction = this.listItem.touchAction;
* ```
*/
get touchAction() {
return this.gesturesSupport ? 'pan-y' : 'auto';
}
/**
* Returns the time `interval` in milliseconds before the slide changes.
* ```typescript
* let timeInterval = this.carousel.interval;
* ```
* @memberof IgxCarouselComponent
*/
get interval() {
return this._interval;
}
/**
* Sets the time `interval` in milliseconds before the slide changes.
* If not set, the carousel will not change `slides` automatically.
* ```html
* <igx-carousel [interval] = "1000"></igx-carousel>
* ```
* @memberof IgxCarouselComponent
*/
set interval(value) {
this._interval = +value;
this.restartInterval();
}
/**
* An accessor that sets the resource strings.
* By default it uses EN resources.
*/
set resourceStrings(value) {
this._resourceStrings = Object.assign({}, this._resourceStrings, value);
}
/**
* An accessor that returns the resource strings.
*/
get resourceStrings() {
return this._resourceStrings;
}
/** @hidden */
ngAfterContentInit() {
this.slides.changes
.pipe(takeUntil(this.destroy$))
.subscribe((change) => { this.initSlides(change); });
this.initSlides(this.slides);
}
/** @hidden */
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
this.destroyed = true;
if (this.lastInterval) {
clearInterval(this.lastInterval);
}
}
unsubscriber(slide) {
return merge(this.destroy$, slide.isDestroyed);
}
onSlideActivated(slide) {
if (slide.active && slide !== this.currentSlide) {
if (slide.direction === Direction.NONE) {
const newIndex = slide.index;
slide.direction = newIndex > this.current ? Direction.NEXT : Direction.PREV;
}
if (this.currentSlide) {
const animationWasStarted = this.finishAnimations();
this.currentSlide.direction = slide.direction;
this.currentSlide.active = false;
this.previousSlide = this.currentSlide;
this.currentSlide = slide;
if (this.animationType !== CarouselAnimationType.none) {
if (animationWasStarted) {
requestAnimationFrame(() => {
this.playAnimations();
});
}
else {
this.playAnimations();
}
}
}
else {
this.currentSlide = slide;
}
this.onSlideChanged.emit({ carousel: this, slide });
this.restartInterval();
}
}
playAnimations() {
this.playLeaveAnimation();
this.playEnterAnimation();
}
finishAnimations() {
let animationWasStarted = false;
if (this.previousSlide && this.previousSlide.previous) {
this.previousSlide.previous = false;
}
if (this.leaveAnimationPlayer) {
animationWasStarted = true;
this.leaveAnimationPlayer.finish();
}
if (this.enterAnimationPlayer) {
animationWasStarted = true;
this.enterAnimationPlayer.finish();
}
return animationWasStarted;
}
getAnimation() {
let duration;
if (this.newDuration) {
duration = this.animationPosition ? this.animationPosition * this.newDuration : this.newDuration;
}
else {
duration = this.animationPosition ? this.animationPosition * this.animationDuration : this.animationDuration;
}
switch (this.animationType) {
case CarouselAnimationType.slide:
const trans = this.animationPosition ? this.animationPosition * 100 : 100;
return {
enterAnimation: useAnimation(slideInLeft, {
params: {
delay: '0s',
duration: `${duration}ms`,
endOpacity: 1,
startOpacity: 1,
fromPosition: `translateX(${this.currentSlide.direction === 1 ? trans : -trans}%)`,
toPosition: 'translateX(0%)'
}
}),
leaveAnimation: useAnimation(slideInLeft, {
params: {
delay: '0s',
duration: `${duration}ms`,
endOpacity: 1,
startOpacity: 1,
fromPosition: `translateX(0%)`,
toPosition: `translateX(${this.currentSlide.direction === 1 ? -trans : trans}%)`,
}
})
};
case CarouselAnimationType.fade:
return {
enterAnimation: useAnimation(fadeIn, { params: { duration: `${duration}ms`, startOpacity: `${this.animationPosition}` } }),
leaveAnimation: null
};
}
return {
enterAnimation: null,
leaveAnimation: null
};
}
playEnterAnimation() {
if (!this.getAnimation().enterAnimation) {
return;
}
const animationBuilder = this.builder.build(this.getAnimation().enterAnimation);
this.enterAnimationPlayer = animationBuilder.create(this.currentSlide.nativeElement);
this.enterAnimationPlayer.onDone(() => {
if (this.enterAnimationPlayer) {
this.enterAnimationPlayer.reset();
this.enterAnimationPlayer = null;
}
this.animationPosition = 0;
this.newDuration = 0;
this.previousSlide.previous = false;
});
this.previousSlide.previous = true;
this.enterAnimationPlayer.play();
}
playLeaveAnimation() {
if (!this.getAnimation().leaveAnimation) {
return;
}
const animationBuilder = this.builder.build(this.getAnimation().leaveAnimation);
this.leaveAnimationPlayer = animationBuilder.create(this.previousSlide.nativeElement);
this.leaveAnimationPlayer.onDone(() => {
if (this.leaveAnimationPlayer) {
this.leaveAnimationPlayer.reset();
this.leaveAnimationPlayer = null;
}
this.animationPosition = 0;
this.newDuration = 0;
});
this.leaveAnimationPlayer.play();
}
initSlides(change) {
const diff = this.differ.diff(change.toArray());
if (diff) {
this.slides.reduce((any, c, ind) => c.index = ind, 0); // reset slides indexes
diff.forEachAddedItem((record) => {
const slide = record.item;
this.onSlideAdded.emit({ carousel: this, slide });
if (slide.active) {
this.currentSlide = slide;
}
slide.activeChange.pipe(takeUntil(this.unsubscriber(slide))).subscribe(() => this.onSlideActivated(slide));
});
diff.forEachRemovedItem((record) => {
const slide = record.item;
this.onSlideRemoved.emit({ carousel: this, slide });
if (slide.active) {
slide.active = false;
this.currentSlide = this.get(slide.index < this.total ? slide.index : this.total - 1);
}
});
this.updateSlidesSelection();
}
}
updateSlidesSelection() {
requestAnimationFrame(() => {
if (this.currentSlide) {
this.currentSlide.active = true;
const activeSlides = this.slides.filter(slide => slide.active && slide.index !== this.currentSlide.index);
activeSlides.forEach(slide => { slide.active = false; });
}
else if (this.total) {
this.slides.first.active = true;
}
this.play();
});
}
/** @hidden */
get getIndicatorTemplate() {
if (this.indicatorTemplate) {
return this.indicatorTemplate;
}
return this.defaultIndicator;
}
/** @hidden */
get getNextButtonTemplate() {
if (this.nextButtonTemplate) {
return this.nextButtonTemplate;
}
return this.defaultNextButton;
}
/** @hidden */
get getPrevButtonTemplate() {
if (this.prevButtonTemplate) {
return this.prevButtonTemplate;
}
return this.defaultPrevButton;
}
/** @hidden */
setAriaLabel(slide) {
return `Item ${slide.index + 1} of ${this.total}`;
}
/** @hidden */
get indicatorsOrientationClass() {
return `igx-carousel-indicators--${this.indicatorsOrientation}`;
}
/** @hidden */
get showIndicators() {
return this.total <= this.maximumIndicatorsCount && this.total > 0;
}
/** @hidden */
get showIndicatorsLabel() {
return this.total > this.maximumIndicatorsCount;
}
/** @hidden */
get getCarouselLabel() {
return `${this.current + 1} ${this.resourceStrings.igx_carousel_of} ${this.total}`;
}
/**
* Returns the total number of `slides` in the carousel.
* ```typescript
* let slideCount = this.carousel.total;
* ```
* @memberOf IgxCarouselComponent
*/
get total() {
return this.slides.length;
}
/**
* The index of the slide being currently shown.
* ```typescript
* let currentSlideNumber = this.carousel.current;
* ```
* @memberOf IgxCarouselComponent
*/
get current() {
return !this.currentSlide ? 0 : this.currentSlide.index;
}
getNextIndex() {
return (this.current + 1) % this.total;
}
getPrevIndex() {
return this.current - 1 < 0 ? this.total - 1 : this.current - 1;
}
/**
* Returns a boolean indicating if the carousel is playing.
* ```typescript
* let isPlaying = this.carousel.isPlaying;
* ```
* @memberOf IgxCarouselComponent
*/
get isPlaying() {
return this.playing;
}
/**
* Returns а boolean indicating if the carousel is destroyed.
* ```typescript
* let isDestroyed = this.carousel.isDestroyed;
* ```
* @memberOf IgxCarouselComponent
*/
get isDestroyed() {
return this.destroyed;
}
/**
* Returns a reference to the carousel element in the DOM.
* ```typescript
* let nativeElement = this.carousel.nativeElement;
* ```
* @memberof IgxCarouselComponent
*/
get nativeElement() {
return this.element.nativeElement;
}
/**
* Returns the slide corresponding to the provided `index` or null.
* ```typescript
* let slide1 = this.carousel.get(1);
* ```
* @memberOf IgxCarouselComponent
*/
get(index) {
return this.slides.find((slide) => slide.index === index);
}
/**
* Adds a new slide to the carousel.
* ```typescript
* this.carousel.add(newSlide);
* ```
* @memberOf IgxCarouselComponent
*/
add(slide) {
const newSlides = this.slides.toArray();
newSlides.push(slide);
this.slides.reset(newSlides);
this.slides.notifyOnChanges();
}
/**
* Removes a slide from the carousel.
* ```typescript
* this.carousel.remove(slide);
* ```
* @memberOf IgxCarouselComponent
*/
remove(slide) {
if (slide && slide === this.get(slide.index)) { // check if the requested slide for delete is present in the carousel
const newSlides = this.slides.toArray();
newSlides.splice(slide.index, 1);
this.slides.reset(newSlides);
this.slides.notifyOnChanges();
}
}
/**
* Kicks in a transition for a given slide with a given `direction`.
* ```typescript
* this.carousel.select(this.carousel.get(2), Direction.NEXT);
* ```
* @memberOf IgxCarouselComponent
*/
select(slide, direction = Direction.NONE) {
if (slide && slide !== this.currentSlide) {
slide.direction = direction;
slide.active = true;
}
}
/**
* Transitions to the next slide in the carousel.
* ```typescript
* this.carousel.next();
* ```
* @memberOf IgxCarouselComponent
*/
next() {
const index = this.getNextIndex();
if (index === 0 && !this.loop) {
this.stop();
return;
}
return this.select(this.get(index), Direction.NEXT);
}
/**
* Transitions to the previous slide in the carousel.
* ```typescript
* this.carousel.prev();
* ```
* @memberOf IgxCarouselComponent
*/
prev() {
const index = this.getPrevIndex();
if (!this.loop && index === this.total - 1) {
this.stop();
return;
}
return this.select(this.get(index), Direction.PREV);
}
/**
* Resumes playing of the carousel if in paused state.
* No operation otherwise.
* ```typescript
* this.carousel.play();
* }
* ```
* @memberOf IgxCarouselComponent
*/
play() {
if (!this.playing) {
this.playing = true;
this.onCarouselPlaying.emit(this);
this.restartInterval();
this.stoppedByInteraction = false;
}
}
/**
* Stops slide transitions if the `pause` option is set to `true`.
* No operation otherwise.
* ```typescript
* this.carousel.stop();
* }
* ```
* @memberOf IgxCarouselComponent
*/
stop() {
if (this.pause) {
this.playing = false;
this.onCarouselPaused.emit(this);
this.resetInterval();
}
}
resetInterval() {
if (this.lastInterval) {
clearInterval(this.lastInterval);
this.lastInterval = null;
}
}
restartInterval() {
this.resetInterval();
if (!isNaN(this.interval) && this.interval > 0 && this.platformUtil.isBrowser) {
this.lastInterval = setInterval(() => {
const tick = +this.interval;
if (this.playing && this.total && !isNaN(tick) && tick > 0) {
this.next();
}
else {
this.stop();
}
}, this.interval);
}
}
/** @hidden */
get nextButtonDisabled() {
return !this.loop && this.current === (this.total - 1);
}
/** @hidden */
get prevButtonDisabled() {
return !this.loop && this.current === 0;
}
/** @hidden */
onKeydownArrowRight(event) {
if (this.keyboardSupport) {
event.preventDefault();
this.next();
requestAnimationFrame(() => this.nativeElement.focus());
}
}
/** @hidden */
onKeydownArrowLeft(event) {
if (this.keyboardSupport) {
event.preventDefault();
this.prev();
requestAnimationFrame(() => this.nativeElement.focus());
}
}
/** @hidden */
onTap(event) {
// play pause only when tap on slide
if (event.target && event.target.classList.contains('igx-slide')) {
if (this.isPlaying) {
if (this.pause) {
this.stoppedByInteraction = true;
}
this.stop();
}
else if (this.stoppedByInteraction) {
this.play();
}
}
}
/** @hidden */
onKeydownHome(event) {
if (this.keyboardSupport && this.slides.length > 0) {
event.preventDefault();
this.slides.first.active = true;
requestAnimationFrame(() => this.nativeElement.focus());
}
}
/** @hidden */
onKeydownEnd(event) {
if (this.keyboardSupport && this.slides.length > 0) {
event.preventDefault();
this.slides.last.active = true;
requestAnimationFrame(() => this.nativeElement.focus());
}
}
/** @hidden */
onMouseEnter() {
if (this.pause && this.isPlaying) {
this.stoppedByInteraction = true;
}
this.stop();
}
/** @hidden */
onMouseLeave() {
if (this.stoppedByInteraction) {
this.play();
}
}
/** @hidden */
onPanLeft(event) {
this.pan(event);
}
/** @hidden */
onPanRight(event) {
this.pan(event);
}
resetSlideStyles(slide) {
slide.nativeElement.style.transform = '';
slide.nativeElement.style.opacity = '';
}
pan(event) {
const slideWidth = this.currentSlide.nativeElement.offsetWidth;
const panOffset = (slideWidth / 1000);
const deltaX = event.deltaX;
const index = deltaX < 0 ? this.getNextIndex() : this.getPrevIndex();
const offset = deltaX < 0 ? slideWidth + deltaX : -slideWidth + deltaX;
if (!this.gesturesSupport || event.isFinal || Math.abs(deltaX) + panOffset >= slideWidth) {
return;
}
if (!this.loop && ((this.current === 0 && deltaX > 0) || (this.current === this.total - 1 && deltaX < 0))) {
this.incomingSlide = null;
return;
}
event.preventDefault();
if (this.isPlaying) {
this.stoppedByInteraction = true;
this.stop();
}
this.finishAnimations();
if (this.incomingSlide) {
if (index !== this.incomingSlide.index) {
this.resetSlideStyles(this.incomingSlide);
this.incomingSlide.previous = false;
this.incomingSlide = this.get(index);
}
}
else {
this.incomingSlide = this.get(index);
}
this.incomingSlide.previous = true;
if (this.animationType === CarouselAnimationType.fade) {
this.currentSlide.nativeElement.style.opacity = `${Math.abs(offset) / slideWidth}`;
}
else {
this.currentSlide.nativeElement.style.transform = `translateX(${deltaX}px)`;
this.incomingSlide.nativeElement.style.transform = `translateX(${offset}px)`;
}
}
/**
* @hidden
*/
onPanEnd(event) {
if (!this.gesturesSupport) {
return;
}
event.preventDefault();
const slideWidth = this.currentSlide.nativeElement.offsetWidth;
const panOffset = (slideWidth / 1000);
const deltaX = Math.abs(event.deltaX) + panOffset < slideWidth ? Math.abs(event.deltaX) : slideWidth - panOffset;
const velocity = Math.abs(event.velocity);
this.resetSlideStyles(this.currentSlide);
if (this.incomingSlide) {
this.resetSlideStyles(this.incomingSlide);
if (slideWidth / 2 < deltaX || velocity > 1) {
this.incomingSlide.direction = event.deltaX < 0 ? Direction.NEXT : Direction.PREV;
this.incomingSlide.previous = false;
this.animationPosition = this.animationType === CarouselAnimationType.fade ?
deltaX / slideWidth : (slideWidth - deltaX) / slideWidth;
if (velocity > 1) {
this.newDuration = this.animationDuration / velocity;
}
this.incomingSlide.active = true;
}
else {
this.currentSlide.direction = event.deltaX > 0 ? Direction.NEXT : Direction.PREV;
this.previousSlide = this.incomingSlide;
this.previousSlide.previous = true;
this.animationPosition = this.animationType === CarouselAnimationType.fade ?
Math.abs((slideWidth - deltaX) / slideWidth) : deltaX / slideWidth;
this.playAnimations();
}
}
if (this.stoppedByInteraction) {
this.play();
}
}
};
IgxCarouselComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: IterableDiffers },
{ type: AnimationBuilder },
{ type: PlatformUtil }
];
__decorate([
HostBinding('attr.role'),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "role", void 0);
__decorate([
HostBinding('attr.id'),
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "id", void 0);
__decorate([
HostBinding('attr.aria-label'),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "ariaLabel", void 0);
__decorate([
HostBinding('attr.tabindex'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxCarouselComponent.prototype, "tabIndex", null);
__decorate([
HostBinding('class.igx-carousel'),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "cssClass", void 0);
__decorate([
HostBinding('style.touch-action'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxCarouselComponent.prototype, "touchAction", null);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "loop", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "pause", void 0);
__decorate([
Input(),
__metadata("design:type", Number),
__metadata("design:paramtypes", [Number])
], IgxCarouselComponent.prototype, "interval", null);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "navigation", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "keyboardSupport", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "gesturesSupport", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "maximumIndicatorsCount", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], IgxCarouselComponent.prototype, "indicatorsOrientation", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "animationType", void 0);
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [Object])
], IgxCarouselComponent.prototype, "resourceStrings", null);
__decorate([
ViewChild('defaultIndicator', { read: TemplateRef, static: true }),
__metadata("design:type", TemplateRef)
], IgxCarouselComponent.prototype, "defaultIndicator", void 0);
__decorate([
ViewChild('defaultNextButton', { read: TemplateRef, static: true }),
__metadata("design:type", TemplateRef)
], IgxCarouselComponent.prototype, "defaultNextButton", void 0);
__decorate([
ViewChild('defaultPrevButton', { read: TemplateRef, static: true }),
__metadata("design:type", TemplateRef)
], IgxCarouselComponent.prototype, "defaultPrevButton", void 0);
__decorate([
ContentChild(IgxCarouselIndicatorDirective, { read: TemplateRef, static: false }),
__metadata("design:type", TemplateRef)
], IgxCarouselComponent.prototype, "indicatorTemplate", void 0);
__decorate([
ContentChild(IgxCarouselNextButtonDirective, { read: TemplateRef, static: false }),
__metadata("design:type", TemplateRef)
], IgxCarouselComponent.prototype, "nextButtonTemplate", void 0);
__decorate([
ContentChild(IgxCarouselPrevButtonDirective, { read: TemplateRef, static: false }),
__metadata("design:type", TemplateRef)
], IgxCarouselComponent.prototype, "prevButtonTemplate", void 0);
__decorate([
ContentChildren(IgxSlideComponent),
__metadata("design:type", QueryList)
], IgxCarouselComponent.prototype, "slides", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "onSlideChanged", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "onSlideAdded", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "onSlideRemoved", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "onCarouselPaused", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxCarouselComponent.prototype, "onCarouselPlaying", void 0);
__decorate([
HostListener('keydown.arrowright', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onKeydownArrowRight", null);
__decorate([
HostListener('keydown.arrowleft', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onKeydownArrowLeft", null);
__decorate([
HostListener('tap', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onTap", null);
__decorate([
HostListener('keydown.home', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onKeydownHome", null);
__decorate([
HostListener('keydown.end', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onKeydownEnd", null);
__decorate([
HostListener('mouseenter'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onMouseEnter", null);
__decorate([
HostListener('mouseleave'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onMouseLeave", null);
__decorate([
HostListener('panleft', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onPanLeft", null);
__decorate([
HostListener('panright', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onPanRight", null);
__decorate([
HostListener('panend', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxCarouselComponent.prototype, "onPanEnd", null);
IgxCarouselComponent = __decorate([
Component({
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: CarouselHammerConfig
}
],
selector: 'igx-carousel',
template: "<ng-template #defaultIndicator let-slide>\n <div class=\"igx-nav-dot\"\n [class.igx-nav-dot--active]=\"slide.active\"\n >\n </div>\n</ng-template>\n\n<ng-template #defaultNextButton let-disabled>\n <a class=\"igx-nav-arrow\"\n [class.igx-nav-arrow--disabled]=\"disabled\"\n >\n <igx-icon fontSet=\"material\">arrow_forward</igx-icon>\n </a>\n</ng-template>\n\n<ng-template #defaultPrevButton let-disabled>\n <a class=\"igx-nav-arrow\"\n [class.igx-nav-arrow--disabled]=\"disabled\"\n >\n <igx-icon fontSet=\"material\">arrow_back</igx-icon>\n </a>\n</ng-template>\n\n\n<div *ngIf=\"showIndicators\" [ngClass]=\"indicatorsOrientationClass\">\n <div *ngFor=\"let slide of slides\"\n class=\"igx-carousel-indicators__indicator\"\n (click)=\"select(slide)\"\n [attr.aria-label]=\"setAriaLabel(slide)\"\n [attr.aria-selected]=\"slide.active\">\n <ng-container *ngTemplateOutlet=\"getIndicatorTemplate; context: {$implicit: slide};\"></ng-container>\n </div>\n</div>\n\n<div *ngIf=\"showIndicatorsLabel\" [ngClass]=\"indicatorsOrientationClass\">\n <span class=\"igx-carousel__label\">{{getCarouselLabel}}</span>\n</div>\n\n<div class=\"igx-carousel__inner\" role=\"list\">\n <ng-content></ng-content>\n</div>\n\n<div *ngIf=\"navigation && slides.length\" role=\"button\" tabindex=\"0\" class=\"igx-carousel__arrow--prev\" (click)=\"prev()\">\n <ng-container *ngTemplateOutlet=\"getPrevButtonTemplate; context: {$implicit: prevButtonDisabled};\"></ng-container>\n</div>\n\n<div *ngIf=\"navigation && slides.length\" role=\"button\" tabindex=\"0\" class=\"igx-carousel__arrow--next\" (click)=\"next()\">\n <ng-container *ngTemplateOutlet=\"getNextButtonTemplate; context: {$implicit: nextButtonDisabled};\"></ng-container>\n</div>\n\n\n\n",
styles: [`
:host {
display: block;
outline-style: none;
}`]
}),
__metadata("design:paramtypes", [ElementRef, IterableDiffers,
AnimationBuilder, PlatformUtil])
], IgxCarouselComponent);
export { IgxCarouselComponent };
/**
* @hidden
*/
let IgxCarouselModule = class IgxCarouselModule {
};
IgxCarouselModule = __decorate([
NgModule({
declarations: [
IgxCarouselComponent,
IgxSlideComponent,
IgxCarouselIndicatorDirective,
IgxCarouselNextButtonDirective,
IgxCarouselPrevButtonDirective
],
exports: [
IgxCarouselComponent,
IgxSlideComponent,
IgxCarouselIndicatorDirective,
IgxCarouselNextButtonDirective,
IgxCarouselPrevButtonDirective
],
imports: [CommonModule, IgxIconModule]
})
], IgxCarouselModule);
export { IgxCarouselModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9jYXJvdXNlbC9jYXJvdXNlbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixLQUFLLEVBQ0wsUUFBUSxFQUNSLFNBQVMsRUFDVCxNQUFNLEVBQ04sZUFBZSxFQUNmLFNBQVMsRUFDVCxjQUFjLEVBQ2QsZUFBZSxFQUNmLGdCQUFnQixFQUNoQixvQkFBb0IsRUFDcEIsV0FBVyxFQUNYLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSw4QkFBOEIsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3RJLE9BQU8sRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsZUFBZSxFQUFFLDBCQUEwQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEgsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFakUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sd0JB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