ngx-virtual-swiper
Version:
Swiper with virtual scroll.
206 lines (198 loc) • 8.3 kB
JavaScript
import { Directionality } from '@angular/cdk/bidi';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import * as i0 from '@angular/core';
import { Injectable, Directive, Inject, Optional, Input, HostListener, NgModule } from '@angular/core';
import { Subscription } from 'rxjs';
class NgxVirtualSwiperOptions {
constructor() {
/** returns to actual integer index */
this.finalize = true;
/**
* It's required by links, the library should know is it real swipe or fake.
* A value in px. If "touch distance" will be lower than this value then swiper will not move.
*/
this.threshold = 20;
/** prevent all type of clicks (e.g. links, Angular`s click) */
this.preventClicks = true;
}
}
NgxVirtualSwiperOptions.ɵprov = i0.ɵɵdefineInjectable({ factory: function NgxVirtualSwiperOptions_Factory() { return new NgxVirtualSwiperOptions(); }, token: NgxVirtualSwiperOptions, providedIn: "root" });
NgxVirtualSwiperOptions.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
NgxVirtualSwiperOptions.ctorParameters = () => [];
const getFirstTouch = (e, key) => { var _a, _b; return (_b = (_a = e === null || e === void 0 ? void 0 : e.touches) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b[key]; };
const ɵ0 = getFirstTouch;
const getClickPositions = (e) => {
const clientX = e.clientX;
const clientY = e.clientY;
return { clientX, clientY };
};
const getTouchPositions = (e) => {
const clientX = getFirstTouch(e, 'clientX');
const clientY = getFirstTouch(e, 'clientY');
return { clientX, clientY };
};
const isNumber = x => typeof x === 'number' && !isNaN(x);
const VERTICAL_ORIENTATION = 'vertical';
const HORIZONTAL_ORIENTATION = 'horizontal';
const RIGHT_TO_LEFT = 'rtl';
class NgxVirtualSwiperDirective {
constructor(options,
/** to lean more see https://material.angular.io/cdk/scrolling/api */
cdk, dir) {
this.options = options;
this.cdk = cdk;
this.dir = dir;
this.subscription = new Subscription();
// eslint-disable-next-line @typescript-eslint/member-ordering
this.onMousedown = (e) => this.start(getClickPositions(e));
this.onTouchstart = (e) => this.start(getTouchPositions(e));
this.onMousemove = (e) => this.move(getClickPositions(e));
this.onTouchmove = (e) => this.move(getTouchPositions(e));
this.onFinish = () => {
if (this.swiped) {
this.toggleSwiped(false);
this.finalize();
}
};
/** the bug-fix to prevent dragging images while swiping */
this.onDragstart = (e) => e.preventDefault();
this.mousemoveX = (e) => {
if (e) {
const offset = this.cdk.measureScrollOffset();
const c = this.rtl ? -1 : 1;
const delta = (this.clientX - e.clientX) * c;
const value = offset + delta;
if (value >= 0 && value <= this.scrollSize) {
this.cdk.scrollToOffset(Math.abs(value));
this.clientX = e.clientX;
}
}
};
this.mousemoveY = (e) => {
if (e) {
const offset = this.cdk.measureScrollOffset();
const value = offset - e.clientY + this.clientY;
if (value >= 0 && value <= this.scrollSize) {
this.cdk.scrollToOffset(value);
this.clientY = e.clientY;
}
}
};
this.start = (e) => {
this.toggleSwiped(true);
this.clientX = e.clientX;
this.clientY = e.clientY;
this.prevClientX = e.clientX;
this.prevClientY = e.clientY;
};
this.move = (e) => {
if (this.swiped) {
if (this.cdk.orientation === HORIZONTAL_ORIENTATION) {
this.mousemoveX(e);
}
else if (this.cdk.orientation === VERTICAL_ORIENTATION) {
this.mousemoveY(e);
}
}
};
this.toggleSwiped = (value) => {
this.swiped = value;
};
this.finalize = () => {
if (this.options.finalize) {
this.scrollToNearestIndex();
}
};
this.scrollToNearestIndex = () => {
const delta = this.cdk.orientation === HORIZONTAL_ORIENTATION ? this.prevClientX - this.clientX :
this.cdk.orientation === VERTICAL_ORIENTATION ? this.prevClientY - this.clientY :
null;
if (isNumber(delta)) {
const directionDelta = this.rtl ? delta * -1 : delta;
const index = directionDelta > 0 && Math.abs(directionDelta) >= this.options.threshold ? this.index + 1 : this.index;
this.cdk.scrollToIndex(index, 'smooth');
}
};
this.addEventListener = () => {
this.cdk.elementRef.nativeElement.addEventListener('click', this.preventClicks, true);
};
this.removeEventListener = () => {
this.cdk.elementRef.nativeElement.removeEventListener('click', this.preventClicks, true);
};
/** prevent all type of clicks (e.g. click on links, Angular`s click) */
this.preventClicks = (e) => {
if (this.changed && this.options.preventClicks) {
e.stopPropagation();
e.preventDefault();
e.stopImmediatePropagation();
}
};
}
ngOnInit() {
this.addEventListener();
this.subscription.add(this.cdk.scrolledIndexChange.subscribe(i => this.index = i));
}
ngOnDestroy() {
this.removeEventListener();
this.subscription.unsubscribe();
}
get changed() {
let result = false;
if (isNumber(this.prevClientX) && isNumber(this.options.threshold)) {
const deltaX = Math.abs(this.prevClientX - this.clientX);
result = deltaX >= this.options.threshold;
}
if (isNumber(this.prevClientY) && isNumber(this.options.threshold)) {
const deltaY = Math.abs(this.prevClientY - this.clientY);
result = result || deltaY >= this.options.threshold;
}
return result;
}
get rtl() {
var _a;
return ((_a = this.dir) === null || _a === void 0 ? void 0 : _a.value) === RIGHT_TO_LEFT;
}
get scrollSize() {
return this.cdk.getDataLength() * this.itemSize;
}
}
NgxVirtualSwiperDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngxVirtualSwiper]'
},] }
];
NgxVirtualSwiperDirective.ctorParameters = () => [
{ type: NgxVirtualSwiperOptions, decorators: [{ type: Inject, args: [NgxVirtualSwiperOptions,] }] },
{ type: CdkVirtualScrollViewport, decorators: [{ type: Inject, args: [CdkVirtualScrollViewport,] }] },
{ type: Directionality, decorators: [{ type: Optional }, { type: Inject, args: [Directionality,] }] }
];
NgxVirtualSwiperDirective.propDecorators = {
itemSize: [{ type: Input }],
onMousedown: [{ type: HostListener, args: ['mousedown', ['$event'],] }],
onTouchstart: [{ type: HostListener, args: ['touchstart', ['$event'],] }],
onMousemove: [{ type: HostListener, args: ['mousemove', ['$event'],] }],
onTouchmove: [{ type: HostListener, args: ['touchmove', ['$event'],] }],
onFinish: [{ type: HostListener, args: ['document:mouseup',] }, { type: HostListener, args: ['touchend',] }],
onDragstart: [{ type: HostListener, args: ['document:dragstart', ['$event'],] }]
};
class NgxVirtualSwiperModule {
}
NgxVirtualSwiperModule.decorators = [
{ type: NgModule, args: [{
imports: [],
declarations: [NgxVirtualSwiperDirective],
exports: [NgxVirtualSwiperDirective]
},] }
];
/*
* Public API Surface of ngx-virtual-swiper
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxVirtualSwiperDirective, NgxVirtualSwiperModule, NgxVirtualSwiperOptions };
//# sourceMappingURL=ngx-virtual-swiper.js.map