Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Commit

Permalink
feat(themes): support function as theme prop (#273)
Browse files Browse the repository at this point in the history
* feat(themes): support function as theme prop

* Update theme-provider.js

* Update .all-contributorsrc
  • Loading branch information
goodmind authored and Kent C. Dodds committed Aug 3, 2017
1 parent 6453155 commit 2654409
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 3 deletions.
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,16 @@
"contributions": [
"code"
]
},
{
"login": "goodmind",
"name": "andretshurotshka",
"avatar_url": "https://avatars2.githubusercontent.com/u/3275424?v=4",
"profile": "https://github.com/goodmind",
"contributions": [
"code",
"test"
]
}
]
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
[![downloads][downloads-badge]][npmcharts]
[![MIT License][license-badge]][LICENSE]

[![All Contributors](https://img.shields.io/badge/all_contributors-47-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-48-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Chat][chat-badge]][chat]
[![Code of Conduct][coc-badge]][coc]
Expand Down Expand Up @@ -103,7 +103,7 @@ Thanks goes to these people ([emoji key][emojis]):
| [<img src="https://avatars3.githubusercontent.com/u/16327281?v=3" width="100px;"/><br /><sub>Bernard Lin</sub>](https://github.com/bernard-lin)<br />[📖](https://github.com/paypal/glamorous/commits?author=bernard-lin "Documentation") [🔌](#plugin-bernard-lin "Plugin/utility libraries") | [<img src="https://avatars2.githubusercontent.com/u/11799597?v=3" width="100px;"/><br /><sub>Miguel Correa</sub>](http://miguelc1221.github.io/)<br />[💻](https://github.com/paypal/glamorous/commits?author=miguelc1221 "Code") | [<img src="https://avatars2.githubusercontent.com/u/769339?v=3" width="100px;"/><br /><sub>Brian Hough</sub>](http://rallypoint.gg)<br />[💡](#example-bhough "Examples") | [<img src="https://avatars3.githubusercontent.com/u/4950425?v=3" width="100px;"/><br /><sub>Erik Cupal</sub>](https://github.com/ErikCupal)<br />[💻](https://github.com/paypal/glamorous/commits?author=ErikCupal "Code") | [<img src="https://avatars1.githubusercontent.com/u/9153498?v=3" width="100px;"/><br /><sub>Kok J Sam</sub>](https://github.com/sammkj)<br />[💻](https://github.com/paypal/glamorous/commits?author=sammkj "Code") | [<img src="https://avatars2.githubusercontent.com/u/14885189?v=3" width="100px;"/><br /><sub>Oleg Proskurin</sub>](http://twitter.com/#!/usulpro)<br />[📖](https://github.com/paypal/glamorous/commits?author=UsulPro "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/848525?v=3" width="100px;"/><br /><sub>Luke John</sub>](https://github.com/luke-john)<br />[💻](https://github.com/paypal/glamorous/commits?author=luke-john "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/4118089?v=3" width="100px;"/><br /><sub>FredericH</sub>](http://fr.linkedin.com/in/fredericheem)<br />[💡](#example-FredericHeem "Examples") | [<img src="https://avatars3.githubusercontent.com/u/656630?v=3" width="100px;"/><br /><sub>Atticus White</sub>](https://atticuswhite.com)<br />[📖](https://github.com/paypal/glamorous/commits?author=ajwhite "Documentation") [🔌](#plugin-ajwhite "Plugin/utility libraries") | [<img src="https://avatars0.githubusercontent.com/u/13483453?v=3" width="100px;"/><br /><sub>marzelin</sub>](https://github.com/marzelin)<br />[💻](https://github.com/paypal/glamorous/commits?author=marzelin "Code") | [<img src="https://avatars2.githubusercontent.com/u/4074973?v=3" width="100px;"/><br /><sub>iwantmyname</sub>](https://iwantmyname.com/)<br />[🚇](#infra-iwantmyname "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars1.githubusercontent.com/u/11809142?v=3" width="100px;"/><br /><sub>Ethan Godt</sub>](http://ethangodt.com)<br /> | [<img src="https://avatars3.githubusercontent.com/u/2175447?v=3" width="100px;"/><br /><sub>Zill Ding</sub>](https://github.com/zillding)<br />[💻](https://github.com/paypal/glamorous/commits?author=zillding "Code") | [<img src="https://avatars3.githubusercontent.com/u/411643?v=3" width="100px;"/><br /><sub>Dan Bradley</sub>](https://github.com/debradley)<br />[💻](https://github.com/paypal/glamorous/commits?author=debradley "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/22868432?v=3" width="100px;"/><br /><sub>Lufty Wiranda</sub>](http://instagram.com/luftywiranda13)<br />[💻](https://github.com/paypal/glamorous/commits?author=luftywiranda13 "Code") | [<img src="https://avatars3.githubusercontent.com/u/3208863?v=3" width="100px;"/><br /><sub>Ansuman Shah</sub>](https://github.com/ansumanshah)<br />[💻](https://github.com/paypal/glamorous/commits?author=ansumanshah "Code") [📖](https://github.com/paypal/glamorous/commits?author=ansumanshah "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/11598?v=3" width="100px;"/><br /><sub>Travis LaDuke</sub>](http://-)<br />[💡](#example-laduke "Examples") | [<img src="https://avatars2.githubusercontent.com/u/11290953?v=3" width="100px;"/><br /><sub>Aydın Çağrı Dumlu</sub>](https://github.com/acgrdumlu)<br />[🐛](https://github.com/paypal/glamorous/issues?q=author%3Aacgrdumlu "Bug reports") [💻](https://github.com/paypal/glamorous/commits?author=acgrdumlu "Code") | [<img src="https://avatars2.githubusercontent.com/u/1383861?v=3" width="100px;"/><br /><sub>Maja Wichrowska</sub>](https://github.com/majapw)<br />[🐛](https://github.com/paypal/glamorous/issues?q=author%3Amajapw "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/6845263?v=3" width="100px;"/><br /><sub>Tom Liu</sub>](https://github.com/gt3240)<br />[📖](https://github.com/paypal/glamorous/commits?author=gt3240 "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1863771?v=3" width="100px;"/><br /><sub>Siddharth Kshetrapal</sub>](https://github.com/siddharthkp)<br />[⚠️](https://github.com/paypal/glamorous/commits?author=siddharthkp "Tests") [🔧](#tool-siddharthkp "Tools") |
| [<img src="https://avatars2.githubusercontent.com/u/5257243?v=3" width="100px;"/><br /><sub>WillowHQ</sub>](https://github.com/WillowHQ)<br />[📖](https://github.com/paypal/glamorous/commits?author=WillowHQ "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/12202757?v=4" width="100px;"/><br /><sub>Mohammad Rajabifard</sub>](https://tarino.ir)<br />[🐛](https://github.com/paypal/glamorous/issues?q=author%3Amorajabi "Bug reports") [📖](https://github.com/paypal/glamorous/commits?author=morajabi "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/17005317?v=3" width="100px;"/><br /><sub>Omar Albacha</sub>](https://github.com/Oalbacha)<br />[💻](https://github.com/paypal/glamorous/commits?author=Oalbacha "Code") [📖](https://github.com/paypal/glamorous/commits?author=Oalbacha "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/28659384?v=3" width="100px;"/><br /><sub>tdeschryver</sub>](https://github.com/tdeschryver)<br />[💻](https://github.com/paypal/glamorous/commits?author=tdeschryver "Code") [⚠️](https://github.com/paypal/glamorous/commits?author=tdeschryver "Tests") | [<img src="https://avatars0.githubusercontent.com/u/4955191?v=4" width="100px;"/><br /><sub>Dylan Mozlowski</sub>](https://github.com/DylanMoz)<br />[💻](https://github.com/paypal/glamorous/commits?author=DylanMoz "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/5257243?v=3" width="100px;"/><br /><sub>WillowHQ</sub>](https://github.com/WillowHQ)<br />[📖](https://github.com/paypal/glamorous/commits?author=WillowHQ "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/12202757?v=4" width="100px;"/><br /><sub>Mohammad Rajabifard</sub>](https://tarino.ir)<br />[🐛](https://github.com/paypal/glamorous/issues?q=author%3Amorajabi "Bug reports") [📖](https://github.com/paypal/glamorous/commits?author=morajabi "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/17005317?v=3" width="100px;"/><br /><sub>Omar Albacha</sub>](https://github.com/Oalbacha)<br />[💻](https://github.com/paypal/glamorous/commits?author=Oalbacha "Code") [📖](https://github.com/paypal/glamorous/commits?author=Oalbacha "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/28659384?v=3" width="100px;"/><br /><sub>tdeschryver</sub>](https://github.com/tdeschryver)<br />[💻](https://github.com/paypal/glamorous/commits?author=tdeschryver "Code") [⚠️](https://github.com/paypal/glamorous/commits?author=tdeschryver "Tests") | [<img src="https://avatars0.githubusercontent.com/u/4955191?v=4" width="100px;"/><br /><sub>Dylan Mozlowski</sub>](https://github.com/DylanMoz)<br />[💻](https://github.com/paypal/glamorous/commits?author=DylanMoz "Code") | [<img src="https://avatars2.githubusercontent.com/u/3275424?v=4" width="100px;"/><br /><sub>andretshurotshka</sub>](https://github.com/goodmind)<br /> |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
"brcast": "^3.0.0",
"fast-memoize": "^2.2.7",
"html-tag-names": "^1.1.1",
"is-function": "^1.0.1",
"is-plain-object": "^2.0.4",
"react-html-attributes": "^1.3.0",
"svg-tag-names": "^1.1.0"
},
Expand Down
25 changes: 25 additions & 0 deletions src/__tests__/__snapshots__/theme-provider.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ exports[`renders if children are null 1`] = `
/>
`;

exports[`renders inverted theme 1`] = `
.glamor-0,
[data-glamor-0] {
background-color: white;
color: palevioletred;
}
.glamor-1,
[data-glamor-1] {
background-color: palevioletred;
color: white;
}
<div>
<div
class="glamor-0"
/>
<div
class="glamor-1"
/>
</div>
`;

exports[`throws if inverted theme is not object 1`] = `"[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!"`;

exports[`with theme prop of margin 2px 1`] = `
<ThemeProvider
theme={
Expand Down
51 changes: 51 additions & 0 deletions src/__tests__/theme-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,57 @@ test('renders a component with theme', () => {
).toMatchSnapshot()
})

test('renders inverted theme', () => {
const Comp = glamorous.div(({theme: {fg, bg}}) => ({
backgroundColor: bg,
color: fg,
}))
const theme = {
fg: 'palevioletred',
bg: 'white',
}
const invertTheme = ({fg, bg}) => ({
fg: bg,
bg: fg,
})
expect(
render(
<ThemeProvider theme={theme}>
<div>
<Comp />
<ThemeProvider theme={invertTheme}>
<Comp />
</ThemeProvider>
</div>
</ThemeProvider>,
),
).toMatchSnapshot()
})

test('throws if inverted theme is not object', () => {
const Comp = glamorous.div(({theme: {fg, bg}}) => ({
backgroundColor: bg,
color: fg,
}))
const theme = {
fg: 'palevioletred',
bg: 'white',
}
const invertTheme = () => 1
expect(() =>
render(
<ThemeProvider theme={theme}>
<div>
<Comp />
<ThemeProvider theme={invertTheme}>
<Comp />
</ThemeProvider>
</div>
</ThemeProvider>,
),
).toThrowErrorMatchingSnapshot()
})

test('theme properties updates get propagated down the tree', () => {
class Parent extends Component {
state = {
Expand Down
15 changes: 14 additions & 1 deletion src/theme-provider.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, {Component} from 'react'
import isFunction from 'is-function'
import isPlainObject from 'is-plain-object'
import brcast from 'brcast'
import {PropTypes} from './react-compat'
import {CHANNEL} from './constants'

/**
* This is a component which will provide a theme to the entire tree
* via context and event listener
Expand All @@ -16,6 +19,16 @@ class ThemeProvider extends Component {
// create theme, by merging with outer theme, if present
getTheme(passedTheme) {
const theme = passedTheme || this.props.theme
if (isFunction(theme)) {
const mergedTheme = theme(this.outerTheme)
if (!isPlainObject(mergedTheme)) {
throw new Error(
'[ThemeProvider] Please return an object from your theme function, ' +
'i.e. theme={() => ({})}!',
)
}
return mergedTheme
}
return {...this.outerTheme, ...theme}
}

Expand Down Expand Up @@ -71,7 +84,7 @@ ThemeProvider.contextTypes = {
}

ThemeProvider.propTypes = {
theme: PropTypes.object.isRequired,
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
children: PropTypes.node,
}

Expand Down

0 comments on commit 2654409

Please sign in to comment.