diff --git a/.storybook/styled.stories.js b/.storybook/styled.stories.js index 9f5791bb..1046a5d7 100644 --- a/.storybook/styled.stories.js +++ b/.storybook/styled.stories.js @@ -29,6 +29,32 @@ const RedBorderItalic = styled(RedBorder)({ fontStyle: 'italic' }); +const Button = styled('button')({ + fontFamily: 'inherit', + fontSize: '14px', + fontWeight: 'bold', + lineHeight: 16/14, + display: 'inline-block', + margin: 0, + verticalAlign: 'middle', + textAlign: 'center', + textDecoration: 'none', + borderRadius: '3px', + border: 0, + appearance: 'none', + color: 'white', + backgroundColor: 'blue', + '&:hover': { + boxShadow: `inset 0 0 0 999px #888` + }, + '&:active': { + boxShadow: `inset 0 0 8px #999` + }, + '&:disabled': { + opacity: 1/4 + } +}) + storiesOf('Addons/styled()', module) .add('Default', () => h(RedBorder, null, 'Hello world') @@ -42,3 +68,6 @@ storiesOf('Addons/styled()', module) .add('Composability', () => h(RedBorderItalic, null, 'Hello world') ) + .add('Button', () => + h(Button, null, 'Click me!') + ) diff --git a/README.md b/README.md index 50f4aebd..9264433c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ The smallest CSS-in-JS library that you can actually use in production. - Performant — does not create wrapper components and caches styles +## Reference + - Usage - Addons - [`put()`](./docs/put.md) diff --git a/addon/rule.js b/addon/rule.js index c85f0330..26af9353 100644 --- a/addon/rule.js +++ b/addon/rule.js @@ -10,27 +10,24 @@ exports.addon = function (renderer) { block = renderer.hash(styles); } - if (renderer.client) { - if (process.env.NODE_ENV !== 'production') { - if (renderer.client) { - /* - if (document.getElementById('css-' + block)) { - console.error( - 'ezcss detected class name collision "css-' + block + '". ' + - 'Multiple components use the same class name.' - ); - } - */ + if (process.env.NODE_ENV !== 'production') { + if (renderer.client) { + /* + if (document.getElementById('css-' + block)) { + console.error( + 'ezcss detected class name collision "css-' + block + '". ' + + 'Multiple components use the same class name.' + ); } - } + */ + if (renderer.cns[block]) { + if (process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line + console.info('Hydration cache hit: "' + block + '"'); + } - if (renderer.cns[block]) { - if (process.env.NODE_ENV !== 'production') { - // eslint-disable-next-line - console.info('Hydration cache hit: "' + block + '"'); + return; } - - return; } } diff --git a/build/webpack.config.cjs.js b/build/webpack.config.cjs.js index 32590179..52632834 100644 --- a/build/webpack.config.cjs.js +++ b/build/webpack.config.cjs.js @@ -4,24 +4,15 @@ var pkg = require('../package.json'); var join = require('path').join; module.exports = { - entry: join(__dirname, '..', 'lib', 'index.js'), + entry: join(__dirname, '..', 'index.js'), output: { filename: pkg.name + '.min.js', path: join(__dirname, '..', 'dist') }, - module: { - rules: [ - { - test: /\.tsx?$/, - loader: 'ts-loader' - } - ] - }, - resolve: { - extensions: ['.ts', '.tsx', '.js', '.jsx'], + extensions: ['.js', '.jsx'], enforceExtension: false } }; diff --git a/demo/demo1.html b/demo/demo1.html new file mode 100644 index 00000000..9e423233 --- /dev/null +++ b/demo/demo1.html @@ -0,0 +1,5 @@ + + + + + diff --git a/demo/demo1.tsx b/demo/demo1.tsx new file mode 100644 index 00000000..41737ed3 --- /dev/null +++ b/demo/demo1.tsx @@ -0,0 +1,5 @@ +const {create} = require('../index'); + +var renderer = create(); + +console.log(renderer); diff --git a/docs/rule.md b/docs/rule.md new file mode 100644 index 00000000..f8f2cdc9 --- /dev/null +++ b/docs/rule.md @@ -0,0 +1,3 @@ +# `rule()` + +`rule()` is the only addon that comes pre-installed with `nano-style`. diff --git a/index.js b/index.js index 6926b250..f7a3296a 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,76 @@ 'use strict'; -var addonConfig = require('./addon/config').addon; -var addonPut = require('./addon/put').addon; +var KEBAB_REGEX = /[A-Z]/g; + +var hash = function (str) { + var hash = 5381, i = str.length; + + while (i) hash = (hash * 33) ^ str.charCodeAt(--i); + + return '_' + (hash >>> 0).toString(36); +}; exports.create = function (config) { - var renderer = {}; + config = config || {}; + var assign = config.assign || Object.assign; + + var renderer = assign({ + raw: '', + cns: {}, + pfx: '_', + client: typeof window === 'object', + assign: assign, + stringify: JSON.stringify, + decl: function (key, value) { + key = key.replace(KEBAB_REGEX, '-$&').toLowerCase(); + return key + ':' + value + ';'; + }, + hash: function (obj) { + return hash(renderer.stringify(obj)); + }, + selector: function (parent, selector) { + return parent + (selector[0] === ':' ? '' : ' ') + selector; + }, + }, config); + + var putRaw; + + if (renderer.client) { + var sheet = document.head.appendChild(document.createElement('style')).sheet; + putRaw = function (rawCss) { + sheet.insertRule(rawCss, 0); + }; + } else { + putRaw = function (rawCss) { + renderer.raw += rawCss; + }; + } + + var put = function (selector, decls, atrule) { + var str = ''; + var prop, value; + + for (prop in decls) { + value = decls[prop]; + + if (value instanceof Object) { + if (prop[0] === '@') { + put(selector, value, prop); + } else { + put(renderer.selector(selector, prop), value, atrule); + } + } else { + str += renderer.decl(prop, value); + } + } + + if (str) { + str = '.' + selector + '{' + str + '}'; + putRaw(atrule ? atrule + '{' + str + '}' : str); + } + }; - addonConfig(renderer, config); - addonPut(renderer); + renderer.put = put; return renderer; }; diff --git a/package.json b/package.json index 9ce5a41b..be782494 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "rimraf": "2.6.2", "source-map-support": "0.5.3", "webpack-dev-server": "2.11.2", - "webpack": "^3.10.0", + "webpack": "^3.5.4", "yarn": "1.5.1", "chai": "4.1.2", "@storybook/react": "3.3.15",