@nex-ui/system
Version:
A lightweight and performant styling library based on Emotion, focusing on component architecture and developer experience.
173 lines (167 loc) • 5.14 kB
JavaScript
;
var utils = require('@nex-ui/utils');
var serialize = require('@x1ngyu/serialize-javascript');
var knownCssProperties = require('known-css-properties');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var serialize__default = /*#__PURE__*/_interopDefault(serialize);
function pathToTokenName(path) {
return path.join('.');
}
function isDecimalString(str) {
return /^\d+\.\d+$/.test(str);
}
function createCssVarName(prefix, path) {
return `--${prefix}-${path.map((k)=>{
if (isDecimalString(k)) {
return k.split('.').join('-');
}
return utils.kebabCase(k);
}).join('-')}`;
}
function isResponsiveColor(value) {
return utils.isPlainObject(value) && (value._light || value._dark || value._DEFAULT);
}
function isValidTokenValue(value) {
if (!utils.isString(value) && typeof value !== 'number') {
return false;
}
return true;
}
function isValidSemanticTokenValue(value) {
if (!utils.isString(value) && typeof value !== 'number' && !isResponsiveColor(value)) {
return false;
}
return true;
}
function isValidTokenCategory(category) {
if (!utils.isString(category)) {
return false;
}
switch(category){
case 'colors':
case 'fontFamilies':
case 'fontSizes':
case 'fontWeights':
case 'sizes':
case 'spaces':
case 'lineHeights':
case 'borders':
case 'radii':
case 'breakpoints':
case 'shadows':
case 'transitions':
case 'borderWidths':
case 'zIndices':
return true;
default:
return false;
}
}
function isValidAliasValue(value) {
if (utils.isString(value) || Array.isArray(value) && value.every(utils.isString)) {
return true;
}
return false;
}
function isValidBreakpointValue(value) {
if (utils.isString(value) && parseInt(value, 10) >= 0) {
return true;
}
return false;
}
function memoizeFn(fn) {
return utils.memoize(fn, (...args)=>serialize__default.default(args));
}
function extractTokenPlaceholders(value) {
const regex = /\{(.*?)\}/g;
const matches = value.matchAll(regex);
return [
...matches
];
}
// TODO 明确 CSS 合并规则
function mergeRecipeConfigs(...args) {
const recipes = JSON.parse(JSON.stringify(args));
return utils.mergeWith({}, ...recipes, (targetValue, srcValue, key)=>{
if (key === 'compoundVariants') {
if (targetValue === undefined) {
return srcValue;
}
if (Array.isArray(targetValue) && Array.isArray(srcValue)) {
return [
...targetValue,
...srcValue
];
}
}
if (typeof targetValue !== typeof srcValue || Array.isArray(targetValue) !== Array.isArray(srcValue) || utils.isPlainObject(targetValue) !== utils.isPlainObject(srcValue)) {
return srcValue;
}
});
}
const toExpression = (operator, ...operands)=>operands.map(String).join(` ${operator} `).replace(/calc/g, '');
const multiply = (...operands)=>`calc(${toExpression('*', ...operands)})`;
const negate = (x)=>{
const value = String(x);
if (value != null && !Number.isNaN(parseFloat(value))) {
if (Number(value) === 0) {
return '0';
}
return value.startsWith('-') ? value.slice(1) : `-${value}`;
}
return multiply(value, -1);
};
const ALL_CSS_PROPERTIES = new Set(knownCssProperties.all.map(utils.camelCase));
const isCSSProperty = (key)=>{
// CSS variable
if (key.startsWith('--')) return true;
return ALL_CSS_PROPERTIES.has(key);
};
const isSelector = (key)=>{
// start with &
if (/&/.test(key)) {
return true;
}
// combinators
if (/^(?!.*@)(?!.*\()(\s*[>+~]\s*|[a-zA-Z]\s+[a-zA-Z])/.test(key)) {
return true;
}
// special rules
if (/^@(media|keyframes|supports|import|namespace|layer)/.test(key)) {
return true;
}
// id or class selector
if (/^[#.]/.test(key)) {
return true;
}
// attribute selector
if (/\[[^\]]*[=~|^$*]?[^\]]*\]/.test(key)) {
return true;
}
// multiple selectors
if (/,/.test(key)) {
return true;
}
// wildcard selector
if (/\*/.test(key)) {
return true;
}
if (isCSSProperty(key)) {
return false;
}
return true;
};
exports.createCssVarName = createCssVarName;
exports.extractTokenPlaceholders = extractTokenPlaceholders;
exports.isResponsiveColor = isResponsiveColor;
exports.isSelector = isSelector;
exports.isValidAliasValue = isValidAliasValue;
exports.isValidBreakpointValue = isValidBreakpointValue;
exports.isValidSemanticTokenValue = isValidSemanticTokenValue;
exports.isValidTokenCategory = isValidTokenCategory;
exports.isValidTokenValue = isValidTokenValue;
exports.memoizeFn = memoizeFn;
exports.mergeRecipeConfigs = mergeRecipeConfigs;
exports.multiply = multiply;
exports.negate = negate;
exports.pathToTokenName = pathToTokenName;