diff --git a/packages/serialize/src/index.js b/packages/serialize/src/index.js index 8352ba935..f2542316a 100644 --- a/packages/serialize/src/index.js +++ b/packages/serialize/src/index.js @@ -239,6 +239,9 @@ function createStringFromObject( } else { for (let key in obj) { let value = obj[key] + if (typeof value === 'function' && mergedProps !== undefined) { + value = value(mergedProps) + } if (typeof value !== 'object') { if (registered != null && registered[value] !== undefined) { string += `${key}{${registered[value]}}` diff --git a/packages/serialize/types/index.d.ts b/packages/serialize/types/index.d.ts index 12482c98e..96158c0f7 100644 --- a/packages/serialize/types/index.d.ts +++ b/packages/serialize/types/index.d.ts @@ -7,18 +7,23 @@ import * as CSS from 'csstype' export { RegisteredCache, SerializedStyles } export type CSSProperties = CSS.PropertiesFallback -export type CSSPropertiesWithMultiValues = { +export type CSSPropertiesWithMultiValues = { [K in keyof CSSProperties]: | CSSProperties[K] - | ReadonlyArray> + | ReadonlyArray + | (( + props: Props + ) => CSSProperties[K] | ReadonlyArray) } -export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject } +export type CSSPseudos = { + [K in CSS.Pseudos]?: CSSObject +} export interface ArrayCSSInterpolation extends ReadonlyArray {} -export type InterpolationPrimitive = +export type InterpolationPrimitive = | null | undefined | boolean @@ -27,18 +32,25 @@ export type InterpolationPrimitive = | ComponentSelector | Keyframes | SerializedStyles - | CSSObject + | CSSObject export type CSSInterpolation = InterpolationPrimitive | ArrayCSSInterpolation -export interface CSSOthersObject { - [propertiesName: string]: CSSInterpolation +export interface CSSOthersObject { + [propertiesName: string]: + | InterpolationPrimitive + | ReadonlyArray> + | (( + props: Props + ) => + | InterpolationPrimitive + | ReadonlyArray>) } -export interface CSSObject - extends CSSPropertiesWithMultiValues, - CSSPseudos, - CSSOthersObject {} +export interface CSSObject + extends CSSPropertiesWithMultiValues, + CSSPseudos, + CSSOthersObject {} export interface ComponentSelector { __emotion_styles: any @@ -59,7 +71,7 @@ export interface FunctionInterpolation { } export type Interpolation = - | InterpolationPrimitive + | InterpolationPrimitive | ArrayInterpolation | FunctionInterpolation diff --git a/packages/serialize/types/tests.ts b/packages/serialize/types/tests.ts index 74f58a2f9..3a7ae79e0 100644 --- a/packages/serialize/types/tests.ts +++ b/packages/serialize/types/tests.ts @@ -37,6 +37,23 @@ serializeStyles( {} ) // $ExpectType SerializedStyles +serializeStyles<{ + vars: { background: string; foreground: string; step: number } +}>([ + { + display: () => ['-webkit-flex', 'flex'], + backgroundColor: ({ vars }) => vars.background, + color: ({ vars }) => vars.foreground, + lineHeight: ({ vars }) => 1.2, + '--spacing': () => 1, + '--step': ({ vars }) => `calc(${vars.step} * var(--spacing))`, + '&:hover': { + backgroundColor: ({ vars }) => vars.foreground, + color: ({ vars }) => vars.background + } + } +]) +// $ExpectType SerializedStyles serializeStyles([testTemplateStringsArray, 5, '4px'], {}, {}) // $ExpectError @@ -44,6 +61,8 @@ serializeStyles() // $ExpectError serializeStyles({}) // $ExpectError +serializeStyles([{ borderCollapse: () => 'unknown' }]) +// $ExpectError serializeStyles({}, {}) let cssObject: CSSObject = { diff --git a/packages/styled/__tests__/__snapshots__/styled.js.snap b/packages/styled/__tests__/__snapshots__/styled.js.snap index 79db82466..0a97a38e1 100644 --- a/packages/styled/__tests__/__snapshots__/styled.js.snap +++ b/packages/styled/__tests__/__snapshots__/styled.js.snap @@ -483,6 +483,18 @@ exports[`styled objects 1`] = ` `; +exports[`styled objects with dynamic value 1`] = ` +.emotion-0 { + padding: 0.5rem; +} + +

+ hello world +

+`; + exports[`styled objects with spread properties 1`] = ` .emotion-0 { font-size: 20px; diff --git a/packages/styled/__tests__/styled.js b/packages/styled/__tests__/styled.js index 853e79f61..462921dc1 100644 --- a/packages/styled/__tests__/styled.js +++ b/packages/styled/__tests__/styled.js @@ -437,6 +437,13 @@ describe('styled', () => { expect(tree).toMatchSnapshot() }) + test('objects with dynamic value', () => { + const H1 = styled('h1')({ padding: props => props.padding || '1rem' }) + const tree = renderer.create(

hello world

).toJSON() + + expect(tree).toMatchSnapshot() + }) + test('composing components', () => { const Button = styled.button` color: green;