UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

1 lines 85 kB
{"version":3,"file":"igniteui-angular-carousel.mjs","sources":["../../../projects/igniteui-angular/carousel/src/carousel/enums.ts","../../../projects/igniteui-angular/carousel/src/carousel/carousel-base.ts","../../../projects/igniteui-angular/carousel/src/carousel/carousel.directives.ts","../../../projects/igniteui-angular/carousel/src/carousel/slide.component.ts","../../../projects/igniteui-angular/carousel/src/carousel/slide.component.html","../../../projects/igniteui-angular/carousel/src/carousel/carousel.component.ts","../../../projects/igniteui-angular/carousel/src/carousel/carousel.component.html","../../../projects/igniteui-angular/carousel/src/carousel/public_api.ts","../../../projects/igniteui-angular/carousel/src/carousel/carousel.module.ts","../../../projects/igniteui-angular/carousel/src/igniteui-angular-carousel.ts"],"sourcesContent":["\nexport const CarouselAnimationType = {\n none: 'none',\n slide: 'slide',\n fade: 'fade'\n} as const;\nexport type CarouselAnimationType = (typeof CarouselAnimationType)[keyof typeof CarouselAnimationType];\n\nexport const CarouselIndicatorsOrientation = {\n /**\n * @deprecated in version 19.1.0. Use `end` instead.\n */\n bottom: 'bottom',\n /**\n * @deprecated in version 19.1.0. Use `start` instead.\n */\n top: 'top',\n start: 'start',\n end: 'end'\n} as const;\nexport type CarouselIndicatorsOrientation = (typeof CarouselIndicatorsOrientation)[keyof typeof CarouselIndicatorsOrientation];\n","import { AnimationReferenceMetadata, useAnimation } from '@angular/animations';\nimport { ChangeDetectorRef, Directive, EventEmitter, inject, OnDestroy } from '@angular/core';\nimport { IgxAngularAnimationService } from 'igniteui-angular/core';\nimport { AnimationPlayer, AnimationService } from 'igniteui-angular/core';\nimport { fadeIn, slideInLeft } from 'igniteui-angular/animations';\nimport { CarouselAnimationType } from './enums';\n\nexport enum CarouselAnimationDirection { NONE, NEXT, PREV }\n\nexport interface CarouselAnimationSettings {\n enterAnimation: AnimationReferenceMetadata;\n leaveAnimation: AnimationReferenceMetadata;\n}\n\n/** @hidden */\nexport interface IgxSlideComponentBase {\n direction: CarouselAnimationDirection;\n previous: boolean;\n}\n\n/** @hidden */\n@Directive()\nexport abstract class IgxCarouselComponentBase implements OnDestroy {\n private animationService = inject<AnimationService>(IgxAngularAnimationService);\n protected cdr = inject(ChangeDetectorRef);\n\n /** @hidden */\n public animationType: CarouselAnimationType = CarouselAnimationType.slide;\n\n /** @hidden @internal */\n public enterAnimationDone = new EventEmitter();\n /** @hidden @internal */\n public leaveAnimationDone = new EventEmitter();\n\n /** @hidden */\n protected currentItem: IgxSlideComponentBase;\n /** @hidden */\n protected previousItem: IgxSlideComponentBase;\n /** @hidden */\n protected enterAnimationPlayer?: AnimationPlayer;\n /** @hidden */\n protected leaveAnimationPlayer?: AnimationPlayer;\n /** @hidden */\n protected defaultAnimationDuration = 320;\n /** @hidden */\n protected animationPosition = 0;\n /** @hidden */\n protected newDuration = 0;\n /** @hidden */\n protected vertical = false;\n\n public ngOnDestroy(): void {\n if (this.enterAnimationPlayer) {\n this.enterAnimationPlayer.destroy();\n this.enterAnimationPlayer = null;\n }\n if (this.leaveAnimationPlayer) {\n this.leaveAnimationPlayer.destroy();\n this.leaveAnimationPlayer = null;\n }\n }\n\n /** @hidden */\n protected triggerAnimations() {\n if (this.animationType !== CarouselAnimationType.none) {\n if (this.animationStarted(this.leaveAnimationPlayer) || this.animationStarted(this.enterAnimationPlayer)) {\n requestAnimationFrame(() => {\n this.resetAnimations();\n this.playAnimations();\n });\n } else {\n this.playAnimations();\n }\n }\n }\n\n /** @hidden */\n protected animationStarted(animation: AnimationPlayer): boolean {\n return animation && animation.hasStarted();\n }\n\n /** @hidden */\n protected playAnimations() {\n this.playLeaveAnimation();\n this.playEnterAnimation();\n }\n\n private resetAnimations() {\n if (this.animationStarted(this.leaveAnimationPlayer)) {\n this.leaveAnimationPlayer.reset();\n this.leaveAnimationDone.emit();\n }\n\n if (this.animationStarted(this.enterAnimationPlayer)) {\n this.enterAnimationPlayer.reset();\n this.enterAnimationDone.emit();\n this.cdr.markForCheck();\n }\n }\n\n private getAnimation(): CarouselAnimationSettings {\n let duration;\n if (this.newDuration) {\n duration = this.animationPosition ? this.animationPosition * this.newDuration : this.newDuration;\n } else {\n duration = this.animationPosition ? this.animationPosition * this.defaultAnimationDuration : this.defaultAnimationDuration;\n }\n\n const trans = this.animationPosition ? this.animationPosition * 100 : 100;\n switch (this.animationType) {\n case CarouselAnimationType.slide:\n return {\n enterAnimation: useAnimation(slideInLeft,\n {\n params: {\n delay: '0s',\n duration: `${duration}ms`,\n endOpacity: 1,\n startOpacity: 1,\n fromPosition: `${this.vertical ? 'translateY' : 'translateX'}(${this.currentItem.direction === 1 ? trans : -trans}%)`,\n toPosition: `${this.vertical ? 'translateY(0%)' : 'translateX(0%)'}`\n }\n }),\n leaveAnimation: useAnimation(slideInLeft,\n {\n params: {\n delay: '0s',\n duration: `${duration}ms`,\n endOpacity: 1,\n startOpacity: 1,\n fromPosition: `${this.vertical ? 'translateY(0%)' : 'translateX(0%)'}`,\n toPosition: `${this.vertical ? 'translateY' : 'translateX'}(${this.currentItem.direction === 1 ? -trans : trans}%)`,\n }\n })\n };\n case CarouselAnimationType.fade:\n return {\n enterAnimation: useAnimation(fadeIn,\n { params: { duration: `${duration}ms`, startOpacity: `${this.animationPosition}` } }),\n leaveAnimation: null\n };\n }\n return {\n enterAnimation: null,\n leaveAnimation: null\n };\n }\n\n private playEnterAnimation() {\n const animation = this.getAnimation().enterAnimation;\n if (!animation) {\n return;\n }\n\n this.enterAnimationPlayer = this.animationService.buildAnimation(animation, this.getCurrentElement());\n this.enterAnimationPlayer.animationEnd.subscribe(() => {\n // TODO: animation may never end. Find better way to clean up the player\n if (this.enterAnimationPlayer) {\n this.enterAnimationPlayer.destroy();\n this.enterAnimationPlayer = null;\n }\n this.animationPosition = 0;\n this.newDuration = 0;\n this.previousItem.previous = false;\n this.enterAnimationDone.emit();\n this.cdr.markForCheck();\n });\n this.previousItem.previous = true;\n this.enterAnimationPlayer.play();\n }\n\n private playLeaveAnimation() {\n const animation = this.getAnimation().leaveAnimation;\n if (!animation) {\n return;\n }\n\n this.leaveAnimationPlayer = this.animationService.buildAnimation(animation, this.getPreviousElement());\n this.leaveAnimationPlayer.animationEnd.subscribe(() => {\n // TODO: animation may never end. Find better way to clean up the player\n if (this.leaveAnimationPlayer) {\n this.leaveAnimationPlayer.destroy();\n this.leaveAnimationPlayer = null;\n }\n this.animationPosition = 0;\n this.newDuration = 0;\n this.leaveAnimationDone.emit();\n });\n this.leaveAnimationPlayer.play();\n }\n\n protected abstract getPreviousElement(): HTMLElement;\n\n protected abstract getCurrentElement(): HTMLElement;\n}\n","import { Directive } from '@angular/core';\n\n@Directive({\n selector: '[igxCarouselIndicator]',\n standalone: true\n})\nexport class IgxCarouselIndicatorDirective {\n}\n\n@Directive({\n selector: '[igxCarouselNextButton]',\n standalone: true\n})\nexport class IgxCarouselNextButtonDirective {\n}\n\n@Directive({\n selector: '[igxCarouselPrevButton]',\n standalone: true\n})\nexport class IgxCarouselPrevButtonDirective {\n}\n","import { Component, OnDestroy, Input, HostBinding, Output, EventEmitter, ElementRef, AfterContentChecked, booleanAttribute, inject } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { CarouselAnimationDirection, IgxSlideComponentBase } from './carousel-base';\n\n/**\n * A slide component that usually holds an image and/or a caption text.\n * IgxSlideComponent is usually a child component of an IgxCarouselComponent.\n *\n * ```\n * <igx-slide [input bindings] >\n * <ng-content></ng-content>\n * </igx-slide>\n * ```\n *\n * @export\n */\n@Component({\n selector: 'igx-slide',\n templateUrl: 'slide.component.html',\n standalone: true\n})\nexport class IgxSlideComponent implements AfterContentChecked, OnDestroy, IgxSlideComponentBase {\n private elementRef = inject(ElementRef);\n\n /**\n * Gets/sets the `index` of the slide inside the carousel.\n * ```html\n * <igx-carousel>\n * <igx-slide index=\"1\"></igx-slide>\n * <igx-carousel>\n * ```\n *\n * @memberOf IgxSlideComponent\n */\n @Input() public index: number;\n\n /**\n * Gets/sets the target `direction` for the slide.\n * ```html\n * <igx-carousel>\n * <igx-slide direction=\"NEXT\"></igx-slide>\n * <igx-carousel>\n * ```\n *\n * @memberOf IgxSlideComponent\n */\n @Input() public direction: CarouselAnimationDirection;\n\n @Input()\n public total: number;\n\n /**\n * Returns the `tabIndex` of the slide component.\n * ```typescript\n * let tabIndex = this.carousel.tabIndex;\n * ```\n *\n * @memberof IgxSlideComponent\n * @deprecated in version 19.2.0.\n */\n @HostBinding('attr.tabindex')\n public get tabIndex() {\n return this.active ? 0 : null;\n }\n\n /**\n * @hidden\n */\n @HostBinding('attr.id')\n public id: string;\n\n /**\n * Returns the `role` of the slide component.\n * By default is set to `tabpanel`\n *\n * @memberof IgxSlideComponent\n */\n @HostBinding('attr.role')\n public tab = 'tabpanel';\n\n /** @hidden */\n @HostBinding('attr.aria-labelledby')\n public ariaLabelledBy;\n\n /**\n * Returns the class of the slide component.\n * ```typescript\n * let class = this.slide.cssClass;\n * ```\n *\n * @memberof IgxSlideComponent\n */\n @HostBinding('class.igx-slide')\n public cssClass = 'igx-slide';\n\n /**\n * Gets/sets the `active` state of the slide.\n * ```html\n * <igx-carousel>\n * <igx-slide [active] =\"false\"></igx-slide>\n * <igx-carousel>\n * ```\n *\n * Two-way data binding.\n * ```html\n * <igx-carousel>\n * <igx-slide [(active)] =\"model.isActive\"></igx-slide>\n * <igx-carousel>\n * ```\n *\n * @memberof IgxSlideComponent\n */\n @HostBinding('class.igx-slide--current')\n @Input({ transform: booleanAttribute })\n public get active(): boolean {\n return this._active;\n }\n\n public set active(value) {\n this._active = value;\n this.activeChange.emit(this._active);\n }\n\n @HostBinding('class.igx-slide--previous')\n @Input({ transform: booleanAttribute }) public previous = false;\n\n /**\n * @hidden\n */\n @Output() public activeChange = new EventEmitter<boolean>();\n\n private _active = false;\n private _destroy$ = new Subject<boolean>();\n\n /**\n * Returns a reference to the carousel element in the DOM.\n * ```typescript\n * let nativeElement = this.slide.nativeElement;\n * ```\n *\n * @memberof IgxSlideComponent\n */\n public get nativeElement() {\n return this.elementRef.nativeElement;\n }\n\n /**\n * @hidden\n */\n public get isDestroyed(): Subject<boolean> {\n return this._destroy$;\n }\n\n public ngAfterContentChecked() {\n this.id = `panel-${this.index}`;\n this.ariaLabelledBy = `tab-${this.index}-${this.total}`;\n }\n\n /**\n * @hidden\n */\n public ngOnDestroy() {\n this._destroy$.next(true);\n this._destroy$.complete();\n }\n}\n","<ng-content></ng-content>\n","import { NgClass, NgTemplateOutlet } from '@angular/common';\nimport { AfterContentInit, Component, ContentChild, ContentChildren, ElementRef, EventEmitter, HostBinding, HostListener, Injectable, Input, IterableChangeRecord, IterableDiffer, IterableDiffers, OnDestroy, Output, QueryList, TemplateRef, ViewChild, ViewChildren, booleanAttribute, DOCUMENT, inject } from '@angular/core';\nimport { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';\nimport { merge, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { CarouselResourceStringsEN, ICarouselResourceStrings, ɵIgxDirectionality } from 'igniteui-angular/core';\nimport { first, IBaseEventArgs, last, PlatformUtil } from 'igniteui-angular/core';\nimport { CarouselAnimationDirection, IgxCarouselComponentBase } from './carousel-base';\nimport { IgxCarouselIndicatorDirective, IgxCarouselNextButtonDirective, IgxCarouselPrevButtonDirective } from './carousel.directives';\nimport { IgxSlideComponent } from './slide.component';\nimport { IgxIconComponent } from 'igniteui-angular/icon';\nimport { IgxButtonDirective } from 'igniteui-angular/directives';\nimport { getCurrentResourceStrings } from 'igniteui-angular/core';\nimport { HammerGesturesManager } from 'igniteui-angular/core';\nimport { CarouselAnimationType, CarouselIndicatorsOrientation } from './enums';\n\nlet NEXT_ID = 0;\n\n\n@Injectable()\nexport class CarouselHammerConfig extends HammerGestureConfig {\n public override overrides = {\n pan: { direction: HammerGesturesManager.Hammer?.DIRECTION_HORIZONTAL }\n };\n}\n/**\n * **Ignite UI for Angular Carousel** -\n * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/carousel.html)\n *\n * The Ignite UI Carousel is used to browse or navigate through a collection of slides. Slides can contain custom\n * content such as images or cards and be used for things such as on-boarding tutorials or page-based interfaces.\n * It can be used as a separate fullscreen element or inside another component.\n *\n * Example:\n * ```html\n * <igx-carousel>\n * <igx-slide>\n * <h3>First Slide Header</h3>\n * <p>First slide Content</p>\n * <igx-slide>\n * <igx-slide>\n * <h3>Second Slide Header</h3>\n * <p>Second Slide Content</p>\n * </igx-carousel>\n * ```\n */\n@Component({\n providers: [\n {\n provide: HAMMER_GESTURE_CONFIG,\n useClass: CarouselHammerConfig\n }\n ],\n selector: 'igx-carousel',\n templateUrl: 'carousel.component.html',\n styles: [`\n :host {\n display: block;\n outline-style: none;\n }`],\n imports: [IgxButtonDirective, IgxIconComponent, NgClass, NgTemplateOutlet]\n})\nexport class IgxCarouselComponent extends IgxCarouselComponentBase implements OnDestroy, AfterContentInit {\n private element = inject(ElementRef);\n private iterableDiffers = inject(IterableDiffers);\n private platformUtil = inject(PlatformUtil);\n private dir = inject(ɵIgxDirectionality);\n private document = inject(DOCUMENT);\n\n\n /**\n * Sets the `id` of the carousel.\n * If not set, the `id` of the first carousel component will be `\"igx-carousel-0\"`.\n * ```html\n * <igx-carousel id=\"my-first-carousel\"></igx-carousel>\n * ```\n *\n * @memberof IgxCarouselComponent\n */\n @HostBinding('attr.id')\n @Input()\n public id = `igx-carousel-${NEXT_ID++}`;\n /**\n * Returns the `role` attribute of the carousel.\n * ```typescript\n * let carouselRole = this.carousel.role;\n * ```\n *\n * @memberof IgxCarouselComponent\n */\n @HostBinding('attr.role') public role = 'region';\n\n /** @hidden */\n @HostBinding('attr.aria-roledescription')\n public roleDescription = 'carousel';\n\n /** @hidden */\n @HostBinding('attr.aria-labelledby')\n public get labelId() {\n return this.showIndicatorsLabel ? `${this.id}-label` : null;\n }\n\n /** @hidden */\n @HostBinding('class.igx-carousel--vertical')\n\tpublic get isVertical(): boolean {\n\t\treturn this.vertical;\n\t}\n\n /**\n * Returns the class of the carousel component.\n * ```typescript\n * let class = this.carousel.cssClass;\n * ```\n *\n * @memberof IgxCarouselComponent\n */\n @HostBinding('class.igx-carousel')\n public cssClass = 'igx-carousel';\n\n /**\n * Gets the `touch-action` style of the `list item`.\n * ```typescript\n * let touchAction = this.listItem.touchAction;\n * ```\n */\n @HostBinding('style.touch-action')\n public get touchAction() {\n return this.gesturesSupport ? 'pan-y' : 'auto';\n }\n\n /**\n * Sets whether the carousel should `loop` back to the first slide after reaching the last slide.\n * Default value is `true`.\n * ```html\n * <igx-carousel [loop]=\"false\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input({ transform: booleanAttribute }) public loop = true;\n\n /**\n * Sets whether the carousel will `pause` the slide transitions on user interactions.\n * Default value is `true`.\n * ```html\n * <igx-carousel [pause]=\"false\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input({ transform: booleanAttribute }) public pause = true;\n\n /**\n * Controls whether the carousel should render the left/right `navigation` buttons.\n * Default value is `true`.\n * ```html\n * <igx-carousel [navigation]=\"false\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input({ transform: booleanAttribute }) public navigation = true;\n\n /**\n * Controls whether the carousel should render the indicators.\n * Default value is `true`.\n * ```html\n * <igx-carousel [indicators]=\"false\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input({ transform: booleanAttribute }) public indicators = true;\n\n\n /**\n * Controls whether the carousel has vertical alignment.\n * Default value is `false`.\n * ```html\n * <igx-carousel [vertical]=\"true\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input({ transform: booleanAttribute }) public override vertical = false;\n\n /**\n * Controls whether the carousel should support gestures.\n * Default value is `true`.\n * ```html\n * <igx-carousel [gesturesSupport]=\"false\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input({ transform: booleanAttribute }) public gesturesSupport = true;\n\n /**\n * Controls the maximum indexes that can be shown.\n * Default value is `10`.\n * ```html\n * <igx-carousel [maximumIndicatorsCount]=\"5\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input() public maximumIndicatorsCount = 10;\n\n /**\n * Gets/sets the display mode of carousel indicators. It can be `start` or `end`.\n * Default value is `end`.\n * ```html\n * <igx-carousel indicatorsOrientation=\"start\">\n * <igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input() public indicatorsOrientation: CarouselIndicatorsOrientation = CarouselIndicatorsOrientation.end;\n\n /**\n * Gets/sets the animation type of carousel.\n * Default value is `slide`.\n * ```html\n * <igx-carousel animationType=\"none\">\n * <igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Input() public override animationType: CarouselAnimationType = CarouselAnimationType.slide;\n\n /**\n * The custom template, if any, that should be used when rendering carousel indicators\n *\n * ```typescript\n * // Set in typescript\n * const myCustomTemplate: TemplateRef<any> = myComponent.customTemplate;\n * myComponent.carousel.indicatorTemplate = myCustomTemplate;\n * ```\n * ```html\n * <!-- Set in markup -->\n * <igx-carousel #carousel>\n * ...\n * <ng-template igxCarouselIndicator let-slide>\n * <igx-icon *ngIf=\"slide.active\">brightness_7</igx-icon>\n * <igx-icon *ngIf=\"!slide.active\">brightness_5</igx-icon>\n * </ng-template>\n * </igx-carousel>\n * ```\n */\n @ContentChild(IgxCarouselIndicatorDirective, { read: TemplateRef, static: false })\n public indicatorTemplate: TemplateRef<any> = null;\n\n /**\n * The custom template, if any, that should be used when rendering carousel next button\n *\n * ```typescript\n * // Set in typescript\n * const myCustomTemplate: TemplateRef<any> = myComponent.customTemplate;\n * myComponent.carousel.nextButtonTemplate = myCustomTemplate;\n * ```\n * ```html\n * <!-- Set in markup -->\n * <igx-carousel #carousel>\n * ...\n * <ng-template igxCarouselNextButton let-disabled>\n * <button type=\"button\" igxButton=\"fab\" igxRipple=\"white\" [disabled]=\"disabled\">\n * <igx-icon name=\"add\"></igx-icon>\n * </button>\n * </ng-template>\n * </igx-carousel>\n * ```\n */\n @ContentChild(IgxCarouselNextButtonDirective, { read: TemplateRef, static: false })\n public nextButtonTemplate: TemplateRef<any> = null;\n\n /**\n * The custom template, if any, that should be used when rendering carousel previous button\n *\n * ```typescript\n * // Set in typescript\n * const myCustomTemplate: TemplateRef<any> = myComponent.customTemplate;\n * myComponent.carousel.prevButtonTemplate = myCustomTemplate;\n * ```\n * ```html\n * <!-- Set in markup -->\n * <igx-carousel #carousel>\n * ...\n * <ng-template igxCarouselPrevButton let-disabled>\n * <button type=\"button\" igxButton=\"fab\" igxRipple=\"white\" [disabled]=\"disabled\">\n * <igx-icon name=\"remove\"></igx-icon>\n * </button>\n * </ng-template>\n * </igx-carousel>\n * ```\n */\n @ContentChild(IgxCarouselPrevButtonDirective, { read: TemplateRef, static: false })\n public prevButtonTemplate: TemplateRef<any> = null;\n\n /**\n * The collection of `slides` currently in the carousel.\n * ```typescript\n * let slides: QueryList<IgxSlideComponent> = this.carousel.slides;\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @ContentChildren(IgxSlideComponent)\n public slides: QueryList<IgxSlideComponent>;\n\n /**\n * An event that is emitted after a slide transition has happened.\n * Provides references to the `IgxCarouselComponent` and `IgxSlideComponent` as event arguments.\n * ```html\n * <igx-carousel (slideChanged)=\"slideChanged($event)\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Output() public slideChanged = new EventEmitter<ISlideEventArgs>();\n\n /**\n * An event that is emitted after a slide has been added to the carousel.\n * Provides references to the `IgxCarouselComponent` and `IgxSlideComponent` as event arguments.\n * ```html\n * <igx-carousel (slideAdded)=\"slideAdded($event)\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Output() public slideAdded = new EventEmitter<ISlideEventArgs>();\n\n /**\n * An event that is emitted after a slide has been removed from the carousel.\n * Provides references to the `IgxCarouselComponent` and `IgxSlideComponent` as event arguments.\n * ```html\n * <igx-carousel (slideRemoved)=\"slideRemoved($event)\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Output() public slideRemoved = new EventEmitter<ISlideEventArgs>();\n\n /**\n * An event that is emitted after the carousel has been paused.\n * Provides a reference to the `IgxCarouselComponent` as an event argument.\n * ```html\n * <igx-carousel (carouselPaused)=\"carouselPaused($event)\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Output() public carouselPaused = new EventEmitter<IgxCarouselComponent>();\n\n /**\n * An event that is emitted after the carousel has resumed transitioning between `slides`.\n * Provides a reference to the `IgxCarouselComponent` as an event argument.\n * ```html\n * <igx-carousel (carouselPlaying)=\"carouselPlaying($event)\"></igx-carousel>\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n @Output() public carouselPlaying = new EventEmitter<IgxCarouselComponent>();\n\n @ViewChild('defaultIndicator', { read: TemplateRef, static: true })\n private defaultIndicator: TemplateRef<any>;\n\n @ViewChild('defaultNextButton', { read: TemplateRef, static: true })\n private defaultNextButton: TemplateRef<any>;\n\n @ViewChild('defaultPrevButton', { read: TemplateRef, static: true })\n private defaultPrevButton: TemplateRef<any>;\n\n @ViewChildren('indicators', { read: ElementRef })\n private _indicators: QueryList<ElementRef<HTMLDivElement>>;\n\n /**\n * @hidden\n * @internal\n */\n public stoppedByInteraction: boolean;\n protected override currentItem: IgxSlideComponent;\n protected override previousItem: IgxSlideComponent;\n private _interval: number;\n private _resourceStrings = getCurrentResourceStrings(CarouselResourceStringsEN);\n private lastInterval: any;\n private playing: boolean;\n private destroyed: boolean;\n private destroy$ = new Subject<any>();\n private differ: IterableDiffer<IgxSlideComponent> | null = null;\n private incomingSlide: IgxSlideComponent;\n private _hasKeyboardFocusOnIndicators = false;\n\n /**\n * An accessor that sets the resource strings.\n * By default it uses EN resources.\n */\n @Input()\n public set resourceStrings(value: ICarouselResourceStrings) {\n this._resourceStrings = Object.assign({}, this._resourceStrings, value);\n }\n\n /**\n * An accessor that returns the resource strings.\n */\n public get resourceStrings(): ICarouselResourceStrings {\n return this._resourceStrings;\n }\n\n /** @hidden */\n public get getIndicatorTemplate(): TemplateRef<any> {\n if (this.indicatorTemplate) {\n return this.indicatorTemplate;\n }\n return this.defaultIndicator;\n }\n\n /** @hidden */\n public get getNextButtonTemplate(): TemplateRef<any> {\n if (this.nextButtonTemplate) {\n return this.nextButtonTemplate;\n }\n\n return this.defaultNextButton\n }\n\n /** @hidden */\n public get getPrevButtonTemplate(): TemplateRef<any> {\n if (this.prevButtonTemplate) {\n return this.prevButtonTemplate;\n }\n\n return this.defaultPrevButton\n }\n\n /** @hidden */\n public get indicatorsClass() {\n return {\n ['igx-carousel-indicators--focused']: this._hasKeyboardFocusOnIndicators,\n [`igx-carousel-indicators--${this.getIndicatorsClass()}`]: true\n };\n }\n\n /** @hidden */\n public get showIndicators(): boolean {\n return this.indicators && this.total <= this.maximumIndicatorsCount && this.total > 0;\n }\n\n /** @hidden */\n public get showIndicatorsLabel(): boolean {\n return this.indicators && this.total > this.maximumIndicatorsCount;\n }\n\n /** @hidden */\n public get getCarouselLabel() {\n return `${this.current + 1} ${this.resourceStrings.igx_carousel_of} ${this.total}`;\n }\n\n /**\n * Returns the total number of `slides` in the carousel.\n * ```typescript\n * let slideCount = this.carousel.total;\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public get total(): number {\n return this.slides?.length;\n }\n\n /**\n * The index of the slide being currently shown.\n * ```typescript\n * let currentSlideNumber = this.carousel.current;\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public get current(): number {\n return !this.currentItem ? 0 : this.currentItem.index;\n }\n\n /**\n * Returns a boolean indicating if the carousel is playing.\n * ```typescript\n * let isPlaying = this.carousel.isPlaying;\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public get isPlaying(): boolean {\n return this.playing;\n }\n\n /**\n * Returns а boolean indicating if the carousel is destroyed.\n * ```typescript\n * let isDestroyed = this.carousel.isDestroyed;\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public get isDestroyed(): boolean {\n return this.destroyed;\n }\n /**\n * Returns a reference to the carousel element in the DOM.\n * ```typescript\n * let nativeElement = this.carousel.nativeElement;\n * ```\n *\n * @memberof IgxCarouselComponent\n */\n public get nativeElement(): any {\n return this.element.nativeElement;\n }\n\n /**\n * Returns the time `interval` in milliseconds before the slide changes.\n * ```typescript\n * let timeInterval = this.carousel.interval;\n * ```\n *\n * @memberof IgxCarouselComponent\n */\n @Input()\n public get interval(): number {\n return this._interval;\n }\n\n /**\n * Sets the time `interval` in milliseconds before the slide changes.\n * If not set, the carousel will not change `slides` automatically.\n * ```html\n * <igx-carousel [interval]=\"1000\"></igx-carousel>\n * ```\n *\n * @memberof IgxCarouselComponent\n */\n public set interval(value: number) {\n this._interval = +value;\n this.restartInterval();\n }\n\n constructor() {\n super();\n this.differ = this.iterableDiffers.find([]).create(null);\n }\n\n /** @hidden */\n @HostListener('tap', ['$event'])\n public onTap(event) {\n // play pause only when tap on slide\n if (event.target && event.target.classList.contains('igx-slide')) {\n if (this.isPlaying) {\n if (this.pause) {\n this.stoppedByInteraction = true;\n }\n this.stop();\n } else if (this.stoppedByInteraction) {\n this.play();\n }\n }\n }\n\n /** @hidden */\n @HostListener('mouseenter')\n public onMouseEnter() {\n if (this.pause && this.isPlaying) {\n this.stoppedByInteraction = true;\n }\n this.stop();\n }\n\n /** @hidden */\n @HostListener('mouseleave')\n public onMouseLeave() {\n if (this.stoppedByInteraction) {\n this.play();\n }\n }\n\n /** @hidden */\n @HostListener('panleft', ['$event'])\n public onPanLeft(event) {\n if (!this.vertical) {\n this.pan(event);\n }\n }\n\n /** @hidden */\n @HostListener('panright', ['$event'])\n public onPanRight(event) {\n if (!this.vertical) {\n this.pan(event);\n }\n }\n\n /** @hidden */\n @HostListener('panup', ['$event'])\n public onPanUp(event) {\n if (this.vertical) {\n this.pan(event);\n }\n }\n\n /** @hidden */\n @HostListener('pandown', ['$event'])\n public onPanDown(event) {\n if (this.vertical) {\n this.pan(event);\n }\n }\n\n /**\n * @hidden\n */\n @HostListener('panend', ['$event'])\n public onPanEnd(event) {\n if (!this.gesturesSupport) {\n return;\n }\n event.preventDefault();\n\n const slideSize = this.vertical\n ? this.currentItem.nativeElement.offsetHeight\n : this.currentItem.nativeElement.offsetWidth;\n const panOffset = (slideSize / 1000);\n const eventDelta = this.vertical ? event.deltaY : event.deltaX;\n const delta = Math.abs(eventDelta) + panOffset < slideSize ? Math.abs(eventDelta) : slideSize - panOffset;\n const velocity = Math.abs(event.velocity);\n this.resetSlideStyles(this.currentItem);\n if (this.incomingSlide) {\n this.resetSlideStyles(this.incomingSlide);\n if (slideSize / 2 < delta || velocity > 1) {\n this.incomingSlide.direction = eventDelta < 0 ? CarouselAnimationDirection.NEXT : CarouselAnimationDirection.PREV;\n this.incomingSlide.previous = false;\n\n this.animationPosition = this.animationType === CarouselAnimationType.fade ?\n delta / slideSize : (slideSize - delta) / slideSize;\n\n if (velocity > 1) {\n this.newDuration = this.defaultAnimationDuration / velocity;\n }\n this.incomingSlide.active = true;\n } else {\n this.currentItem.direction = eventDelta > 0 ? CarouselAnimationDirection.NEXT : CarouselAnimationDirection.PREV;\n this.previousItem = this.incomingSlide;\n this.previousItem.previous = true;\n this.animationPosition = this.animationType === CarouselAnimationType.fade ?\n Math.abs((slideSize - delta) / slideSize) : delta / slideSize;\n this.playAnimations();\n }\n }\n\n if (this.stoppedByInteraction) {\n this.play();\n }\n }\n\n /** @hidden */\n public ngAfterContentInit() {\n this.slides.changes\n .pipe(takeUntil(this.destroy$))\n .subscribe((change: QueryList<IgxSlideComponent>) => this.initSlides(change));\n\n this.initSlides(this.slides);\n }\n\n /** @hidden */\n public override ngOnDestroy() {\n super.ngOnDestroy();\n this.destroy$.next(true);\n this.destroy$.complete();\n this.destroyed = true;\n if (this.lastInterval) {\n clearInterval(this.lastInterval);\n }\n }\n\n /** @hidden */\n public handleKeydownPrev(event: KeyboardEvent): void {\n if (this.platformUtil.isActivationKey(event)) {\n event.preventDefault();\n this.prev();\n }\n }\n\n /** @hidden */\n public handleKeydownNext(event: KeyboardEvent): void {\n if (this.platformUtil.isActivationKey(event)) {\n event.preventDefault();\n this.next();\n }\n }\n\n /** @hidden */\n public handleKeyUp(event: KeyboardEvent): void {\n if (event.key === this.platformUtil.KEYMAP.TAB) {\n this._hasKeyboardFocusOnIndicators = true;\n }\n }\n\n /** @hidden */\n public handleFocusOut(event: FocusEvent): void {\n const target = event.relatedTarget as HTMLElement;\n\n if (!target || !target.classList.contains('igx-carousel-indicators__indicator')) {\n this._hasKeyboardFocusOnIndicators = false;\n }\n }\n\n /** @hidden */\n public handleClick(): void {\n this._hasKeyboardFocusOnIndicators = false;\n }\n\n /** @hidden */\n public handleKeydown(event: KeyboardEvent): void {\n const { key } = event;\n const slides = this.slides.toArray();\n\n switch (key) {\n case this.platformUtil.KEYMAP.ARROW_LEFT:\n this.dir.rtl ? this.next() : this.prev();\n break;\n case this.platformUtil.KEYMAP.ARROW_RIGHT:\n this.dir.rtl ? this.prev() : this.next();\n break;\n case this.platformUtil.KEYMAP.HOME:\n event.preventDefault();\n this.select(this.dir.rtl ? last(slides) : first(slides));\n break;\n case this.platformUtil.KEYMAP.END:\n event.preventDefault();\n this.select(this.dir.rtl ? first(slides) : last(slides));\n break;\n }\n\n this.indicatorsElements[this.current].nativeElement.focus();\n }\n\n /**\n * Returns the slide corresponding to the provided `index` or null.\n * ```typescript\n * let slide1 = this.carousel.get(1);\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public get(index: number): IgxSlideComponent {\n return this.slides.find((slide) => slide.index === index);\n }\n\n /**\n * Adds a new slide to the carousel.\n * ```typescript\n * this.carousel.add(newSlide);\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public add(slide: IgxSlideComponent) {\n const newSlides = this.slides.toArray();\n newSlides.push(slide);\n this.slides.reset(newSlides);\n this.slides.notifyOnChanges();\n }\n\n /**\n * Removes a slide from the carousel.\n * ```typescript\n * this.carousel.remove(slide);\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public remove(slide: IgxSlideComponent) {\n if (slide && slide === this.get(slide.index)) { // check if the requested slide for delete is present in the carousel\n const newSlides = this.slides.toArray();\n newSlides.splice(slide.index, 1);\n this.slides.reset(newSlides);\n this.slides.notifyOnChanges();\n }\n }\n\n /**\n * Switches to the passed-in slide with a given `direction`.\n * ```typescript\n * const slide = this.carousel.get(2);\n * this.carousel.select(slide, CarouselAnimationDirection.NEXT);\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public select(slide: IgxSlideComponent, direction?: CarouselAnimationDirection): void;\n /**\n * Switches to slide by index with a given `direction`.\n * ```typescript\n * this.carousel.select(2, CarouselAnimationDirection.NEXT);\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public select(index: number, direction?: CarouselAnimationDirection): void;\n public select(slideOrIndex: IgxSlideComponent | number, direction: CarouselAnimationDirection = CarouselAnimationDirection.NONE): void {\n const slide = typeof slideOrIndex === 'number'\n ? this.get(slideOrIndex)\n : slideOrIndex;\n\n if (slide && slide !== this.currentItem) {\n slide.direction = direction;\n slide.active = true;\n }\n }\n\n /**\n * Transitions to the next slide in the carousel.\n * ```typescript\n * this.carousel.next();\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public next() {\n const index = this.getNextIndex();\n\n if (index === 0 && !this.loop) {\n this.stop();\n return;\n }\n return this.select(this.get(index), CarouselAnimationDirection.NEXT);\n }\n\n /**\n * Transitions to the previous slide in the carousel.\n * ```typescript\n * this.carousel.prev();\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public prev() {\n const index = this.getPrevIndex();\n\n if (!this.loop && index === this.total - 1) {\n this.stop();\n return;\n }\n return this.select(this.get(index), CarouselAnimationDirection.PREV);\n }\n\n /**\n * Resumes playing of the carousel if in paused state.\n * No operation otherwise.\n * ```typescript\n * this.carousel.play();\n * }\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public play() {\n if (!this.playing) {\n this.playing = true;\n this.carouselPlaying.emit(this);\n this.restartInterval();\n this.stoppedByInteraction = false;\n }\n }\n\n /**\n * Stops slide transitions if the `pause` option is set to `true`.\n * No operation otherwise.\n * ```typescript\n * this.carousel.stop();\n * }\n * ```\n *\n * @memberOf IgxCarouselComponent\n */\n public stop() {\n if (this.pause) {\n this.playing = false;\n this.carouselPaused.emit(this);\n this.resetInterval();\n }\n }\n\n protected getPreviousElement(): HTMLElement {\n return this.previousItem.nativeElement;\n }\n\n protected getCurrentElement(): HTMLElement {\n return this.currentItem.nativeElement;\n }\n\n private resetInterval() {\n if (this.lastInterval) {\n clearInterval(this.lastInterval);\n this.lastInterval = null;\n }\n }\n\n private restartInterval() {\n this.resetInterval();\n\n if (!isNaN(this.interval) && this.interval > 0 && this.platformUtil.isBrowser) {\n this.lastInterval = setInterval(() => {\n const tick = +this.interval;\n if (this.playing && this.total && !isNaN(tick) && tick > 0) {\n this.next();\n } else {\n this.stop();\n }\n }, this.interval);\n }\n }\n\n /** @hidden */\n public get nextButtonDisabled() {\n return !this.loop && this.current === (this.total - 1);\n }\n\n /** @hidden */\n public get prevButtonDisabled() {\n return !this.loop && this.current === 0;\n }\n\n private get indicatorsElements() {\n return this._indicators.toArray();\n }\n\n private getIndicatorsClass(): string {\n switch (this.indicatorsOrientation) {\n case CarouselIndicatorsOrientation.top:\n return CarouselIndicatorsOrientation.start;\n case CarouselIndicatorsOrientation.bottom:\n return CarouselIndicatorsOrientation.end;\n default:\n return this.indicatorsOrientation;\n }\n }\n\n private getNextIndex(): number {\n return (this.current + 1) % this.total;\n }\n\n private getPrevIndex(): number {\n return this.current - 1 < 0 ? this.total - 1 : this.current - 1;\n }\n\n private resetSlideStyles(slide: IgxSlideComponent) {\n slide.nativeElement.style.transform = '';\n slide.nativeElement.style.opacity = '';\n }\n\n private pan(event) {\n const slideSize = this.vertical\n ? this.currentItem.nativeElement.offsetHeight\n : this.currentItem.nativeElement.offsetWidth;\n const panOffset = (slideSize / 1000);\n const delta = this.vertical ? event.deltaY : event.deltaX;\n const index = delta < 0 ? this.getNextIndex() : this.getPrevIndex();\n const offset = delta < 0 ? slideSize + delta : -slideSize + delta;\n\n if (!this.gesturesSupport || event.isFinal || Math.abs(delta) + panOffset >= slideSize) {\n return;\n }\n\n if (!this.loop && ((this.current === 0 && delta > 0) || (this.current === this.total - 1 && delta < 0))) {\n this.incomingSlide = null;\n return;\n }\n\n event.preventDefault();\n if (this.isPlaying) {\n this.stoppedByInteraction = true;\n this.stop();\n }\n\n if (this.previousItem && this.previousItem.previous) {\n this.previousItem.previous = false;\n }\n this.finishAnimations();\n\n if (this.incomingSlide) {\n if (index !== this.incomingSlide.index) {\n this.resetSlideStyles(this.incomingSlide);\n this.incomingSlide.previous = false;\n this.incomingSlide = this.get(index);\n }\n } else {\n this.incomingSlide = this.get(index);\n }\n this.incomingSlide.previous = true;\n\n if (this.animationType === CarouselAnimationType.fade) {\n this.currentItem.nativeElement.style.opacity = `${Math.abs(offset) / slideSize}`;\n } else {\n this.currentItem.nativeElement.style.transform = this.vertical\n ? `translateY(${delta}px)`\n : `translateX(${delta}px)`;\n this.incomingSlide.nativeElement.style.transform = this.vertical\n ? `translateY(${offset}px)`\n : `translateX(${offset}px)`;\n }\n }\n\n private unsubscriber(slide: IgxSlideComponent) {\n return merge(this.destroy$, slide.isDestroyed);\n }\n\n private onSlideActivated(slide: IgxSlideComponent) {\n if (slide.active && slide !== this.currentItem) {\n if (slide.direction === CarouselAnimationDirection.NONE) {\n const newIndex = slide.index;\n slide.direction = newIndex > this.current ? CarouselAnimationDirection.NEXT : CarouselAnimationDirection.PREV;\n }\n\n if (this.currentItem) {\n if (this.previousItem && this.previousItem.previous) {\n this.previousItem.previous = false;\n }\n this.currentItem.direction = slide.direction;\n this.currentItem.active = false;\n\n this.previousItem = this.currentItem;\n this.currentItem = slide;\n this.triggerAnimations();\n } else {\n this.currentItem = slide;\n }\n this.slideChanged.emit({ carousel: this, slide });\n this.restartInterval();\n this.cdr.markForCheck();\n }\n }\n\n\n private finishAnimations() {\n if (this.animationStarted(this.leaveAnimationPlayer)) {\n this.leaveAnimationPlayer.finish();\n }\n\n if (this.animationStarted(this.enterAnimationPlayer)) {\n this.enterAnimationPlayer.finish();\n }\n }\n\n private initSlides(change: QueryList<IgxSlideComponent>) {\n const diff = this.differ.diff(change.toArray());\n if (diff) {\n this.slides.reduce((any, c, ind) => c.index = ind, 0); // reset slides indexes\n diff.forEachAddedItem((record: IterableChangeRecord<IgxSlideComponent>) => {\n const slide = record.item;\n slide.total = this.total;\n this.slideAdded.emit({ carousel: this, slide });\n if (slide.active) {\n this.currentItem = slide;\n }\n slide.activeChange.pipe(takeUntil(this.unsubscriber(slide))).subscribe(() => this.onSlideActivated(slide));\n });\n\n diff.forEachRemovedItem((record: IterableChangeRecord<IgxSlideComponent>) => {\n const slide = record.item;\n this.slideRemoved.emit({ carousel: this, slide });\n if (slide.active) {\n slide.active = false;\n this.currentItem = this.get(slide.index < this.total ? slide.index : this.total - 1);\n }\n });\n\n this.updateSlidesSelection();\n }\n }\n\n private updateSlidesSelection() {\n if (this.platformUtil.isBrowser) {\n requestAnimationFrame(() => {\n if (this.currentItem) {\n this.currentItem.active = true;\n const activeSlides = this.slides.filter(slide => slide.active && slide.index !== this.currentItem.index);\n activeSlides.forEach(slide => slide.active = false);\n } else if (this.total) {\n this.slides.first.active = true;\n }\n this.play();\n });\n }\n }\n}\n\nexport interface ISlideEventArgs extends IBaseEventArgs {\n carousel: IgxCarouselComponent;\n slide: IgxSlideComponent;\n}\n","<ng-template #defaultIndicator let-slide>\n <div class=\"igx-nav-dot\"\n [class.igx-nav-dot--active]=\"slide.active\">\n </div>\n</ng-template>\n\n<ng-template #defaultNextButton>\n <igx-icon aria-hidden=\"true\" family=\"de