Skip to content

Commit bcf7475

Browse files
committed
Get rid from dynamicStyleSheet, fix nested dynamic rules
1 parent ac5cb91 commit bcf7475

5 files changed

Lines changed: 68 additions & 37 deletions

File tree

.flowconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@
55

66
<PROJECT_ROOT>/lib/
77

8+
[libs]
9+
node_modules/jss/flow-typed
10+
811
[options]
912
all=true

src/createStyled.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,17 @@ const getStyledArgs = (
2121
}
2222

2323
const createStyled = (jss: Function) => (baseStyles: BaseStylesType = {}): StyledType => {
24-
let staticSheet
25-
let dynamicSheet
24+
let sheet
2625

27-
const mountSheets = () => {
28-
if (!staticSheet) {
29-
staticSheet = jss.createStyleSheet(baseStyles, {
30-
meta: 'StaticBaseSheet',
31-
}).attach()
32-
33-
dynamicSheet = jss.createStyleSheet({}, {
26+
const mountSheet = () => {
27+
if (!sheet) {
28+
sheet = jss.createStyleSheet(baseStyles, {
3429
link: true,
35-
meta: 'DynamicComponentSheet',
30+
meta: 'sheet',
3631
}).attach()
3732
}
3833

39-
return {staticSheet, dynamicSheet}
34+
return sheet
4035
}
4136

4237
return Object.assign((
@@ -47,8 +42,8 @@ const createStyled = (jss: Function) => (baseStyles: BaseStylesType = {}): Style
4742
const {tagName, style} = getStyledArgs(tagNameOrStyledElement)
4843
const elementStyle = {...style, ...ownStyle}
4944

50-
return styled({tagName, baseStyles, elementStyle, mountSheets})
51-
}, {mountSheets, styles: baseStyles})
45+
return styled({tagName, baseStyles, elementStyle, mountSheet})
46+
}, {mountSheet, styles: baseStyles})
5247
}
5348

5449
export default createStyled

src/injectStyled.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import composeClasses from './utils/composeClasses'
44
import type {StyledType} from './types'
55

66
const injectStyled = (styled: StyledType) => (InnerComponent: ReactClass<any>) => {
7-
const {staticSheet, dynamicSheet} = styled.mountSheets()
7+
const sheet = styled.mountSheet()
88

9-
const classNames = Object.keys({...staticSheet.classes, ...dynamicSheet.classes})
9+
const classNames = Object.keys(sheet.classes)
1010

1111
const classes = [...classNames]
1212
.reduce((acc, name) => ({
1313
...acc,
14-
[name]: composeClasses([staticSheet.classes[name], dynamicSheet.classes[name]]),
14+
[name]: composeClasses([sheet.classes[name]]),
1515
}), {})
1616

1717
return (props: Object) => createElement(InnerComponent, {classes, ...props})

src/styled.js

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
import {Component, createElement} from 'react'
22
import {getDynamicStyles} from 'jss'
3+
import type {
4+
Rule,
5+
} from 'jss/lib/types'
36

47
import filterProps from './utils/filterProps'
58
import composeClasses from './utils/composeClasses'
69
import generateTagName from './utils/generateTagName'
710

811
import type {
9-
JssStaticSheet,
10-
JssDynamicSheet,
12+
JssSheet,
1113
ComponentStyleType,
1214
StyledElementPropsType
1315
} from './types'
1416

1517
type StyledArgs = {
1618
tagName: string,
1719
elementStyle: ComponentStyleType,
18-
mountSheets: Function
20+
mountSheet: Function
1921
}
2022

21-
const styled = ({tagName, elementStyle, mountSheets}: StyledArgs) => {
23+
const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
2224
const dynamicStyle = getDynamicStyles(elementStyle)
2325
const staticTagName = generateTagName(tagName)
2426

2527
const availableDynamicTagNames = []
28+
const classMap = {}
2629

2730
return class StyledElement extends Component {
2831
static tagName: string = tagName
@@ -31,8 +34,10 @@ const styled = ({tagName, elementStyle, mountSheets}: StyledArgs) => {
3134
props: StyledElementPropsType
3235

3336
dynamicTagName = ''
34-
staticSheet: JssStaticSheet
35-
dynamicSheet: JssDynamicSheet
37+
38+
sheet: JssSheet
39+
cssRules: CSSStyleRule[]
40+
rulesIndex: Rule[]
3641

3742
constructor(props: StyledElementPropsType) {
3843
super(props)
@@ -42,24 +47,55 @@ const styled = ({tagName, elementStyle, mountSheets}: StyledArgs) => {
4247
}
4348

4449
componentWillMount() {
45-
Object.assign(this, mountSheets())
50+
this.sheet = this.sheet || mountSheet()
51+
this.rulesIndex = this.sheet.rules.index
52+
this.cssRules = this.cssRules || this.sheet.renderer.getRules() || []
53+
54+
const rulesTotal = this.rulesIndex.length
55+
const cssRulesTotal = this.cssRules.length
4656

47-
if (!this.staticSheet.getRule(staticTagName)) {
48-
this.staticSheet.addRule(staticTagName, elementStyle)
57+
if (!this.sheet.getRule(staticTagName)) {
58+
this.sheet.addRule(staticTagName, elementStyle)
4959
}
5060

5161
if (!dynamicStyle) return
5262

53-
if (!this.dynamicSheet.getRule(this.dynamicTagName)) {
54-
this.dynamicSheet.addRule(this.dynamicTagName, dynamicStyle)
63+
if (!this.sheet.getRule(this.dynamicTagName)) {
64+
this.sheet.addRule(this.dynamicTagName, dynamicStyle)
5565
}
5666

57-
this.dynamicSheet.update(this.dynamicTagName, this.props)
67+
classMap[this.dynamicTagName] = this.rulesIndex.slice(rulesTotal)
68+
69+
let cssRule
70+
let rule
71+
let cssRuleIndex = 0
72+
let ruleIndex = 0
73+
// nested styles become to flatten rules, so we need to update each nested rule
74+
for (ruleIndex; ruleIndex < classMap[this.dynamicTagName].length; ruleIndex++) {
75+
rule = classMap[this.dynamicTagName][ruleIndex]
76+
cssRule = this.cssRules[cssRulesTotal + cssRuleIndex]
77+
if (cssRule && cssRule.selectorText === rule.selectorText) {
78+
/**
79+
* we need to set cssRule in rule.renderable
80+
* @see {@link https://github.com/cssinjs/jss/issues/500}
81+
* and we don't want to use link(), because there is no need to iterate over all rules
82+
*/
83+
rule.renderable = cssRule
84+
cssRuleIndex++
85+
}
86+
this.sheet.update(rule.name, this.props)
87+
}
5888
}
5989

60-
componentWillReceiveProps(nextProps: StyledElementPropsType) {
90+
componentWillReceiveProps() {
6191
if (dynamicStyle) {
62-
this.dynamicSheet.update(this.dynamicTagName, nextProps)
92+
let rule
93+
let ruleIndex = 0
94+
// the same rules update as in constructor
95+
for (ruleIndex; ruleIndex < classMap[this.dynamicTagName].length; ruleIndex++) {
96+
rule = classMap[this.dynamicTagName][ruleIndex]
97+
this.sheet.update(rule.name, this.props)
98+
}
6399
}
64100
}
65101

@@ -68,14 +104,12 @@ const styled = ({tagName, elementStyle, mountSheets}: StyledArgs) => {
68104
}
69105

70106
render() {
71-
if (!this.staticSheet) return null
72-
73107
const {children, className, ...attrs} = this.props
74108

75109
const props = filterProps(attrs)
76110
const tagClass = composeClasses([
77-
this.staticSheet.classes[staticTagName],
78-
this.dynamicSheet.classes[this.dynamicTagName],
111+
this.sheet.classes[staticTagName],
112+
this.sheet.classes[this.dynamicTagName],
79113
className
80114
])
81115

src/types/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
export type JssStyles = Object
22
export type JssStyle = Object
3-
export type JssStaticSheet = Object
4-
export type JssDynamicSheet = JssStaticSheet
3+
export type JssSheet = Object
54

65
export type BaseStylesType = JssStyles
76
export type ComponentStyleType = JssStyle
87
export type StyledType = Function & {
9-
mountSheets: Function,
8+
mountSheet: Function,
109
styles: JssStyles
1110
}
1211
export type StyledElementAttrsType = {tagName: string, style: ComponentStyleType}

0 commit comments

Comments
 (0)