Skip to content

Commit df1732c

Browse files
authored
add ability to merge arrays of objects when using extend (#2700)
1 parent 584316f commit df1732c

File tree

2 files changed

+91
-3
lines changed

2 files changed

+91
-3
lines changed

__tests__/resolveConfig.test.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ test('theme values in the extend section can extend values that are depended on
810810
})
811811
})
812812

813-
test('theme values in the extend section are not deeply merged', () => {
813+
test('theme values in the extend section are not deeply merged when they are simple arrays', () => {
814814
const userConfig = {
815815
theme: {
816816
extend: {
@@ -856,6 +856,76 @@ test('theme values in the extend section are not deeply merged', () => {
856856
})
857857
})
858858

859+
test('theme values in the extend section are deeply merged, when they are arrays of objects', () => {
860+
const userConfig = {
861+
theme: {
862+
extend: {
863+
typography: {
864+
ArrayArray: {
865+
css: [{ a: { backgroundColor: 'red' } }, { a: { color: 'green' } }],
866+
},
867+
ObjectArray: {
868+
css: { a: { backgroundColor: 'red' } },
869+
},
870+
ArrayObject: {
871+
css: [{ a: { backgroundColor: 'red' } }, { a: { color: 'green' } }],
872+
},
873+
},
874+
},
875+
},
876+
}
877+
878+
const defaultConfig = {
879+
prefix: '-',
880+
important: false,
881+
separator: ':',
882+
theme: {
883+
typography: {
884+
ArrayArray: {
885+
css: [{ a: { underline: 'none' } }],
886+
},
887+
ObjectArray: {
888+
css: [{ a: { underline: 'none' } }],
889+
},
890+
ArrayObject: {
891+
css: { a: { underline: 'none' } },
892+
},
893+
},
894+
},
895+
variants: {},
896+
}
897+
898+
const result = resolveConfig([userConfig, defaultConfig])
899+
900+
expect(result).toMatchObject({
901+
prefix: '-',
902+
important: false,
903+
separator: ':',
904+
theme: {
905+
typography: {
906+
ArrayArray: {
907+
css: [
908+
{ a: { underline: 'none' } },
909+
{ a: { backgroundColor: 'red' } },
910+
{ a: { color: 'green' } },
911+
],
912+
},
913+
ObjectArray: {
914+
css: [{ a: { underline: 'none' } }, { a: { backgroundColor: 'red' } }],
915+
},
916+
ArrayObject: {
917+
css: [
918+
{ a: { underline: 'none' } },
919+
{ a: { backgroundColor: 'red' } },
920+
{ a: { color: 'green' } },
921+
],
922+
},
923+
},
924+
},
925+
variants: {},
926+
})
927+
})
928+
859929
test('the theme function can use a default value if the key is missing', () => {
860930
const userConfig = {
861931
theme: {

src/util/resolveConfig.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import map from 'lodash/map'
77
import get from 'lodash/get'
88
import uniq from 'lodash/uniq'
99
import toPath from 'lodash/toPath'
10+
import head from 'lodash/head'
11+
import isPlainObject from 'lodash/isPlainObject'
1012
import negateValue from './negateValue'
1113
import { corePluginList } from '../corePluginList'
1214
import configurePlugins from './configurePlugins'
@@ -67,8 +69,24 @@ function mergeThemes(themes) {
6769
}
6870
}
6971

70-
function mergeExtensionCustomizer(_merged, value) {
71-
if (Array.isArray(value)) return value
72+
function mergeExtensionCustomizer(merged, value) {
73+
// When we have an array of objects, we do want to merge it
74+
if (Array.isArray(merged) && isPlainObject(head(merged))) {
75+
return merged.concat(value)
76+
}
77+
78+
// When the incoming value is an array, and the existing config is an object, prepend the existing object
79+
if (Array.isArray(value) && isPlainObject(head(value)) && isPlainObject(merged)) {
80+
return [merged, ...value]
81+
}
82+
83+
// Override arrays (for example for font-families, box-shadows, ...)
84+
if (Array.isArray(value)) {
85+
return value
86+
}
87+
88+
// Execute default behaviour
89+
return undefined
7290
}
7391

7492
function mergeExtensions({ extend, ...theme }) {

0 commit comments

Comments
 (0)