Skip to content

Commit

Permalink
feat(esl-carousel): change carousel move API
Browse files Browse the repository at this point in the history
- Renderer `onMove` method renamed to `move`
- Both `move` and `commit` methods expect optional base slide to make shift
- Replace `indexByOffset` common move method with actual purpose - `INDEX_MOVE_MULTIPLIER` getter

Co-authored-by: Anna Barmina <[email protected]>
  • Loading branch information
ala-n and abarmina committed Jul 30, 2024
1 parent 2472723 commit 085f977
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 36 deletions.
16 changes: 12 additions & 4 deletions src/modules/esl-carousel/core/esl-carousel.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,18 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
/** Post-processing animation action. */
public async onAfterAnimate(index: number, direction: ESLCarouselDirection): Promise<void> {}

/** Handles the slides transition. */
public abstract onMove(offset: number): void;
/** Ends current transition and makes permanent all changes performed in the transition. */
public abstract commit(offset?: number): void;
/**
* Move slide by the passed offset in px.
* @param offset - offset in px
* @param from - start index (default: current active index)
*/
public abstract move(offset: number, from?: number): void;
/**
* Normalizes move offset to the "nearest stable" slide position.
* @param offset - offset in px
* @param from - start index (default: current active index)
*/
public abstract commit(offset?: number, from?: number): void;

/** Sets active slides from passed index **/
public setActive(current: number, event?: Partial<ESLCarouselSlideEventInit>): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin<ESLCarouselTouchCon
swipeTimeout: 400
};

/** Start index of the drag action */
protected startIndex: number;
/** Start pointer event to detect action */
protected startEvent?: PointerEvent;
/** Initial scroll offsets, filled on touch action start */
Expand Down Expand Up @@ -110,6 +112,7 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin<ESLCarouselTouchCon
if (this.isDisabled) return;

this.startEvent = event;
this.startIndex = this.$host.activeIndex;
this.startScrollOffsets = getParentScrollOffsets(event.target as Element, this.$host);

this.$$on({group: 'pointer'});
Expand All @@ -130,7 +133,7 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin<ESLCarouselTouchCon

this.$host.setPointerCapture(event.pointerId);

if (this.isDragMode) this.$host.renderer.onMove(offset);
if (this.isDragMode) this.$host.renderer.move(offset, this.startIndex);
}

/** Processes `mouseup` and `touchend` events. */
Expand All @@ -147,7 +150,7 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin<ESLCarouselTouchCon

const offset = this.getOffset(event);
// Commit drag offset (should be commited to 0 if the event is canceled)
if (this.isDragMode) this.$host.renderer.commit(offset);
if (this.isDragMode) this.$host.renderer.commit(offset, this.startIndex);
// Swipe final check
if (this.isSwipeMode && offset && !this.isPrevented && this.isSwipeAccepted(event)) {
const target = `${this.config.swipeType}:${offset < 0 ? 'next' : 'prev'}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
/** First index of active slides. */
protected currentIndex: number = 0;

/** Multiplier for the index move on the slide move */
protected get INDEX_MOVE_MULTIPLIER(): number {
return 1;
}

/** Actual slide size (uses average) */
protected get slideSize(): number {
return this.$slides.reduce((size, $slide) => {
Expand Down Expand Up @@ -126,17 +131,13 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
this.$carousel.$$attr('animating', false);
}

protected indexByOffset(count: number): number {
return this.$carousel.activeIndex + count;
}

/** Handles the slides transition. */
public onMove(offset: number): void {
public move(offset: number, from = this.$carousel.activeIndex): void {
this.$carousel.toggleAttribute('active', true);

const slideSize = this.slideSize + this.gap;
const count = Math.floor(Math.abs(offset) / slideSize);
const index = this.indexByOffset(count * (offset < 0 ? 1 : -1));
const index = from + count * this.INDEX_MOVE_MULTIPLIER * (offset < 0 ? 1 : -1);

// check left border of non-loop state
if (!this.loop && offset > 0 && index <= 0) return;
Expand All @@ -148,17 +149,22 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {

const stageOffset = this.getOffset(this.currentIndex) - (offset % slideSize);
this.setTransformOffset(-stageOffset);

if (this.currentIndex !== this.$carousel.activeIndex) {
console.log('Apply active index %d (before %d)', this.currentIndex, this.$carousel.activeIndex);
this.setActive(this.currentIndex, {direction: offset < 0 ? 'next' : 'prev'});
}
}

/** Ends current transition and make permanent all changes performed in the transition. */
// eslint-disable-next-line sonarjs/cognitive-complexity
public async commit(offset: number): Promise<void> {
public async commit(offset: number, from = this.$carousel.activeIndex): Promise<void> {
const slideSize = this.slideSize + this.gap;

const amount = Math.abs(offset) / slideSize;
const tolerance = ESLDefaultCarouselRenderer.NEXT_SLIDE_TOLERANCE;
const count = (amount - Math.floor(amount)) > tolerance ? Math.ceil(amount) : Math.floor(amount);
const index = this.indexByOffset(count * (offset < 0 ? 1 : -1));
const index = from + count * this.INDEX_MOVE_MULTIPLIER * (offset < 0 ? 1 : -1);

this.currentIndex = normalizeIndex(index, this);

Expand All @@ -173,8 +179,11 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {

this.reorder();
this.setTransformOffset(-this.getOffset(this.currentIndex));
this.setActive(this.currentIndex, {direction: offset < 0 ? 'next' : 'prev'});
this.$carousel.$$attr('active', false);

if (this.currentIndex !== this.$carousel.activeIndex) {
this.setActive(this.currentIndex, {direction: offset < 0 ? 'next' : 'prev'});
}
}

/**
Expand Down
13 changes: 7 additions & 6 deletions src/modules/esl-carousel/renderers/esl-carousel.grid.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ export class ESLGridCarouselRenderer extends ESLDefaultCarouselRenderer {
@prop(2, {readonly: true})
public readonly ROWS: number;

/** @returns count of fake slides to fill the last "row" or incomplete carousel state */
/** Multiplier for the index move on the slide move */
protected override get INDEX_MOVE_MULTIPLIER(): number {
return this.ROWS;
}

/** Count of fake slides to fill the last "row" or incomplete carousel state */
public get fakeSlidesCount(): number {
if (this.$carousel.$slides.length < this.count) {
return this.count - this.$carousel.$slides.length;
Expand All @@ -41,7 +46,7 @@ export class ESLGridCarouselRenderer extends ESLDefaultCarouselRenderer {
return Array.from({length}, this.buildFakeSlide.bind(this));
}

/** @returns all slides including {@link ESLGridCarouselRenderer.$fakeSlides} slides created in grid mode */
/** All slides including {@link ESLGridCarouselRenderer.$fakeSlides} slides created in grid mode */
public override get $slides(): HTMLElement[] {
return (this.$carousel.$slides || []).concat(this.$fakeSlides);
}
Expand Down Expand Up @@ -89,10 +94,6 @@ export class ESLGridCarouselRenderer extends ESLDefaultCarouselRenderer {
while (this.currentIndex !== nextIndex) await this.onStepAnimate(step);
}

protected override indexByOffset(offset: number): number {
return super.indexByOffset(offset * this.ROWS);
}

/**
* @returns count of slides to be rendered (reserved) before the first slide does not include fake slides
*/
Expand Down
18 changes: 5 additions & 13 deletions src/modules/esl-carousel/renderers/esl-carousel.none.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,12 @@ export class ESLNoneCarouselRenderer extends ESLCarouselRenderer {
this.setActive(0);
}

public override onUnbind(): void {
// this.$carousel.scrollTop = this.$carousel.scrollLeft = 0;
}
public override onUnbind(): void {}

/** Processes animation. */
public async onAnimate(nextIndex: number, direction: ESLCarouselDirection): Promise<void> {
}
public async onAnimate(nextIndex: number, direction: ESLCarouselDirection): Promise<void> {}

/** Handles the slides transition. */
public onMove(offset: number): void {
// TODO: implement if scroll behaviour requested
// const property = this.vertical ? 'scrollTop' : 'scrollLeft';
// this.$carousel[property] = -offset;
}
public commit(offset?: number): void {
}
/* Handles the slide move actions */
public move(offset: number, from?: number): void {}
public commit(offset: number, from?: number): void {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export class ESLCarouselDummyRenderer extends ESLCarouselRenderer {
public override onBeforeAnimate = jest.fn();
public override onAfterAnimate = jest.fn();

public override onMove = jest.fn();

public override move = jest.fn();
public override commit = jest.fn();
}

0 comments on commit 085f977

Please sign in to comment.