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 +