diff --git a/.storybook/animate.stories.js b/.storybook/animate.stories.js new file mode 100644 index 00000000..99ed103f --- /dev/null +++ b/.storybook/animate.stories.js @@ -0,0 +1,33 @@ +import {createElement as h} from 'react'; +import {storiesOf} from '@storybook/react'; +const {action} = require('@storybook/addon-actions'); +const {linkTo} = require('@storybook/addon-links'); +const {create} = require('../index'); +const {addon: addonRule} = require('../addon/rule'); +const {addon: addonKeyframes} = require('../addon/keyframes'); + +const animations = [ + 'fadeIn', + 'fadeInDown', + 'fadeInExpand', +]; + +const nano = create(); +addonRule(nano); +addonKeyframes(nano); +const {rule} = nano; + +var className = rule({ + width: '200px', + height: '200px', + background: 'red', +}); + +let stories = storiesOf('Addons/Animate', module); + +animations.forEach(name => { + stories = stories.add(name, () => { + require('../addon/animate/' + name).addon(nano); + return h('div', {className: name + className}); + }); +}); diff --git a/.storybook/global-css.stories.js b/.storybook/global-css.stories.js new file mode 100644 index 00000000..ab0959d2 --- /dev/null +++ b/.storybook/global-css.stories.js @@ -0,0 +1,14 @@ +import {createElement as h} from 'react'; +import {storiesOf} from '@storybook/react'; +const {action} = require('@storybook/addon-actions'); +const {linkTo} = require('@storybook/addon-links'); +const {create} = require('../index'); +const {addon: resetEricMeyerCondensed} = require('../addon/reset/EricMeyerCondensed'); + +const nano = create(); +resetEricMeyerCondensed(nano); + +storiesOf('CSS resets', module) + .add('Eric Meyer - condensed', () => + h('div', null, 'Hello world') + ) diff --git a/.storybook/stylis.stories.js b/.storybook/stylis.stories.js new file mode 100644 index 00000000..aeb3648f --- /dev/null +++ b/.storybook/stylis.stories.js @@ -0,0 +1,24 @@ +import {createElement as h} from 'react'; +import {storiesOf} from '@storybook/react'; +const {action} = require('@storybook/addon-actions'); +const {linkTo} = require('@storybook/addon-links'); +const {create} = require('../index'); +const {addon: addonStylis} = require('../addon/stylis'); +const {addon: addonRule} = require('../addon/rule'); + +const renderer = create({h}); +addonStylis(renderer); +addonRule(renderer); +const {rule} = renderer; + +const className = rule(` + color: red; + &:hover { + color: blue; + } +`); + +storiesOf('Addons/stylis', module) + .add('Default', () => + h('div', {className}, 'Hello world') + ) diff --git a/.travis.yml b/.travis.yml index 33f1b33c..b3862a8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ node_js: - '8' script: - npm run test - - npm run build matrix: allow_failures: [] fast_finish: true diff --git a/README.md b/README.md index 6f56e9c5..43d8f6ee 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,12 @@ __Tiny [5th generation](https://github.com/streamich/freestyler/blob/ - [`nesting`](./docs/nesting.md) - [`keyframes()`](./docs/keyframes.md) - [`hydrate`](./docs/hydrate.md) + - [`stylis`](./docs/stylis.md) - [`unitless`](./docs/unitless.md) - [`!important`](./docs/important.md) - [`:global`](./docs/global.md) + - [Animations](./docs/animations.md) + - [CSS resets](./docs/resets.md) - [Server-side rendering](./docs/SSR.md) diff --git a/addon/__tests__/__snapshots__/reset.test.js.snap b/addon/__tests__/__snapshots__/reset.test.js.snap new file mode 100644 index 00000000..3a8469bd --- /dev/null +++ b/addon/__tests__/__snapshots__/reset.test.js.snap @@ -0,0 +1,332 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`reset EricMeyer 1`] = ` +Object { + ":focus": Object { + "out": 0, + }, + "blockquote, q": Object { + "quotes": "\\"\\" \\"\\"", + }, + "blockquote:before, blockquote:after, q:before, q:after": Object { + "content": "\\"\\"", + }, + "body": Object { + "bg": "white", + "col": "black", + "lh": 1, + }, + "caption, th, td": Object { + "fw": "normal", + "ta": "left", + }, + "html,body,div,span,applet,object,iframe,table,caption,tbody,tfoot,thead,tr,th,td,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,dl,dt,dd,ol,ul,li,fieldset,form,label,legend": Object { + "bd": 0, + "ff": "inherit", + "fs": "inherit", + "fw": "inherit", + "fz": "100%", + "mar": 0, + "out": 0, + "pad": 0, + "vertical-align": "baseline", + }, + "ol, ul": Object { + "list-style": "none", + }, + "table": Object { + "border-collapse": "separate", + "border-spacing": 0, + }, +} +`; + +exports[`reset EricMeyerCondensed 1`] = ` +Object { + "abbr, acronym": Object { + "bd": 0, + }, + "address, caption, cite, code, dfn, em, strong, th, var": Object { + "fs": "normal", + "fw": "normal", + }, + "body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td": Object { + "mar": 0, + "pad": 0, + }, + "caption, th": Object { + "ta": "left", + }, + "fieldset, img": Object { + "bd": 0, + }, + "h1, h2, h3, h4, h5, h6": Object { + "fs": "100%", + "fw": "normal", + }, + "ol, ul": Object { + "list-style": "none", + }, + "q:before, q:after": Object { + "con": "''", + }, + "table": Object { + "border-collapse": "collapse", + "border-spacing": 0, + }, +} +`; + +exports[`reset Minimalistic 1`] = ` +Object { + "*": Object { + "mar": 0, + "pad": 0, + }, +} +`; + +exports[`reset Minimalistic2 1`] = ` +Object { + "*": Object { + "bd": 0, + "mar": 0, + "pad": 0, + }, +} +`; + +exports[`reset Minimalistic3 1`] = ` +Object { + "*": Object { + "bd": 0, + "mar": 0, + "out": 0, + "pad": 0, + }, +} +`; + +exports[`reset PoorMan 1`] = ` +Object { + "a img, :link img, :visited img": Object { + "bd": 0, + }, + "body": Object { + "fz": "100%", + }, + "html": Object { + "fz": "1em", + }, + "html, body": Object { + "mar": 0, + "pad": 0, + }, +} +`; + +exports[`reset ShaunInman 1`] = ` +Object { + "a,ins": Object { + "td": "none", + }, + "address,caption,cite,code,dfn,em,h1,h2,h3,h4,h5,h6,strong,th,var": Object { + "fs": "normal", + "fw": "normal", + }, + "body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,table,th,td,embed,object": Object { + "mar": 0, + "pad": 0, + }, + "caption,th": Object { + "ta": "left", + }, + "fieldset,img,abbr": Object { + "bd": 0, + }, + "h1,h2,h3,h4,h5,h6": Object { + "fz": "1.0em", + }, + "q:before,q:after": Object { + "con": "\\"\\"", + }, + "table": Object { + "border-collapse": "collapse", + "border-spacing": 0, + }, + "ul": Object { + "list-style": "none", + }, +} +`; + +exports[`reset Siolon 1`] = ` +Object { + "*": Object { + "bd": "none", + "ff": "inherit", + "fs": "inherit", + "fz": "100%", + "mar": 0, + "pad": 0, + "vertical-align": "baseline", + }, + "body": Object { + "pad": "5px", + }, + "h1, h2, h3, h4, h5, h6, p, pre, blockquote, form, ul, ol, dl": Object { + "mar": "20px 0", + }, + "li, dd, blockquote": Object { + "marl": "40px", + }, + "table": Object { + "border-collapse": "collapse", + "border-spacing": 0, + }, +} +`; + +exports[`reset Tantek 1`] = ` +Object { + ":link,:visited": Object { + "td": "none", + }, + "a img,:link img,:visited img": Object { + "bd": "none", + }, + "address": Object { + "fs": "normal", + }, + "h1,h2,h3,h4,h5,h6,pre,code,p": Object { + "fz": "1em", + }, + "ul,ol": Object { + "list-style": "none", + }, + "ul,ol,dl,li,dt,dd,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input": Object { + "mar": 0, + "pad": 0, + }, +} +`; + +exports[`reset Tripoli 1`] = ` +Object { + "*": Object { + "fz": "1em", + "mar": 0, + "out": "none", + "pad": 0, + "td": "none", + }, + "a": Object { + "col": "inherit", + }, + "a,img,a img,iframe,form,fieldset,abbr,acronym,object,applet,table": Object { + "bd": "none", + }, + "blink": Object { + "td": "none", + }, + "body": Object { + "bg": "white", + "col": "black", + "lh": 1, + }, + "caption,th,td,center": Object { + "ta": "left", + "vertical-align": "top", + }, + "code,kbd,samp,pre,tt,var,textarea,input,select,isindex,listing,xmp,plaintext": Object { + "font": "inherit", + "fz": "1em", + "white-space": "normal", + }, + "dfn,i,cite,var,address,em": Object { + "fs": "normal", + }, + "font": Object { + "col": "inherit !important", + "font": "inherit !important", + }, + "hr": Object { + "d": "none", + }, + "marquee": Object { + "-moz-binding": "none", + "ov": "inherit !important", + }, + "nobr": Object { + "white-space": "normal", + }, + "q": Object { + "quotes": "\\"\\" \\"\\"", + }, + "sub,sup": Object { + "vertical-align": "baseline", + }, + "table": Object { + "border-collapse": "collapse", + "border-spacing": 0, + }, + "th,b,strong,h1,h2,h3,h4,h5,h6": Object { + "fw": "normal", + }, + "ul,ol,dir,menu": Object { + "list-style": "none", + }, +} +`; + +exports[`reset Universal 1`] = ` +Object { + "*": Object { + "bd": "0 none", + "ff": "inherit", + "fs": "inherit", + "fw": "inherit", + "fz": "100%", + "mar": 0, + "out": 0, + "pad": 0, + "vertical-align": "baseline", + }, +} +`; + +exports[`reset Yahoo 1`] = ` +Object { + "abbr,acronym": Object { + "bd": 0, + }, + "address,caption,cite,code,dfn,em,strong,th,var": Object { + "fs": "normal", + "fw": "normal", + }, + "body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td": Object { + "mar": 0, + "pad": 0, + }, + "caption,th": Object { + "ta": "left", + }, + "fieldset,img": Object { + "bd": 0, + }, + "h1,h2,h3,h4,h5,h6": Object { + "fw": "normal", + "fz": "100%", + }, + "ol,ul": Object { + "list-style": "none", + }, + "q:before,q:after": Object { + "con": "\\"\\"", + }, + "table": Object { + "border-collapse": "collapse", + "border-spacing": 0, + }, +} +`; diff --git a/addon/__tests__/reset.test.js b/addon/__tests__/reset.test.js new file mode 100644 index 00000000..e748abe0 --- /dev/null +++ b/addon/__tests__/reset.test.js @@ -0,0 +1,37 @@ +/* eslint-disable */ +'use strict'; + +var create = require('../../index').create; + +var resets = [ + 'EricMeyer', + 'EricMeyerCondensed', + 'Minimalistic', + 'Minimalistic2', + 'Minimalistic3', + 'PoorMan', + 'ShaunInman', + 'Siolon', + 'Tantek', + 'Tripoli', + 'Universal', + 'Yahoo' +]; + +describe('reset', function () { + resets.forEach(function (name) { + var addon = require('../../addon/reset/' + name).addon; + + it(name, function () { + var nano = create(); + + nano.put = jest.fn(); + + addon(nano); + + expect(nano.put).toHaveBeenCalledTimes(1); + expect(nano.put.mock.calls[0][0]).toBe(''); + expect(nano.put.mock.calls[0][1]).toMatchSnapshot(); + }); + }); +}); diff --git a/addon/animate/fadeIn.js b/addon/animate/fadeIn.js index db46d7a1..24c04474 100644 --- a/addon/animate/fadeIn.js +++ b/addon/animate/fadeIn.js @@ -16,7 +16,7 @@ exports.addon = function (renderer) { }, '.fadeIn': { - animationName: 'fadeIn', + animation: 'fadeIn .4s linear', } }); }; diff --git a/addon/animate/fadeInDown.js b/addon/animate/fadeInDown.js new file mode 100644 index 00000000..f60ccb31 --- /dev/null +++ b/addon/animate/fadeInDown.js @@ -0,0 +1,25 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('animate', renderer, ['keyframes']); + } + + renderer.put('', { + '@keyframes fadeInDown': { + from: { + opacity: 0, + transform: 'translate3d(0, -10%, 0)' + }, + + to: { + opacity: 1, + transform: 'translate3d(0, 0, 0)', + } + }, + + '.fadeInDown': { + animation: 'fadeInDown .3s', + } + }); +}; diff --git a/addon/animate/fadeInExpand.js b/addon/animate/fadeInExpand.js new file mode 100644 index 00000000..993d65f0 --- /dev/null +++ b/addon/animate/fadeInExpand.js @@ -0,0 +1,25 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('animate', renderer, ['keyframes']); + } + + renderer.put('', { + '@keyframes fadeInExpand': { + from: { + opacity: 0, + transform: 'scale(.95)' + }, + + to: { + opacity: 1, + transform: 'scale(1)', + } + }, + + '.fadeInExpand': { + animation: 'fadeInExpand .3s', + } + }); +}; diff --git a/addon/reset/EricMeyer.js b/addon/reset/EricMeyer.js new file mode 100644 index 00000000..7a64cba8 --- /dev/null +++ b/addon/reset/EricMeyer.js @@ -0,0 +1,48 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + 'html,body,div,span,applet,object,iframe,table,caption,tbody,tfoot,thead,tr,th,td,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,dl,dt,dd,ol,ul,li,fieldset,form,label,legend': { + 'vertical-align': 'baseline', + ff: 'inherit', + fw: 'inherit', + fs: 'inherit', + fz: '100%', + out: 0, + pad: 0, + mar: 0, + bd: 0, + }, + ':focus': { + out: 0, + }, + body: { + bg: 'white', + lh: 1, + col: 'black', + }, + 'ol, ul': { + 'list-style': 'none', + }, + table: { + 'border-collapse': 'separate', + 'border-spacing': 0, + }, + 'caption, th, td': { + fw: 'normal', + ta: 'left', + }, + 'blockquote:before, blockquote:after, q:before, q:after': { + content: '""', + }, + 'blockquote, q': { + quotes: '"" ""', + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/EricMeyerCondensed.js b/addon/reset/EricMeyerCondensed.js new file mode 100644 index 00000000..9516a6b2 --- /dev/null +++ b/addon/reset/EricMeyerCondensed.js @@ -0,0 +1,44 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + 'body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td': { + pad: 0, + mar: 0, + }, + 'fieldset, img': { + bd: 0, + }, + table: { + 'border-collapse': 'collapse', + 'border-spacing': 0, + }, + 'ol, ul': { + 'list-style': 'none', + }, + 'address, caption, cite, code, dfn, em, strong, th, var': { + fw: 'normal', + fs: 'normal', + }, + 'caption, th': { + ta: 'left', + }, + 'h1, h2, h3, h4, h5, h6': { + fw: 'normal', + fs: '100%', + }, + 'q:before, q:after': { + con: "''", + }, + 'abbr, acronym': { + bd: 0, + }, + }; + + renderer.put('', css); +}; + diff --git a/addon/reset/Minimalistic.js b/addon/reset/Minimalistic.js new file mode 100644 index 00000000..67e91f34 --- /dev/null +++ b/addon/reset/Minimalistic.js @@ -0,0 +1,16 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + '*': { + pad: 0, + mar: 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Minimalistic2.js b/addon/reset/Minimalistic2.js new file mode 100644 index 00000000..ec852508 --- /dev/null +++ b/addon/reset/Minimalistic2.js @@ -0,0 +1,17 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + '*': { + pad: 0, + mar: 0, + bd: 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Minimalistic3.js b/addon/reset/Minimalistic3.js new file mode 100644 index 00000000..6e8dc76e --- /dev/null +++ b/addon/reset/Minimalistic3.js @@ -0,0 +1,18 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + '*': { + pad: 0, + mar: 0, + bd: 0, + out: 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/PoorMan.js b/addon/reset/PoorMan.js new file mode 100644 index 00000000..b382855a --- /dev/null +++ b/addon/reset/PoorMan.js @@ -0,0 +1,25 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + 'html, body': { + pad: 0, + mar: 0, + }, + html: { + fz: '1em', + }, + body: { + fz: '100%', + }, + 'a img, :link img, :visited img': { + bd: 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/ShaunInman.js b/addon/reset/ShaunInman.js new file mode 100644 index 00000000..7a4a5894 --- /dev/null +++ b/addon/reset/ShaunInman.js @@ -0,0 +1,42 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + 'body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,table,th,td,embed,object': { + pad: 0, + mar: 0, + }, + table: { + 'border-collapse': 'collapse', + 'border-spacing': 0, + }, + 'fieldset,img,abbr': { + bd: 0, + }, + 'address,caption,cite,code,dfn,em,h1,h2,h3,h4,h5,h6,strong,th,var': { + fw: 'normal', + fs: 'normal', + }, + ul: { + 'list-style': 'none', + }, + 'caption,th': { + ta: 'left', + }, + 'h1,h2,h3,h4,h5,h6': { + fz: '1.0em', + }, + 'q:before,q:after': { + con: '""', + }, + 'a,ins': { + td: 'none', + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Siolon.js b/addon/reset/Siolon.js new file mode 100644 index 00000000..0bb403c1 --- /dev/null +++ b/addon/reset/Siolon.js @@ -0,0 +1,34 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + '*': { + 'vertical-align': 'baseline', + ff: 'inherit', + fs: 'inherit', + fz: '100%', + bd: 'none', + pad: 0, + mar: 0, + }, + body: { + pad: '5px', + }, + 'h1, h2, h3, h4, h5, h6, p, pre, blockquote, form, ul, ol, dl': { + mar: '20px 0', + }, + 'li, dd, blockquote': { + marl: '40px', + }, + table: { + 'border-collapse': 'collapse', + 'border-spacing': 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Tantek.js b/addon/reset/Tantek.js new file mode 100644 index 00000000..78ab81a0 --- /dev/null +++ b/addon/reset/Tantek.js @@ -0,0 +1,31 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + ':link,:visited': { + td: 'none', + }, + 'ul,ol': { + 'list-style': 'none', + }, + 'h1,h2,h3,h4,h5,h6,pre,code,p': { + fz: '1em', + }, + 'ul,ol,dl,li,dt,dd,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input': { + pad: 0, + mar: 0, + }, + 'a img,:link img,:visited img': { + bd: 'none', + }, + address: { + fs: 'normal', + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Tripoli.js b/addon/reset/Tripoli.js new file mode 100644 index 00000000..411fd74a --- /dev/null +++ b/addon/reset/Tripoli.js @@ -0,0 +1,75 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + '*': { + td: 'none', + fz: '1em', + out: 'none', + pad: 0, + mar: 0, + }, + 'code,kbd,samp,pre,tt,var,textarea,input,select,isindex,listing,xmp,plaintext': { + 'white-space': 'normal', + fz: '1em', + font: 'inherit', + }, + 'dfn,i,cite,var,address,em': { + fs: 'normal', + }, + 'th,b,strong,h1,h2,h3,h4,h5,h6': { + fw: 'normal', + }, + 'a,img,a img,iframe,form,fieldset,abbr,acronym,object,applet,table': { + bd: 'none', + }, + table: { + 'border-collapse': 'collapse', + 'border-spacing': 0, + }, + 'caption,th,td,center': { + 'vertical-align': 'top', + ta: 'left', + }, + body: { + bg: 'white', + lh: 1, + col: 'black', + }, + q: { + quotes: '"" ""', + }, + 'ul,ol,dir,menu': { + 'list-style': 'none', + }, + 'sub,sup': { + 'vertical-align': 'baseline', + }, + a: { + col: 'inherit', + }, + hr: { + d: 'none', + }, + font: { + col: 'inherit !important', + font: 'inherit !important', + }, + marquee: { + ov: 'inherit !important', + '-moz-binding': 'none', + }, + blink: { + td: 'none', + }, + nobr: { + 'white-space': 'normal', + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Universal.js b/addon/reset/Universal.js new file mode 100644 index 00000000..d18ce156 --- /dev/null +++ b/addon/reset/Universal.js @@ -0,0 +1,23 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + '*': { + 'vertical-align': 'baseline', + fw: 'inherit', + ff: 'inherit', + fs: 'inherit', + fz: '100%', + bd: '0 none', + out: 0, + pad: 0, + mar: 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/reset/Yahoo.js b/addon/reset/Yahoo.js new file mode 100644 index 00000000..7616c817 --- /dev/null +++ b/addon/reset/Yahoo.js @@ -0,0 +1,43 @@ +'use strict'; + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('../__dev__/warnOnMissingDependencies')('reset', renderer, ['put']); + } + + var css = { + 'body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td': { + pad: 0, + mar: 0, + }, + table: { + 'border-collapse': 'collapse', + 'border-spacing': 0, + }, + 'fieldset,img': { + bd: 0, + }, + 'address,caption,cite,code,dfn,em,strong,th,var': { + fw: 'normal', + fs: 'normal', + }, + 'ol,ul': { + 'list-style': 'none', + }, + 'caption,th': { + ta: 'left', + }, + 'h1,h2,h3,h4,h5,h6': { + fw: 'normal', + fz: '100%', + }, + 'q:before,q:after': { + con: '""', + }, + 'abbr,acronym': { + bd: 0, + }, + }; + + renderer.put('', css); +}; diff --git a/addon/stylis.js b/addon/stylis.js new file mode 100644 index 00000000..46dc9d84 --- /dev/null +++ b/addon/stylis.js @@ -0,0 +1,28 @@ +'use strict'; + +var Stylis = require('stylis'); +var onRulePlugin = require('./stylis/plugin-onRule'); + +exports.addon = function (renderer) { + if (process.env.NODE_ENV !== 'production') { + require('./__dev__/warnOnMissingDependencies')('stylis', renderer, ['put']); + } + + renderer.stylis = new Stylis(); + + var plugin = onRulePlugin(function (rawCssRule) { + renderer.putRaw(rawCssRule); + }); + + renderer.stylis.use(plugin); + + var put = renderer.put; + + renderer.put = function (selector, css) { + if (typeof css !== 'string') { + return put(selector, css); + } + + renderer.stylis(selector, css); + }; +}; diff --git a/addon/stylis/plugin-onRule.js b/addon/stylis/plugin-onRule.js new file mode 100644 index 00000000..62d6aba2 --- /dev/null +++ b/addon/stylis/plugin-onRule.js @@ -0,0 +1,43 @@ +'use strict'; + +module.exports = function (insertRule) { + var delimiter = '/*|*/'; + var needle = delimiter + '}'; + + function toSheet (block) { + if (block) + try { + insertRule(block + '}'); + } catch (e) { + // eslint-disable-next-line + }; + } + + return function ruleSheet (context, content, selectors, parents, line, column, length, ns, depth, at) { + switch (context) { + // property + case 1: + // @import + if (depth === 0 && content.charCodeAt(0) === 64) + return insertRule(content+';'), ''; + break; + // selector + case 2: + if (ns === 0) + return content + delimiter; + break; + // at-rule + case 3: + switch (ns) { + // @font-face, @page + case 102: + case 112: + return insertRule(selectors[0]+content), ''; + default: + return content + (at === 0 ? delimiter : ''); + } + case -2: + content.split(needle).forEach(toSheet); + } + }; +}; diff --git a/docs/Addons.md b/docs/Addons.md index 8d02bb90..f58cfc2a 100644 --- a/docs/Addons.md +++ b/docs/Addons.md @@ -3,27 +3,30 @@ `nano-css` comes only with a single [`put()`](./put.md) addon pre-installed. However, it has plenty more to chose from. Below is a list of addons shipped with `nano-css`. -- [`put()`](./put.md) -- [`rule()`](./rule.md) -- [`drule()`](./drule.md) -- [`sheet()`](./sheet.md) -- [`dsheet()`](./dsheet.md) -- [`jsx()`](./jsx.md) -- [`useStyles()`](./useStyles.md) -- [`withStyles()`](./withStyles.md) -- [`decorator`](./decorator.md) -- [`component`](./component.md) -- [`style()`](./style.md) -- [`styled()()`](./styled.md) -- [`hyperstyle()`](./hyperstyle.md) -- [`stable`](./stable.md) -- [`atoms`](./atoms.md) -- [`nesting`](./nesting.md) -- [`keyframes()`](./keyframes.md) -- [`hydrate`](./hydrate.md) -- [`unitless`](./unitless.md) -- [`!important`](./important.md) -- [`:global`](./global.md) +- [`put()`](./put.md) — injects CSS styles given a selector +- [`rule()`](./rule.md) — injects CSS styles and returns a generated selector +- [`drule()`](./drule.md) — like `rule()`, but allows to add on-the-fly overrides +- [`sheet()`](./sheet.md) — collection of `rule()`s, injects CSS styles only when used +- [`dsheet()`](./dsheet.md) — like `sheet()`, but allows to add on-the-fly overrides +- [`jsx()`](./jsx.md) — creates styling blocks for virtual DOM libraries +- [`useStyles()`](./useStyles.md) — adds `styles` as a second argument for your component +- [`withStyles()`](./withStyles.md) — injects `styles` prop into your component +- [`decorator`](./decorator.md) — provides `@css` decorator for styling stateful React components +- [`component`](./component.md) — provides React `Component` class to inherit from +- [`style()`](./style.md) — allows you to create *styled components* +- [`styled()()`](./styled.md) — better syntax for *styled components* +- [`hyperstyle()`](./hyperstyle.md) — creates styled hyperscript `h` function +- [`stable`](./stable.md) — generates consistent class names +- [`atoms`](./atoms.md) — CSS shorthands for better DX +- [`nesting`](./nesting.md) — better nesting features +- [`keyframes()`](./keyframes.md) — adds `@keyframes` support +- [`hydrate`](./hydrate.md) — adds support for re-hydration on client side +- [`stylis`](./stylis.md) — write CSS as strings +- [`unitless`](./unitless.md) — automatically adds `px` to styles +- [`!important`](./important.md) — adds `!important` to all declarations +- [`:global`](./global.md) — allows emitting global styles +- [Animations](./animations.md) — collection of animation styles +- [CSS resets](./resets.md) — collection of CSS resets ## Addon Installation @@ -32,6 +35,17 @@ All addons are in the `nano-css/addon/` folder and are exported as an `addon` named export. Addon is simply a function that receives `nano-css` renderer object as a single argument. +When these docs mention that you need to install an addon, say `xxx`, you simply import it +from the addon folder and apply to the nano renderer object: + +```js +import {addon as addonXXX} from 'nano-css/addon/xxx'; + +addonXXX(nano); + +nano.xxx(/* ... */); +``` + Here we install [`rule()`](./rule.md) and [`atoms`](./atoms.md) addons: ```js @@ -44,14 +58,3 @@ const nano = create(); addonRule(nano); addonAtoms(nano); ``` - -When these docs mention that you need to install an addon, say `xxx`, you simply import it -from the addon folder and apply to the nano renderer object: - -```js -import {addon as addonXXX} from 'nano-css/addon/xxx'; - -addonXXX(nano); - -nano.xxx(/* ... */); -``` diff --git a/docs/Installation.md b/docs/Installation.md index 740b9373..8096d928 100644 --- a/docs/Installation.md +++ b/docs/Installation.md @@ -71,10 +71,9 @@ addonRule(nano); addonSheet(nano); addonJsx(nano); -const {put, rule, sheet, jsx, keyframes} = nano; +const {rule, sheet, jsx, keyframes} = nano; export { - put, rule, sheet, jsx, diff --git a/docs/animations.md b/docs/animations.md new file mode 100644 index 00000000..1b06621b --- /dev/null +++ b/docs/animations.md @@ -0,0 +1,32 @@ +# Animations + +`nano-css` has a number of CSS animation addons. Simply install any of the +below animation addons and you will have available class and animation with that same +name. + +- `animate/fadeIn` +- `animate/fadeInDown` +- `animate/fadeInExpand` + +Read more about the [Addons Installation](./Addons.md#addon-installation). + + +## Example + +```js +import {addon as addonAnimateFadeIn} from 'nano-css/addon/animate/fadeIn'; + +addonAnimateFadeIn(nano); +``` + +Now you can use the `fadeIn` class name to *"fade in"* your elements. + +```html +
Hello world!
+``` + +Or use the `fadeIn` animation directly to apply custom tween settings. + +```html +
Hello world!
+``` diff --git a/docs/atoms.md b/docs/atoms.md index 0de0ac7c..5b3f5825 100644 --- a/docs/atoms.md +++ b/docs/atoms.md @@ -24,7 +24,7 @@ const className = rule({ }); ``` -Those are handy DX and they will decrease your overall bundle size after +Those are good for __DX__ and they will decrease your overall bundle size after sufficient use. You can find the full up-to-date atom list [here](../addon/atoms.js). Below is the atom list at the moment of this writing: @@ -82,4 +82,4 @@ var atoms = { ## Installation -Simply install `atoms` addon. Read more about the [Addons](./Addons.md). +Simply install `atoms` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/component.md b/docs/component.md index 091823ad..e679eb5c 100644 --- a/docs/component.md +++ b/docs/component.md @@ -49,4 +49,4 @@ Simply install `component` addon and its dependencies: - `cache` - [`rule()`](./rule.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/decorator.md b/docs/decorator.md index 5fba27c0..36b801de 100644 --- a/docs/decorator.md +++ b/docs/decorator.md @@ -102,4 +102,4 @@ Simply install `decorator` addon and its dependencies: - `cache` - [`rule()`](./rule.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/drule.md b/docs/drule.md index 88ae20ee..c3849f4a 100644 --- a/docs/drule.md +++ b/docs/drule.md @@ -55,7 +55,7 @@ const Button = ({children, primary}) => ## Installation -To use, install `drule` addon, which depends on `rule` and `cache` addons, read more about the [Addons](./Addons.md). +To use, install `drule` addon, which depends on `rule` and `cache` addons. ```js import {create} from 'nano-css'; @@ -74,3 +74,5 @@ export { drule } ``` + +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/dsheet.md b/docs/dsheet.md index 603b8e88..96566707 100644 --- a/docs/dsheet.md +++ b/docs/dsheet.md @@ -48,4 +48,4 @@ Install `dsheet` addon and its dependencies: - [`rule()`](./rule.md) - [`sheet()`](./sheet.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/global.md b/docs/global.md index 05fe7ce4..2e6a6335 100644 --- a/docs/global.md +++ b/docs/global.md @@ -46,4 +46,4 @@ nano.global({ ## Installation -Simply install `global` addon. Read more about the [Addons](./Addons.md). +Simply install `global` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/hydrate.md b/docs/hydrate.md index f9fba165..1bde8648 100644 --- a/docs/hydrate.md +++ b/docs/hydrate.md @@ -10,8 +10,19 @@ That's it! `hydrate` addon will find this stylesheet in the browser and will not rules that were already generated by the server. +## Configuration + +You can set a custom id for you style sheet. + +```js +import {addon as addonHydrate} from 'nano-css/addon/hydrate'; + +addonHydrate(nano, 'custom-id'); +``` + + ## Installation Simply install `hydrate` addon. -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/hyperstyle.md b/docs/hyperstyle.md index 2af21cfb..b450639c 100644 --- a/docs/hyperstyle.md +++ b/docs/hyperstyle.md @@ -57,4 +57,4 @@ Simply install `hyperstyle` addon and its dependencies: - [`rule()`](./rule.md) - [`sheet()`](./sheet.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/important.md b/docs/important.md index 978b0205..56bb0e91 100644 --- a/docs/important.md +++ b/docs/important.md @@ -5,4 +5,4 @@ Adds `!important` to every style declaration. ## Installation -Simply install `important` addon. Read more about the [Addons](./Addons.md). +Simply install `important` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/jsx.md b/docs/jsx.md index 1f1d32ad..6777ea6a 100644 --- a/docs/jsx.md +++ b/docs/jsx.md @@ -168,4 +168,4 @@ Simply install `jsx` addon and its dependencies: - `cache` - [`rule()`](./rule.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/keyframes.md b/docs/keyframes.md index 21d87639..59f71b43 100644 --- a/docs/keyframes.md +++ b/docs/keyframes.md @@ -21,4 +21,4 @@ const className = rule({ ## Installation -Simply install `keyframes` addon. Read more about the [Addons](./Addons.md). +Simply install `keyframes` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/nesting.md b/docs/nesting.md index 6aaab183..b5688719 100644 --- a/docs/nesting.md +++ b/docs/nesting.md @@ -52,4 +52,4 @@ This results in: ## Installation -Simply install `nesting` addon. Read more about the [Addons](./Addons.md). +Simply install `nesting` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/resets.md b/docs/resets.md new file mode 100644 index 00000000..2703f862 --- /dev/null +++ b/docs/resets.md @@ -0,0 +1,27 @@ +# CSS Resets + +`nano-css` has a number of CSS reset addons. Simply, install one of the following +addons and that CSS reset will be injected on your page. + +- `reset/EricMeyer` +- `reset/EricMeyerCondensed` +- `reset/Minimalistic` +- `reset/Minimalistic2` +- `reset/Minimalistic3` +- `reset/PoorMan` +- `reset/ShaunInman` +- `reset/Siolon` +- `reset/Tantek` +- `reset/Tripoli` +- `reset/Universal` + +Read more about the [Addons Installation](./Addons.md#addon-installation). + + +## Example + +```js +import {addon as addonReset} from 'nano-css/addon/reset/EricMeyerCondensed'; + +adddonReset(nano); +``` diff --git a/docs/rule.md b/docs/rule.md index facc6f4f..ed46cbee 100644 --- a/docs/rule.md +++ b/docs/rule.md @@ -58,7 +58,7 @@ This results in: ## Installation -Simply add the the `rule` addon, read more about the [Addons](./Addons.md). +Simply add the the `rule` addon. ```js import {create} from 'nano-css'; @@ -72,3 +72,5 @@ export { rule } ``` + +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/sheet.md b/docs/sheet.md index b9d85b73..5bc3384d 100644 --- a/docs/sheet.md +++ b/docs/sheet.md @@ -51,4 +51,4 @@ console.log(styles.input); // pfx-ContactForm-input Simply install `rule` and `sheet` addons. -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/stable.md b/docs/stable.md index c1b1532c..1197fb77 100644 --- a/docs/stable.md +++ b/docs/stable.md @@ -6,4 +6,4 @@ to generate fast predictable hashes across JavaScript runtimes. ## Installation -Simply install `stable` addon. Read more about the [Addons](./Addons.md). +Simply install `stable` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/style.md b/docs/style.md index 9d3c800a..179046b0 100644 --- a/docs/style.md +++ b/docs/style.md @@ -118,4 +118,4 @@ Simply install `style` addon and its dependencies: - [`rule()`](./rule.md) - [`jsx()`](./jsx.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/styled.md b/docs/styled.md index 7f0a76f6..8bcf296e 100644 --- a/docs/styled.md +++ b/docs/styled.md @@ -48,4 +48,4 @@ Simply install `styled` addon and its dependencies: - [`jsx()`](./jsx.md) - [`style()`](./style.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/stylis.md b/docs/stylis.md new file mode 100644 index 00000000..61d339a3 --- /dev/null +++ b/docs/stylis.md @@ -0,0 +1,18 @@ +# `stylis` Addon + +Addes [`stylis`](https://github.com/thysultan/stylis.js) pre-processor. This allows you +to write CSS as a string using `stylis` syntax everywhere where CSS-like object is expected. + +```js +const className = nano.rule(` + color: red; + &:hover { + color: blue + } +`); +``` + + +## Installation + +Simply install `stylis` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/unitless.md b/docs/unitless.md index 835429fb..806d12fc 100644 --- a/docs/unitless.md +++ b/docs/unitless.md @@ -30,4 +30,4 @@ Result: ## Installation -Simply install `unitless` addon. Read more about the [Addons](./Addons.md). +Simply install `unitless` addon. Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/useStyles.md b/docs/useStyles.md index cabcc3f5..dbb58a0a 100644 --- a/docs/useStyles.md +++ b/docs/useStyles.md @@ -38,4 +38,4 @@ Install `useStyles` addon and its dependencies: - [`rule()`](./rule.md) - [`sheet()`](./sheet.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/docs/withStyles.md b/docs/withStyles.md index 35455cc5..756159ae 100644 --- a/docs/withStyles.md +++ b/docs/withStyles.md @@ -37,4 +37,4 @@ Install `withStyles` addon and its dependencies: - [`rule()`](./rule.md) - [`sheet()`](./sheet.md) -Read more about the [Addons](./Addons.md). +Read more about the [Addons Installation](./Addons.md#addon-installation). diff --git a/package.json b/package.json index a874fd4f..88e1aab4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nano-css", - "version": "0.1.0", + "version": "1.1.0", "description": "Smallest 5th gen CSS-in-JS library", "main": "index.js", "unpkg": "dist/nano-css.umd.min.js", @@ -36,7 +36,8 @@ "react-dom": "*" }, "dependencies": { - "fastest-stable-stringify": "^1.0.1" + "fastest-stable-stringify": "^1.0.1", + "stylis": "3.5.0" }, "devDependencies": { "@types/react": "16.0.40",