Skip to content

Commit

Permalink
add support for propMerge() in react package
Browse files Browse the repository at this point in the history
  • Loading branch information
otbe committed Oct 27, 2016
1 parent 01072d0 commit 6864818
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 2 deletions.
8 changes: 8 additions & 0 deletions docs/composition.md
Expand Up @@ -40,6 +40,14 @@ let Button = ({ type, children, onClick = ::console.log }) =>
<Button type='primary'>click me!</Button>
</div>

// compose glamor styled react components (with propMerge the order of css rules/styles doesn't matter
// because it will take care of a proper merge)
const specificStyle = style({ height: '100px' });
const defaultStyle = style({ height: '200px' });

let DefaultContainer = (props) => <div {...propMerge(defaultStyle, props)}/>
let SpecificContainer = (props) => <DefaultContainer {...specificStyle}>{props.children}</div>

// or make your own helper function alá aphrodite et al
let sheet = createSheet({
container: {...},
Expand Down
3 changes: 2 additions & 1 deletion react.d.ts
@@ -1,6 +1,7 @@
export * from './index.d.ts';
import { CSSProperties, StyleAttribute } from './index';

export const createElement: any;
export const dom: any;
export const vars: any;
export const makeTheme: any;
export function propMerge<T>(styles: StyleAttribute | CSSProperties, obj: T): T;
41 changes: 41 additions & 0 deletions src/react.js
Expand Up @@ -101,3 +101,44 @@ export function makeTheme() {
return fn

}

function toStyle(s) {
return s!= null && isLikeRule(s) ? s : style(s);
}

// propMerge will take an arbitrary object "props", filter out glamor data-css-* styles and merge it with "mergeStyle"
// use it for react components composing
export function propMerge(mergeStyle, props) {
const glamorStyleKeys = Object.keys(props).filter(x => !!/data\-css\-([a-zA-Z0-9]+)/.exec(x))

// no glamor styles in obj
if (glamorStyleKeys.length === 0) {
return {
...props,
...toStyle(mergeStyle)
}
}

if (glamorStyleKeys.length > 1) {
console.warn('[glamor] detected multiple data attributes on an element. This may lead to unexpected style because of css insertion order.');

// just append "mergeStyle" to props, because we dunno in which order glamor styles were added to props
return {
...props,
...toStyle(mergeStyle)
}
}

const dataCssKey= glamorStyleKeys[0]
const cssData = props[dataCssKey]

const mergedStyles = merge(mergeStyle, { [dataCssKey]: cssData })

const restProps = Object.assign({}, props)
delete restProps[dataCssKey]

return {
...restProps,
...mergedStyles
}
}
36 changes: 35 additions & 1 deletion tests/index.js
Expand Up @@ -25,6 +25,8 @@ import { style, hover, nthChild, firstLetter, media, merge, compose, select, vi
flush, styleSheet, rehydrate }
from '../src'

import { propMerge } from '../src/react'

import clean from '../src/clean'

import { View } from '../src/jsxstyle'
Expand Down Expand Up @@ -697,9 +699,41 @@ describe('plugins', () => {
})

describe('react', () => {
let node
beforeEach(() => {
node = document.createElement('div')
document.body.appendChild(node)
})

afterEach(() => {
unmountComponentAtNode(node)
document.body.removeChild(node)
flush()
})

it('dom elements accept css prop')
it('can use vars to set/unset values vertically on the dom-tree')
it('can use themes to compose styles vertically on the dom-tree')
it('can use themes to compose styles vertically on the dom-tree')

it('propMerge will merge styles with react props', () => {
// the order of the styles matter here
// thats how css works :/
const specificStyle = style({ height: '100px' })
const defaultStyle = style({ height: '200px' })
const dummyStyle = style({ color: 'green' })

let DefaultContainer = (props) => <div {...propMerge(defaultStyle, props)}/>
let SpecificContainer = (props) => <DefaultContainer {...specificStyle} {...props}/>

render(<SpecificContainer/>, node, () => {
expect(childStyle(node).height).toEqual('100px')
})

// this would only work properly if we use propMerge also on <SpecificContainer/> definition
render(<SpecificContainer {...dummyStyle}/>, node, () => {
expect(childStyle(node).height).toEqual('200px')
})
})
})

describe('aphrodite', () => {
Expand Down

0 comments on commit 6864818

Please sign in to comment.