-
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 7 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 |
|---|---|---|
|
|
@@ -31,16 +31,21 @@ const PrimaryButton = styled(Button, { | |
| Using base Style Sheet we can share classes between styled primitives. | ||
|
|
||
| ```js | ||
| import { Styled } from 'styled-jss' | ||
| import injectSheet from 'react-jss' | ||
| import { Styled, injectStyled } from 'styled-jss' | ||
|
|
||
| // Base styles, like a regular jss object. | ||
| const styled = Styled({ | ||
| root: { | ||
| margin: 10 | ||
| margin: 10, | ||
| '& $baseButton': { | ||
| fontSize: 16 | ||
| } | ||
| }, | ||
| baseButton: { | ||
| padding: 10 | ||
| padding: 10, | ||
| '& + &': { | ||
| marginLeft; 10 | ||
|
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. typo |
||
| } | ||
| } | ||
| }) | ||
|
|
||
|
|
@@ -58,11 +63,12 @@ const PrimaryButton = styled(NormalButton, { | |
| // One can use classes AND styled primitives. | ||
| const MyComponent = ({classes}) => ( | ||
| <div className={classes.root}> | ||
| <NormalButton>normal button</NormalButton> | ||
| <PrimaryButton>primary button</PrimaryButton> | ||
| </div> | ||
| ) | ||
|
|
||
| const MyStyledComponent = injectSheet(styled.styles)(MyComponent) | ||
| const MyStyledComponent = injectStyled(styled)(MyComponent) | ||
| ``` | ||
|
|
||
| ### With custom JSS setup: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,37 @@ | ||
| 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 composeClasses from './utils/compose-classes' | ||
| import type { | ||
| styledType, | ||
| StyledElementAttrsType, | ||
| StyledElementType, | ||
| tagOrStyledElementTypeype, | ||
| 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 | ||
| const createStyled = (jss?: Function = jssDefault) => (baseStyles: Object = {}): styledType => { | ||
|
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. styledType should be capitelized, no?
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. Also lets use a type JssStyles = Object and type JssStyle = Object and put it into types, once we have a fully typed styles object for jss we can easily replace Object with the new one in types.
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. 👍 |
||
| const sheets = {} | ||
| let counter = 0 | ||
|
|
||
| const mountSheets = () => { | ||
| if (!sheets.staticSheet) { | ||
| sheets.staticSheet = jss.createStyleSheet(baseStyles, { | ||
| link: true, | ||
|
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 you need link: true for static sheet? |
||
| meta: 'StaticBaseSheet', | ||
| }).attach() | ||
|
|
||
| sheets.dynamicSheet = jss.createStyleSheet({}, { | ||
| link: true, | ||
| meta: 'DynamicComponentSheet', | ||
| }).attach() | ||
| } | ||
| } | ||
|
|
||
| const styled = ( | ||
| tagOrStyledElement: tagOrStyledElementTypeype, | ||
| ownStyles: Object | ||
|
|
@@ -46,27 +59,17 @@ const createStyled = (jss?: Function = jssDefault) => (baseStyles: Object = {}) | |
| } | ||
|
|
||
| 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(staticTag)) { | ||
| sheets.staticSheet.addRule(staticTag, elementStyles) | ||
| } | ||
|
|
||
| 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 (dynamicStyles && !sheets.dynamicSheet.getRule(this.tagScoped)) { | ||
| 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 | ||
| sheets.dynamicSheet | ||
| .update(this.tagScoped, this.props) | ||
| .attach() | ||
| .link() | ||
|
|
@@ -75,34 +78,36 @@ const createStyled = (jss?: Function = jssDefault) => (baseStyles: Object = {}) | |
|
|
||
| componentWillReceiveProps(nextProps: StyledElementPropsType) { | ||
| if (dynamicStyles) { | ||
| dynamicSheet.update(this.tagScoped, nextProps) | ||
| sheets.dynamicSheet.update(this.tagScoped, nextProps) | ||
| } | ||
| } | ||
|
|
||
| componentWillUnmount() { | ||
| dynamicSheet.deleteRule(this.tagScoped) | ||
| sheets.dynamicSheet.deleteRule(this.tagScoped) | ||
| } | ||
|
|
||
| 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(' ') | ||
| const tagClass = composeClasses( | ||
| sheets.staticSheet.classes[staticTag], | ||
| sheets.dynamicSheet.classes[this.tagScoped], | ||
| className | ||
| ) | ||
|
|
||
| return createElement(tag, {...props, className: tagClass}, children) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return Object.assign(styled, {styles: baseStyles}) | ||
| return Object.assign(styled, { | ||
| sheets, | ||
| mountSheets, | ||
| styles: baseStyles | ||
| }) | ||
| } | ||
|
|
||
| const defaultStyledCreator = createStyled() | ||
|
|
@@ -114,3 +119,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/compose-classes' | ||
| import type {styledType} from './types' | ||
|
|
||
| const injectStyled = (styled: styledType) => (InnerComponent: ReactClass<any>) => { | ||
|
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. Where does ReactClass come from?
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. This is native flow type |
||
| 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 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| export type styledType = Function & { | ||
| sheets: { | ||
| // TODO: use types from jss | ||
| staticSheet: Object, | ||
| dynamicSheet: Object, | ||
| }, | ||
| mountSheets: Function, | ||
| styles: Object | ||
| } | ||
| export type StyledElementAttrsType = {tag: string, styles: Object} | ||
| export type StyledElementType = Function & StyledElementAttrsType | ||
| export type tagOrStyledElementTypeype = string | StyledElementType | ||
|
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. should be capitalized |
||
| export type StyledElementPropsType = { | ||
| classes: Object, | ||
| children: ?any, | ||
| className: ?string, | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default (...args: any) => args.filter(Boolean).join(' ') | ||
|
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, why do we use sometimes camel case and sometimes dash separated file names? In JSS I stick to camel case. |
||
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