-
-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathgenerateAtomics.js
96 lines (90 loc) · 3.16 KB
/
generateAtomics.js
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
import cx from 'clsx';
export function generateAtomics() {
throw new Error(
`${process.env.PACKAGE_NAME}: You were trying to call "generateAtomics" function without configuring your bundler. Make sure to install the bundler specific plugin and use it. @pigment-css/vite-plugin for Vite integration or @pigment-css/nextjs-plugin for Next.js integration.`,
);
}
/**
* @typedef {Object} RuntimeConfig
* @property {Object.<string, Object.<string, Object.<string, string>>>} styles
* @property {Object.<string, string[]>} shorthands
* @property {string[]} conditions
* @property {string} defaultCondition
* @property {string} multiplier
*/
/**
* Given a mapping of atomic classes to css properties for each breakpoint, this function
* returns all the classnames associated with the runtime values.
*
* @param {RuntimeConfig} runtimeConfig
*/
export function atomics({ styles, shorthands, conditions, defaultCondition, multiplier }) {
function addStyles(cssProperty, propertyValue, classes, inlineStyle) {
const styleClasses = styles[cssProperty];
if (!styleClasses) {
return;
}
function handlePrimitive(value, breakpoint = defaultCondition) {
if (!(value in styleClasses)) {
const keys = Object.keys(styleClasses);
if (keys.length !== 1) {
return;
}
const key = keys[0];
let styleValue = value;
if (typeof value === 'number') {
styleValue = multiplier ? `calc(${value} * ${multiplier})` : `${value}px`;
}
classes.push(styleClasses[key][breakpoint]);
inlineStyle[`${key}${breakpoint === defaultCondition ? '' : `-${breakpoint}`}`] =
styleValue;
} else {
classes.push(styleClasses[value][breakpoint]);
}
}
if (typeof propertyValue === 'string' || typeof propertyValue === 'number') {
handlePrimitive(propertyValue);
} else if (Array.isArray(propertyValue)) {
propertyValue.forEach((value, index) => {
const breakpoint = conditions[index];
if (!breakpoint) {
return;
}
handlePrimitive(value, conditions[index]);
});
} else {
Object.keys(propertyValue).forEach((condition) => {
const propertyClasses = styleClasses[propertyValue[condition]];
if (!propertyClasses) {
handlePrimitive(propertyValue[condition], condition);
return;
}
handlePrimitive(propertyClasses[condition], condition);
});
}
}
function generateClass(props) {
const classes = [];
const inlineStyle = {};
const runtimeStyles = props;
Object.keys(runtimeStyles).forEach((cssProperty) => {
const values = runtimeStyles[cssProperty];
if (cssProperty in shorthands) {
const configShorthands = shorthands[cssProperty];
if (!configShorthands) {
return;
}
configShorthands.forEach((shorthand) => {
addStyles(shorthand, values, classes, inlineStyle);
});
} else {
addStyles(cssProperty, values, classes, inlineStyle);
}
});
return {
className: cx(Array.from(new Set(classes))),
style: inlineStyle,
};
}
return generateClass;
}