Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic value support for extract static in the styled function. #279

Closed
wants to merge 14 commits into from
34 changes: 33 additions & 1 deletion packages/emotion/src/index.js
Expand Up @@ -9,6 +9,7 @@ import {
clean,
createMarkupForStyles,
hashString as hash,
hashArray,
hashObject
} from 'emotion-utils'

Expand Down Expand Up @@ -82,7 +83,38 @@ export function css(objs: any, vars: Array<any>, content: () => Array<any>) {
return computedClassName.trim()
}

function insertRawRule(css: string) {
type inputVar = string | number

export function customProperties(baseClassName: string, vars: Array<inputVar>) {
const hash = hashArray([baseClassName, ...vars])
const varCls = `css-vars-${hash}`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this so that users could SSR and extract the custom property values, but I'm not sure if it will trip up in other places.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to write a test for it but I think we have to do something different to get SSR to work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wrong! it works right now! 🎉

if (inserted[hash]) {
return varCls
}

let src = ''
forEach(vars, (val: inputVar, i: number) => {
src && (src += '; ')
src += `--${baseClassName}-${i}: ${val}`
})

let spec = {
id: hash,
css: `.${varCls} {${src}}`,
type: 'raw'
}

register(spec)

if (!inserted[spec.id]) {
sheet.insert(spec.css)
inserted[spec.id] = true
}

return varCls
}

export function insertRawRule(css: string) {
let spec = {
id: hash(css),
css,
Expand Down
21 changes: 10 additions & 11 deletions packages/emotion/test/extract/__snapshots__/extract.test.js.snap
Expand Up @@ -6,36 +6,35 @@ exports[`styled basic render nested 1`] = `
>
hello world
</h1>
`
`;

exports[`styled name 1`] = `
<h1
className="styled-H1-131pfth styled-H1-r6dkuc3"
>
hello world
</h1>
`
`;

exports[`styled no dynamic 1`] = `
<h1
className="styled-H1-ijh7uz styled-H1-r6dkuc0"
>
hello world
</h1>
`
`;

exports[`styled with expressions 1`] = `
.glamor-0 {
--styled-H1-1t8i2zo-0: 24;
}

<h1
className="styled-H1-1t8i2zo styled-H1-r6dkuc2"
style={
Object {
"styled-H1-1t8i2zo-0": 24,
}
}
className="styled-H1-1t8i2zo glamor-0 styled-H1-r6dkuc2"
>
hello world
</h1>
`
`;

exports[`styled writes the correct css 1`] = `
".styled-H1-ijh7uz {
Expand Down Expand Up @@ -68,4 +67,4 @@ html {
color: yellow;
background-color: purple
}"
`
`;
33 changes: 6 additions & 27 deletions packages/react-emotion/src/index.js
@@ -1,5 +1,5 @@
import { createElement as h } from 'react'
import { css } from 'emotion'
import { css, customProperties } from 'emotion'
import { map, reduce, assign, omit } from 'emotion-utils'
import propsRegexString from /* preval */ './props'

Expand All @@ -18,7 +18,7 @@ export default function(tag, cls, objs, vars = [], content) {
)
}

const FAST_PATH = vars && vars.length && !content
const EXTRACTED_DYNAMIC = vars && vars.length && !content

const componentTag = tag.displayName || tag.name || 'Component'
const spec = {
Expand Down Expand Up @@ -48,31 +48,6 @@ export default function(tag, cls, objs, vars = [], content) {
return v
}

if (FAST_PATH) {
return h(
localTag,
omit(
assign({}, props, {
ref: props.innerRef,
className: objs[0],
style: assign(
{},
props.style,
reduce(
map(vars, getValue),
(accum, value, i) => {
accum[`${objs[0]}-${i}`] = value
return accum
},
{}
)
)
}),
omitFn
)
)
}

let finalObjs = []

push(
Expand All @@ -83,6 +58,10 @@ export default function(tag, cls, objs, vars = [], content) {
push(accum, spec.objs)
if (spec.content) {
accum.push(spec.content.apply(null, map(spec.vars, getValue)))
} else if (spec.vars.length) {
// Dynamic properties for extracted css will have variables
// but no content function
accum.push(customProperties(spec.objs[0], map(spec.vars, getValue)))
}
accum.push(spec.cls)
return accum
Expand Down