diff --git a/src/theme-preval.ts b/src/theme-preval.ts index b1c8b9b1ad5..83b1778170b 100644 --- a/src/theme-preval.ts +++ b/src/theme-preval.ts @@ -349,8 +349,14 @@ const stateLabels = { } } -const functionalColors = splitCompoundColor(primitives.colors.light) -const mergedColors = deepmerge(colors, functionalColors) +const {scale: _excludeScaleColors, ...functionalColors} = shadowFilter(primitives.colors.light, false) +const {scale: _excludeScaleShadows, auto: _excludeAuto, ...functionalShadows} = shadowFilter(primitives.colors.light, true) + +const filteredShadows = recursivelyFilterEmptyObjects(functionalShadows) +const filteredColors = recursivelyFilterEmptyObjects(functionalColors) + +const mergedColors = deepmerge(colors, filteredColors) +const mergedShadows = deepmerge(shadows, filteredShadows) export const theme = { // General @@ -362,7 +368,7 @@ export const theme = { fontWeights, lineHeights, radii, - shadows, + shadows: mergedShadows, sizes, space, @@ -379,19 +385,69 @@ function fontStack(fonts: string[]) { return fonts.map(font => (font.includes(' ') ? `"${font}"` : font)).join(', ') } -function splitCompoundColor(o: { [key: string]: any }) { +// The following few methods are data wrangling to split apart shadow values from non-shadow values +// and also ensure the resulting objects don't contain empty objects from filtering +// These methods are a temporary measure until we push these changes upstream to primer primitives + +function shadowFilter(o: { [key: string]: any }, filterShadow: boolean) { const newObject: { [key: string]: any } = {} Object.keys(o).forEach(function(key: string) { const value: any | undefined = o[key]; - if (typeof value === "string" && value.match(/(inset\s|)([0-9.empx\s]+){1,4}rgb[a]?\(.*\)/)) { - const numericParams = value.replace(/rgb[a]?\(.*\)/g, '').trim() - newObject[key] = numericParams - newObject[key+"Color"] = value.replace(numericParams, '').trim() - } else if (typeof value === "object") { - newObject[key] = splitCompoundColor(value) + if (typeof value == "object" && !Array.isArray(value)) { + newObject[key] = shadowFilter(value, filterShadow) + } else if (typeof value === "string" && value.match(/(inset\s|)([0-9.empx\s]+){1,4}rgb[a]?\(.*\)/)) { + // this is a shadow value + if (filterShadow) { + newObject[key] = value + } + } else if (typeof value === "string") { + // this is any other non shadow string value + if (!filterShadow) { + newObject[key] = value + } } else { newObject[key] = value } }) return newObject; } + +function recursivelyFilterEmptyObjects(o: { [key: string]: any }) { + const newObject: { [key: string]: any } = {} + Object.keys(o).forEach(function(key: string) { + const value: any | undefined = o[key]; + if (typeof value == "object" && !Array.isArray(value)) { + if (isObjectRecursivelyPresent(value)) { + newObject[key] = value + } else { + const filteredChild = recursivelyFilterEmptyObjects(value) + if (Object.keys(filteredChild).length > 0) { + newObject[key] = filteredChild + } + } + } else { + newObject[key] = value + } + }) + return newObject; +} + +function isObjectRecursivelyPresent(o: { [key: string]: any }) { + const presenceValues: boolean[] = [] + if (Object.keys(o).length === 0) { return false } + Object.keys(o).forEach(function(key: string) { + const value: any | undefined = o[key]; + if (typeof value === 'object' && !Array.isArray(value)) { + if (Object.keys(value).length === 0) { + presenceValues.push(false) + } else { + const isRecursivelyPresent = isObjectRecursivelyPresent(value) + presenceValues.push(isRecursivelyPresent) + } + } else { + presenceValues.push(true) + } + }) + + return presenceValues.every(p=>p) +}