Skip to content

Commit

Permalink
Merge pull request #3 from awesomecss/stylesheet-class
Browse files Browse the repository at this point in the history
Manage CSSRules with "Stylesheet" instance
  • Loading branch information
ItsJonQ committed May 2, 2018
2 parents 05bca90 + 0301715 commit 1deffc9
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 86 deletions.
62 changes: 62 additions & 0 deletions src/StyleSheet/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const makeStyleSheet = () => {
const state = {
id: 0,
CSSRules: {}
}

const addRule = (id, styles) => {
state.CSSRules[id] = styles
}

const getRule = (id) => {
return state.CSSRules[id]
}

const hasRule = (id) => {
return !!getRule(id)
}

const removeRule = (id) => {
state.CSSRules[id] = undefined
}

const makeRule = (CSSRules) => {
state.id = state.id + 1
return { id: state.id, CSSRules }
}

const makeStyles = (props) => {
return generateStyles(props)
}

return {
addRule,
getRule,
hasRule,
removeRule,
makeRule,
makeStyles,
CSSRules: state.CSSRules
}
}

/**
* Creates the tokenized styles based.
*/
export const generateStyles = ({id, props, CSSRules}) => {
const parsedCSSRules = typeof CSSRules === 'function'
? CSSRules(props) : CSSRules

return tokenize(id, parsedCSSRules)
}

/**
* Renders the CSSRule with tokenized with the unique ID.
*
* @param {string} id
* @param {string} CSSRules
* @returns {string}
*/
export const tokenize = (id, CSSRules) => `/* ${id} */\n${CSSRules.trim()}\n`

export default makeStyleSheet
5 changes: 0 additions & 5 deletions src/utilities/id.js

This file was deleted.

4 changes: 3 additions & 1 deletion src/withStyles/__tests__/withStyles.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import { mount } from 'enzyme'
import withStyles, { removeStyle } from '../index'
import withStyles from '../index'

const removeStyle = withStyles.StyleSheet.removeRule

describe('HOC Composition', () => {
const Button = props => (<button {...props} />)
Expand Down
20 changes: 1 addition & 19 deletions src/withStyles/helpers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ID } from './index'
import { uuid } from '../utilities/id'
export const ID = '__REACT_REACTOR_STYLES__'

/**
* Creates the <style> tag, and adds it to the <head>.
Expand Down Expand Up @@ -27,20 +26,3 @@ export const getStyleTag = () => {
const tag = document.getElementById(ID)
return tag || makeStyleTag()
}

/**
* Renders the CSSRule with tokenized with the unique ID.
*
* @param {string} id
* @param {string} CSSRules
* @returns {string}
*/
export const tokenize = (id, CSSRules) => `/* ${id} */\n${CSSRules.trim()}\n`

/**
* Generates the styleProps with uniqueID for withStyles to consume.
*
* @param {string} CSSRules
* @returns {object}
*/
export const makeCSS = (CSSRules) => ({ id: uuid(), CSSRules })
78 changes: 17 additions & 61 deletions src/withStyles/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, { Component } from 'react'
import Style from './Style'
import {
getStyleTag,
makeCSS,
tokenize
getStyleTag
} from './helpers'
import { getComponentName } from '../utilities/components'
import makeStyleSheet from '../StyleSheet'

export const ID = '__REACT_REACTOR_STYLES__'
export const MANAGER = {}
export const STYLESHEET = makeStyleSheet()

/**
* HOC that renders specified CSS rules.
Expand All @@ -18,17 +16,22 @@ export const MANAGER = {}
* @returns {React.Component}
*/
const withStyles = (styles) => Composed => {
const { id, CSSRules } = makeCSS(styles)
const { id, CSSRules } = STYLESHEET.makeRule(styles)

class WithStylesComponent extends Component {
constructor (props) {
super(props)
this.styleSheet = STYLESHEET
}

componentDidMount () {
if (!id || !CSSRules || hasStyle(id)) return
if (!id || !CSSRules || this.styleSheet.hasRule(id)) return

const cssStyles = generateStyles({ id, props: this.props, CSSRules })
const cssStyles = this.styleSheet.makeStyles({ id, props: this.props, CSSRules })
const tagNode = getStyleTag()
tagNode.innerHTML += cssStyles

addStyle(id, cssStyles)
this.styleSheet.addRule(id, cssStyles)
}

componentDidUpdate (prevProps) {
Expand All @@ -38,21 +41,21 @@ const withStyles = (styles) => Composed => {
/* istanbul ignore next */
if (prevProps === this.props) return

const prevStyles = getStyle(id)
const prevStyles = this.styleSheet.getRule(id)
/**
* Cannot really tested in Enzyme, as there is always styles whe a
* component is initialized. This is a fail-safe guard.
*/
/* istanbul ignore next */
if (!prevStyles) return

const nextStyles = generateStyles({ id, props: this.props, CSSRules })
const nextStyles = this.styleSheet.makeStyles({ id, props: this.props, CSSRules })
if (prevStyles === nextStyles) return

const tagNode = getStyleTag()
tagNode.innerHTML = tagNode.innerHTML.replace(prevStyles, nextStyles)

addStyle(id, nextStyles)
this.styleSheet.addRule(id, nextStyles)
}

render () {
Expand All @@ -62,61 +65,14 @@ const withStyles = (styles) => Composed => {

WithStylesComponent.displayName = `withStyle(${getComponentName(Composed)})`
WithStylesComponent._withStylesId = id
WithStylesComponent._styleSheet = STYLESHEET

return WithStylesComponent
}

/**
* Creates the tokenized styles based.
*/
export const generateStyles = ({id, props, CSSRules}) => {
const parsedCSSRules = typeof CSSRules === 'function'
? CSSRules(props) : CSSRules

return tokenize(id, parsedCSSRules)
}

/**
* Retrieves the cached styles based on id.
*
* @param {string} id
* @returns {bool}
*/
export const getStyle = (id) => MANAGER[id]

/**
* Checks to the see if the styles have been previously added by ID.
*
* @param {string} id
* @returns {bool}
*/
export const hasStyle = (id) => !!getStyle(id)

/**
* Adds ID to mark that styles have been added.
*
* @param {string} id
* @returns {object}
*/
const addStyle = (id, styles) => {
MANAGER[id] = styles
return MANAGER
}

/**
* Removes an ID from the styles manager.
*
* @param {string} id
* @returns {undefined}
*/
export const removeStyle = id => {
MANAGER[id] = undefined
return MANAGER
}

/**
* Sub-components
*/
withStyles.Style = Style
withStyles.StyleSheet = STYLESHEET

export default withStyles

0 comments on commit 1deffc9

Please sign in to comment.