@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
143 lines (142 loc) • 6.79 kB
JavaScript
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var ESLCSSCarouselRenderer_1;
import { promisifyNextRender } from '../../esl-utils/async/promise';
import { CSSClassUtils } from '../../esl-utils/dom/class';
import { ESLCarouselRenderer } from '../core/esl-carousel.renderer';
import { sign, bounds } from '../core/esl-carousel.utils';
import { ESLCarouselDirection } from '../core/esl-carousel.types';
let ESLCSSCarouselRenderer = ESLCSSCarouselRenderer_1 = class ESLCSSCarouselRenderer extends ESLCarouselRenderer {
constructor() {
super(...arguments);
/** Active index */
this.currentIndex = 0;
}
get tolerance() {
return this.$carousel.clientWidth * ESLCSSCarouselRenderer_1.NEXT_SLIDE_TOLERANCE;
}
get offset() {
const offset = this.$area.style.getPropertyValue(ESLCSSCarouselRenderer_1.OFFSET_PROP);
return parseFloat(offset) || 0;
}
set offset(offset) {
if (offset) {
const abs = Math.min(1, Math.abs(offset) / this.tolerance);
this.$area.style.setProperty(ESLCSSCarouselRenderer_1.OFFSET_PROP, `${offset.toFixed(1)}px`);
this.$area.style.setProperty(ESLCSSCarouselRenderer_1.OFFSET_PROP_REL, abs.toFixed(4));
}
else {
this.$area.style.removeProperty(ESLCSSCarouselRenderer_1.OFFSET_PROP);
this.$area.style.removeProperty(ESLCSSCarouselRenderer_1.OFFSET_PROP_REL);
}
}
/**
* Processes binding of defined renderer to the carousel {@link ESLCarousel}.
* Prepare to renderer animation.
*/
onBind() {
this.currentIndex = bounds(this.$carousel.activeIndex, 0, this.size - this.count);
this.setActive(this.currentIndex);
}
/**
* Processes unbinding of defined view from the carousel {@link ESLCarousel}.
* Clear animation.
*/
onUnbind() {
this.animating = false;
CSSClassUtils.remove(this.$area, 'forward backward');
}
/** Processes animation. */
onAnimate(index, direction) {
return __awaiter(this, void 0, void 0, function* () {
const { $activeSlide } = this.$carousel;
if (!$activeSlide)
throw new Error('[ESL] Carousel: no active slide');
yield promisifyNextRender();
this.animating = true;
this.$area.classList.add(direction === ESLCarouselDirection.NEXT ? 'forward' : 'backward');
yield promisifyNextRender();
yield this.transitionDuration$$;
});
}
/** Post-processing animation action. */
onAfterAnimate(index, direction, params) {
const _super = Object.create(null, {
onAfterAnimate: { get: () => super.onAfterAnimate }
});
return __awaiter(this, void 0, void 0, function* () {
this.currentIndex = index;
this.animating = false;
this.offset = 0;
CSSClassUtils.remove(this.$area, 'forward backward');
return _super.onAfterAnimate.call(this, index, direction, params);
});
}
move(offset, from, params) {
if (this.animating)
return;
const { $activeSlide } = this.$carousel;
if (!$activeSlide)
throw new Error('[ESL] Carousel: no active slide');
if (Math.abs(offset) > $activeSlide.offsetWidth)
return;
const direction = sign(-offset);
const nextIndex = this.normalizeIndex(this.currentIndex + direction);
const $nextSlide = this.$carousel.$slides[nextIndex];
if (!$nextSlide || $nextSlide === $activeSlide)
return;
const offsetBefore = this.offset;
this.offset = offset;
this.$carousel.$$attr('shifted', !!offset);
this.setPreActive(nextIndex, Object.assign(Object.assign({}, params), { direction }));
this.dispatchMoveEvent(offsetBefore, params);
}
commit(params) {
return __awaiter(this, void 0, void 0, function* () {
const { offset } = this;
const $activeSlide = this.$carousel.$activeSlide;
if (!$activeSlide)
throw new Error('[ESL] Carousel: no active slide');
const dir = sign(-offset);
const nextIndex = this.currentIndex + sign(-offset);
const slideWidth = this.$carousel.clientWidth;
const isBorderSlide = !this.loop && (nextIndex < 0 || nextIndex + this.count > this.size);
const shouldChangeSlide = Math.abs(offset) >= slideWidth * ESLCSSCarouselRenderer_1.NEXT_SLIDE_TOLERANCE;
this.animating = true;
let direction = dir;
if (!isBorderSlide && shouldChangeSlide) {
this.offset = -1 * dir * slideWidth;
this.currentIndex = this.normalizeIndex(nextIndex);
}
else {
this.offset = 0;
direction = -direction;
}
yield this.transitionDuration$$;
this.$carousel.$$attr('shifted', false);
yield this.onAfterAnimate(this.currentIndex, direction, params);
});
}
};
ESLCSSCarouselRenderer.is = 'css';
ESLCSSCarouselRenderer.classes = ['esl-carousel-css-renderer'];
ESLCSSCarouselRenderer.NEXT_SLIDE_TOLERANCE = 0.25;
ESLCSSCarouselRenderer.OFFSET_PROP = '--esl-carousel-offset';
ESLCSSCarouselRenderer.OFFSET_PROP_REL = '--esl-carousel-offset-ratio';
ESLCSSCarouselRenderer = ESLCSSCarouselRenderer_1 = __decorate([
ESLCarouselRenderer.register
], ESLCSSCarouselRenderer);
export { ESLCSSCarouselRenderer };