From 23b720bb313661f42a1aa89d76f1bc49096e60ae Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Wed, 8 May 2019 22:11:10 +0200 Subject: [PATCH] Allow accessing deep paths with function values via theme helper Example: ```js theme: { spacing: { '0': '0', }, width: theme => ({ ...theme('spacing'), '1/3': '33.33333%', }), minWidth: theme => ({ '1/3': theme('width.1/3'), }), } ``` --- __tests__/resolveConfig.test.js | 53 +++++++++++++++++++++++++++++++++ src/util/resolveConfig.js | 15 ++++++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/__tests__/resolveConfig.test.js b/__tests__/resolveConfig.test.js index a37f0b59c..ea44f9f65 100644 --- a/__tests__/resolveConfig.test.js +++ b/__tests__/resolveConfig.test.js @@ -830,6 +830,59 @@ test('the theme function can resolve function values', () => { }) }) +test('the theme function can resolve deep function values', () => { + const userConfig = { + theme: { + minWidth: theme => ({ + '1/3': theme('width.1/3'), + }), + }, + } + + const defaultConfig = { + prefix: '-', + important: false, + separator: ':', + theme: { + spacing: { + '0': '0', + }, + width: theme => ({ + ...theme('spacing'), + '1/3': '33.33333%', + }), + }, + variants: { + backgroundColor: ['responsive', 'hover', 'focus'], + borderColor: ['responsive', 'hover', 'focus'], + }, + } + + const result = resolveConfig([userConfig, defaultConfig]) + + expect(result).toEqual({ + prefix: '-', + important: false, + separator: ':', + theme: { + spacing: { + '0': '0', + }, + width: { + '0': '0', + '1/3': '33.33333%', + }, + minWidth: { + '1/3': '33.33333%', + }, + }, + variants: { + backgroundColor: ['responsive', 'hover', 'focus'], + borderColor: ['responsive', 'hover', 'focus'], + }, + }) +}) + test('theme values in the extend section are lazily evaluated', () => { const userConfig = { theme: { diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index 7fc4fb65e..826d36466 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -2,7 +2,7 @@ import mergeWith from 'lodash/mergeWith' import isFunction from 'lodash/isFunction' import defaults from 'lodash/defaults' import map from 'lodash/map' -import get from 'lodash/get' +import toPath from 'lodash/toPath' const configUtils = { negative(scale) { @@ -40,8 +40,17 @@ function mergeExtensions({ extend, ...theme }) { function resolveFunctionKeys(object) { const resolveThemePath = (key, defaultValue) => { - const val = get(object, key, defaultValue) - return isFunction(val) ? val(resolveThemePath) : val + const path = toPath(key) + + let index = 0 + let val = object + + while (val !== undefined && val !== null && index < path.length) { + val = val[path[index++]] + val = isFunction(val) ? val(resolveThemePath) : val + } + + return val === undefined ? defaultValue : val } return Object.keys(object).reduce((resolved, key) => {