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

Added basic support for accepting custom shouldForwardProp option in React Native related packages. #1642

Merged
merged 1 commit into from
Nov 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member Author

Choose a reason for hiding this comment

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

those changes align the implementation to what we have in @emotion/styled

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()
})
})