UNPKG

@exadel/esl

Version:

Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components

83 lines (82 loc) 2.9 kB
import { SyntheticEventTarget } from '../../../esl-utils/dom/events'; import { ESLMediaChangeEvent } from './media-query-base'; import { ALL, NOT_ALL } from './media-query-const'; /** * Abstract multiple media conditions container * @author Alexey Stsefanovich (ala'n) * * Observe all child items. Dispatch changes when the whole condition result is changed */ class MediaQueryContainer extends SyntheticEventTarget { constructor(items = []) { super(); this.items = items; this._matches = this.matches; this._onChange = this._onChange.bind(this); } addEventListener(type, callback = type) { super.addEventListener(type, callback); if (this.getEventListeners('change').length > 1) return; this.items.forEach((item) => item.addEventListener('change', this._onChange)); } removeEventListener(type, callback = type) { super.removeEventListener(type, callback); if (this.hasEventListener()) return; this.items.forEach((item) => item.removeEventListener('change', this._onChange)); } optimize() { return this; } get matches() { return false; } /** Handles query change and dispatches it on top level in case result value is changed */ _onChange() { const { matches } = this; if (this._matches === matches) return; this.dispatchEvent(new ESLMediaChangeEvent(this._matches = matches)); } } /** Conjunction (AND) group of media conditions */ export class MediaQueryConjunction extends MediaQueryContainer { get matches() { return this.items.every((item) => item.matches); } optimize() { const optimizedItems = this.items.map((item) => item.optimize()); if (optimizedItems.some((item) => NOT_ALL.eq(item))) return NOT_ALL; const items = optimizedItems.filter((item) => !ALL.eq(item)); if (items.length === 0) return ALL; if (items.length === 1) return items[0]; return new MediaQueryConjunction(items); } toString() { return this.items.join(' and '); } } /** Disjunction (OR) group of media conditions */ export class MediaQueryDisjunction extends MediaQueryContainer { get matches() { return this.items.some((item) => item.matches); } optimize() { const optimizedItems = this.items.map((item) => item.optimize()); if (optimizedItems.some((item) => ALL.eq(item))) return ALL; const items = optimizedItems.filter((item) => !NOT_ALL.eq(item)); if (items.length === 0) return NOT_ALL; if (items.length === 1) return items[0]; return new MediaQueryDisjunction(items); } toString(pretty = false) { return this.items.join(pretty ? ' or ' : ', '); } }