Skip to content

Commit

Permalink
Merge pull request #2522 from exadel-inc/feat/esl-carousel-container
Browse files Browse the repository at this point in the history
refactor(esl-carousel): complete rework of carousel container & events API
  • Loading branch information
ala-n authored Jul 18, 2024
2 parents 80f567a + 99b9621 commit ef418f1
Show file tree
Hide file tree
Showing 21 changed files with 297 additions and 135 deletions.
15 changes: 15 additions & 0 deletions site/src/common/close.less
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
&:not(:disabled):focus {
opacity: 0.75;
}

&.inverse {
color: #fff;
text-shadow: 0 1px 0 #000;
&:hover {
color: #fff;
}
}

.img-container & {
position: absolute;
top: 0.25rem;
right: 0.5rem;
z-index: 10;
}
}

button.close {
Expand Down
12 changes: 6 additions & 6 deletions site/views/draft/carousel.njk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ icon: examples/carousel.svg

<section>
<h2>Multi-slide Carousel (cards, adaptive, loop, with footnotes example): </h2>
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs"
esl-carousel-nav="group:prev"><span class="sr-only">Previous Slide</span></button>

Expand Down Expand Up @@ -52,7 +52,7 @@ icon: examples/carousel.svg

<section>
<h2>Multi-slide Carousel (cards, adaptive, loop): </h2>
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs"
esl-carousel-nav="group:prev"><span class="sr-only">Previous Slide</span></button>

Expand Down Expand Up @@ -93,7 +93,7 @@ icon: examples/carousel.svg
<a href="#"> Something accessible</a>
<section>
<h2>Carousel with siblings: </h2>
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow inner prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand Down Expand Up @@ -125,7 +125,7 @@ icon: examples/carousel.svg

<section>
<h2>Multi-slide Carousel (simplified cards, adaptive, loop): </h2>
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand Down Expand Up @@ -156,7 +156,7 @@ icon: examples/carousel.svg

<section>
<h2>Multi-slide Carousel (simplified cards, adaptive, without loop): </h2>
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand Down Expand Up @@ -186,7 +186,7 @@ icon: examples/carousel.svg

<section>
<h2>Single active slide demo: </h2>
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand Down
12 changes: 8 additions & 4 deletions site/views/examples/carousel/default.sample.njk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Carousel (Multi-slide)
order: 1
tags: carousel-sample
---
<div class="mx-6" esl-carousel-container>
<div class="mx-6 esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs"
esl-carousel-nav="group:prev"><span class="sr-only">Previous Slide</span></button>

Expand All @@ -13,12 +13,17 @@ tags: carousel-sample
tabindex="0"
media="@XS|@SM|@MD|@LG|@XL"
count="1|2|3|4|5"
loop="true">
loop="true"
container="::parent(div)"
container-incomplete-class="!carousel-filled">
<ul esl-carousel-slides>
{% for item in range(0, 16) %}
<li esl-carousel-slide {{ 'active' if loop.first }}>
<div class="card">
<div class="card-image img-container img-container-16-9">
<button type="button" class="close inverse" aria-label="Close" onclick="this.closest('li').remove()">
<span aria-hidden="true">×</span>
</button>
<esl-image lazy
mode="cover"
data-alt="{{ 'Carousel slide ' + loop.index }}"
Expand All @@ -37,6 +42,5 @@ tags: carousel-sample

<button class="esl-carousel-arrow next hide-xs"
esl-carousel-nav="group:next"><span class="sr-only">Next Slide</span></button>

<esl-carousel-dots class="carousel-dots-wrapper" tabindex="0"></esl-carousel-dots>
</div>
<esl-carousel-dots class="carousel-dots-wrapper" target="::prev::child(esl-carousel)" tabindex="0"></esl-carousel-dots>
5 changes: 2 additions & 3 deletions site/views/examples/carousel/multirow.sample.njk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Carousel (Multi-row, multi-slide)
order: 4
tags: carousel-sample
---
<div class="mx-6" esl-carousel-container>
<div class="mx-6 esl-carousel-nav-container">
<button class="esl-carousel-arrow prev hide-xs"
esl-carousel-nav="group:prev"><span class="sr-only">Previous Slide</span></button>

Expand Down Expand Up @@ -38,6 +38,5 @@ tags: carousel-sample

<button class="esl-carousel-arrow next hide-xs"
esl-carousel-nav="group:next"><span class="sr-only">Next Slide</span></button>

<esl-carousel-dots class="carousel-dots-wrapper" tabindex="0"></esl-carousel-dots>
</div>
<esl-carousel-dots class="carousel-dots-wrapper" target="::prev::find(esl-carousel)" tabindex="0"></esl-carousel-dots>
4 changes: 2 additions & 2 deletions site/views/examples/carousel/nav-carousel.sample.njk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Carousel (Nav Carousel)
order: 10
tags: carousel-sample
---
<div class="flex-column main-carousel" esl-carousel-container>
<div class="flex-column main-carousel esl-carousel-nav-container">
<esl-carousel demo-options-target
id="main-carousel"
type="default"
Expand All @@ -23,7 +23,7 @@ tags: carousel-sample
</ul>
</esl-carousel>
</div>
<div class="flex-column marquee-nav-carousel" esl-carousel-container>
<div class="flex-column marquee-nav-carousel esl-carousel-nav-container">
<button class="esl-carousel-arrow inner prev" esl-carousel-nav="-4"></button>

<esl-carousel id="nav-carousel"
Expand Down
6 changes: 3 additions & 3 deletions site/views/examples/carousel/siblings.sample.njk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Carousel (Sibling)
order: 3
tags: carousel-sample
---
<div esl-carousel-container>
<div class="esl-carousel-nav-container">
<button class="esl-carousel-arrow inner prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand All @@ -29,6 +29,6 @@ tags: carousel-sample
<button class="esl-carousel-arrow inner next hide-xs" esl-carousel-nav="group:next">
<span class="sr-only">Next Slide</span>
</button>

<esl-carousel-dots class="carousel-dots-wrapper"></esl-carousel-dots>
</div>

<esl-carousel-dots class="carousel-dots-wrapper" target="::prev::child(esl-carousel)"></esl-carousel-dots>
2 changes: 1 addition & 1 deletion site/views/examples/carousel/single.sample.njk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ order: 2
tags: carousel-sample
---

<div class="esl-carousel-no-extra-space" esl-carousel-container>
<div class="esl-carousel-no-extra-space esl-carousel-nav-container">
<button class="esl-carousel-arrow inner prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand Down
2 changes: 1 addition & 1 deletion site/views/examples/carousel/vertical.sample.njk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ order: 5
tags: carousel-sample
---

<div class="esl-carousel-no-extra-space" esl-carousel-container>
<div class="esl-carousel-no-extra-space esl-carousel-nav-container">
<button class="esl-carousel-arrow inner prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>
Expand Down
47 changes: 26 additions & 21 deletions src/modules/esl-carousel/core/esl-carousel.events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import type {ESLCarouselDirection, ESLCarouselStaticState} from './nav/esl-carou

/** {@link ESLCarouselSlideEvent} init object */
export interface ESLCarouselSlideEventInit {
/** Current slide index */
current: number;
/** Related slide index (target on pre-event, current on post-event) */
related: number;
/** A list of indexes of slides that were active before the change */
indexesBefore: number[];
/** A list of indexes of slides that are active after the change */
indexesAfter: number[];
/** Direction of slide animation */
direction: ESLCarouselDirection;
/** Auxiliary request attribute that represents object that initiates slide change */
Expand All @@ -21,8 +21,8 @@ export class ESLCarouselSlideEvent extends Event implements ESLCarouselSlideEven
public static readonly AFTER = 'esl:slide-change';

public override readonly target: ESLCarousel;
public readonly current: number;
public readonly related: number;
public readonly indexesBefore: number[];
public readonly indexesAfter: number[];
public readonly direction: ESLCarouselDirection;
public readonly activator?: any;

Expand All @@ -38,14 +38,24 @@ export class ESLCarouselSlideEvent extends Event implements ESLCarouselSlideEven
Object.assign(this, init);
}

/** @returns current slide element */
public get $currentSlide(): HTMLElement | null {
return this.target.slideAt(this.current);
/** @returns first index of before sate */
public get indexBefore(): number {
return this.indexesBefore[0];
}

/** @returns related slide element */
public get $relatedSlide(): HTMLElement | null {
return this.target.slideAt(this.related);
/** @returns first index of after state */
public get indexAfter(): number {
return this.indexesAfter[0];
}

/** @returns list of slides that are active before the change */
public get $slidesBefore(): HTMLElement[] {
return this.indexesBefore.map((index) => this.target.slideAt(index));
}

/** @returns list of slides that are active after the change */
public get $slidesAfter(): HTMLElement[] {
return this.indexesAfter.map((index) => this.target.slideAt(index));
}

public static create(type: 'BEFORE' | 'AFTER', init: ESLCarouselSlideEventInit): ESLCarouselSlideEvent {
Expand All @@ -55,6 +65,8 @@ export class ESLCarouselSlideEvent extends Event implements ESLCarouselSlideEven

/** {@link ESLCarouselChangeEvent} init object */
interface ESLCarouselChangeEventInit {
/** Whether the event is initial (on carousel creation) */
initial?: boolean;
/** Current {@link ESLCarousel} instance config */
config: ESLCarouselStaticState;
/** Previous {@link ESLCarousel} instance config */
Expand All @@ -69,16 +81,16 @@ interface ESLCarouselChangeEventInit {
export class ESLCarouselChangeEvent extends Event implements ESLCarouselChangeEventInit {
/** {@link ESLCarouselSlideEvent} event type dispatched on carousel config changes */
public static readonly TYPE = 'esl:carousel:change';
public static readonly INITIAL = 'esl:carousel:init';

public override readonly target: ESLCarousel;
public readonly initial: boolean = false;
public readonly config: ESLCarouselStaticState;
public readonly oldConfig?: ESLCarouselStaticState;
public readonly added: HTMLElement[] = [];
public readonly removed: HTMLElement[] = [];

protected constructor(
type: typeof ESLCarouselChangeEvent.TYPE | typeof ESLCarouselChangeEvent.INITIAL,
type: typeof ESLCarouselChangeEvent.TYPE,
init: ESLCarouselChangeEventInit
) {
super(type, {
Expand All @@ -92,11 +104,4 @@ export class ESLCarouselChangeEvent extends Event implements ESLCarouselChangeEv
public static create(init: ESLCarouselChangeEventInit): ESLCarouselChangeEvent {
return new ESLCarouselChangeEvent(ESLCarouselChangeEvent.TYPE, init);
}
public static createInitial(carousel: ESLCarousel): ESLCarouselChangeEvent {
return new ESLCarouselChangeEvent(ESLCarouselChangeEvent.INITIAL, {
added: carousel.$slides,
removed: [],
config: carousel.config
});
}
}
14 changes: 4 additions & 10 deletions src/modules/esl-carousel/core/esl-carousel.less
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
:root {
--esl-carousel-side-space: 5px;
}

// CORE styles
esl-carousel {
position: relative;
Expand Down Expand Up @@ -60,16 +64,6 @@ esl-carousel {
list-style: none;
}

[esl-carousel-container] {
--esl-carousel-control-visibility: visible;
--esl-carousel-side-space: 5px;
position: relative;
}

[esl-carousel-container][incomplete] {
--esl-carousel-control-visibility: hidden;
}

.esl-carousel-no-extra-space {
--esl-carousel-side-space: 0;
}
19 changes: 15 additions & 4 deletions src/modules/esl-carousel/core/esl-carousel.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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 {calcDirection, normalize} from './nav/esl-carousel.nav.utils';
import {calcDirection, normalize, sequence} from './nav/esl-carousel.nav.utils';

import type {ESLCarousel, ESLCarouselActionParams} from './esl-carousel';
import type {ESLCarouselConfig, ESLCarouselDirection} from './nav/esl-carousel.nav.types';
Expand Down Expand Up @@ -31,6 +31,11 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
this.vertical = options.vertical;
}

/** @returns marker if the renderer is applied to the carousel */
public get bound(): boolean {
return this._bound;
}

/** @returns renderer type name */
public get type(): string {
return (this.constructor as typeof ESLCarouselRenderer).is;
Expand Down Expand Up @@ -70,6 +75,8 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
this.onBind();
}
public unbind(): void {
if (!this._bound) return;

const type = this.constructor as typeof ESLCarouselRenderer;
const orientationCls = ['esl-carousel-vertical', 'esl-carousel-horizontal'];
this.$carousel.classList.remove(...orientationCls, ...type.classes);
Expand All @@ -92,8 +99,8 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
if (!this.$carousel.dispatchEvent(ESLCarouselSlideEvent.create('BEFORE', {
direction,
activator,
current: activeIndex,
related: index
indexesBefore: activeIndexes,
indexesAfter: sequence(index, this.count, this.size)
}))) return;

this.setPreActive(index);
Expand Down Expand Up @@ -124,11 +131,15 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {
/** Sets active slides from passed index **/
public setActive(current: number, event?: Partial<ESLCarouselSlideEventInit>): void {
const related = this.$carousel.activeIndex;
const indexesBefore = this.$carousel.activeIndexes;
const count = Math.min(this.count, this.size);
const indexesAfter = [];

for (let i = 0; i < this.size; i++) {
const position = normalize(i + current, this.size);
const $slide = this.$slides[position];
if (i < count) indexesAfter.push(position);

$slide.toggleAttribute('active', i < count);
$slide.toggleAttribute('pre-active', false);
$slide.toggleAttribute('next', i === count && (this.loop || position !== 0));
Expand All @@ -137,7 +148,7 @@ export abstract class ESLCarouselRenderer implements ESLCarouselConfig {

if (event && typeof event === 'object') {
const direction = event.direction || calcDirection(related, current, this.size);
const details = {...event, direction, current, related};
const details = {...event, direction, indexesBefore, indexesAfter};
this.$carousel.dispatchEvent(ESLCarouselSlideEvent.create('AFTER', details));
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/modules/esl-carousel/core/esl-carousel.slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ export class ESLCarouselSlide extends ESLMixinElement {
this.$$attr('inert', !this.active);
}
if (!this.$carousel) return;
CSSClassUtils.toggle(this.$carousel.$container || this.$carousel, this.containerClass, this.active, this.$host);
if (this.$carousel.$container) {
CSSClassUtils.toggle(this.$carousel.$container, this.containerClass, this.active, this.$host);
}
if (!this.active) this.blurIfInactive();
}

Expand Down
Loading

0 comments on commit ef418f1

Please sign in to comment.