├── .babelrc ├── src ├── index.js ├── css.js ├── keyframes.js ├── injectGlobal.js ├── module.js ├── parseArguments.js └── styled.js ├── webpack.config.js ├── .gitignore ├── package.json ├── LICENSE └── README.md /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "targets": { 5 | "browsers": ["> 1%", "last 4 versions", "Firefox ESR", "not ie < 9"] 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import styled from "./styled"; 2 | import css from "./css"; 3 | import keyframes from "./keyframes"; 4 | import injectGlobal from "./injectGlobal"; 5 | 6 | export default styled; 7 | export { css, keyframes, injectGlobal }; 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | entry: "./build/module.js", 5 | output: { 6 | path: path.resolve(__dirname, "build"), 7 | library: "styled", 8 | libraryTarget: "umd" 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/css.js: -------------------------------------------------------------------------------- 1 | import { css } from "styled-components"; 2 | 3 | import parseArguments from "./parseArguments"; 4 | 5 | const parsedCSS = (...args) => { 6 | const { strings, interpolations } = parseArguments(args); 7 | return css(strings, ...interpolations); 8 | }; 9 | 10 | export default parsedCSS; 11 | -------------------------------------------------------------------------------- /src/keyframes.js: -------------------------------------------------------------------------------- 1 | import { keyframes } from "styled-components"; 2 | 3 | import parseArguments from "./parseArguments"; 4 | 5 | const parsedKeyframes = (...args) => { 6 | const { strings, interpolations } = parseArguments(args); 7 | return keyframes(strings, ...interpolations); 8 | }; 9 | 10 | export default parsedKeyframes; 11 | -------------------------------------------------------------------------------- /src/injectGlobal.js: -------------------------------------------------------------------------------- 1 | import { injectGlobal } from "styled-components"; 2 | 3 | import parseArguments from "./parseArguments"; 4 | 5 | const parsedInjectGlobal = (...args) => { 6 | const { strings, interpolations } = parseArguments(args); 7 | return injectGlobal(strings, ...interpolations); 8 | }; 9 | 10 | export default parsedInjectGlobal; 11 | -------------------------------------------------------------------------------- /src/module.js: -------------------------------------------------------------------------------- 1 | import styled from "./styled"; 2 | import css from "./css"; 3 | import keyframes from "./keyframes"; 4 | import injectGlobal from "./injectGlobal"; 5 | 6 | module.exports = styled; 7 | module.exports.default = styled; 8 | module.exports.css = css; 9 | module.exports.keyframes = keyframes; 10 | module.exports.injectGlobal = injectGlobal; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | .DS_Store 40 | 41 | # Build 42 | build 43 | -------------------------------------------------------------------------------- /src/parseArguments.js: -------------------------------------------------------------------------------- 1 | export default function(args) { 2 | // if the first arg is an array, assume JS tagged template literal form 3 | if (Array.isArray(args[0])) { 4 | const [strings, ...interpolations] = args; 5 | return { strings, interpolations }; 6 | 7 | // if the first arg is a string, assume CLJS form 8 | } else if (typeof args[0] === "string") { 9 | return args.reduce( 10 | (acc, item, i) => { 11 | if (i % 2 === 0) { 12 | acc.strings.push(item); 13 | } else { 14 | acc.interpolations.push(item); 15 | } 16 | return acc; 17 | }, 18 | { strings: [], interpolations: [] } 19 | ); 20 | } else { 21 | console.error( 22 | `Invalid arguments passed to styled: ${JSON.stringify(args)}` 23 | ); 24 | return { strings: [], interpolations: [] }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "styled-classnames", 3 | "version": "2.2.1", 4 | "description": "styled-components without the components", 5 | "main": "build/index.js", 6 | "scripts": { 7 | "build": "rm -rf build && babel src --out-dir build && webpack --output-filename styled-classnames.umd.js && webpack -p --output-filename styled-classnames.umd.min.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/rgdelato/styled-classnames.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/rgdelato/styled-classnames/issues" 18 | }, 19 | "homepage": "https://github.com/rgdelato/styled-classnames#readme", 20 | "dependencies": { 21 | "styled-components": "^2.1.1" 22 | }, 23 | "peerDependencies": { 24 | "react": ">= 0.14.0 < 17.0.0-0" 25 | }, 26 | "devDependencies": { 27 | "babel-cli": "^6.24.1", 28 | "babel-preset-env": "^1.6.0", 29 | "webpack": "^3.3.0" 30 | }, 31 | "files": [ 32 | "build" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /src/styled.js: -------------------------------------------------------------------------------- 1 | import componentStyle from "styled-components/lib/models/ComponentStyle"; 2 | import generateAlphabeticName from "styled-components/lib/utils/generateAlphabeticName"; 3 | import flatten from "styled-components/lib/utils/flatten"; 4 | import stringifyRules from "styled-components/lib/utils/stringifyRules"; 5 | import css from "./css"; 6 | import StyleSheet from "styled-components/lib/models/StyleSheet"; 7 | 8 | import parseArguments from "./parseArguments"; 9 | 10 | const ComponentStyle = componentStyle( 11 | generateAlphabeticName, 12 | flatten, 13 | stringifyRules 14 | ); 15 | 16 | const generateCSSClassName = (...args) => { 17 | const { strings, interpolations } = parseArguments(args); 18 | const instance = new ComponentStyle( 19 | css(strings, ...interpolations), 20 | "styled-classnames" 21 | ); 22 | 23 | let className = function(props = {}) { 24 | return instance.generateAndInjectStyles(props, StyleSheet.instance); 25 | }; 26 | 27 | className.toString = className; 28 | 29 | return className; 30 | }; 31 | 32 | export default generateCSSClassName; 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ryan De La Torre 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 | # Warning: This library is no longer being maintained! 2 | I would strongly recommend using another CSS-in-JS library, such as [Emotion](https://emotion.sh/) 3 | 4 | # styled-classnames 5 | Use [`styled-components`](https://github.com/styled-components/styled-components) without the components! 6 | 7 | ...it's a short hack that still uses `styled-components` under the hood, so all the credit for this goes to [Glen Maddern](https://twitter.com/glenmaddern), [Max Stoiber](https://twitter.com/mxstbr), and the `styled-components` community. 8 | 9 | Be aware that including `styled-classnames` adds a noticeable amount to your final JS bundle size. 10 | 11 | ## Javascript 12 | 13 | [![npm version](https://img.shields.io/npm/v/styled-classnames.svg?style=flat)](https://www.npmjs.com/package/styled-classnames) 14 | 15 | ``` 16 | npm install --save-dev styled-classnames 17 | ``` 18 | 19 | ```javascript 20 | import React from "react"; 21 | import Link from "react-router/Link"; 22 | import styled from "styled-classnames"; 23 | 24 | const linkClassName = styled` 25 | color: ${props => props.color}; 26 | margin: 3px; 27 | padding: 3px 7px; 28 | text-decoration: none; 29 | border: 1px solid transparent; 30 | border-radius: 3px; 31 | 32 | &:hover { border-color: rgba(175, 47, 47, 0.1); } 33 | `; 34 | 35 | const activeClassName = styled` 36 | border-color: rgba(175, 47, 47, 0.2); 37 | `; 38 | 39 | const FilterLink = (props) => { 40 | return ( 41 | 46 | ); 47 | }; 48 | 49 | export default FilterLink; 50 | ``` 51 | 52 | ## ClojureScript 53 | 54 | [![Clojars Project](https://img.shields.io/clojars/v/cljsjs/styled-classnames.svg)](https://clojars.org/cljsjs/styled-classnames) 55 | 56 | ```clojure 57 | (ns demo.core 58 | (:require [reagent.core :as reagent] 59 | cljsjs.styled-classnames)) 60 | 61 | (def font-family (atom "Baskerville")) 62 | 63 | (def home-class (js/styled " 64 | font-size: 72px; 65 | font-family: " @font-family "; 66 | font-style: italic; 67 | color: " #(:color %) "; 68 | ")) 69 | 70 | (defn home-page [] 71 | [:div 72 | [:h2 {:class (home-class {:color "rebeccapurple"})} 73 | "Welcome to Reagent"]]) 74 | ``` 75 | 76 | ## Details 77 | Helper methods from `styled-components` are also exposed: 78 | ```javascript 79 | import styled, { css, keyframes, injectGlobal } from "styled-classnames"; 80 | ``` 81 | 82 | Note that `ThemeProvider` and `withTheme` are React-specific and are not included in this library. If you need them, you can still import them from `styled-components`, or if you know how context works in React, you could write them yourself. 83 | --------------------------------------------------------------------------------