ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
795 lines (783 loc) • 26.3 kB
JavaScript
import { __decorate, __metadata } from 'tslib';
import { LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
import { Platform } from '@angular/cdk/platform';
import { DOCUMENT, CommonModule } from '@angular/common';
import { Directive, ElementRef, Renderer2, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, EventEmitter, Inject, Input, NgZone, Output, ViewChild, ViewEncapsulation, NgModule } from '@angular/core';
import { isTouchEvent, InputBoolean, InputNumber } from 'ng-zorro-antd/core';
import { take, takeUntil, throttleTime } from 'rxjs/operators';
import { Subject, fromEvent } from 'rxjs';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NzCarouselContentDirective {
/**
* @param {?} elementRef
* @param {?} renderer
*/
constructor(elementRef, renderer) {
this.elementRef = elementRef;
this.renderer = renderer;
this.el = this.elementRef.nativeElement;
this._active = false;
renderer.addClass(elementRef.nativeElement, 'slick-slide');
}
/**
* @param {?} value
* @return {?}
*/
set isActive(value) {
this._active = value;
if (this.isActive) {
this.renderer.addClass(this.el, 'slick-active');
}
else {
this.renderer.removeClass(this.el, 'slick-active');
}
}
/**
* @return {?}
*/
get isActive() {
return this._active;
}
}
NzCarouselContentDirective.decorators = [
{ type: Directive, args: [{
selector: '[nz-carousel-content]',
exportAs: 'nzCarouselContent'
},] }
];
/** @nocollapse */
NzCarouselContentDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @abstract
*/
class NzCarouselBaseStrategy {
/**
* @param {?} carouselComponent
* @param {?} cdr
* @param {?} renderer
*/
constructor(carouselComponent, cdr, renderer) {
this.cdr = cdr;
this.renderer = renderer;
this.carouselComponent = carouselComponent;
}
/**
* @protected
* @return {?}
*/
get maxIndex() {
return this.length - 1;
}
/**
* @protected
* @return {?}
*/
get firstEl() {
return this.contents[0].el;
}
/**
* @protected
* @return {?}
*/
get lastEl() {
return this.contents[this.maxIndex].el;
}
/**
* Initialize dragging sequences.
* @param {?} contents
* @return {?}
*/
withCarouselContents(contents) {
// TODO: carousel and its contents should be separated.
/** @type {?} */
const carousel = (/** @type {?} */ (this.carouselComponent));
/** @type {?} */
const rect = carousel.el.getBoundingClientRect();
this.slickListEl = carousel.slickListEl;
this.slickTrackEl = carousel.slickTrackEl;
this.unitWidth = rect.width;
this.unitHeight = rect.height;
this.contents = contents ? contents.toArray() : [];
this.length = this.contents.length;
}
/**
* When user drag the carousel component.
* \@optional
* @param {?} _vector
* @return {?}
*/
dragging(_vector) { }
/**
* Destroy a scroll strategy.
* @return {?}
*/
dispose() { }
/**
* @protected
* @param {?} f
* @param {?} t
* @return {?}
*/
getFromToInBoundary(f, t) {
/** @type {?} */
const length = this.maxIndex + 1;
return { from: (f + length) % length, to: (t + length) % length };
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NzCarouselOpacityStrategy extends NzCarouselBaseStrategy {
/**
* @param {?} contents
* @return {?}
*/
withCarouselContents(contents) {
super.withCarouselContents(contents);
if (this.contents) {
this.slickTrackEl.style.width = `${this.length * this.unitWidth}px`;
this.contents.forEach((/**
* @param {?} content
* @param {?} i
* @return {?}
*/
(content, i) => {
this.renderer.setStyle(content.el, 'opacity', (/** @type {?} */ (this.carouselComponent)).activeIndex === i ? '1' : '0');
this.renderer.setStyle(content.el, 'position', 'relative');
this.renderer.setStyle(content.el, 'width', `${this.unitWidth}px`);
this.renderer.setStyle(content.el, 'left', `${-this.unitWidth * i}px`);
this.renderer.setStyle(content.el, 'transition', ['opacity 500ms ease 0s', 'visibility 500ms ease 0s']);
}));
}
}
/**
* @param {?} _f
* @param {?} _t
* @return {?}
*/
switch(_f, _t) {
const { to: t } = this.getFromToInBoundary(_f, _t);
/** @type {?} */
const complete$ = new Subject();
this.contents.forEach((/**
* @param {?} content
* @param {?} i
* @return {?}
*/
(content, i) => {
this.renderer.setStyle(content.el, 'opacity', t === i ? '1' : '0');
}));
setTimeout((/**
* @return {?}
*/
() => {
complete$.next();
complete$.complete();
}), (/** @type {?} */ (this.carouselComponent)).nzTransitionSpeed);
return complete$;
}
/**
* @return {?}
*/
dispose() {
this.contents.forEach((/**
* @param {?} content
* @return {?}
*/
(content) => {
this.renderer.setStyle(content.el, 'transition', null);
}));
super.dispose();
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NzCarouselTransformStrategy extends NzCarouselBaseStrategy {
constructor() {
super(...arguments);
this.isDragging = false;
this.isTransitioning = false;
}
/**
* @private
* @return {?}
*/
get vertical() {
return (/** @type {?} */ (this.carouselComponent)).nzVertical;
}
/**
* @return {?}
*/
dispose() {
super.dispose();
this.renderer.setStyle(this.slickTrackEl, 'transform', null);
}
/**
* @param {?} contents
* @return {?}
*/
withCarouselContents(contents) {
super.withCarouselContents(contents);
/** @type {?} */
const carousel = (/** @type {?} */ (this.carouselComponent));
/** @type {?} */
const activeIndex = carousel.activeIndex;
if (this.contents.length) {
if (this.vertical) {
this.renderer.setStyle(this.slickListEl, 'height', `${this.unitHeight}px`);
this.renderer.setStyle(this.slickTrackEl, 'height', `${this.length * this.unitHeight}px`);
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(0, ${-activeIndex * this.unitHeight}px, 0)`);
}
else {
this.renderer.setStyle(this.slickTrackEl, 'width', `${this.length * this.unitWidth}px`);
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(${-activeIndex * this.unitWidth}px, 0, 0)`);
}
this.contents.forEach((/**
* @param {?} content
* @return {?}
*/
(content) => {
this.renderer.setStyle(content.el, 'position', 'relative');
this.renderer.setStyle(content.el, 'width', `${this.unitWidth}px`);
}));
}
}
/**
* @param {?} _f
* @param {?} _t
* @return {?}
*/
switch(_f, _t) {
const { to: t } = this.getFromToInBoundary(_f, _t);
/** @type {?} */
const complete$ = new Subject();
this.renderer.setStyle(this.slickTrackEl, 'transition', 'transform 500ms ease');
if (this.vertical) {
this.verticalTransform(_f, _t);
}
else {
this.horizontalTransform(_f, _t);
}
this.isTransitioning = true;
this.isDragging = false;
setTimeout((/**
* @return {?}
*/
() => {
this.renderer.setStyle(this.slickTrackEl, 'transition', null);
this.contents.forEach((/**
* @param {?} content
* @return {?}
*/
(content) => {
this.renderer.setStyle(content.el, this.vertical ? 'top' : 'left', null);
}));
if (this.vertical) {
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(0, ${-t * this.unitHeight}px, 0)`);
}
else {
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(${-t * this.unitWidth}px, 0, 0)`);
}
this.isTransitioning = false;
complete$.next();
complete$.complete();
}), (/** @type {?} */ (this.carouselComponent)).nzTransitionSpeed);
return complete$.asObservable();
}
/**
* @param {?} _vector
* @return {?}
*/
dragging(_vector) {
if (this.isTransitioning) {
return;
}
/** @type {?} */
const activeIndex = (/** @type {?} */ (this.carouselComponent)).activeIndex;
if ((/** @type {?} */ (this.carouselComponent)).nzVertical) {
if (!this.isDragging && this.length > 2) {
if (activeIndex === this.maxIndex) {
this.prepareVerticalContext(true);
}
else if (activeIndex === 0) {
this.prepareVerticalContext(false);
}
}
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(0, ${-activeIndex * this.unitHeight + _vector.x}px, 0)`);
}
else {
if (!this.isDragging && this.length > 2) {
if (activeIndex === this.maxIndex) {
this.prepareHorizontalContext(true);
}
else if (activeIndex === 0) {
this.prepareHorizontalContext(false);
}
}
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(${-activeIndex * this.unitWidth + _vector.x}px, 0, 0)`);
}
this.isDragging = true;
}
/**
* @private
* @param {?} _f
* @param {?} _t
* @return {?}
*/
verticalTransform(_f, _t) {
const { from: f, to: t } = this.getFromToInBoundary(_f, _t);
/** @type {?} */
const needToAdjust = this.length > 2 && _t !== t;
if (needToAdjust) {
this.prepareVerticalContext(t < f);
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(0, ${-_t * this.unitHeight}px, 0)`);
}
else {
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(0, ${-t * this.unitHeight}px, 0`);
}
}
/**
* @private
* @param {?} _f
* @param {?} _t
* @return {?}
*/
horizontalTransform(_f, _t) {
const { from: f, to: t } = this.getFromToInBoundary(_f, _t);
/** @type {?} */
const needToAdjust = this.length > 2 && _t !== t;
if (needToAdjust) {
this.prepareHorizontalContext(t < f);
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(${-_t * this.unitWidth}px, 0, 0)`);
}
else {
this.renderer.setStyle(this.slickTrackEl, 'transform', `translate3d(${-t * this.unitWidth}px, 0, 0`);
}
}
/**
* @private
* @param {?} lastToFirst
* @return {?}
*/
prepareVerticalContext(lastToFirst) {
if (lastToFirst) {
this.renderer.setStyle(this.firstEl, 'top', `${this.length * this.unitHeight}px`);
this.renderer.setStyle(this.lastEl, 'top', null);
}
else {
this.renderer.setStyle(this.firstEl, 'top', null);
this.renderer.setStyle(this.lastEl, 'top', `${-this.unitHeight * this.length}px`);
}
}
/**
* @private
* @param {?} lastToFirst
* @return {?}
*/
prepareHorizontalContext(lastToFirst) {
if (lastToFirst) {
this.renderer.setStyle(this.firstEl, 'left', `${this.length * this.unitWidth}px`);
this.renderer.setStyle(this.lastEl, 'left', null);
}
else {
this.renderer.setStyle(this.firstEl, 'left', null);
this.renderer.setStyle(this.lastEl, 'left', `${-this.unitWidth * this.length}px`);
}
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NzCarouselComponent {
/**
* @param {?} elementRef
* @param {?} document
* @param {?} renderer
* @param {?} cdr
* @param {?} ngZone
* @param {?} platform
*/
constructor(elementRef, document, // tslint:disable-line:no-any
renderer, cdr, ngZone, platform) {
this.renderer = renderer;
this.cdr = cdr;
this.ngZone = ngZone;
this.platform = platform;
this.nzEffect = 'scrollx';
this.nzEnableSwipe = true;
this.nzDots = true;
this.nzVertical = false;
this.nzAutoPlay = false;
this.nzAutoPlaySpeed = 3000;
this.nzTransitionSpeed = 500;
this.nzBeforeChange = new EventEmitter();
this.nzAfterChange = new EventEmitter();
this.activeIndex = 0;
this.destroy$ = new Subject();
this.gestureRect = null;
this.pointerDelta = null;
this.pointerPosition = null;
this.isTransiting = false;
this.isDragging = false;
this.pointerDown = (/**
* @param {?} event
* @return {?}
*/
(event) => {
if (!this.isDragging && !this.isTransiting && this.nzEnableSwipe) {
/** @type {?} */
const point = isTouchEvent(event) ? event.touches[0] || event.changedTouches[0] : event;
this.isDragging = true;
this.clearScheduledTransition();
this.gestureRect = this.slickListEl.getBoundingClientRect();
this.pointerPosition = { x: point.clientX, y: point.clientY };
this.document.addEventListener('mousemove', this.pointerMove);
this.document.addEventListener('touchmove', this.pointerMove);
this.document.addEventListener('mouseup', this.pointerUp);
this.document.addEventListener('touchend', this.pointerUp);
}
});
this.pointerMove = (/**
* @param {?} event
* @return {?}
*/
(event) => {
if (this.isDragging) {
/** @type {?} */
const point = isTouchEvent(event) ? event.touches[0] || event.changedTouches[0] : event;
this.pointerDelta = { x: point.clientX - (/** @type {?} */ (this.pointerPosition)).x, y: point.clientY - (/** @type {?} */ (this.pointerPosition)).y };
if (Math.abs(this.pointerDelta.x) > 5) {
this.strategy.dragging(this.pointerDelta);
}
}
});
this.pointerUp = (/**
* @return {?}
*/
() => {
if (this.isDragging && this.nzEnableSwipe) {
/** @type {?} */
const delta = this.pointerDelta ? this.pointerDelta.x : 0;
// Switch to another slide if delta is third of the width.
if (Math.abs(delta) > (/** @type {?} */ (this.gestureRect)).width / 3) {
this.goTo(delta > 0 ? this.activeIndex - 1 : this.activeIndex + 1);
}
else {
this.goTo(this.activeIndex);
}
this.gestureRect = null;
this.pointerDelta = null;
this.isDragging = false;
this.dispose();
}
});
this.document = document;
this.renderer.addClass(elementRef.nativeElement, 'ant-carousel');
this.el = elementRef.nativeElement;
}
/**
* @return {?}
*/
ngAfterContentInit() {
this.markContentActive(0);
}
/**
* @return {?}
*/
ngAfterViewInit() {
if (!this.platform.isBrowser) {
return;
}
this.slickListEl = this.slickList.nativeElement;
this.slickTrackEl = this.slickTrack.nativeElement;
this.carouselContents.changes.pipe(takeUntil(this.destroy$)).subscribe((/**
* @return {?}
*/
() => {
this.markContentActive(0);
this.strategy.withCarouselContents(this.carouselContents);
}));
this.ngZone.runOutsideAngular((/**
* @return {?}
*/
() => {
fromEvent(window, 'resize')
.pipe(takeUntil(this.destroy$), throttleTime(16))
.subscribe((/**
* @return {?}
*/
() => {
this.strategy.withCarouselContents(this.carouselContents);
}));
}));
this.ngZone.onStable.pipe(take(1)).subscribe((/**
* @return {?}
*/
() => {
this.switchStrategy();
this.strategy.withCarouselContents(this.carouselContents);
}));
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
const { nzEffect } = changes;
if (nzEffect && !nzEffect.isFirstChange()) {
this.switchStrategy();
}
if (!this.nzAutoPlay || !this.nzAutoPlaySpeed) {
this.clearScheduledTransition();
}
else {
this.scheduleNextTransition();
}
}
/**
* @return {?}
*/
ngOnDestroy() {
this.clearScheduledTransition();
if (this.strategy) {
this.strategy.dispose();
}
this.dispose();
this.destroy$.next();
this.destroy$.complete();
}
/**
* @param {?} e
* @return {?}
*/
onKeyDown(e) {
if (e.keyCode === LEFT_ARROW) {
e.preventDefault();
this.pre();
}
else if (e.keyCode === RIGHT_ARROW) {
this.next();
e.preventDefault();
}
}
/**
* @return {?}
*/
next() {
this.goTo(this.activeIndex + 1);
}
/**
* @return {?}
*/
pre() {
this.goTo(this.activeIndex - 1);
}
/**
* @param {?} index
* @return {?}
*/
goTo(index) {
if (this.carouselContents && this.carouselContents.length && !this.isTransiting) {
/** @type {?} */
const length = this.carouselContents.length;
/** @type {?} */
const from = this.activeIndex;
/** @type {?} */
const to = (index + length) % length;
this.isTransiting = true;
this.nzBeforeChange.emit({ from, to });
this.strategy.switch(this.activeIndex, index).subscribe((/**
* @return {?}
*/
() => {
this.scheduleNextTransition();
this.nzAfterChange.emit(index);
this.isTransiting = false;
}));
this.markContentActive(to);
this.cdr.markForCheck();
}
}
/**
* @private
* @return {?}
*/
switchStrategy() {
if (this.strategy) {
this.strategy.dispose();
}
this.strategy =
this.nzEffect === 'scrollx'
? new NzCarouselTransformStrategy(this, this.cdr, this.renderer)
: new NzCarouselOpacityStrategy(this, this.cdr, this.renderer);
this.markContentActive(0);
this.strategy.withCarouselContents(this.carouselContents);
}
/**
* @private
* @return {?}
*/
scheduleNextTransition() {
this.clearScheduledTransition();
if (this.nzAutoPlay && this.nzAutoPlaySpeed > 0 && this.platform.isBrowser) {
this.transitionInProgress = setTimeout((/**
* @return {?}
*/
() => {
this.goTo(this.activeIndex + 1);
}), this.nzAutoPlaySpeed);
}
}
/**
* @private
* @return {?}
*/
clearScheduledTransition() {
if (this.transitionInProgress) {
clearTimeout(this.transitionInProgress);
this.transitionInProgress = null;
}
}
/**
* @private
* @param {?} index
* @return {?}
*/
markContentActive(index) {
this.activeIndex = index;
if (this.carouselContents) {
this.carouselContents.forEach((/**
* @param {?} slide
* @param {?} i
* @return {?}
*/
(slide, i) => {
slide.isActive = index === i;
}));
}
this.cdr.markForCheck();
}
/**
* @private
* @return {?}
*/
dispose() {
this.document.removeEventListener('mousemove', this.pointerMove);
this.document.removeEventListener('touchmove', this.pointerMove);
this.document.removeEventListener('touchend', this.pointerMove);
this.document.removeEventListener('mouseup', this.pointerMove);
}
}
NzCarouselComponent.decorators = [
{ type: Component, args: [{
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
selector: 'nz-carousel',
exportAs: 'nzCarousel',
preserveWhitespaces: false,
template: "<div class=\"slick-initialized slick-slider\" [class.slick-vertical]=\"nzVertical\">\n <div\n #slickList\n class=\"slick-list\"\n tabindex=\"-1\"\n (keydown)=\"onKeyDown($event)\"\n (mousedown)=\"pointerDown($event)\"\n (touchstart)=\"pointerDown($event)\"\n >\n <!-- Render carousel items. -->\n <div class=\"slick-track\" #slickTrack>\n <ng-content></ng-content>\n </div>\n </div>\n <!-- Render dots. -->\n <ul class=\"slick-dots\" *ngIf=\"nzDots\">\n <li\n *ngFor=\"let content of carouselContents; let i = index\"\n [class.slick-active]=\"content.isActive\"\n (click)=\"goTo(i)\"\n >\n <ng-template [ngTemplateOutlet]=\"nzDotRender || renderDotTemplate\" [ngTemplateOutletContext]=\"{ $implicit: i }\">\n </ng-template>\n </li>\n </ul>\n</div>\n\n<ng-template #renderDotTemplate let-index>\n <button>{{ index + 1 }}</button>\n</ng-template>\n",
host: {
'[class.ant-carousel-vertical]': 'nzVertical'
},
styles: [`
nz-carousel {
display: block;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}
.slick-dots {
display: block;
}
.slick-track {
opacity: 1;
}
`]
}] }
];
/** @nocollapse */
NzCarouselComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
{ type: Renderer2 },
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: Platform }
];
NzCarouselComponent.propDecorators = {
carouselContents: [{ type: ContentChildren, args: [NzCarouselContentDirective,] }],
slickList: [{ type: ViewChild, args: ['slickList',] }],
slickTrack: [{ type: ViewChild, args: ['slickTrack',] }],
nzDotRender: [{ type: Input }],
nzEffect: [{ type: Input }],
nzEnableSwipe: [{ type: Input }],
nzDots: [{ type: Input }],
nzVertical: [{ type: Input }],
nzAutoPlay: [{ type: Input }],
nzAutoPlaySpeed: [{ type: Input }],
nzTransitionSpeed: [{ type: Input }],
nzBeforeChange: [{ type: Output }],
nzAfterChange: [{ type: Output }]
};
__decorate([
InputBoolean(),
__metadata("design:type", Object)
], NzCarouselComponent.prototype, "nzEnableSwipe", void 0);
__decorate([
InputBoolean(),
__metadata("design:type", Boolean)
], NzCarouselComponent.prototype, "nzDots", void 0);
__decorate([
InputBoolean(),
__metadata("design:type", Boolean)
], NzCarouselComponent.prototype, "nzVertical", void 0);
__decorate([
InputBoolean(),
__metadata("design:type", Object)
], NzCarouselComponent.prototype, "nzAutoPlay", void 0);
__decorate([
InputNumber(),
__metadata("design:type", Object)
], NzCarouselComponent.prototype, "nzAutoPlaySpeed", void 0);
__decorate([
InputNumber(),
__metadata("design:type", Object)
], NzCarouselComponent.prototype, "nzTransitionSpeed", void 0);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NzCarouselModule {
}
NzCarouselModule.decorators = [
{ type: NgModule, args: [{
declarations: [NzCarouselComponent, NzCarouselContentDirective],
exports: [NzCarouselComponent, NzCarouselContentDirective],
imports: [CommonModule]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { NzCarouselModule, NzCarouselComponent, NzCarouselContentDirective };
//# sourceMappingURL=ng-zorro-antd-carousel.js.map