UNPKG

1.43 kBJavaScriptView Raw
1export function isNestedStyle(value) {
2 // Don't merge objects overriding toString, since they should be converted
3 // to string values.
4 return value &&
5 value.constructor === Object &&
6 value.toString === Object.prototype.toString;
7}
8
9// Merge style objects. Deep merge plain object values.
10export function mergeStyles(styles) {
11 const result = {};
12
13 styles.forEach(style => {
14 if (!style || typeof style !== 'object') {
15 return;
16 }
17
18 if (Array.isArray(style)) {
19 style = mergeStyles(style);
20 }
21
22 Object.keys(style).forEach(key => {
23 // Simple case, nothing nested
24 if (!isNestedStyle(style[key]) || !isNestedStyle(result[key])) {
25 result[key] = style[key];
26 return;
27 }
28
29 // If nested media, don't merge the nested styles, append a space to the
30 // end (benign when converted to CSS). This way we don't end up merging
31 // media queries that appear later in the chain with those that appear
32 // earlier.
33 if (key.indexOf('@media') === 0) {
34 let newKey = key;
35 // eslint-disable-next-line no-constant-condition
36 while (true) {
37 newKey += ' ';
38 if (!result[newKey]) {
39 result[newKey] = style[key];
40 return;
41 }
42 }
43 }
44
45 // Merge all other nested styles recursively
46 result[key] = mergeStyles([result[key], style[key]]);
47 });
48 });
49
50 return result;
51}