-
Notifications
You must be signed in to change notification settings - Fork 15
Implement injectStyled #6
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
Changes from 11 commits
43853de
0ad79df
3a90aa3
253a136
b555ba6
e994113
3ff81d1
fbbb43b
caec53a
35eac8b
3860127
0d79dbb
b375d41
41a24aa
8a0a61d
8cf691f
775dcbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| { | ||
| presets: [ | ||
| 'es2015', | ||
| 'react', | ||
| ], | ||
| plugins: [ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,3 +3,6 @@ parser: babel-eslint | |
|
|
||
| env: | ||
| jest: true | ||
|
|
||
| globals: | ||
| ReactClass: true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,108 +1,118 @@ | ||
| import {PureComponent, createElement} from 'react' | ||
| import {create as createJss, getDynamicStyles} from 'jss' | ||
| import preset from 'jss-preset-default' | ||
| import filterProps from './utils/filter-props' | ||
|
|
||
| import filterProps from './utils/filterProps' | ||
| import composeClasses from './utils/composeClasses' | ||
| import generateTagName from './utils/generateTagName' | ||
| import type { | ||
| BaseStylesType, | ||
| ComponentStyleType, | ||
| StyledType, | ||
| StyledElementAttrsType, | ||
| StyledElementType, | ||
| TagNameOrStyledElementType, | ||
| StyledElementPropsType | ||
| } from './types' | ||
|
|
||
| const jssDefault = createJss(preset()) | ||
|
|
||
| type StyledElementAttrsType = { tag: string, styles: Object } | ||
| type StyledElementType = Function & StyledElementAttrsType | ||
| type tagOrStyledElementTypeype = string | StyledElementType | ||
| type StyledElementPropsType = { | ||
| classes: Object, | ||
| children: ?any, | ||
| className: ?string, | ||
| } | ||
|
|
||
| const createStyled = (jss?: Function = jssDefault) => (baseStyles: Object = {}) => { | ||
| let sheet | ||
| let dynamicSheet | ||
| let counter = 0 | ||
| const createStyled = ( | ||
| jss?: Function = jssDefault | ||
| ) => ( | ||
| baseStyles: BaseStylesType = {} | ||
| ): StyledType => { | ||
| const sheets = {} | ||
|
|
||
| const mountSheets = () => { | ||
| if (!sheets.staticSheet) { | ||
| sheets.staticSheet = jss.createStyleSheet(baseStyles, { | ||
| meta: 'StaticBaseSheet', | ||
| }).attach() | ||
|
|
||
| sheets.dynamicSheet = jss.createStyleSheet({}, { | ||
| link: true, | ||
| meta: 'DynamicComponentSheet', | ||
| }).attach() | ||
| } | ||
| } | ||
|
|
||
| const styled = ( | ||
| tagOrStyledElement: tagOrStyledElementTypeype, | ||
| ownStyles: Object | ||
| tagNameOrStyledElement: TagNameOrStyledElementType, | ||
| ownStyle: ComponentStyleType | ||
| ): StyledElementType => { | ||
| const {tag, styles}: StyledElementAttrsType = typeof tagOrStyledElement === 'string' | ||
| ? {tag: tagOrStyledElement, styles: {}} | ||
| : tagOrStyledElement | ||
| const {tagName, style}: StyledElementAttrsType = typeof tagNameOrStyledElement === 'string' | ||
| ? {tagName: tagNameOrStyledElement, style: {}} | ||
| : tagNameOrStyledElement | ||
|
|
||
| const elementStyles = {...styles, ...ownStyles} | ||
| const dynamicStyles = getDynamicStyles(elementStyles) | ||
| const staticTag = `${tag}-${++counter}` | ||
| const elementStyle = {...style, ...ownStyle} | ||
| const dynamicStyle = getDynamicStyles(elementStyle) | ||
| const staticTagName = generateTagName(tagName) | ||
|
|
||
| return class StyledElement extends PureComponent { | ||
| static tag = tag | ||
|
|
||
| static styles = elementStyles | ||
| static tagName: string = tagName | ||
| static style: ComponentStyleType = elementStyle | ||
|
|
||
| props: StyledElementPropsType | ||
|
|
||
| tagScoped = '' | ||
| dynamicTagName = '' | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could set
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nope, cause we can call Components with different styles <Button color="pink" />
<Button color="green" />and we need to have a scoped tagName for each instance
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right |
||
|
|
||
| constructor(props) { | ||
| super(props) | ||
| this.tagScoped = `${tag}-${++counter}` | ||
| this.dynamicTagName = generateTagName(tagName) | ||
| } | ||
|
|
||
| componentWillMount() { | ||
| if (!sheet) { | ||
| sheet = jss.createStyleSheet(baseStyles, { | ||
| link: true, | ||
| meta: 'StaticBaseSheet', | ||
| }).attach() | ||
|
|
||
| dynamicSheet = jss.createStyleSheet({}, { | ||
| link: true, | ||
| meta: 'DynamicComponentSheet', | ||
| }).attach() | ||
| } | ||
| mountSheets() | ||
|
|
||
| if (!sheet.getRule(staticTag)) { | ||
| sheet.addRule(staticTag, elementStyles) | ||
| if (!sheets.staticSheet.getRule(staticTagName)) { | ||
| sheets.staticSheet.addRule(staticTagName, elementStyle) | ||
| } | ||
|
|
||
| if (dynamicStyles && !dynamicSheet.getRule(this.tagScoped)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of tagScoped:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe |
||
| dynamicSheet | ||
| if (dynamicStyle && !sheets.dynamicSheet.getRule(this.dynamicTagName)) { | ||
| sheets.dynamicSheet | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just realized we don't need
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need, because we need mutated sheets here too https://github.com/cssinjs/styled-jss/pull/6/files#diff-f336995dd331140b2022485b207c9fc1R10 if we just export them, with reassign we will lost links to new sheets
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we reassign them somewhere else than in
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, you are right, we can just return them. |
||
| .detach() | ||
| .addRule(this.tagScoped, dynamicStyles) | ||
| dynamicSheet | ||
| .update(this.tagScoped, this.props) | ||
| .addRule(this.dynamicTagName, dynamicStyle) | ||
| sheets.dynamicSheet | ||
| .update(this.dynamicTagName, this.props) | ||
| .attach() | ||
| .link() | ||
| } | ||
| } | ||
|
|
||
| componentWillReceiveProps(nextProps: StyledElementPropsType) { | ||
| if (dynamicStyles) { | ||
| dynamicSheet.update(this.tagScoped, nextProps) | ||
| if (dynamicStyle) { | ||
| sheets.dynamicSheet.update(this.dynamicTagName, nextProps) | ||
| } | ||
| } | ||
|
|
||
| componentWillUnmount() { | ||
| dynamicSheet.deleteRule(this.tagScoped) | ||
| sheets.dynamicSheet.deleteRule(this.dynamicTagName) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we remove the rule, we could reuse that rule next time the component mounts, no?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because we generate new scoped name in constructor, so we can't get and old dynamicTagName for the pervious instance
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? the instance will be reused in react ....
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, but react will call
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well, don't redefine it in this case if it is already defined? |
||
| } | ||
|
|
||
| render() { | ||
| if (!sheet) return null | ||
| if (!sheets.staticSheet) return null | ||
|
|
||
| const {children, className, ...attrs} = this.props | ||
|
|
||
| const props = filterProps(attrs) | ||
| const tagClass = [ | ||
| sheet.classes[staticTag], | ||
| dynamicSheet.classes[this.tagScoped], | ||
| className, | ||
| ] | ||
| .filter(Boolean) | ||
| .join(' ') | ||
|
|
||
| return createElement(tag, {...props, className: tagClass}, children) | ||
| const tagClass = composeClasses( | ||
| sheets.staticSheet.classes[staticTagName], | ||
| sheets.dynamicSheet.classes[this.dynamicTagName], | ||
| className | ||
| ) | ||
|
|
||
| return createElement(tagName, {...props, className: tagClass}, children) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return Object.assign(styled, {styles: baseStyles}) | ||
| return Object.assign(styled, { | ||
| sheets, | ||
| mountSheets, | ||
| styles: baseStyles | ||
| }) | ||
| } | ||
|
|
||
| const defaultStyledCreator = createStyled() | ||
|
|
@@ -114,3 +124,5 @@ export { | |
| } | ||
|
|
||
| export default defaultStyled | ||
|
|
||
| export {default as injectStyled} from './injectStyled' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import {createElement} from 'react' | ||
|
|
||
| import composeClasses from './utils/composeClasses' | ||
| import type {StyledType} from './types' | ||
|
|
||
| const injectStyled = (styled: StyledType) => (InnerComponent: ReactClass<any>) => { | ||
| styled.mountSheets() | ||
|
|
||
| const {sheets} = styled | ||
| const {staticSheet, dynamicSheet} = sheets | ||
|
|
||
| const classNames = Object.keys({...staticSheet.classes, ...dynamicSheet.classes}) | ||
|
|
||
| const classes = [...classNames] | ||
| .reduce((acc, name) => ({ | ||
| ...acc, | ||
| [name]: composeClasses(staticSheet.classes[name], dynamicSheet.classes[name]), | ||
| }), {}) | ||
|
|
||
| return (props: Object) => createElement(InnerComponent, {classes, ...props}) | ||
| } | ||
|
|
||
| export default injectStyled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed, where do we use such a global?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eslint consider flow types and it works with rules like 'no-undef`, but it dosnt about this flow type. so we need to add it as global.
but maybe there is better solution with some plugin etc., I'll take a look