Skip to content

Commit

Permalink
Added basic support for accepting custom shouldForwardProp option i…
Browse files Browse the repository at this point in the history
…n React Native related packages. (#1642)
  • Loading branch information
Andarist authored Nov 18, 2019
1 parent 828111c commit f1b7c9d
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 37 deletions.
6 changes: 6 additions & 0 deletions .changeset/wicked-mails-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@emotion/native': minor
'@emotion/primitives': minor
---

Added basic support for accepting custom `shouldForwardProp` option.
56 changes: 40 additions & 16 deletions packages/primitives-core/src/styled.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
// @flow
import * as React from 'react'
import { testAlwaysTrue, pickAssign, interleave } from './utils'
import { interleave } from './utils'
import { ThemeContext } from '@emotion/core'
import { createCss } from './css'

let defaultPickTest = prop => prop !== 'theme'
let testOmitPropsOnComponent = prop => prop !== 'theme'

type options = {
type CreateStyledOptions = {
getShouldForwardProp: (cmp: React.ElementType) => (prop: string) => boolean
}

type StyledOptions = {
shouldForwardProp?: (prop: string) => boolean
}

export function createStyled(
StyleSheet: Object,
{ getShouldForwardProp = () => defaultPickTest }: options = {}
{
getShouldForwardProp = () => testOmitPropsOnComponent
}: CreateStyledOptions = {}
) {
const css = createCss(StyleSheet)

return function createEmotion(component: React.ElementType) {
let pickTest = getShouldForwardProp(component)
return function createEmotion(
component: React.ElementType,
options?: StyledOptions
) {
let shouldForwardProp =
options && options.shouldForwardProp
? options.shouldForwardProp
: getShouldForwardProp(component)

return function createStyledComponent(...rawStyles: *) {
let styles
Expand All @@ -31,22 +43,34 @@ export function createStyled(
// do we really want to use the same infra as the web since it only really uses theming?
// $FlowFixMe
let Styled = React.forwardRef((props, ref) => {
let mergedProps = pickAssign(testAlwaysTrue, {}, props, {
theme: props.theme || React.useContext(ThemeContext)
})
let mergedProps = props
if (props.theme == null) {
mergedProps = {}
for (let key in props) {
mergedProps[key] = props[key]
}
mergedProps.theme = React.useContext(ThemeContext)
}

let stylesWithStyleProp = styles
if (props.style) {
stylesWithStyleProp = styles.concat(props.style)
}
const emotionStyles = css.apply(mergedProps, stylesWithStyleProp)

return React.createElement(
component,
pickAssign(pickTest, {}, props, {
ref: ref,
style: emotionStyles
})
)
let newProps = {}

for (let key in props) {
if (shouldForwardProp(key)) {
newProps[key] = props[key]
}
}

newProps.style = emotionStyles
newProps.ref = ref

// $FlowFixMe
return React.createElement(component, newProps)
})
// $FlowFixMe
Styled.withComponent = (newComponent: React.ElementType) =>
Expand Down
21 changes: 0 additions & 21 deletions packages/primitives-core/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,5 @@
// @flow

export const testAlwaysTrue = () => true

export const pickAssign: (
testFn: (key: string) => boolean,
target: {},
...sources: Array<{}>
) => Object = function(testFn, target) {
let i = 2
let length = arguments.length
for (; i < length; i++) {
let source = arguments[i]
let key
for (key in source) {
if (testFn(key)) {
target[key] = source[key]
}
}
}
return target
}

export function interleave(vals: Array<*>) {
let strings = vals[0]
let finalArray = [strings[0]]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Emotion primitives custom shouldForwardProp works 1`] = `
<Text
style={
Object {
"color": "hotpink",
}
}
>
Emotion
</Text>
`;

exports[`Emotion primitives primitive should work with \`withComponent\` 1`] = `
<Text
style={
Expand Down
16 changes: 16 additions & 0 deletions packages/primitives/test/emotion-primitives.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,20 @@ describe('Emotion primitives', () => {

expect(tree).toMatchSnapshot()
})

test('custom shouldForwardProp works', () => {
const Text = styled.Text``
const Title = props => <Text {...props} />
// $FlowFixMe
const StyledTitle = styled(Title, {
shouldForwardProp: prop => prop !== 'color' && prop !== 'theme'
})`
color: ${props => props.color};
`

const tree = renderer
.create(<StyledTitle color="hotpink">{'Emotion'}</StyledTitle>)
.toJSON()
expect(tree).toMatchSnapshot()
})
})

0 comments on commit f1b7c9d

Please sign in to comment.