Skip to content

Commit

Permalink
feat(esl-carousel): Default Renderer: the reordering algorithm improv…
Browse files Browse the repository at this point in the history
…ed to respect slides semantical order an available limit of slides
  • Loading branch information
ala-n committed May 22, 2024
1 parent c48d803 commit b2efe6f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 21 deletions.
2 changes: 1 addition & 1 deletion site/views/examples/carousel.marquee.njk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ icon: examples/carousel.svg
<ul esl-carousel-slides>
{% for item in slides %}
<li esl-carousel-slide>
<div class="img-container">
<div class="img-container img-container-16-9">
<esl-image mode="cover"
lazy
data-alt="{{ 'Carousel slide ' + loop.index }}"
Expand Down
43 changes: 23 additions & 20 deletions src/modules/esl-carousel/renderers/esl-carousel.default.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
/** Tolerance to treat offset enough to move to the next slide. Relative (0-1) to slide width */
public static readonly NEXT_SLIDE_TOLERANCE = 0.25;

/** Min slides to position from both sides if possible */
protected reserve: number = 1;
/** Slides gap size */
protected gap: number = 0;
/** Slide size cached value */
Expand Down Expand Up @@ -89,7 +87,7 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
/** Post-processing animation action. */
public override async onAfterAnimate(): Promise<void> {
// Make sure we end up in a defined state on transition end
this.reorder(this.currentIndex);
this.reorder();
this.setTransformOffset(-this.getOffset(this.currentIndex));
this.$carousel.$$attr('active', false);
}
Expand All @@ -99,7 +97,7 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
const index = normalize(this.currentIndex + (direction === 'next' ? 1 : -1), this.size);

// Make sure there is a slide in required direction
this.reorder(index, direction !== 'prev');
this.reorder(direction === 'prev');

const offsetFrom = -this.getOffset(this.currentIndex);
this.setTransformOffset(offsetFrom);
Expand Down Expand Up @@ -131,11 +129,8 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
// check right border of non-loop state
if (!this.loop && offset < 0 && index + 1 + this.count > this.$carousel.size) return;

const currentIndex = normalize(index, this.size);
const orderIndex = offset < 0 ? currentIndex : normalize(currentIndex - 1, this.size);

this.reorder(orderIndex);
this.currentIndex = currentIndex;
this.currentIndex = normalize(index, this.size);
this.reorder(offset > 0);

const stageOffset = this.getOffset(this.currentIndex) - (offset % slideSize);
this.setTransformOffset(-stageOffset);
Expand Down Expand Up @@ -163,22 +158,30 @@ export class ESLDefaultCarouselRenderer extends ESLCarouselRenderer {
}
this.$carousel.$$attr('animating', false);

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

/** Sets order style property for slides starting at index */
protected reorder(index: number = this.currentIndex, back?: boolean): void {
if (index < 0 || index > this.$carousel.size) return;
const {size, $slides} = this;
if (!$slides.length) return;

// max reserve limited to a half of free slides, unless backward reorder requested (for back animation)
const maxReserve = Math.max(back ? 1 : 0, Math.floor((this.size - this.count) / 2));
// reserve slides from both sides if requested (or for loop carousel by default); reserve in normal direction is in priority
const reserve = Math.min((typeof back === 'boolean' ? back : this.loop) ? this.reserve : 0, maxReserve);
/**
* Sets order style property for slides starting at index
* @param back - if true, ensures that there is a slide rendered before the current one
*/
protected reorder(back?: boolean): void {
const {size, count, loop, currentIndex, $slides} = this;

const reserve = ((): number => {
const freeSlides = size - count;
// no need to reorder if there are no free slides or loop is disabled
if (!loop || !freeSlides) return 0;
// if there is only one free slide, it should be rendered after the current one unless it's the first slide and back option is not set
if (freeSlides === 1 && !back) return !currentIndex ? 0 : 1;
// otherwise, ensure that there are at least half of free slides reserved (if the back option is set - round up, otherwise - round down)
return Math.min(count, back ? Math.ceil(freeSlides / 2) : Math.floor(freeSlides / 2));
})();

const index = loop ? currentIndex : 0;
for (let i = 0; i < size; ++i) {
let offset = (size + i - index) % size;
// inverses index for backward reserve
Expand Down

0 comments on commit b2efe6f

Please sign in to comment.