import { ALL_ATTRIBUTES, ARIA_CONTROLS, ARIA_LABEL } from '../../constants/attributes'; import { EVENT_ARROWS_MOUNTED, EVENT_ARROWS_UPDATED, EVENT_MOUNTED, EVENT_MOVE, EVENT_MOVED, EVENT_REFRESH, EVENT_SCROLLED, EVENT_UPDATED, } from '../../constants/events'; import { EventInterface } from '../../constructors'; import { Splide } from '../../core/Splide/Splide'; import { BaseComponent, Components, Options } from '../../types'; import { append, before, child, create, display, parseHtml, remove, removeAttribute, setAttribute } from '../../utils'; import { PATH, SIZE, XML_NAME_SPACE } from './path'; /** * The interface for the Arrows component. * * @since 3.0.0 */ export interface ArrowsComponent extends BaseComponent { arrows: { prev?: HTMLButtonElement, next?: HTMLButtonElement }; } /** * The component for handling previous and next arrows. * * @since 3.0.0 * * @param Splide - A Splide instance. * @param Components - A collection of components. * @param options - Options. * * @return An Arrows component object. */ export function Arrows( Splide: Splide, Components: Components, options: Options ): ArrowsComponent { const { on, bind, emit } = EventInterface( Splide ); const { classes, i18n } = options; const { Elements, Controller } = Components; /** * The wrapper element. */ let wrapper = Elements.arrows; /** * The previous arrow element. */ let prev = Elements.prev; /** * The next arrow element. */ let next = Elements.next; /** * Indicates whether the component creates arrows or retrieved from the DOM. */ let created: boolean; /** * An object with previous and next arrows. */ const arrows: ArrowsComponent[ 'arrows' ] = {}; /** * Called when the component is mounted. */ function mount(): void { init(); on( EVENT_UPDATED, init ); } /** * Initializes the component. */ function init(): void { if ( options.arrows ) { if ( ! prev || ! next ) { createArrows(); } } if ( prev && next ) { if ( ! arrows.prev ) { const { id } = Elements.track; setAttribute( prev, ARIA_CONTROLS, id ); setAttribute( next, ARIA_CONTROLS, id ); arrows.prev = prev; arrows.next = next; listen(); emit( EVENT_ARROWS_MOUNTED, prev, next ); } else { display( wrapper, options.arrows === false ? 'none' : '' ); } } } /** * Destroys the component. */ function destroy(): void { if ( created ) { remove( wrapper ); } else { removeAttribute( prev, ALL_ATTRIBUTES ); removeAttribute( next, ALL_ATTRIBUTES ); } } /** * Listens to some events. */ function listen(): void { const { go } = Controller; on( [ EVENT_MOUNTED, EVENT_MOVED, EVENT_UPDATED, EVENT_REFRESH, EVENT_SCROLLED ], update ); bind( next, 'click', () => { go( '>', true ) } ); bind( prev, 'click', () => { go( '<', true ) } ); } /** * Create arrows and append them to the slider. */ function createArrows(): void { wrapper = create( 'div', classes.arrows ); prev = createArrow( true ); next = createArrow( false ); created = true; append( wrapper, [ prev, next ] ); before( wrapper, child( options.arrows === 'slider' && Elements.slider || Splide.root ) ); } /** * Creates an arrow button. * * @param prev - Determines whether to create a previous or next arrow. * * @return A created button element. */ function createArrow( prev: boolean ): HTMLButtonElement { const arrow = `