UNPKG

breakjs

Version:

Responsive breakpoints in Javascript made simple.

165 lines (134 loc) 3.84 kB
function find(array, cb) { for (let i = array.length - 1; i >= 0; i--) { if (cb(array[i])) { return array[i]; } } } const mediaQueries = { between(val1, val2) { return window.matchMedia(`screen and (min-width: ${val1}px) and ` + `(max-width: ${val2 - 1}px)`); }, atLeast(val) { return window.matchMedia(`screen and (min-width: ${val}px)`); }, atMost(val) { return window.matchMedia(`screen and (max-width: ${val - 1}px)`); } }; const query = function(bp, nextBp) { return { is: typeof nextBp === 'number' ? mediaQueries.between(bp, nextBp) : mediaQueries.atLeast(bp), atLeast: mediaQueries.atLeast(bp), atMost: mediaQueries.atMost(nextBp || Number.MAX_VALUE) }; }; const Breakjs = function(bpEntries) { if (!bpEntries) { throw new Error('No breakpoints were defined!'); } const bps = []; for (const key in bpEntries) { const entry = {name: key, value: bpEntries[key]}; if (find(bps, bp => bp.value === entry.value)) { throw new Error('Breakpoint values must be unique.'); } bps.push(entry); } const breakpoints = bps .sort((a, b) => { return a.value > b.value; }) .map((bp, index) => { if (typeof bp.name !== 'string') { throw new Error('Invalid breakpoint name -- should be a string.'); } if (typeof bp.value !== 'number' || bp.value < 0) { throw new Error(`Invalid breakpoint value for ${bp.name}: ${bp.value}`); } const breakpoint = {name: bp.name}; // only query if (bps.length === 1) { breakpoint.query = query(0, null); } // last query else if (index === bps.length - 1) { breakpoint.query = query(bp.value, null); } // query inbetween else { breakpoint.query = query(bp.value, bps[index + 1].value); } return breakpoint; }); function getBreakpoint(breakpointName) { const findObj = find(breakpoints, bp => bp.name === breakpointName); if (!findObj) { throw new Error('invalid breakpoint name'); } return findObj; } const changeListeners = []; return { breakpoints: bps, /** * Check if the current window size is the given size * @param {String} size * @return {Boolean} */ is(name) { return getBreakpoint(name).query.is.matches; }, /** * Check if the current window size at least the given size * @param {String} size * @return {Boolean} */ atLeast(name) { return getBreakpoint(name).query.atLeast.matches; }, /** * Check if the current window size at most the given size * @param {String} size * @return {Boolean} */ atMost(name) { return getBreakpoint(name).query.atMost.matches; }, current() { const findObj = find(breakpoints, bp => bp.query.is.matches); if (findObj) { return findObj.name; } }, addChangeListener(listener) { breakpoints.forEach(bp => { const changeListener = () => { var current = this.current(); if (current === bp.name) { listener(current); } }; changeListeners.push({ original: listener, created: changeListener }); bp.query.is.addListener(changeListener); }); }, removeChangeListener(listener) { breakpoints.forEach(bp => { const findObj = find(changeListeners, cl => cl.original === listener); if (findObj) { bp.query.is.removeListener(findObj.created); changeListeners.splice(changeListeners.indexOf(findObj), 1); } }); } }; }; if (typeof window !== 'undefined') { window.Breakjs = Breakjs; } export default Breakjs;