Spaces:
Sleeping
Sleeping
File size: 4,747 Bytes
56fda74 |
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 |
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.assignNestedKeys = void 0;
exports.default = cssVarsParser;
exports.walkObjectDeep = void 0;
/**
* This function create an object from keys, value and then assign to target
*
* @param {Object} obj : the target object to be assigned
* @param {string[]} keys
* @param {string | number} value
*
* @example
* const source = {}
* assignNestedKeys(source, ['palette', 'primary'], 'var(--palette-primary)')
* console.log(source) // { palette: { primary: 'var(--palette-primary)' } }
*
* @example
* const source = { palette: { primary: 'var(--palette-primary)' } }
* assignNestedKeys(source, ['palette', 'secondary'], 'var(--palette-secondary)')
* console.log(source) // { palette: { primary: 'var(--palette-primary)', secondary: 'var(--palette-secondary)' } }
*/
const assignNestedKeys = (obj, keys, value, arrayKeys = []) => {
let temp = obj;
keys.forEach((k, index) => {
if (index === keys.length - 1) {
if (Array.isArray(temp)) {
temp[Number(k)] = value;
} else if (temp && typeof temp === 'object') {
temp[k] = value;
}
} else if (temp && typeof temp === 'object') {
if (!temp[k]) {
temp[k] = arrayKeys.includes(k) ? [] : {};
}
temp = temp[k];
}
});
};
/**
*
* @param {Object} obj : source object
* @param {Function} callback : a function that will be called when
* - the deepest key in source object is reached
* - the value of the deepest key is NOT `undefined` | `null`
*
* @example
* walkObjectDeep({ palette: { primary: { main: '#000000' } } }, console.log)
* // ['palette', 'primary', 'main'] '#000000'
*/
exports.assignNestedKeys = assignNestedKeys;
const walkObjectDeep = (obj, callback, shouldSkipPaths) => {
function recurse(object, parentKeys = [], arrayKeys = []) {
Object.entries(object).forEach(([key, value]) => {
if (!shouldSkipPaths || shouldSkipPaths && !shouldSkipPaths([...parentKeys, key])) {
if (value !== undefined && value !== null) {
if (typeof value === 'object' && Object.keys(value).length > 0) {
recurse(value, [...parentKeys, key], Array.isArray(value) ? [...arrayKeys, key] : arrayKeys);
} else {
callback([...parentKeys, key], value, arrayKeys);
}
}
}
});
}
recurse(obj);
};
exports.walkObjectDeep = walkObjectDeep;
const getCssValue = (keys, value) => {
if (typeof value === 'number') {
if (['lineHeight', 'fontWeight', 'opacity', 'zIndex'].some(prop => keys.includes(prop))) {
// CSS property that are unitless
return value;
}
const lastKey = keys[keys.length - 1];
if (lastKey.toLowerCase().indexOf('opacity') >= 0) {
// opacity values are unitless
return value;
}
return `${value}px`;
}
return value;
};
/**
* a function that parse theme and return { css, vars }
*
* @param {Object} theme
* @param {{
* prefix?: string,
* shouldSkipGeneratingVar?: (objectPathKeys: Array<string>, value: string | number) => boolean
* }} options.
* `prefix`: The prefix of the generated CSS variables. This function does not change the value.
*
* @returns {{ css: Object, vars: Object }} `css` is the stylesheet, `vars` is an object to get css variable (same structure as theme).
*
* @example
* const { css, vars } = parser({
* fontSize: 12,
* lineHeight: 1.2,
* palette: { primary: { 500: 'var(--color)' } }
* }, { prefix: 'foo' })
*
* console.log(css) // { '--foo-fontSize': '12px', '--foo-lineHeight': 1.2, '--foo-palette-primary-500': 'var(--color)' }
* console.log(vars) // { fontSize: 'var(--foo-fontSize)', lineHeight: 'var(--foo-lineHeight)', palette: { primary: { 500: 'var(--foo-palette-primary-500)' } } }
*/
function cssVarsParser(theme, options) {
const {
prefix,
shouldSkipGeneratingVar
} = options || {};
const css = {};
const vars = {};
const varsWithDefaults = {};
walkObjectDeep(theme, (keys, value, arrayKeys) => {
if (typeof value === 'string' || typeof value === 'number') {
if (!shouldSkipGeneratingVar || !shouldSkipGeneratingVar(keys, value)) {
// only create css & var if `shouldSkipGeneratingVar` return false
const cssVar = `--${prefix ? `${prefix}-` : ''}${keys.join('-')}`;
Object.assign(css, {
[cssVar]: getCssValue(keys, value)
});
assignNestedKeys(vars, keys, `var(${cssVar})`, arrayKeys);
assignNestedKeys(varsWithDefaults, keys, `var(${cssVar}, ${value})`, arrayKeys);
}
}
}, keys => keys[0] === 'vars' // skip 'vars/*' paths
);
return {
css,
vars,
varsWithDefaults
};
} |