├── .babelrc
├── .editorconfig
├── .eslintrc
├── .flowconfig
├── .gitattributes
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── _config.yml
├── composer.js
├── index.js
├── package.json
├── src
├── composer.js
├── index.js
├── theme.js
└── types.js
├── test
├── composer.js
└── index.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "targets": {
5 | "browsers": "last 2 versions"
6 | }
7 | }],
8 | "stage-2"
9 | ],
10 | "plugins": ["transform-flow-strip-types"]
11 | }
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "airbnb-base",
5 | "plugin:flowtype/recommended"
6 | ],
7 | "plugins": [
8 | "flowtype",
9 | "flowtype-errors"
10 | ],
11 | "env": {
12 | "jest": true
13 | },
14 | "rules": {
15 | "semi": [2, never],
16 | "comma-dangle": 0,
17 | "flowtype-errors/show-errors": 2,
18 | "import/prefer-default-export": 0
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | .*/dist
3 | .*/coverage
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.js text eol=lf
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | coverage
4 | dist
5 | *.log
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - v6
4 | script:
5 | - npm run lint && npm test -- --coverage
6 | after_success:
7 | - bash <(curl -s https://codecov.io/bash)
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Diego Haz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # styled-theme 💅🏿
2 |
3 | [](https://github.com/diegohaz/nod)
4 | [](https://npmjs.org/package/styled-theme)
5 | [](https://travis-ci.org/diegohaz/styled-theme) [](https://codecov.io/gh/diegohaz/styled-theme/branch/master)
6 |
7 | Theming system for [styled-components 💅](https://github.com/styled-components/styled-components)
8 |
9 | ## Install
10 |
11 | $ npm install --save styled-theme
12 |
13 | ## Usage
14 |
15 | Play with it on [WebpackBin](https://www.webpackbin.com/bins/-KeZfaFl3_761CAGa0CC)
16 | ```js
17 | import styled from 'styled-components'
18 | import { font, palette } from 'styled-theme'
19 |
20 | const Text = styled.span`
21 | font-family: ${font('primary')};
22 | background-color: ${palette(1)};
23 | color: ${palette('grayscale', 0, true)};
24 | `
25 |
26 | Text.defaultProps = {
27 | palette: 'primary'
28 | }
29 | ```
30 |
31 | ```jsx
32 | Hello
33 | ```
34 |
35 | 
36 |
37 | ```jsx
38 | Hello
39 | ```
40 |
41 | 
42 |
43 | ```jsx
44 | Hello
45 | ```
46 |
47 | 
48 |
49 | ### Provide your own theme
50 |
51 | ```jsx
52 | import { ThemeProvider } from 'styled-components'
53 |
54 | const xmasTheme = {
55 | fonts: {
56 | primary: 'Georgia, serif'
57 | },
58 | palette: {
59 | // red gradient
60 | primary: ['#D32F2F', '#F44336', '#F8877F', '#FFCDD2']
61 | }
62 | }
63 |
64 |
65 | Hello
66 |
67 | ```
68 |
69 | 
70 |
71 | ## Default theme structure
72 |
73 | This is the content of [`src/theme.js`](src/theme.js):
74 |
75 | ```js
76 | import coolorsToHex from 'coolors-to-hex'
77 | import { reversePalette } from './composer'
78 |
79 | const theme = {}
80 |
81 | theme.palette = {
82 | primary: coolorsToHex('https://coolors.co/1976d2-2196f3-71bcf7-97cef9-c2e2fb'),
83 | secondary: coolorsToHex('https://coolors.co/c2185b-e91e63-f06292-f48caf-f8bbd0'),
84 | danger: coolorsToHex('https://coolors.co/d32f2f-f44336-f8877f-f9a7a1-ffcdd2'),
85 | alert: coolorsToHex('https://coolors.co/ffa000-ffc107-ffd761-ffecb3-fff2ce'),
86 | success: coolorsToHex('https://coolors.co/388e3c-4caf50-7cc47f-9fd4a1-c8e6c9'),
87 | grayscale: ['#212121', '#616161', '#9e9e9e', '#bdbdbd', '#e0e0e0', '#ffffff']
88 | }
89 |
90 | theme.reversePalette = reversePalette(theme.palette)
91 |
92 | theme.fonts = {
93 | primary: 'Helvetica Neue, Helvetica, Roboto, sans-serif',
94 | pre: 'Consolas, Liberation Mono, Menlo, Courier, monospace',
95 | quote: 'Georgia, serif'
96 | }
97 |
98 | theme.sizes = {
99 | maxWidth: '1100px'
100 | }
101 |
102 | export default theme
103 | ```
104 |
105 | [`reversePalette`](#reversePalette) is a helper method. Import it from `styled-theme/composer`.
106 |
107 | ## API
108 |
109 |
110 |
111 | ### reversePalette
112 |
113 | Revert the palette
114 |
115 | **Parameters**
116 |
117 | - `palette` **[Palette](#palette)**
118 |
119 | **Examples**
120 |
121 | ```javascript
122 | reversePalette({ primary: ['red', 'yellow', 'green'] })
123 | // { primary: ['green', 'yellow', 'red'] }
124 | ```
125 |
126 | Returns **[Palette](#palette)**
127 |
128 | ### key
129 |
130 | Returns the value of `props.theme[path]` or `styledTheme[path]`
131 |
132 | **Parameters**
133 |
134 | - `path` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>)**
135 | - `defaultValue` **any**
136 |
137 | **Examples**
138 |
139 | ```javascript
140 | const Button = styled.button`
141 | font-family: ${key('fonts.primary')};
142 | color: ${key(['colors', 'primary', 0])};
143 | `
144 | ```
145 |
146 | Returns **any**
147 |
148 | ### font
149 |
150 | Shorthand to `key(['fonts', path])`
151 |
152 | **Parameters**
153 |
154 | - `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)**
155 | - `defaultValue` **any**
156 |
157 | **Examples**
158 |
159 | ```javascript
160 | const Button = styled.button`
161 | font-family: ${font('primary')};
162 | `
163 | ```
164 |
165 | Returns **[Font](#font)**
166 |
167 | ### size
168 |
169 | Shorthand to `key(['sizes', path])`
170 |
171 | **Parameters**
172 |
173 | - `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)**
174 | - `defaultValue` **any**
175 |
176 | **Examples**
177 |
178 | ```javascript
179 | const Button = styled.button`
180 | padding: ${size('padding')};
181 | `
182 | ```
183 |
184 | Returns **[Size](#size)**
185 |
186 | ### palette
187 |
188 | Returns the value of `props.theme[palette || reversePalette][path][index]` or
189 | `styledTheme[palette || reversePalette][path][index]` (default theme)
190 |
191 | The arguments can be passed in any order, as long as types are kept.
192 |
193 | **Parameters**
194 |
195 | - `index` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** The index of tone in theme palette tones array
196 | - `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The key of the tones in theme palette object (optional, default `props.palette`)
197 | - `exceptions` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** An object with path as key and index as value
198 | - `reverse` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Flag to return tone from `reversePalette` or `palette`
199 | - `defaultValue` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Default value
200 | - `args` **...any**
201 |
202 | **Examples**
203 |
204 | ```javascript
205 | // index = 1
206 | // exception = { grayscale: 0 }
207 | // reverse = true
208 | const Button = styled.button`
209 | background-color: ${palette({ grayscale: 0 }, 1, true)};
210 | `
211 |
212 | // renders props.theme.reversePalette.grayscale[0]
213 |
214 |
215 | // renders props.theme.palette.danger[1] (nullify reverse)
216 |
217 | ```
218 |
219 | Returns **[Tones](#tones)**
220 |
221 | ### Tone
222 |
223 | Type: [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
224 |
225 | ### Tones
226 |
227 | Type: [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Tone](#tone)>
228 |
229 | ### Font
230 |
231 | Type: [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
232 |
233 | ### Size
234 |
235 | Type: [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
236 |
237 | ### Palette
238 |
239 | Type: {}
240 |
241 | ### Fonts
242 |
243 | Type: {}
244 |
245 | ### Sizes
246 |
247 | Type: {}
248 |
249 | ### Theme
250 |
251 | Type: {palette: [Palette](#palette)?, reversePalette: [Palette](#palette)?, fonts: [Fonts](#fonts)?, sizes: [Sizes](#sizes)?}
252 |
253 | ## Related
254 |
255 | - [styled-tools](https://github.com/diegohaz/styled-tools) - Utilities for styled-components (like lodash)
256 |
257 | ## License
258 |
259 | MIT © [Diego Haz](https://github.com/diegohaz)
260 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/composer.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./dist/composer')
2 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./dist')
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "styled-theme",
3 | "version": "0.3.3",
4 | "description": "Theming system for styled-components",
5 | "license": "MIT",
6 | "repository": "diegohaz/styled-theme",
7 | "main": "index.js",
8 | "author": {
9 | "name": "Diego Haz",
10 | "email": "hazdiego@gmail.com",
11 | "url": "github.com/diegohaz"
12 | },
13 | "files": [
14 | "dist",
15 | "index.js",
16 | "composer.js"
17 | ],
18 | "scripts": {
19 | "test": "jest",
20 | "coverage": "npm test -- --coverage",
21 | "postcoverage": "opn coverage/lcov-report/index.html",
22 | "lint": "eslint src test",
23 | "flow": "flow check",
24 | "docs": "documentation readme src --section=API",
25 | "clean": "del dist",
26 | "prebuild": "npm run docs && npm run clean",
27 | "build": "babel src -d dist",
28 | "watch": "npm-watch",
29 | "patch": "npm version patch && npm publish",
30 | "minor": "npm version minor && npm publish",
31 | "major": "npm version major && npm publish",
32 | "prepublish": "npm run lint && npm test && npm run build",
33 | "postpublish": "git push origin master --follow-tags"
34 | },
35 | "watch": {
36 | "test": "{src,test}/*.js",
37 | "lint": "{src,test}/*.js",
38 | "build": "src"
39 | },
40 | "jest": {
41 | "testRegex": "/test/.*",
42 | "testEnvironment": "node"
43 | },
44 | "keywords": [
45 | "styled-components",
46 | "styled",
47 | "style",
48 | "theme",
49 | "theming"
50 | ],
51 | "dependencies": {
52 | "coolors-to-hex": "^1.0.0",
53 | "styled-tools": "^0.1.4"
54 | },
55 | "devDependencies": {
56 | "babel-cli": "^6.18.0",
57 | "babel-eslint": "^7.1.1",
58 | "babel-jest": "^20.0.2",
59 | "babel-plugin-transform-flow-strip-types": "^6.21.0",
60 | "babel-preset-env": "^1.1.8",
61 | "babel-preset-stage-2": "^6.18.0",
62 | "del-cli": "^1.0.0",
63 | "documentation": "4.0.0-rc.0",
64 | "eslint": "^3.14.0",
65 | "eslint-config-airbnb-base": "^11.0.1",
66 | "eslint-plugin-flowtype": "^2.29.2",
67 | "eslint-plugin-flowtype-errors": "^3.0.0",
68 | "eslint-plugin-import": "^2.2.0",
69 | "flow-bin": "^0.50.0",
70 | "jest-cli": "^20.0.2",
71 | "npm-watch": "^0.2.0",
72 | "opn-cli": "^3.1.0"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/composer.js:
--------------------------------------------------------------------------------
1 | // @flow
2 | import type { Palette } from './types'
3 |
4 | /**
5 | * Revert the palette
6 | * @example
7 | * reversePalette({ primary: ['red', 'yellow', 'green'] })
8 | * // { primary: ['green', 'yellow', 'red'] }
9 | */
10 | export const reversePalette = (palette: Palette): Palette =>
11 | Object.keys(palette).reduce((newPalette, key) => ({
12 | ...newPalette,
13 | [key]: [...palette[key]].reverse()
14 | }), {})
15 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | // @flow
2 | import { prop } from 'styled-tools'
3 | import theme from './theme'
4 | import type { Theme, Tones, Font, Size } from './types'
5 |
6 | type Props = {
7 | theme?: Theme,
8 | palette?: string,
9 | reverse?: boolean
10 | }
11 |
12 | /**
13 | * Returns the value of `props.theme[path]` or `styledTheme[path]`
14 | * @example
15 | * const Button = styled.button`
16 | * font-family: ${key('fonts.primary')};
17 | * color: ${key(['colors', 'primary', 0])};
18 | * `
19 | */
20 | export const key = (path: string | string[], defaultValue?: any): any =>
21 | (props: Props = {}): any => prop(path, prop(path, defaultValue)(theme))(props.theme)
22 |
23 | /**
24 | * Shorthand to `key(['fonts', path])`
25 | * @example
26 | * const Button = styled.button`
27 | * font-family: ${font('primary')};
28 | * `
29 | */
30 | export const font = (path: string, defaultValue?: any): Font =>
31 | key(['fonts', path], defaultValue)
32 |
33 | /**
34 | * Shorthand to `key(['sizes', path])`
35 | * @example
36 | * const Button = styled.button`
37 | * padding: ${size('padding')};
38 | * `
39 | */
40 | export const size = (path: string, defaultValue?: any): Size =>
41 | key(['sizes', path], defaultValue)
42 |
43 | /**
44 | * Returns the value of `props.theme[palette || reversePalette][path][index]` or
45 | * `styledTheme[palette || reversePalette][path][index]` (default theme)
46 | *
47 | * The arguments can be passed in any order, as long as types are kept.
48 | * @param {number} index The index of tone in theme palette tones array
49 | * @param {string} [path=props.palette] The key of the tones in theme palette object
50 | * @param {Object} [exceptions] An object with path as key and index as value
51 | * @param {boolean} [reverse] Flag to return tone from `reversePalette` or `palette`
52 | * @param {string} [defaultValue] Default value
53 | * @example
54 | * // index = 1
55 | * // exception = { grayscale: 0 }
56 | * // reverse = true
57 | * const Button = styled.button`
58 | * background-color: ${palette({ grayscale: 0 }, 1, true)};
59 | * `
60 | *
61 | * // renders props.theme.reversePalette.grayscale[0]
62 | *
63 | *
64 | * // renders props.theme.palette.danger[1] (nullify reverse)
65 | *
66 | * @returns {Tones}
67 | */
68 | // eslint-disable-next-line flowtype-errors/show-errors
69 | export const palette = (...args) => (props: Props = {}): Tones => {
70 | const exceptions = args.find(arg => typeof arg === 'object') || {}
71 | const path = args.find(arg => typeof arg === 'string') || props.palette
72 | const defaultValue = [...args].reverse().find(arg => typeof arg === 'string')
73 | let index = args.find(arg => typeof arg === 'number')
74 | let reverse = args.find(arg => typeof arg === 'boolean')
75 | reverse = reverse ? !props.reverse : props.reverse
76 |
77 | if (typeof index === 'undefined') {
78 | throw new Error('[palette] You must pass index')
79 | }
80 | if (typeof path === 'undefined') {
81 | throw new Error('[palette] You must pass palette path')
82 | }
83 |
84 | if (Object.keys(exceptions).indexOf(path) >= 0) {
85 | index = exceptions[path]
86 | }
87 |
88 | const palettePath = reverse ? 'reversePalette' : 'palette'
89 | return key([palettePath, path, index], defaultValue !== path && defaultValue)(props)
90 | }
91 |
--------------------------------------------------------------------------------
/src/theme.js:
--------------------------------------------------------------------------------
1 | // @flow
2 | import coolorsToHex from 'coolors-to-hex'
3 | import { reversePalette } from './composer'
4 | import type { Theme } from './types'
5 |
6 | const theme: Theme = {}
7 |
8 | theme.palette = {
9 | primary: coolorsToHex('https://coolors.co/1976d2-2196f3-71bcf7-97cef9-c2e2fb'),
10 | secondary: coolorsToHex('https://coolors.co/c2185b-e91e63-f06292-f48caf-f8bbd0'),
11 | danger: coolorsToHex('https://coolors.co/d32f2f-f44336-f8877f-f9a7a1-ffcdd2'),
12 | alert: coolorsToHex('https://coolors.co/ffa000-ffc107-ffd761-ffecb3-fff2ce'),
13 | success: coolorsToHex('https://coolors.co/388e3c-4caf50-7cc47f-9fd4a1-c8e6c9'),
14 | grayscale: ['#212121', '#616161', '#9e9e9e', '#bdbdbd', '#e0e0e0', '#ffffff']
15 | }
16 |
17 | theme.reversePalette = reversePalette(theme.palette)
18 |
19 | theme.fonts = {
20 | primary: 'Helvetica Neue, Helvetica, Roboto, sans-serif',
21 | pre: 'Consolas, Liberation Mono, Menlo, Courier, monospace',
22 | quote: 'Georgia, serif'
23 | }
24 |
25 | theme.sizes = {
26 | maxWidth: '1100px'
27 | }
28 |
29 | export default theme
30 |
--------------------------------------------------------------------------------
/src/types.js:
--------------------------------------------------------------------------------
1 | // @flow
2 | /** */
3 | export type Tone = string
4 |
5 | /** */
6 | export type Tones = Array
7 |
8 | /** */
9 | export type Font = string
10 |
11 | /** */
12 | export type Size = string
13 |
14 | /** */
15 | export type Palette = {[string]: Tones}
16 |
17 | /** */
18 | export type Fonts = {[string]: Font}
19 |
20 | /** */
21 | export type Sizes = {[string]: Size}
22 |
23 | /** */
24 | export type Theme = {
25 | palette?: Palette,
26 | reversePalette?: Palette,
27 | fonts?: Fonts,
28 | sizes?: Sizes
29 | }
30 |
--------------------------------------------------------------------------------
/test/composer.js:
--------------------------------------------------------------------------------
1 | import { reversePalette } from '../src/composer'
2 |
3 | test('reversePalette', () => {
4 | const palette = {
5 | key1: [1, 2, 3],
6 | key2: [3, 2, 1]
7 | }
8 | expect(reversePalette(palette)).toEqual({
9 | key1: [3, 2, 1],
10 | key2: [1, 2, 3]
11 | })
12 | })
13 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | import theme from '../src/theme'
2 | import { key, font, palette, size } from '../src'
3 |
4 | describe('key', () => {
5 | const theme2 = {
6 | foo: 'bar'
7 | }
8 |
9 | it('returns value from theme when no anotherTheme was passed in', () => {
10 | expect(key('palette')()).toBe(theme.palette)
11 | })
12 |
13 | it('returns value from anotherTheme when passed in', () => {
14 | expect(key('foo')({ theme: theme2 })).toBe(theme2.foo)
15 | })
16 |
17 | it('returns defaultValue', () => {
18 | expect(key('foo', 'baz')()).toBe('baz')
19 | })
20 | })
21 |
22 | describe('size', () => {
23 | const theme2 = {
24 | sizes: {
25 | foo: 'bar'
26 | }
27 | }
28 |
29 | it('returns value from theme when no anotherTheme was passed in', () => {
30 | expect(size('maxWidth')()).toBe(theme.sizes.maxWidth)
31 | })
32 |
33 | it('returns value from anotherTheme when passed in', () => {
34 | expect(size('foo')({ theme: theme2 })).toBe(theme2.sizes.foo)
35 | })
36 |
37 | it('returns defaultValue', () => {
38 | expect(size('foo', 'baz')()).toBe('baz')
39 | })
40 | })
41 |
42 | describe('font', () => {
43 | const theme2 = {
44 | fonts: {
45 | foo: 'bar',
46 | pre: 'test'
47 | }
48 | }
49 |
50 | it('returns default font when no anotherTheme was passed in', () => {
51 | expect(font('primary')()).toBe(theme.fonts.primary)
52 | })
53 |
54 | it('returns default font when it does not exist on anotherTheme', () => {
55 | expect(font('primary')({ theme: theme2 })).toBe(theme.fonts.primary)
56 | expect(font('quote')({ theme: theme2 })).toBe(theme.fonts.quote)
57 | })
58 |
59 | it('returns anotherTheme font when it exists', () => {
60 | expect(font('foo')({ theme: theme2 })).toBe(theme2.fonts.foo)
61 | expect(font('pre')({ theme: theme2 })).toBe(theme2.fonts.pre)
62 | })
63 |
64 | it('returns defaultValue', () => {
65 | expect(font('foo', 'baz')()).toBe('baz')
66 | })
67 | })
68 |
69 | describe('palette', () => {
70 | const theme2 = {
71 | palette: {
72 | foo: ['bar', 'baz']
73 | },
74 | reversePalette: {
75 | foo: ['baz', 'bar']
76 | }
77 | }
78 |
79 | it('throws when no index was passed in', () => {
80 | expect(() => palette()({ theme: theme2, palette: 'primary' })).toThrow()
81 | })
82 |
83 | it('throws when no palette was passed in', () => {
84 | expect(() => palette(0)({ theme: theme2 })).toThrow()
85 | })
86 |
87 | it('returns palette at index when palette was passed in with props', () => {
88 | expect(palette(0)({ theme: theme2, palette: 'primary' })).toBe(theme.palette.primary[0])
89 | expect(palette(0)({ theme: theme2, palette: 'foo' })).toBe(theme2.palette.foo[0])
90 | expect(palette(0)({ theme: theme2, palette: 'danger', reverse: true }))
91 | .toBe(theme.reversePalette.danger[0])
92 | })
93 |
94 | it('returns palette at index when palette was passed in with args ignoring props', () => {
95 | expect(palette('danger', 1)()).toBe(theme.palette.danger[1])
96 | expect(palette('danger', 1)({ theme: theme2 })).toBe(theme.palette.danger[1])
97 | expect(palette('danger', 1)({ theme: theme2, palette: 'foo' })).toBe(theme.palette.danger[1])
98 | expect(palette('danger', 1)({ theme: theme2, reverse: true }))
99 | .toBe(theme.reversePalette.danger[1])
100 | })
101 |
102 | it('returns palette at proper index when exception was passed in', () => {
103 | expect(palette(1, { danger: 0 })({ theme: theme2, palette: 'foo' })).toBe(theme2.palette.foo[1])
104 | expect(palette(1, { danger: 0 })({ theme: theme2, palette: 'danger' }))
105 | .toBe(theme.palette.danger[0])
106 | })
107 |
108 | it('returns reverse palette when true argument is passed in', () => {
109 | expect(palette(1, true)({ theme: theme2, palette: 'foo' })).toBe(theme2.reversePalette.foo[1])
110 | expect(palette(1, true)({ theme: theme2, palette: 'foo', reverse: true }))
111 | .toBe(theme2.palette.foo[1])
112 | expect(palette(1, true)({ theme: theme2, palette: 'danger' }))
113 | .toBe(theme.reversePalette.danger[1])
114 | })
115 |
116 | it('returns defaultValue', () => {
117 | expect(palette('foo', 1, 'red')()).toBe('red')
118 | expect(palette('foo', 1, 'red')({ theme: theme2 })).toBe(theme2.palette.foo[1])
119 | })
120 | })
121 |
--------------------------------------------------------------------------------