All files / src/utils lib.js

98.08% Statements 51/52
88.89% Branches 40/45
100% Functions 8/8
98% Lines 49/50

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147        304x                   304x 66780x 66772x             8x                   304x 252788x 252764x 252294x     470x   470x   470x     24x                   304x 8982x 8982x   8982x 8982x     8982x 8942x 8942x   8942x   8942x 8309x   8942x 7051x   8942x 5654x   8942x 4331x   8942x 2878x       8942x     40x                     304x 66756x   66756x                   22282x                   304x 6848x 3424x     3424x   3424x 3424x 15434x 2954x       2954x   12480x         3424x  
import {css} from 'styled-components';
 
import {CONF_KEY, DEFAULT_CONF} from '../defaultConfig';
 
const configCache = new Map();
 
/**
 * Creates an media query literal.
 *
 * @param {Object} theme      The styled-components theme.
 * @param {String} screenSize The screensize for the query.
 *
 * @returns {Function} An template literal function.
 */
export const media = (theme, screenSize) => {
    if (typeof theme === 'object' && CONF_KEY in theme) {
        return (...args) => css`
            @media ${generateMediaString(theme, screenSize)} {
                ${css(...args)}
            }
        `;
    }
 
    throw new Error('Theme must be an grid config theme.');
};
 
/**
 * Gets the config merged with the defaults.
 *
 * @param {Object} theme The theme provider theme.
 *
 * @returns {Object} The actual complete config.
 */
export const getConfig = theme => {
    if (typeof theme === 'object' && CONF_KEY in theme) {
        if (configCache.has(theme[String(CONF_KEY)])) {
            return configCache.get(theme[String(CONF_KEY)]);
        }
 
        const conf = mergeDeep(DEFAULT_CONF, theme[String(CONF_KEY)]);
 
        configCache.set(theme[String(CONF_KEY)], conf);
 
        return conf;
    }
 
    throw new Error('Theme must be an grid config theme.');
};
 
/**
 * Gets the actual screen class.
 *
 * @param {Object} theme The styled-components theme.
 *
 * @returns {String} The actual screen class.
 */
export const getScreenClass = theme => {
    let viewport = null;
    let newScreenClass = 'xxl';
 
    Eif (typeof window !== 'undefined' && window.innerWidth) {
        viewport = window.innerWidth;
    }
 
    if (typeof theme === 'object' && CONF_KEY in theme) {
        Eif (viewport) {
            const {breakpoints} = getConfig(theme);
 
            newScreenClass = 'xs';
 
            if (breakpoints.sm <= viewport) {
                newScreenClass = 'sm';
            }
            if (breakpoints.md <= viewport) {
                newScreenClass = 'md';
            }
            if (breakpoints.lg <= viewport) {
                newScreenClass = 'lg';
            }
            if (breakpoints.xl <= viewport) {
                newScreenClass = 'xl';
            }
            if (breakpoints.xxl <= viewport) {
                newScreenClass = 'xxl';
            }
        }
 
        return newScreenClass;
    }
 
    throw new Error('Theme must be an grid config theme.');
};
 
/**
 * generates the media query string.
 *
 * @param {Object} theme      The styled-components theme.
 * @param {String} screenSize The screensize for the query.
 *
 * @returns {String} The media query head.
 */
const generateMediaString = (theme, screenSize) => {
    const conf = getConfig(theme);
 
    return `${conf.mediaQuery}${conf.breakpoints[String(screenSize)] >= 0 ? ` and (min-width: ${conf.breakpoints[String(screenSize)]}px)` : ''}`;
};
 
/**
 * Checks if value is an Object.
 *
 * @param {*} item Any value to check.
 *
 * @returns {Boolean} If the item is an object.
 */
const isObject = item => (item && typeof item === 'object' && !Array.isArray(item));
 
/**
 * Merges objects with another.
 *
 * @param {Object} target  The target object to merge everything into.
 * @param {Array}  sources All sources to merge from.
 *
 * @returns {Object} The merged object.
 */
const mergeDeep = (target, ...sources) => {
    if (!sources.length) {
        return target;
    }
 
    const source = sources.shift();
 
    Eif (isObject(target) && isObject(source)) {
        Object.keys(source).forEach(key => {
            if (isObject(source[String(key)])) {
                Iif (!target[String(key)]) {
                    Object.assign(target, {[key]: {}});
                }
 
                mergeDeep(target[String(key)], source[String(key)]);
            } else {
                Object.assign(target, {[key]: source[String(key)]});
            }
        });
    }
 
    return mergeDeep(target, ...sources);
};