Skip to content

Commit 3fe85ad

Browse files
committed
Implement property validation with is-native-prop
1 parent 4b9b6ad commit 3fe85ad

6 files changed

Lines changed: 87 additions & 25 deletions

File tree

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@
3333
},
3434
"homepage": "https://github.com/lttb/jss-styled#readme",
3535
"dependencies": {
36-
"react": "^15.5.4",
3736
"react-jss": "^6.1.1"
3837
},
38+
"peerDependencies": {
39+
"react": "^15.5.4",
40+
"react-dom": "^15.5.4"
41+
},
3942
"devDependencies": {
4043
"babel-cli": "^6.23.0",
4144
"babel-core": "^6.23.1",
@@ -47,6 +50,8 @@
4750
"eslint": "^3.13.0",
4851
"eslint-config-airbnb": "^14.1.0",
4952
"eslint-config-jss": "^3.0.0",
53+
"eslint-plugin-import": "^2.2.0",
54+
"eslint-plugin-jsx-a11y": "^4.0.0",
5055
"eslint-plugin-react": "^6.10.3",
5156
"flow-bin": "^0.44.2",
5257
"flow-typed": "^2.0.0",

src/index.jsx

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import React from 'react'
22
import injectSheetDefault from 'react-jss'
33

4+
import filterProps from './utils/filter-props'
5+
46

57
type StyledElementType = Function & { Tag: string, styles: Object }
6-
type PrimitiveProps = {
8+
type TagNameOrStyledElementType = string | StyledElementType
9+
type PrimitivePropsType = {
710
classes: Object,
8-
children?: any,
9-
className?: string,
11+
children: ?any,
12+
className: ?string,
1013
}
1114

1215

13-
export const prepareStyled = (injectSheet?: Function = injectSheetDefault) =>
16+
export const createStyled = (injectSheet?: Function = injectSheetDefault) =>
1417
(
15-
Element: string | StyledElementType,
18+
TagNameOrStyledElement: TagNameOrStyledElementType,
1619
styles: Object,
1720
baseStyles?: Object = {},
1821
): StyledElementType => {
@@ -22,30 +25,39 @@ export const prepareStyled = (injectSheet?: Function = injectSheetDefault) =>
2225
}: {
2326
Tag: string,
2427
styles?: Object
25-
} = typeof Element === 'string' ? { Tag: Element } : Element
28+
} = typeof TagNameOrStyledElement === 'string'
29+
? {Tag: TagNameOrStyledElement}
30+
: TagNameOrStyledElement
31+
32+
const elementStyles = {...inheritStyles, ...styles}
2633

27-
const elementStyles = { ...inheritStyles, ...styles }
34+
const Primitive = ({classes, children, className, ...attrs}: PrimitivePropsType) => {
35+
const props = filterProps(attrs)
2836

29-
const Primitive = ({ classes, children, className }: PrimitiveProps) =>
30-
<Tag className={classes[Tag].concat(className ? ` ${className}` : '')}>
31-
{children}
32-
</Tag>
37+
return (
38+
<Tag className={className ? `${classes[Tag]} ${className}` : classes[Tag]} {...props}>
39+
{children}
40+
</Tag>
41+
)
42+
}
3343

3444
const StyledPrimitive = injectSheet({
3545
[Tag]: elementStyles,
3646
...baseStyles,
3747
})(Primitive)
3848

39-
return Object.assign(StyledPrimitive, { Tag, styles: elementStyles })
49+
return Object.assign(StyledPrimitive, {Tag, styles: elementStyles})
4050
}
4151

42-
export const styled = prepareStyled()
52+
const defaultStyled = createStyled()
53+
54+
export {defaultStyled as styled}
4355

44-
export const setStyledCreator = (styledFunction: Function = styled) =>
56+
export const createStyledCreator = (styled: Function = defaultStyled) =>
4557
(baseStyles: Object) => Object.assign(
46-
(Element: string | StyledElementType, styles: Object) =>
47-
styledFunction(Element, styles, baseStyles),
48-
{ styles: baseStyles },
58+
(TagNameOrStyledElement: TagNameOrStyledElementType, styles: Object) =>
59+
styled(TagNameOrStyledElement, styles, baseStyles),
60+
{styles: baseStyles},
4961
)
5062

51-
export default setStyledCreator()
63+
export default createStyledCreator()

src/tests/App.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import React from 'react'
33

44
export default (styled: Function) => {
55
const App = styled('div', {
6-
margin: '50px',
6+
margin: 50,
77
})
88

99
const Header = styled('header', {
10-
padding: '10px',
10+
padding: 10,
1111
})
1212

1313
const Section = styled('section', {
@@ -23,7 +23,7 @@ export default (styled: Function) => {
2323
})
2424

2525
const Button = styled('button', {
26-
margin: ({ margin = 0 }) => `${margin}px`,
26+
margin: ({margin = 0}) => margin,
2727
})
2828

2929

@@ -35,7 +35,7 @@ export default (styled: Function) => {
3535

3636
<Section data-name="content">
3737
<Button>primitive test</Button>
38-
<Button _margin={10}>dynamic primitive test</Button>
38+
<Button margin={10}>dynamic primitive test</Button>
3939
</Section>
4040

4141
<AnotherSection>Another section</AnotherSection>

src/tests/__snapshots__/index.spec.jsx.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ exports[`test renders correctly App with default Styled 1`] = `
1515
primitive test
1616
</button>
1717
<button
18-
className="button-0-19 button-0-16">
18+
className="button-0-20 button-0-16">
1919
dynamic primitive test
2020
</button>
2121
</section>
2222
<section
23-
className="section-0-20">
23+
className="section-0-22">
2424
Another section
2525
</section>
2626
</div>

src/utils/filter-props.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import isNativeProp from './is-native-prop'
2+
3+
4+
export default (props: Object) => Object
5+
.entries(props)
6+
.reduce((acc, [name, value]) => (isNativeProp(name)
7+
? {...acc, [name]: value}
8+
: acc
9+
), {})

src/utils/is-native-prop.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import DOMProperty from 'react-dom/lib/DOMProperty'
2+
import EventPluginRegistry from 'react-dom/lib/EventPluginRegistry'
3+
4+
5+
const reactProps = {
6+
children: true,
7+
dangerouslySetInnerHTML: true,
8+
key: true,
9+
ref: true,
10+
11+
autoFocus: true,
12+
defaultValue: true,
13+
defaultChecked: true,
14+
innerHTML: true,
15+
suppressContentEditableWarning: true,
16+
onFocusIn: true,
17+
onFocusOut: true,
18+
}
19+
20+
21+
export default (prop: string) => {
22+
if (
23+
Object.prototype.hasOwnProperty.call(DOMProperty, prop) ||
24+
DOMProperty.isCustomAttribute(prop)
25+
) {
26+
return true
27+
}
28+
if (Object.prototype.hasOwnProperty.call(reactProps, prop) && reactProps[prop]) {
29+
return true
30+
}
31+
if (Object.prototype.hasOwnProperty.call(EventPluginRegistry.registrationNameModules, prop)) {
32+
return true
33+
}
34+
35+
return false
36+
}

0 commit comments

Comments
 (0)