Skip to content

Commit f8a7e59

Browse files
committed
Implement common style sheets
1 parent f756cef commit f8a7e59

3 files changed

Lines changed: 111 additions & 59 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"homepage": "https://github.com/lttb/jss-styled#readme",
3535
"dependencies": {
3636
"is-react-prop": "^0.0.2",
37-
"react-jss": "^6.1.1"
37+
"jss": "^7.0.3",
38+
"jss-preset-default": "^2.0.0"
3839
},
3940
"peerDependencies": {
4041
"react": "^15.5.4",

src/index.jsx

Lines changed: 95 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,114 @@
1-
import React from 'react'
2-
import injectSheetDefault from 'react-jss'
1+
import React, {PureComponent} from 'react'
2+
3+
import {create as createJSS, getDynamicStyles} from 'jss'
4+
import preset from 'jss-preset-default'
35

46
import filterProps from './utils/filter-props'
57

68

7-
type StyledElementType = Function & { Tag: string, styles: Object }
8-
type TagNameOrStyledElementType = string | StyledElementType
9-
type PrimitivePropsType = {
9+
const JSS = createJSS(preset())
10+
11+
type StyledElementAttrsT = { Tag: string, styles: Object }
12+
type StyledElementT = Function & StyledElementAttrsT
13+
type TagOrStyledElementT = string | StyledElementT
14+
type StyledElementPropsT = {
1015
classes: Object,
1116
children: ?any,
1217
className: ?string,
1318
}
1419

1520

16-
export const createStyled = (injectSheet?: Function = injectSheetDefault) =>
17-
(
18-
TagNameOrStyledElement: TagNameOrStyledElementType,
19-
styles: Object,
20-
baseStyles?: Object = {},
21-
): StyledElementType => {
22-
const {
23-
Tag,
24-
styles: inheritStyles = {},
25-
}: {
26-
Tag: string,
27-
styles?: Object
28-
} = typeof TagNameOrStyledElement === 'string'
29-
? {Tag: TagNameOrStyledElement}
30-
: TagNameOrStyledElement
31-
32-
const elementStyles = {...inheritStyles, ...styles}
33-
34-
const Primitive = ({classes, children, className, ...attrs}: PrimitivePropsType) => {
35-
const props = filterProps(attrs)
36-
37-
return (
38-
<Tag className={className ? `${classes[Tag]} ${className}` : classes[Tag]} {...props}>
39-
{children}
40-
</Tag>
41-
)
42-
}
21+
export const createStyled = (jss?: Function = JSS) => (baseStyles: Object = {}) => {
22+
let sheet
23+
24+
let currentId = 0
25+
26+
return (TagOrStyledElement: TagOrStyledElementT, ownStyles: Object): StyledElementT => {
27+
const {Tag, styles}: StyledElementAttrsT = typeof TagOrStyledElement === 'string'
28+
? {Tag: TagOrStyledElement, styles: {}}
29+
: TagOrStyledElement
30+
31+
const elementStyles = {...styles, ...ownStyles}
32+
const dynamicStyles = getDynamicStyles(elementStyles)
33+
34+
const staticTag = `${Tag}-${++currentId}`
35+
36+
return class StyledElement extends PureComponent {
37+
props: StyledElementPropsT
38+
39+
static Tag = Tag
40+
static styles = elementStyles
41+
42+
tagScoped = ''
43+
dynamicSheet = null
44+
45+
constructor(props) {
46+
super(props)
4347

44-
const StyledPrimitive = injectSheet({
45-
[Tag]: elementStyles,
46-
...baseStyles,
47-
})(Primitive)
48+
this.tagScoped = `${Tag}-${++currentId}`
49+
}
4850

49-
return Object.assign(StyledPrimitive, {Tag, styles: elementStyles})
51+
componentWillMount() {
52+
if (!sheet) {
53+
sheet = jss.createStyleSheet(baseStyles, {
54+
link: true,
55+
meta: 'StaticBaseSheet',
56+
}).attach()
57+
}
58+
59+
if (!sheet.getRule(staticTag)) {
60+
sheet.addRule(staticTag, elementStyles)
61+
}
62+
63+
if (dynamicStyles && !this.dynamicSheet) {
64+
this.dynamicSheet = jss.createStyleSheet({[this.tagScoped]: dynamicStyles}, {
65+
link: true,
66+
meta: `DynamicComponentSheet-${this.tagScoped}`,
67+
}).update(this.props).attach()
68+
}
69+
}
70+
71+
componentWillReceiveProps(nextProps: StyledElementPropsT) {
72+
if (this.dynamicSheet) this.dynamicSheet.update(nextProps)
73+
}
74+
75+
componentWillUnmount() {
76+
if (this.dynamicSheet) {
77+
jss.removeStyleSheet(this.dynamicSheet)
78+
this.dynamicSheet = null
79+
}
80+
}
81+
82+
render() {
83+
if (!sheet) return null
84+
85+
const {children, className, ...attrs} = this.props
86+
87+
const props = filterProps(attrs)
88+
const tagClass = [
89+
sheet.classes[staticTag],
90+
this.dynamicSheet && this.dynamicSheet.classes[this.tagScoped],
91+
className,
92+
]
93+
.filter(Boolean)
94+
.join(' ')
95+
96+
return (
97+
<Tag className={tagClass} {...props}>
98+
{children}
99+
</Tag>
100+
)
101+
}
102+
}
50103
}
104+
}
51105

52-
const defaultStyled = createStyled()
106+
const defaultStyledBased = createStyled()
107+
const defaultStyled = defaultStyledBased()
53108

54109
export {defaultStyled as styled}
55110

56-
export const createStyledCreator = (styled: Function = defaultStyled) =>
57-
(baseStyles: Object) => Object.assign(
58-
(TagNameOrStyledElement: TagNameOrStyledElementType, styles: Object) =>
59-
styled(TagNameOrStyledElement, styles, baseStyles),
60-
{styles: baseStyles},
61-
)
111+
export const createStyledCreator = (styled: Function = defaultStyledBased) =>
112+
(baseStyles: Object) => Object.assign(styled(baseStyles), {styles: baseStyles})
62113

63114
export default createStyledCreator()

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,54 @@
11
exports[`test renders correctly App with default Styled 1`] = `
22
<div
3-
className="div-0-8">
3+
className="div-1-0-9">
44
<header
5-
className="header-0-10">
5+
className="header-2-0-10">
66
<h1
7-
className="h1-0-12">
7+
className="h1-5-0-11">
88
Title
99
</h1>
1010
</header>
1111
<section
12-
className="section-0-14">
12+
className="section-3-0-12">
1313
<button
14-
className="button-0-18 button-0-16">
14+
className="button-6-0-13 button-11-0-14">
1515
primitive test
1616
</button>
1717
<button
18-
className="button-0-20 button-0-16">
18+
className="button-6-0-13 button-12-0-15">
1919
dynamic primitive test
2020
</button>
2121
</section>
2222
<section
23-
className="section-0-22">
23+
className="section-4-0-16">
2424
Another section
2525
</section>
2626
</div>
2727
`;
2828

2929
exports[`test renders correctly App with default styled 1`] = `
3030
<div
31-
className="div-0-0">
31+
className="div-1-0-0">
3232
<header
33-
className="header-0-1">
33+
className="header-2-0-1">
3434
<h1
35-
className="h1-0-2">
35+
className="h1-5-0-2">
3636
Title
3737
</h1>
3838
</header>
3939
<section
40-
className="section-0-3">
40+
className="section-3-0-3">
4141
<button
42-
className="button-0-5 button-0-4">
42+
className="button-6-0-4 button-11-0-5">
4343
primitive test
4444
</button>
4545
<button
46-
className="button-0-6 button-0-4">
46+
className="button-6-0-4 button-12-0-6">
4747
dynamic primitive test
4848
</button>
4949
</section>
5050
<section
51-
className="section-0-7">
51+
className="section-4-0-7">
5252
Another section
5353
</section>
5454
</div>

0 commit comments

Comments
 (0)