123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- import { MEDIA_PREFERS_REDUCED_MOTION } from '../../constants/media';
- import { CREATED, DESTROYED } from '../../constants/states';
- import { EventBinder } from '../../constructors';
- import { Splide } from '../../core/Splide/Splide';
- import { BaseComponent, Components, Options } from '../../types';
- import { merge, omit, ownKeys } from '../../utils';
- import { EVENT_UPDATED } from '../../constants/events';
- /**
- * The interface for the Media component.
- *
- * @since 4.0.0
- */
- export interface MediaComponent extends BaseComponent {
- /** @internal */
- reduce( reduced: boolean ): void;
- set( options: Options, base?: boolean, notify?: boolean ): void;
- }
- /**
- * The component for observing media queries and updating options if necessary.
- * This used to be the Options component.
- *
- * @since 4.0.0
- *
- * @param Splide - A Splide instance.
- * @param Components - A collection of components.
- * @param options - Options.
- *
- * @return A Media component object.
- */
- export function Media( Splide: Splide, Components: Components, options: Options ): MediaComponent {
- const { state } = Splide;
- const breakpoints = options.breakpoints || {};
- const reducedMotion = options.reducedMotion || {};
- const binder = EventBinder();
- /**
- * Stores options and MediaQueryList object.
- */
- const queries: Array<[ Options, MediaQueryList ]> = [];
- /**
- * Called when the component is constructed.
- */
- function setup(): void {
- const isMin = options.mediaQuery === 'min';
- ownKeys( breakpoints )
- .sort( ( n, m ) => isMin ? +n - +m : +m - +n )
- .forEach( key => {
- register( breakpoints[ key ], `(${ isMin ? 'min' : 'max' }-width:${ key }px)` );
- } );
- register( reducedMotion, MEDIA_PREFERS_REDUCED_MOTION );
- update();
- }
- /**
- * Destroys the component.
- *
- * @param completely - Will be `true` for complete destruction.
- */
- function destroy( completely: boolean ): void {
- if ( completely ) {
- binder.destroy();
- }
- }
- /**
- * Registers entries as [ Options, media query string ].
- *
- * @param options - Options merged to current options when the document matches the query.
- * @param query - A query string.
- */
- function register( options: Options, query: string ): void {
- const queryList = matchMedia( query );
- binder.bind( queryList, 'change', update );
- queries.push( [ options, queryList ] );
- }
- /**
- * Checks all media queries in entries and updates options.
- */
- function update(): void {
- const destroyed = state.is( DESTROYED );
- const direction = options.direction;
- const merged = queries.reduce<Options>( ( merged, entry ) => {
- return merge( merged, entry[ 1 ].matches ? entry[ 0 ] : {} );
- }, {} );
- omit( options );
- set( merged );
- if ( options.destroy ) {
- Splide.destroy( options.destroy === 'completely' );
- } else if ( destroyed ) {
- destroy( true );
- Splide.mount();
- } else {
- direction !== options.direction && Splide.refresh();
- }
- }
- /**
- * Disables or enables `reducedMotion` options.
- * This method does nothing when the document does not match the query.
- *
- * @internal
- *
- * @param enable - Determines whether to apply `reducedMotion` options or not.
- */
- function reduce( enable: boolean ): void {
- if ( matchMedia( MEDIA_PREFERS_REDUCED_MOTION ).matches ) {
- enable ? merge( options, reducedMotion ) : omit( options, ownKeys( reducedMotion ) );
- }
- }
- /**
- * Sets current options or base options (prototype).
- * If changing base options, always emits the `updated` event.
- *
- * @internal
- *
- * @param opts - New options.
- * @param base - Optional. Determines whether to also update base options or not.
- * @param notify - Optional. If `true`, always emits the `update` event.
- */
- function set( opts: Options, base?: boolean, notify?: boolean ): void {
- merge( options, opts );
- base && merge( Object.getPrototypeOf( options ), opts );
- if ( notify || ! state.is( CREATED ) ) {
- Splide.emit( EVENT_UPDATED, options );
- }
- }
- return {
- setup,
- destroy,
- reduce,
- set,
- };
- }
|