Skip to content

Commit

Permalink
refactor(esl-carousel): move types to the common place, rearrange nav…
Browse files Browse the repository at this point in the history
…igation request and initial update
  • Loading branch information
ala-n committed Aug 6, 2024
1 parent 0bd7a77 commit 4a57c17
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 46 deletions.
4 changes: 2 additions & 2 deletions src/modules/esl-carousel/core/esl-carousel.events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {ESLCarousel} from './esl-carousel';
import type {ESLCarouselDirection, ESLCarouselStaticState} from './nav/esl-carousel.nav.types';
import type {ESLCarouselDirection, ESLCarouselStaticState} from './esl-carousel.types';

/** {@link ESLCarouselSlideEvent} init object */
export interface ESLCarouselSlideEventInit {
Expand All @@ -8,7 +8,7 @@ export interface ESLCarouselSlideEventInit {
/** A list of indexes of slides that are active after the change */
indexesAfter: number[];
/** Direction of slide animation */
direction: ESLCarouselDirection | null;
direction?: ESLCarouselDirection;
/** Auxiliary request attribute that represents object that initiates slide change */
activator?: any;
}
Expand Down
34 changes: 24 additions & 10 deletions src/modules/esl-carousel/core/esl-carousel.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {memoize} from '../../esl-utils/decorators';
import {isEqual} from '../../esl-utils/misc/object';
import {SyntheticEventTarget} from '../../esl-utils/dom';
import {ESLCarouselSlideEvent} from './esl-carousel.events';
import {normalize, sequence, indexToDirection} from './nav/esl-carousel.nav.utils';
import {normalize, sequence, indexToDirection, normalizeIndex} from './nav/esl-carousel.nav.utils';

import type {ESLCarousel, ESLCarouselActionParams} from './esl-carousel';
import type {ESLCarouselConfig, ESLCarouselDirection} from './nav/esl-carousel.nav.types';
import type {ESLCarousel} from './esl-carousel';
import type {ESLCarouselActionParams, ESLCarouselConfig, ESLCarouselDirection, ESLCarouselNavInfo} from './esl-carousel.types';
import type {ESLCarouselSlideEventInit} from './esl-carousel.events';

export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
Expand Down Expand Up @@ -91,16 +91,30 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
public onUnbind(): void {}
/** Processes drawing of the carousel {@link ESLCarousel}. */
public redraw(): void {}

/** Normalizes an index before navigation */
protected normalizeIndex(index: number, params?: ESLCarouselActionParams): number {
return normalizeIndex(index, this);
}
/** Normalizes a direction before navigation */
protected normalizeDirection(direction: ESLCarouselDirection | undefined, params?: ESLCarouselActionParams): ESLCarouselDirection {
return (this.loop ? params && params.direction : null) || direction || 'next';
}

/** Processes changing slides */
public async navigate(index: number, direction: ESLCarouselDirection, {activator}: ESLCarouselActionParams): Promise<void> {
const {activeIndex, activeIndexes} = this.$carousel;
public async navigate(to: ESLCarouselNavInfo, params: ESLCarouselActionParams): Promise<void> {
const index = this.normalizeIndex(to.index, params);
const direction = this.normalizeDirection(to.direction, params);

const indexesAfter = sequence(index, this.count, this.size);
const indexesBefore = this.$carousel.activeIndexes;

if (activeIndex === index && activeIndexes.length === this.count) return;
if (indexesBefore.toString() === indexesAfter.toString()) return;
if (!this.$carousel.dispatchEvent(ESLCarouselSlideEvent.create('BEFORE', {
...params,
direction,
activator,
indexesBefore: activeIndexes,
indexesAfter: sequence(index, this.count, this.size)
indexesBefore,
indexesAfter
}))) return;

this.setPreActive(index);
Expand All @@ -113,7 +127,7 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
console.error(e);
}

this.setActive(index, {direction, activator});
this.setActive(index, {direction, ...params});
}

/** Pre-processing animation action. */
Expand Down
20 changes: 4 additions & 16 deletions src/modules/esl-carousel/core/esl-carousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,11 @@ import {ESLCarouselChangeEvent} from './esl-carousel.events';

import type {
ESLCarouselState,
ESLCarouselDirection,
ESLCarouselSlideTarget,
ESLCarouselStaticState,
ESLCarouselConfig
} from './nav/esl-carousel.nav.types';

/** {@link ESLCarousel} action params interface */
export interface ESLCarouselActionParams {
/** Element requester of the change */
activator?: any;
/** Direction to move to. */
direction?: ESLCarouselDirection;
// TODO: implement
// noAnimation?: boolean;
}
ESLCarouselConfig,
ESLCarouselActionParams
} from './esl-carousel.types';

/**
* ESLCarousel component
Expand Down Expand Up @@ -301,9 +291,7 @@ export class ESLCarousel extends ESLBaseElement {
public goTo(target: HTMLElement | ESLCarouselSlideTarget, params: ESLCarouselActionParams = {}): Promise<void> {
if (target instanceof HTMLElement) return this.goTo(this.indexOf(target), params);
if (!this.renderer) return Promise.reject();
const nav = toIndex(target, this.state);
const direction = (this.loop ? params.direction : null) || nav.direction || 'next';
return this.renderer.navigate(nav.index, direction, params);
return this.renderer.navigate(toIndex(target, this.state), params);
}

/** @returns slide by index (supports not normalized indexes) */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,15 @@ export type ESLCarouselNavInfo = {
/** Target index */
index: number;
/** Direction to reach the index */
direction: ESLCarouselDirection | null;
direction?: ESLCarouselDirection;
};

/** {@link ESLCarousel} action params interface */
export interface ESLCarouselActionParams {
/** Element requester of the change */
activator?: any;
/** Direction to move to. */
direction?: ESLCarouselDirection;
/** Animation duration in milliseconds. (Pass 0 to disable animation) */
duration?: number;
}
7 changes: 3 additions & 4 deletions src/modules/esl-carousel/core/nav/esl-carousel.nav.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
ESLCarouselSlideTarget,
ESLCarouselState,
ESLCarouselStaticState
} from './esl-carousel.nav.types';
} from '../esl-carousel.types';

/** @returns normalized slide index in bounds of [0, count] range */
export function normalize(index: number, size: number): number {
Expand Down Expand Up @@ -66,11 +66,10 @@ export function indexToGroup(index: number, count: number, size: number): number
}

/** @returns closest direction to move to the passed index */
export function indexToDirection(index: number, {activeIndex, size, loop}: ESLCarouselState): ESLCarouselDirection | null {
export function indexToDirection(index: number, {activeIndex, size, loop}: ESLCarouselState): ESLCarouselDirection | undefined {
if (loop) return calcDirection(activeIndex, index, size);
if (activeIndex < index) return 'next';
if (activeIndex > index) return 'prev';
return null;
}

/** Splits target string into type and index parts */
Expand Down Expand Up @@ -129,7 +128,7 @@ export function toIndex(target: ESLCarouselSlideTarget, cfg: ESLCarouselState):
const {type, index} = splitTarget(target);
if (type === 'group') return resolveGroupIndex(index, cfg);
if (type === 'slide') return resolveSlideIndex(index, cfg);
return {index: cfg.activeIndex, direction: null};
return {index: cfg.activeIndex};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {ESLTraversingQuery} from '../../../esl-traversing-query/core';
import {ESLCarouselChangeEvent, ESLCarouselSlideEvent} from '../../core/esl-carousel.events';

import type {ESLCarousel} from '../../core/esl-carousel';
import type {ESLCarouselSlideTarget} from '../../core/nav/esl-carousel.nav.types';
import type {ESLCarouselSlideTarget} from '../../core/esl-carousel.types';

/**
* ESLCarousel navigation helper to define triggers for carousel navigation.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {normalize, normalizeIndex} from '../core/nav/esl-carousel.nav.utils';
import {ESLCarouselRenderer} from '../core/esl-carousel.renderer';

import type {ESLCarouselDirection} from '../core/nav/esl-carousel.nav.types';
import type {ESLCarouselDirection} from '../core/esl-carousel.types';

/**
* Default carousel renderer based on CSS Flexbox stage, order (flex), and stage animated movement via CSS transform.
Expand Down Expand Up @@ -42,7 +42,7 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
* Prepare to renderer animation.
*/
public override onBind(): void {
this.currentIndex = this.$carousel.activeIndex >= 0 ? this.$carousel.activeIndex : 0;
this.currentIndex = this.normalizeIndex(this.$carousel.activeIndex);
this.redraw();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import {prop, memoize} from '../../esl-utils/decorators';
import {ESLCarouselRenderer} from '../core/esl-carousel.renderer';
import {ESLDefaultCarouselRenderer} from './esl-carousel.default.renderer';

import type {ESLCarouselDirection} from '../core/nav/esl-carousel.nav.types';
import type {ESLCarouselActionParams} from '../core/esl-carousel';
import type {ESLCarouselActionParams, ESLCarouselDirection} from '../core/esl-carousel.types';

/**
* {@link ESLDefaultCarouselRenderer} extension to render slides as a multi-row grid.
Expand Down Expand Up @@ -79,11 +78,10 @@ export class ESLGridCarouselRenderer extends ESLDefaultCarouselRenderer {
}

/**
* Processes changing slides
* Normalize actual active index to the first slide in the current dimension ('row')
*/
public override async navigate(index: number, direction: ESLCarouselDirection, {activator}: ESLCarouselActionParams): Promise<void> {
await super.navigate(index - (index % this.ROWS), direction, {activator});
protected override normalizeIndex(index: number, params?: ESLCarouselActionParams): number {
return super.normalizeIndex(index - (index % this.ROWS), params);
}

/** Processes animation. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ESLCarouselRenderer} from '../core/esl-carousel.renderer';

import type {ESLCarousel} from '../core/esl-carousel';
import type {ESLCarouselConfig, ESLCarouselDirection} from '../core/nav/esl-carousel.nav.types';
import type {ESLCarouselConfig, ESLCarouselDirection} from '../core/esl-carousel.types';

/**
* None effect carousel renderer. Does not provide any animation, transition. Does not limit slide stage.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
ESLCarouselDirection,
ESLCarouselSlideTarget,
ESLCarouselState
} from '../../core/nav/esl-carousel.nav.types';
} from '../../core/esl-carousel.types';

describe('ESLCarousel: Nav Utils', () => {
describe('normalize', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('ESLCarouselRenderer: Slide change events created correctly', () => {
});

test('ESLCarouselSlideEvent: Initial slide triggered correct events', async () => {
const request = $carousel.renderer.navigate(0, 'next', {activator: 'user'});
const request = $carousel.renderer.navigate({index: 0, direction: 'next'}, {activator: 'user'});
expect(beforeEventTrap).toHaveBeenCalledTimes(1);
expect(afterEventTrap).toHaveBeenCalledTimes(0);
expect(beforeEventTrap).toHaveBeenLastCalledWith(expect.objectContaining({
Expand All @@ -47,7 +47,7 @@ describe('ESLCarouselRenderer: Slide change events created correctly', () => {
});

test('ESLCarouselSlideEvent: correct events triggered in the middle state', async () => {
const request = $carousel.renderer.navigate(1, 'next', {activator: 'user'});
const request = $carousel.renderer.navigate({index: 1, direction: 'next'}, {activator: 'user'});
expect(beforeEventTrap).toHaveBeenCalledTimes(1);
expect(afterEventTrap).toHaveBeenCalledTimes(0);
expect(beforeEventTrap).toHaveBeenLastCalledWith(expect.objectContaining({
Expand All @@ -70,7 +70,7 @@ describe('ESLCarouselRenderer: Slide change events created correctly', () => {
});

test('ESLCarouselSlideEvent: Last slide triggered correct events', async () => {
const request = $carousel.renderer.navigate(2, 'next', {activator: 'user'});
const request = $carousel.renderer.navigate({index: 2, direction: 'next'}, {activator: 'user'});
expect(beforeEventTrap).toHaveBeenCalledTimes(1);
expect(afterEventTrap).toHaveBeenCalledTimes(0);
expect(beforeEventTrap).toHaveBeenLastCalledWith(expect.objectContaining({
Expand Down

0 comments on commit 4a57c17

Please sign in to comment.