Skip to content

Commit cb7ca3d

Browse files
committed
Support defining variants as functions for easier extending
1 parent b3270a5 commit cb7ca3d

File tree

2 files changed

+125
-8
lines changed

2 files changed

+125
-8
lines changed

__tests__/resolveConfig.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,3 +1736,61 @@ test('user theme extensions take precedence over plugin theme extensions with th
17361736
plugins: userConfig.plugins,
17371737
})
17381738
})
1739+
1740+
test('variants can be defined as a function', () => {
1741+
const userConfig = {
1742+
variants: {
1743+
backgroundColor: ({ variants }) => [...variants('backgroundColor'), 'disabled'],
1744+
padding: ({ before }) => before(['active']),
1745+
float: ({ before }) => before(['disabled'], 'focus'),
1746+
margin: ({ before }) => before(['hover'], 'focus'),
1747+
borderWidth: ({ after }) => after(['active']),
1748+
backgroundImage: ({ after }) => after(['disabled'], 'hover'),
1749+
opacity: ({ after }) => after(['hover'], 'focus'),
1750+
cursor: ({ before, after }) => before(['checked'], 'hover', after(['hover'], 'focus')),
1751+
},
1752+
}
1753+
1754+
const otherConfig = {
1755+
variants: {
1756+
backgroundColor: ({ variants }) => [...variants('backgroundColor'), 'active'],
1757+
},
1758+
}
1759+
1760+
const defaultConfig = {
1761+
prefix: '',
1762+
important: false,
1763+
separator: ':',
1764+
theme: {},
1765+
variants: {
1766+
backgroundColor: ['responsive', 'hover', 'focus'],
1767+
padding: ['responsive', 'focus'],
1768+
float: ['responsive', 'hover', 'focus'],
1769+
margin: ['responsive'],
1770+
borderWidth: ['responsive', 'focus'],
1771+
backgroundImage: ['responsive', 'hover', 'focus'],
1772+
opacity: ['responsive'],
1773+
cursor: ['responsive', 'focus'],
1774+
},
1775+
}
1776+
1777+
const result = resolveConfig([userConfig, otherConfig, defaultConfig])
1778+
1779+
expect(result).toEqual({
1780+
prefix: '',
1781+
important: false,
1782+
separator: ':',
1783+
theme: {},
1784+
variants: {
1785+
backgroundColor: ['responsive', 'hover', 'focus', 'active', 'disabled'],
1786+
padding: ['active', 'responsive', 'focus'],
1787+
float: ['responsive', 'hover', 'disabled', 'focus'],
1788+
margin: ['responsive', 'hover'],
1789+
borderWidth: ['responsive', 'focus', 'active'],
1790+
backgroundImage: ['responsive', 'hover', 'disabled', 'focus'],
1791+
opacity: ['hover', 'responsive'],
1792+
cursor: ['responsive', 'focus', 'checked', 'hover'],
1793+
},
1794+
plugins: userConfig.plugins,
1795+
})
1796+
})

src/util/resolveConfig.js

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ function mergeExtensions({ extend, ...theme }) {
8383
}
8484

8585
function resolveFunctionKeys(object) {
86-
const resolveThemePath = (key, defaultValue) => {
86+
const resolvePath = (key, defaultValue) => {
8787
const path = toPath(key)
8888

8989
let index = 0
9090
let val = object
9191

9292
while (val !== undefined && val !== null && index < path.length) {
9393
val = val[path[index++]]
94-
val = isFunction(val) ? val(resolveThemePath, configUtils) : val
94+
val = isFunction(val) ? val(resolvePath, configUtils) : val
9595
}
9696

9797
return val === undefined ? defaultValue : val
@@ -100,7 +100,7 @@ function resolveFunctionKeys(object) {
100100
return Object.keys(object).reduce((resolved, key) => {
101101
return {
102102
...resolved,
103-
[key]: isFunction(object[key]) ? object[key](resolveThemePath, configUtils) : object[key],
103+
[key]: isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key],
104104
}
105105
}, {})
106106
}
@@ -128,6 +128,62 @@ function extractPluginConfigs(configs) {
128128
return allConfigs
129129
}
130130

131+
function resolveVariants([firstConfig, ...variantConfigs]) {
132+
if (Array.isArray(firstConfig)) {
133+
return firstConfig
134+
}
135+
136+
return [firstConfig, ...variantConfigs].reverse().reduce((resolved, variants) => {
137+
Object.entries(variants || {}).forEach(([plugin, pluginVariants]) => {
138+
if (isFunction(pluginVariants)) {
139+
resolved[plugin] = pluginVariants({
140+
variants: function(path) {
141+
return get(resolved, path, [])
142+
},
143+
before: function(toInsert, variant, existingPluginVariants = get(resolved, plugin, [])) {
144+
if (variant === undefined) {
145+
return [...toInsert, ...existingPluginVariants]
146+
}
147+
148+
const index = existingPluginVariants.indexOf(variant)
149+
150+
if (index === -1) {
151+
return [...existingPluginVariants, ...toInsert]
152+
}
153+
154+
return [
155+
...existingPluginVariants.slice(0, index),
156+
...toInsert,
157+
...existingPluginVariants.slice(index),
158+
]
159+
},
160+
after: function(toInsert, variant, existingPluginVariants = get(resolved, plugin, [])) {
161+
if (variant === undefined) {
162+
return [...existingPluginVariants, ...toInsert]
163+
}
164+
165+
const index = existingPluginVariants.indexOf(variant)
166+
167+
if (index === -1) {
168+
return [...toInsert, ...existingPluginVariants]
169+
}
170+
171+
return [
172+
...existingPluginVariants.slice(0, index + 1),
173+
...toInsert,
174+
...existingPluginVariants.slice(index + 1),
175+
]
176+
},
177+
})
178+
} else {
179+
resolved[plugin] = pluginVariants
180+
}
181+
})
182+
183+
return resolved
184+
}, {})
185+
}
186+
131187
export default function resolveConfig(configs) {
132188
const allConfigs = extractPluginConfigs(configs)
133189

@@ -136,11 +192,14 @@ export default function resolveConfig(configs) {
136192
theme: resolveFunctionKeys(
137193
mergeExtensions(mergeThemes(map(allConfigs, t => get(t, 'theme', {}))))
138194
),
139-
variants: (firstVariants => {
140-
return Array.isArray(firstVariants)
141-
? firstVariants
142-
: defaults({}, ...map(allConfigs, 'variants'))
143-
})(defaults({}, ...map(allConfigs)).variants),
195+
variants: resolveVariants(allConfigs.map(c => c.variants)),
196+
// variants: resolveFunctionKeys(
197+
// (firstVariants => {
198+
// return Array.isArray(firstVariants)
199+
// ? firstVariants
200+
// : defaults({}, ...map(allConfigs, 'variants'))
201+
// })(defaults({}, ...map(allConfigs)).variants)
202+
// ),
144203
},
145204
...allConfigs
146205
)

0 commit comments

Comments
 (0)