UNPKG

@exadel/esl

Version:

Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components

148 lines (147 loc) 6.52 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var ESLCarouselTouchMixin_1; import { ExportNs } from '../../../esl-utils/environment/export-ns'; import { listen } from '../../../esl-utils/decorators'; import { getParentScrollOffsets, isOffsetChanged } from '../../../esl-utils/dom/scroll'; import { ESLCarouselPlugin } from '../esl-carousel.plugin'; /** * {@link ESLCarousel} Touch handler mixin * * Usage: * ``` * <esl-carousel esl-carousel-touch></esl-carousel> * * <esl-carousel esl-carousel-touch="@XS => swipe | @+SM => drag"></esl-carousel> * ``` */ let ESLCarouselTouchMixin = ESLCarouselTouchMixin_1 = class ESLCarouselTouchMixin extends ESLCarouselPlugin { /** @returns whether the swipe mode is active */ get isSwipeMode() { return this.config.type === ESLCarouselTouchMixin_1.SWIPE_TYPE; } /** @returns whether the drag mode is active */ get isDragMode() { return this.config.type === ESLCarouselTouchMixin_1.DRAG_TYPE; } /** @returns whether the free mode is active */ get isFreeMode() { return this.config.type === ESLCarouselTouchMixin_1.FREE_TYPE; } /** @returns whether the plugin is disabled (due to carousel state or plugin config) */ get isDisabled() { // Plugin is disabled if (!this.isDragMode && !this.isSwipeMode && !this.isFreeMode) return true; // Carousel is not ready if (!this.$host.renderer || this.$host.animating) return true; // No nav required return this.$host.size <= this.$host.config.count; } /** @returns whether the drugging is prevented by external conditions (scroll, selection) */ get isPrevented() { var _a; // Prevents draggable state if the content is scrolled if (isOffsetChanged(this.startScrollOffsets)) return true; // Prevents draggable state if the text is selected return ((_a = document.getSelection()) === null || _a === void 0 ? void 0 : _a.isCollapsed) === false; } /** @returns offset between start point and passed event point */ getOffset(event) { if (event.type === 'pointercancel') return 0; const property = this.$host.config.vertical ? 'clientY' : 'clientX'; return this.startOffset + (this.startEvent ? (event[property] - this.startEvent[property]) : 0); } /** @returns if the passed event leads to swipe action */ isSwipeAccepted(event) { if (!this.startEvent) return false; // Ignore swipe if timeout threshold exceeded if (event.timeStamp - this.startEvent.timeStamp > this.config.swipeTimeout) return false; // Ignore swipe if offset is not enough return Math.abs(this.getOffset(event)) > this.config.swipeDistance; } /** Handles `mousedown` / `touchstart` event to manage thumb drag start and scroll clicks */ _onPointerDown(event) { if (this.isDisabled) return; this.startEvent = event; this.startIndex = this.$host.activeIndex; this.startOffset = this.$host.offset; this.startScrollOffsets = getParentScrollOffsets(event.target, this.$host); this.$$on({ group: 'pointer' }); } /** Processes `mousemove` and `touchmove` events. */ _onPointerMove(event) { const offset = this.getOffset(event); if (!this.$host.hasAttribute('dragging')) { // Stop tracking if prevented before dragging started if (this.isPrevented) return this._onPointerUp(event); // Does not start dragging mode if offset have not reached tolerance if (Math.abs(offset) < this.config.tolerance) return; this.$$attr('dragging', true); } this.$host.setPointerCapture(event.pointerId); if (this.isDragMode || this.isFreeMode) { this.$host.move(offset, this.startIndex, { activator: this }); } } /** Processes `mouseup` and `touchend` events. */ _onPointerUp(event) { // Unbinds drag listeners this.$$off({ group: 'pointer' }); if (this.$host.hasPointerCapture(event.pointerId)) { this.$host.releasePointerCapture(event.pointerId); } if (this.$$attr('dragging', false) === null) return; const offset = this.getOffset(event); // Commit drag offset (should be commited to 0 if the event is canceled) if (this.isDragMode) { this.$host.move(offset, this.startIndex, { activator: this }); this.$host.commit({ activator: this }).catch(console.debug); } // Swipe final check if (this.isSwipeMode && offset && !this.isPrevented && this.isSwipeAccepted(event)) { const target = `${this.config.swipeType}:${offset < 0 ? 'next' : 'prev'}`; if (!this.$host.canNavigate(target)) return; this.$host.goTo(target, { activator: this }).catch(console.debug); } } }; ESLCarouselTouchMixin.is = 'esl-carousel-touch'; ESLCarouselTouchMixin.DRAG_TYPE = 'drag'; ESLCarouselTouchMixin.FREE_TYPE = 'free'; ESLCarouselTouchMixin.SWIPE_TYPE = 'swipe'; ESLCarouselTouchMixin.DEFAULT_CONFIG_KEY = 'type'; ESLCarouselTouchMixin.DEFAULT_CONFIG = { tolerance: 10, type: 'drag', swipeType: 'group', swipeDistance: 20, swipeTimeout: 400 }; __decorate([ listen('pointerdown') ], ESLCarouselTouchMixin.prototype, "_onPointerDown", null); __decorate([ listen({ auto: false, event: 'pointermove', group: 'pointer' }) ], ESLCarouselTouchMixin.prototype, "_onPointerMove", null); __decorate([ listen({ auto: false, event: 'pointerup pointercancel', group: 'pointer' }) ], ESLCarouselTouchMixin.prototype, "_onPointerUp", null); ESLCarouselTouchMixin = ESLCarouselTouchMixin_1 = __decorate([ ExportNs('Carousel.Touch') ], ESLCarouselTouchMixin); export { ESLCarouselTouchMixin };