Skip to content

Commit

Permalink
Add comments and improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
Rowno committed Feb 18, 2018
1 parent 4432265 commit c6fae59
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 149 deletions.
13 changes: 8 additions & 5 deletions src/box.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,32 @@ export default class Box extends React.PureComponent {

render() {
const {is, css, innerRef, children, ...props} = this.props
// Convert the CSS props to class names (and inject the styles)
const [className, parsedProps] = enhanceProps(props)
const finalProps = parsedProps

// Add glamor class
if (css) {
// Warn that it's deprecated in the development
if (process.env.NODE_ENV !== 'production') {
// Don't spam the warning
if (!cssWarned) {
cssWarned = true
console.warn(
`ui-box deprecation: the “css” prop will be removed in the next major version in favour of importing glamor directly and passing it՚s generated class to the “className” prop.`
)
}
}
finalProps.className = cx(className, gcss(css).toString())
parsedProps.className = cx(className, gcss(css).toString())
} else {
finalProps.className = className
parsedProps.className = className
}

if (innerRef) {
finalProps.ref = node => {
parsedProps.ref = node => {
innerRef(node)
}
}

return React.createElement(is, finalProps, children)
return React.createElement(is, parsedProps, children)
}
}
6 changes: 4 additions & 2 deletions src/enhance-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import expandAliases from './expand-aliases'
import * as styles from './styles'
import * as cache from './cache'

// This is optimized for performance. It gets called a lot of times
/**
* Converts the CSS props to class names and inserts the styles.
*/
export default function enhanceProps(rawProps) {
const propsMap = expandAliases(rawProps)
const enhancedProps = {}
Expand All @@ -23,7 +25,7 @@ export default function enhanceProps(rawProps) {
if (enhancer && !propValue) {
continue
} else if (!enhancer) {
// Native prop. e.g: disabled, value, type
// Pass through native props. e.g: disabled, value, type
enhancedProps[propName] = propValue
continue
}
Expand Down
21 changes: 11 additions & 10 deletions src/expand-aliases.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import {propAliases, propValidators} from './enhancers'

/**
* Expands aliases like `margin` to `marginTop`, `marginBottom`, `marginLeft` and `marginRight`.
*
* This prevents edge cases where longhand properties can't override shorthand
* properties due to the style insertion order.
*/
export default function expandAliases(props) {
const propNames = Object.keys(props)
// Use a Map because it's faster for setting values and looping over than an Object
const newProps = new Map()

// Loop in reverse order so that the last props override the previous props
for (let i = propNames.length - 1; i >= 0; i--) {
for (let i = 0; i < propNames.length; i++) {
const propName = propNames[i]
const propValue = props[propName]
const aliases = propAliases[propName] || [propName]

// Check that the alias has a valid value in development
if (process.env.NODE_ENV !== 'production') {
const validator = propValidators[propName]
if (validator) {
Expand All @@ -22,15 +29,9 @@ export default function expandAliases(props) {

// Expand aliases
for (let i = 0; i < aliases.length; i++) {
const enhancerName = aliases[i]
// Don't return duplicate props
if (!newProps.has(enhancerName)) {
newProps.set(enhancerName, propValue)
}
newProps.set(aliases[i], propValue)
}
}

// Return props in the order they defined so that the css gets injected in a
// predictable order
return Array.from(newProps).reverse()
return newProps
}
5 changes: 3 additions & 2 deletions src/get-class-name.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import hash from './utils/hash'
import getSafeValue from './get-safe-value'

// This is only used for hash based caching
// Array/index based caching doesn't reach this code
/**
* Generates the class name.
*/
export default function getClassName(propertyInfo, value) {
const {
className,
Expand Down
4 changes: 4 additions & 0 deletions src/get-css.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import prefixer from './prefixer'
import valueToString from './value-to-string'
import getClassName from './get-class-name'

/**
* Generates the class name and styles.
*/
export default function getCss(propertyInfo, value) {
let rules

const valueString = valueToString(value, propertyInfo.defaultUnit)

const className = getClassName(propertyInfo, valueString)

// Avoid running the prefixer when possible because it's slow
if (propertyInfo.isPrefixed) {
rules = prefixer(propertyInfo.jsName, valueString)
} else {
Expand Down
3 changes: 3 additions & 0 deletions src/get-safe-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import {unsafeClassNameCharacters} from './utils/regex'
const dashRegex = /[ .]/g
const percentRegex = /%/g

/**
* Makes the value safe for use in a class name.
*/
export default function getSafeValue(value) {
return value
.replace(dashRegex, '-')
Expand Down
3 changes: 3 additions & 0 deletions src/prefixer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import decamelize from './utils/decamelize'

const prefixRegex = /^(Webkit|ms|Moz|O)/

/**
* Adds vendor prefixes to properties and values.
*/
export default function prefixer(property, value) {
const rules = prefixAll({[property]: value})
const rulesArray = []
Expand Down
1 change: 1 addition & 0 deletions src/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export function add(styles) {
}

export function getAll() {
// Convert rules array to a string
return styleSheet
.rules()
.reduce((combinedRules, rule) => combinedRules + rule.cssText, '')
Expand Down
3 changes: 3 additions & 0 deletions src/value-to-string.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* Converts number values to a string with a unit.
*/
export default function valueToString(value, unit = 'px') {
return typeof value === 'number' ? `${value}${unit}` : value
}
2 changes: 1 addition & 1 deletion test/enhance-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test.serial('enhances a prop', t => {

test.serial('expands aliases', t => {
const [className, enhancedProps] = enhanceProps({margin: 11})
t.is(className, '📦mt_11px 📦mr_11px 📦ml_11px 📦mb_11px')
t.is(className, '📦mb_11px 📦ml_11px 📦mr_11px 📦mt_11px')
t.deepEqual(enhancedProps, {})
})

Expand Down
28 changes: 14 additions & 14 deletions test/expand-aliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ test('expands an alias', t => {
expandAliases({
margin: '10px',
}),
[
['marginTop', '10px'],
['marginRight', '10px'],
['marginLeft', '10px'],
new Map([
['marginBottom', '10px'],
]
['marginLeft', '10px'],
['marginRight', '10px'],
['marginTop', '10px'],
])
)
})

Expand All @@ -21,12 +21,12 @@ test('aliases override earlier props', t => {
marginTop: '20px',
margin: '10px',
}),
[
new Map([
['marginTop', '10px'],
['marginRight', '10px'],
['marginLeft', '10px'],
['marginBottom', '10px'],
]
['marginLeft', '10px'],
['marginRight', '10px'],
])
)
})

Expand All @@ -36,12 +36,12 @@ test('props override earlier aliases', t => {
margin: '10px',
marginTop: '20px',
}),
[
['marginRight', '10px'],
['marginLeft', '10px'],
new Map([
['marginBottom', '10px'],
['marginLeft', '10px'],
['marginRight', '10px'],
['marginTop', '20px'],
]
])
)
})

Expand All @@ -52,6 +52,6 @@ test('maintains original prop order', t => {
height: '10px',
marginTop: '10px',
}),
[['width', '10px'], ['height', '10px'], ['marginTop', '10px']]
new Map([['width', '10px'], ['height', '10px'], ['marginTop', '10px']])
)
})
Loading

0 comments on commit c6fae59

Please sign in to comment.