11import { Component , createElement } from 'react'
22import { getDynamicStyles } from 'jss'
3+ import type {
4+ Rule ,
5+ } from 'jss/lib/types'
36
47import filterProps from './utils/filterProps'
58import composeClasses from './utils/composeClasses'
69import generateTagName from './utils/generateTagName'
710
811import type {
9- JssStaticSheet ,
10- JssDynamicSheet ,
12+ JssSheet ,
1113 ComponentStyleType ,
1214 StyledElementPropsType
1315} from './types'
1416
1517type 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
0 commit comments