├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .nvmrc ├── .prettierrc ├── .travis.yml ├── api.md ├── changelog.md ├── examples ├── .gitignore ├── index.html ├── index.js ├── package.json ├── readme.md └── webpack.config.js ├── lib └── index.js ├── license ├── package-lock.json ├── package.json ├── readme.md ├── src └── index.js └── test ├── helper.js ├── index-test.js └── mocha.opts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "stage-2", "react" ], 3 | "plugins": [ "add-module-exports" ] 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "expect": true, 4 | "sinon": true, 5 | "describe": true, 6 | "chai": true, 7 | "it": true 8 | }, 9 | "parserOptions": { 10 | "ecmaFeatures": { 11 | "experimentalObjectRestSpread": true, 12 | "globalReturn": true, 13 | "jsx": true 14 | }, 15 | "ecmaVersion": 6, 16 | "sourceType": "module" 17 | }, 18 | "env": { 19 | "amd": true, 20 | "browser": true, 21 | "es6": true, 22 | "mocha": true, 23 | "node": true 24 | }, 25 | "plugins": [ 26 | "nodeca", 27 | "react" 28 | ], 29 | "rules": { 30 | "array-bracket-spacing": [2, "always"], 31 | "brace-style": [ 32 | 2, 33 | "1tbs", 34 | { "allowSingleLine": false } 35 | ], 36 | "camelcase": 2, 37 | "comma-dangle": [2, "always-multiline"], 38 | "complexity": [1, 5], 39 | "computed-property-spacing": [2, "never"], 40 | "consistent-this": [2, "self"], 41 | "consistent-return": 2, 42 | "curly": [2, "all"], 43 | "dot-notation": 0, 44 | "eqeqeq": [2, "allow-null"], 45 | "guard-for-in": 2, 46 | "indent": [2, 2], 47 | "jsx-quotes": 1, 48 | "key-spacing": [2, { 49 | "beforeColon": false, 50 | "afterColon": true 51 | }], 52 | "keyword-spacing": 2, 53 | "max-depth": [2, 3], 54 | "max-len": [2, 120], 55 | "max-params": [2, 5], 56 | "max-statements": [2, 50], 57 | "new-cap": 2, 58 | "no-bitwise": 2, 59 | "no-caller": 2, 60 | "no-empty": 2, 61 | "no-extend-native": 2, 62 | "no-floating-decimal": 2, 63 | "no-lone-blocks": 2, 64 | "no-loop-func": 2, 65 | "no-mixed-spaces-and-tabs": 2, 66 | "no-multi-str": 2, 67 | "no-native-reassign": 2, 68 | "no-new": 2, 69 | "no-new-wrappers": 2, 70 | "no-redeclare": 2, 71 | "no-trailing-spaces": 2, 72 | "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], 73 | "no-undef": 2, 74 | "no-underscore-dangle": 0, 75 | "no-use-before-define": 2, 76 | "nodeca/no-lodash-aliases": 2, 77 | "object-curly-spacing": [2, "always"], 78 | "quotes": [2, "single"], 79 | "react/display-name": 1, 80 | "react/jsx-boolean-value": 1, 81 | "react/jsx-no-undef": 2, 82 | "react/jsx-sort-props": 1, 83 | "react/jsx-uses-react": 1, 84 | "react/jsx-uses-vars": 1, 85 | "react/no-did-mount-set-state": 1, 86 | "react/no-did-update-set-state": 1, 87 | "react/no-multi-comp": 1, 88 | "react/no-unknown-property": 1, 89 | "react/prop-types": 1, 90 | "react/react-in-jsx-scope": 1, 91 | "react/self-closing-comp": 1, 92 | "react/sort-prop-types": 1, 93 | "react/wrap-multilines": 1, 94 | "semi": [2, "never"], 95 | "semi-spacing": 2, 96 | "strict": 2, 97 | "space-before-function-paren": [ 98 | 2, 99 | { 100 | "anonymous": "always", 101 | "named": "never" 102 | } 103 | ], 104 | "space-in-parens": [2, "never"], 105 | "space-infix-ops": 2, 106 | "space-unary-ops": 2, 107 | "valid-jsdoc": [ 108 | 2, 109 | { 110 | "prefer": { 111 | "virtual": "abstract", 112 | "extends": "augments", 113 | "constructor": "class", 114 | "const": "constant", 115 | "defaultvalue": "default", 116 | "desc": "description", 117 | "host": "external", 118 | "fileoverview": "file", 119 | "overview": "file", 120 | "emits": "fires", 121 | "func": "function", 122 | "method": "function", 123 | "var": "member", 124 | "arg": "param", 125 | "argument": "param", 126 | "return": "returns", 127 | "exception": "throws" 128 | }, 129 | "requireReturn": false 130 | } 131 | ], 132 | "wrap-iife": [2, "outside"] 133 | }, 134 | "settings": { 135 | "ecmascript": 6, 136 | "jsx": true 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | node_modules/ 4 | *.log 5 | .yo-rc.json 6 | npm-debug.log* 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | .editorconfig 4 | .eslintrc 5 | .eslintignore 6 | .nvmrc 7 | .travis.yml 8 | .yo-rc.json 9 | api.md 10 | examples 11 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v13.0.1 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '4' 5 | - '5' 6 | - '6' 7 | - '7' 8 | script: 'npm test' 9 | -------------------------------------------------------------------------------- /api.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## FontAwesome : ReactClass 4 | A React component for the font-awesome icon library. 5 | 6 | 7 | | Param | Type | Default | Description | 8 | | --- | --- | --- | --- | 9 | | [ariaLabel] | String | | An extra accessibility label to put on the icon | 10 | | [border] | Boolean | false | Whether or not to show a border radius | 11 | | [className] | String | | An extra set of CSS classes to add to the component | 12 | | [cssModule] | Object | | Option to pass FontAwesome CSS as a module | 13 | | [fixedWidth] | Boolean | false | Make buttons fixed width | 14 | | [flip] | String | false | Flip the icon's orientation. | 15 | | [inverse] | Boolean | false | Inverse the icon's color | 16 | | [name] | String | | Name of the icon to use | 17 | | [pulse] | Boolean | false | Rotate icon with 8 steps, rather than smoothly | 18 | | [rotate] | Number | | The degress to rotate the icon by | 19 | | [size] | String | | The icon scaling size | 20 | | [spin] | Boolean | false | Spin the icon | 21 | | [stack] | String | | Stack an icon on top of another. Arguments specify z-index such as '1x' See documentation for example http://fontawesome.io/examples/#stacked | 22 | | [tag] | String | span | The HTML tag to use as a string, eg 'i' or 'em' | 23 | 24 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v.1.6.1 4 | 5 | - Remove support for iojs 6 | - Add test for node 6 and 7 7 | 8 | ## v.1.6.0 9 | 10 | - Use prettier-eslint to auto-format code 11 | - Changed syntax to use ES6 class and package prop-types since the are both deprecated #41 12 | - Use prop-types package instead of deprecated React.PropTypes #40 13 | - Upgrade to node v7.8.0 14 | - Some cleanup 15 | 16 | ## v.1.5.0 17 | 18 | - Move screenreader styles to separate file to fix build issues (see #32) 19 | 20 | ## v1.4.0 21 | 22 | - Merged #30: Add support for aria screen reader support, thanks @Phyks 23 | 24 | ## v1.3.1 25 | 26 | - Add documentation for overriding tag name 27 | 28 | ## v1.3.0 29 | 30 | - Merged #28: Add ability to change base tag (default is still ``), thanks @lucaskatayama 31 | - Cleaned up tests a bit 32 | - Version control lib directory since `prepublish` script is gone. 33 | 34 | ## v1.2.0 35 | 36 | - Add CSS module support (#21, thanks @callumsmits!) 37 | - Simplify CSS tag creation code 38 | - Cleanup test suite 39 | 40 | ## v1.1.0 41 | 42 | - Remove `prepublish` step so builds work on Windows 43 | 44 | ## v1.0.0 45 | 46 | We are production ready! 😬🤘🎉 47 | 48 | - Upgrade development node version 49 | - [Tests] Use the modern ReactDOM.render+findDOMNode APIs for React 15 (#10, thanks @ide!) 50 | - Filter which props are passed into the underlying span (#8, thanks @ide!) 51 | - Upgrade ESLint to v2 (#7, thanks @ide!) 52 | - Upgrade to Babel 6 (#6, thanks @ide!) 53 | 54 | ## v0.3.0 55 | 56 | - Refactor to use new application structure 57 | - Use eslint 58 | - src folder for ES6/7 code ran through babel to lib 59 | - More helpful scripts 60 | - Simpler test 61 | - Less dependencies 62 | - Remove webpack 63 | - Add api docs 64 | - Updated readme 65 | 66 | ## v0.2.5 67 | 68 | - Allow React to be 0.12 or greater, actually fixing #2. 69 | 70 | ## v0.2.4 71 | 72 | - Relax React dependency which closes #2. 73 | 74 | ## v0.2.3 75 | 76 | - Revert back to using `lg` instead of `1x` for size. 77 | 78 | ## v0.2.2 79 | 80 | - Update README 81 | - Add API reference. 82 | - General cleaup. 83 | 84 | ## v0.2.1 85 | 86 | - Properly assign props to component. 87 | 88 | ## v0.2.0 89 | 90 | - Reverting back to non-ES6 code to make more consumable. 91 | 92 | ## v0.1.0 93 | 94 | - Move over to ES6 imports/emports 95 | - Use JSX instead of `React.createElement` 96 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build.js 3 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | react-fontawesome examples 5 | 6 | 7 | 8 | 9 |

Spin

10 |
11 | 12 |

Stacked

13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | const React = require('react') 2 | const ReactDOM = require('react-dom') 3 | const FA = require('react-fontawesome') 4 | 5 | // Spinning 6 | ReactDOM.render( 7 | , 8 | document.getElementById('spin') 9 | ) 10 | 11 | // Stack 12 | ReactDOM.render( 13 | 14 | 15 | 16 | , 17 | document.getElementById('stacked') 18 | ) 19 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Dana Woodman (http://danawoodman.com/)", 11 | "license": "ISC", 12 | "dependencies": { 13 | "react": "15.4.1", 14 | "react-dom": "15.4.1", 15 | "react-fontawesome": "1.5.0" 16 | }, 17 | "devDependencies": { 18 | "babel": "6.5.2", 19 | "babel-core": "6.20.0", 20 | "babel-loader": "6.2.9", 21 | "babel-polyfill": "6.20.0", 22 | "babel-preset-es2015": "6.18.0", 23 | "babel-preset-react": "6.16.0", 24 | "babel-preset-stage-1": "6.16.0", 25 | "webpack": "1.14.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/readme.md: -------------------------------------------------------------------------------- 1 | # react-fontawesome examples 2 | 3 | ## Setup 4 | 5 | ```bash 6 | npm install 7 | npm start 8 | open index.html 9 | ``` 10 | -------------------------------------------------------------------------------- /examples/webpack.config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | devtool: 'eval', 3 | entry: [ 4 | 'babel-polyfill', 5 | './index.js', 6 | ], 7 | output: { 8 | path: __dirname, 9 | filename: 'build.js', 10 | }, 11 | plugins: [], 12 | module: { 13 | loaders: [ 14 | { 15 | test: /\.js$/, 16 | exclude: /(node_modules)/, 17 | loader: 'babel', 18 | query: { 19 | presets: [ 'react'/*, 'es2015', 'stage-1'*/ ], 20 | }, 21 | }, 22 | ], 23 | }, 24 | } 25 | 26 | module.exports = config 27 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 10 | 11 | var _react = require('react'); 12 | 13 | var _react2 = _interopRequireDefault(_react); 14 | 15 | var _propTypes = require('prop-types'); 16 | 17 | var _propTypes2 = _interopRequireDefault(_propTypes); 18 | 19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 20 | 21 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 22 | 23 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 24 | 25 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 26 | 27 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 28 | 29 | /** 30 | * A React component for the font-awesome icon library. 31 | * 32 | * @param {String} [ariaLabel] An extra accessibility label to put on the icon 33 | * @param {Boolean} [border=false] Whether or not to show a border radius 34 | * @param {String} [className] An extra set of CSS classes to add to the component 35 | * @param {Object} [cssModule] Option to pass FontAwesome CSS as a module 36 | * @param {Boolean} [fixedWidth=false] Make buttons fixed width 37 | * @param {String} [flip=false] Flip the icon's orientation. 38 | * @param {Boolean} [inverse=false] Inverse the icon's color 39 | * @param {String} [name] Name of the icon to use 40 | * @param {Boolean} [pulse=false] Rotate icon with 8 steps, rather than smoothly 41 | * @param {Number} [rotate] The degress to rotate the icon by 42 | * @param {String} [size] The icon scaling size 43 | * @param {Boolean} [spin=false] Spin the icon 44 | * @param {String} [stack] Stack an icon on top of another. Arguments specify z-index such as '1x' See documentation for example http://fontawesome.io/examples/#stacked 45 | * @param {String} [tag=span] The HTML tag to use as a string, eg 'i' or 'em' 46 | * @module FontAwesome 47 | * @type {ReactClass} 48 | */ 49 | var FontAwesome = function (_React$Component) { 50 | _inherits(FontAwesome, _React$Component); 51 | 52 | function FontAwesome() { 53 | _classCallCheck(this, FontAwesome); 54 | 55 | var _this = _possibleConstructorReturn(this, (FontAwesome.__proto__ || Object.getPrototypeOf(FontAwesome)).call(this)); 56 | 57 | _this.displayName = 'FontAwesome'; 58 | return _this; 59 | } 60 | 61 | _createClass(FontAwesome, [{ 62 | key: 'render', 63 | value: function render() { 64 | var _props = this.props, 65 | border = _props.border, 66 | cssModule = _props.cssModule, 67 | className = _props.className, 68 | fixedWidth = _props.fixedWidth, 69 | flip = _props.flip, 70 | inverse = _props.inverse, 71 | name = _props.name, 72 | pulse = _props.pulse, 73 | rotate = _props.rotate, 74 | size = _props.size, 75 | spin = _props.spin, 76 | stack = _props.stack, 77 | _props$tag = _props.tag, 78 | tag = _props$tag === undefined ? 'span' : _props$tag, 79 | ariaLabel = _props.ariaLabel, 80 | props = _objectWithoutProperties(_props, ['border', 'cssModule', 'className', 'fixedWidth', 'flip', 'inverse', 'name', 'pulse', 'rotate', 'size', 'spin', 'stack', 'tag', 'ariaLabel']); 81 | 82 | var ariaProps = ariaLabel ? { 'aria-label': ariaLabel } : { 'aria-hidden': true }; 83 | var classNames = []; 84 | 85 | if (cssModule) { 86 | classNames.push(cssModule['fa']); 87 | classNames.push(cssModule['fa-' + name]); 88 | size && classNames.push(cssModule['fa-' + size]); 89 | spin && classNames.push(cssModule['fa-spin']); 90 | pulse && classNames.push(cssModule['fa-pulse']); 91 | border && classNames.push(cssModule['fa-border']); 92 | fixedWidth && classNames.push(cssModule['fa-fw']); 93 | inverse && classNames.push(cssModule['fa-inverse']); 94 | flip && classNames.push(cssModule['fa-flip-' + flip]); 95 | rotate && classNames.push(cssModule['fa-rotate-' + rotate]); 96 | stack && classNames.push(cssModule['fa-stack-' + stack]); 97 | } else { 98 | classNames.push('fa'); 99 | classNames.push('fa-' + name); 100 | size && classNames.push('fa-' + size); 101 | spin && classNames.push('fa-spin'); 102 | pulse && classNames.push('fa-pulse'); 103 | border && classNames.push('fa-border'); 104 | fixedWidth && classNames.push('fa-fw'); 105 | inverse && classNames.push('fa-inverse'); 106 | flip && classNames.push('fa-flip-' + flip); 107 | rotate && classNames.push('fa-rotate-' + rotate); 108 | stack && classNames.push('fa-stack-' + stack); 109 | } 110 | 111 | // Add any custom class names at the end. 112 | className && classNames.push(className); 113 | return _react2.default.createElement(tag, _extends({}, props, ariaProps, { 114 | className: classNames.join(' ') 115 | })); 116 | } 117 | }]); 118 | 119 | return FontAwesome; 120 | }(_react2.default.Component); 121 | 122 | FontAwesome.propTypes = { 123 | ariaLabel: _propTypes2.default.string, 124 | border: _propTypes2.default.bool, 125 | className: _propTypes2.default.string, 126 | cssModule: _propTypes2.default.object, 127 | fixedWidth: _propTypes2.default.bool, 128 | flip: _propTypes2.default.oneOf(['horizontal', 'vertical']), 129 | inverse: _propTypes2.default.bool, 130 | name: _propTypes2.default.string.isRequired, 131 | pulse: _propTypes2.default.bool, 132 | rotate: _propTypes2.default.oneOf([90, 180, 270]), 133 | size: _propTypes2.default.oneOf(['lg', '2x', '3x', '4x', '5x']), 134 | spin: _propTypes2.default.bool, 135 | stack: _propTypes2.default.oneOf(['1x', '2x']), 136 | tag: _propTypes2.default.string 137 | }; 138 | 139 | exports.default = FontAwesome; 140 | module.exports = exports.default; -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dana Woodman 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-fontawesome", 3 | "version": "1.7.1", 4 | "description": "A React component for the font-awesome icon library.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/danawoodman/react-fontawesome.git" 8 | }, 9 | "bugs": { 10 | "url": "https://github.com/danawoodman/react-fontawesome/issues" 11 | }, 12 | "main": "lib/index.js", 13 | "scripts": { 14 | "build": "babel src --out-dir lib", 15 | "dist": "npm run format && npm run build && npm test && npm run docs", 16 | "docs": "jsdoc2md lib/index.js > api.md", 17 | "format": "prettier-eslint '{src,test}/**/*.js' --single-quote --no-semi es5 --write", 18 | "test": "mocha", 19 | "watch": "npm run watch-build & npm run watch-test", 20 | "watch-build": "npm run build -- --watch", 21 | "watch-test": "npm run test -- -w" 22 | }, 23 | "keywords": [ 24 | "react", 25 | "font-awesome", 26 | "fontawesome", 27 | "bootstrap", 28 | "icons", 29 | "fonts", 30 | "icon", 31 | "danawoodman", 32 | "big", 33 | "style", 34 | "jsx", 35 | "react-component", 36 | "component" 37 | ], 38 | "author": { 39 | "name": "Dana Woodman", 40 | "email": "dana@danawoodman.com", 41 | "url": "danawoodman.com" 42 | }, 43 | "license": "MIT", 44 | "devDependencies": { 45 | "babel-cli": "^6.6.5", 46 | "babel-core": "^6.7.4", 47 | "babel-plugin-add-module-exports": "1.0.2", 48 | "babel-preset-es2015": "^6.6.0", 49 | "babel-preset-react": "^6.5.0", 50 | "babel-preset-stage-2": "^6.5.0", 51 | "chai": "4.2.0", 52 | "eslint": "6.6.0", 53 | "eslint-plugin-nodeca": "^1.0.3", 54 | "eslint-plugin-react": "7.16.0", 55 | "jsdoc-to-markdown": "5.0.2", 56 | "mocha": "6.2.2", 57 | "mocha-jsdom": "2.0.0", 58 | "mocha-sinon": "^2.0.0", 59 | "prettier-eslint": "9.0.0", 60 | "prettier-eslint-cli": "5.0.0", 61 | "react": "16.11.0", 62 | "react-dom": "16.11.0", 63 | "sinon": "7.5.0", 64 | "sinon-chai": "3.3.0" 65 | }, 66 | "homepage": "https://github.com/danawoodman/react-fontawesome#readme", 67 | "engines": { 68 | "node": ">=0.10.0" 69 | }, 70 | "peerDependencies": { 71 | "react": ">=0.12.0" 72 | }, 73 | "dependencies": { 74 | "prop-types": "^15.5.6" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # react-fontawesome 2 | 3 | [![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 4 | [![Travis CI build status](https://img.shields.io/travis/danawoodman/react-fontawesome.svg)](https://travis-ci.org/danawoodman/react-fontawesome) 5 | [![Dependency Status](https://img.shields.io/david/danawoodman/react-fontawesome.svg)](https://david-dm.org/danawoodman/react-fontawesome) 6 | [![View on npm](https://img.shields.io/npm/dm/react-fontawesome.svg)](https://www.npmjs.com/package/react-fontawesome) 7 | [![View on npm](https://img.shields.io/npm/v/react-fontawesome.svg)](https://www.npmjs.com/package/react-fontawesome) 8 | 9 | > A React component for the font-awesome icon library. 10 | 11 | **If you are using Font Awesome v5+, please use [the official React component!](https://github.com/FortAwesome/react-fontawesome). `react-fontawesome` does not support FontAwesome v5!** 12 | 13 | **This project is no longer actively maintained. Please try and use the official component above if you are able!** 14 | 15 | ## Install 16 | 17 | ```bash 18 | npm install --save react-fontawesome 19 | ``` 20 | 21 | _**Note:** This component does not include any of the Font Awesome CSS or fonts, so you'll need to make sure to include those on your end somehow, either by adding them to your build process or linking to [CDN versions](https://www.bootstrapcdn.com/fontawesome/)._ 22 | 23 | 24 | ### Using CDN version 25 | 26 | The fastest way to get started is to import FontAwesome with a link tag in your page's ``: 27 | 28 | ```html 29 | 30 | ``` 31 | 32 | You can change the version number to use whatever version of FontAwesome you'd like. 33 | 34 | ### Using with Webpack 35 | 36 | If you're using WebPack, you will need to install FontAwesome, import the FontAwesome Sass/Less, and configure the font path. Please see this [blog post](https://medium.com/@chanonroy/webpack-2-and-font-awesome-icon-importing-59df3364f35c) on how to get Webpack and FontAwesome working together. 37 | 38 | ## Usage 39 | 40 | ```js 41 | var React = require('react') 42 | var FA = require('react-fontawesome') 43 | 44 | React.render(, document.body) 45 | ``` 46 | 47 | ## Features 48 | 49 | * No dependencies (other than React) 50 | * Simple API that mirrors Font Awesome's class names. 51 | * Supports all Font Awesome modifiers (see [API](#API) below). 52 | * Make use of Css Modules 53 | * Add your own `className`s, styles and other props (all additional props are passed directly to the component). 54 | 55 | ## Examples 56 | 57 | **Regular usage** 58 | 59 | ```js 60 | var React = require('react') 61 | var FontAwesome = require('react-fontawesome') 62 | 63 | var MyComponent = React.createClass({ 64 | render: function() { 65 | return ( 66 | 73 | ) 74 | }, 75 | }) 76 | ``` 77 | 78 | **With the use of CSS Modules** 79 | 80 | ```js 81 | import React from 'react' 82 | import FontAwesome from 'react-fontawesome' 83 | import faStyles from 'font-awesome/css/font-awesome.css' 84 | 85 | var MyComponent = React.createClass({ 86 | render: function() { 87 | return ( 88 | 96 | ) 97 | }, 98 | }) 99 | ``` 100 | 101 | The above will create output like this: 102 | 103 | ``` 104 | 105 | ``` 106 | 107 | ## API 108 | 109 | See [the API docs](api.md) for full documentation. 110 | 111 | ## Contributing 112 | 113 | Pull requests welcome! 114 | 115 | Run the test suite with `npm test` and format your code with `npm run format`. Make sure tests are passing and that you write tests for new features and document changes to the API with updates to the JSDocs. 116 | 117 | Before you submit your pull request, run `npm run dist` to build the project and commit the changes. 118 | 119 | ## License 120 | 121 | [MIT](license) © [Dana Woodman][author] 122 | 123 | [author]: https://github.com/danawoodman 124 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | /** 5 | * A React component for the font-awesome icon library. 6 | * 7 | * @param {String} [ariaLabel] An extra accessibility label to put on the icon 8 | * @param {Boolean} [border=false] Whether or not to show a border radius 9 | * @param {String} [className] An extra set of CSS classes to add to the component 10 | * @param {Object} [cssModule] Option to pass FontAwesome CSS as a module 11 | * @param {Boolean} [fixedWidth=false] Make buttons fixed width 12 | * @param {String} [flip=false] Flip the icon's orientation. 13 | * @param {Boolean} [inverse=false] Inverse the icon's color 14 | * @param {String} [name] Name of the icon to use 15 | * @param {Boolean} [pulse=false] Rotate icon with 8 steps, rather than smoothly 16 | * @param {Number} [rotate] The degress to rotate the icon by 17 | * @param {String} [size] The icon scaling size 18 | * @param {Boolean} [spin=false] Spin the icon 19 | * @param {String} [stack] Stack an icon on top of another. Arguments specify z-index such as '1x' See documentation for example http://fontawesome.io/examples/#stacked 20 | * @param {String} [tag=span] The HTML tag to use as a string, eg 'i' or 'em' 21 | * @module FontAwesome 22 | * @type {ReactClass} 23 | */ 24 | class FontAwesome extends React.Component { 25 | constructor() { 26 | super() 27 | this.displayName = 'FontAwesome' 28 | } 29 | 30 | render() { 31 | const { 32 | border, 33 | cssModule, 34 | className, 35 | fixedWidth, 36 | flip, 37 | inverse, 38 | name, 39 | pulse, 40 | rotate, 41 | size, 42 | spin, 43 | stack, 44 | tag = 'span', 45 | ariaLabel, 46 | ...props 47 | } = this.props 48 | 49 | const ariaProps = ariaLabel ? { 'aria-label': ariaLabel } : { 'aria-hidden': true } 50 | const classNames = [] 51 | 52 | if (cssModule) { 53 | classNames.push(cssModule['fa']) 54 | classNames.push(cssModule['fa-' + name]) 55 | size && classNames.push(cssModule['fa-' + size]) 56 | spin && classNames.push(cssModule['fa-spin']) 57 | pulse && classNames.push(cssModule['fa-pulse']) 58 | border && classNames.push(cssModule['fa-border']) 59 | fixedWidth && classNames.push(cssModule['fa-fw']) 60 | inverse && classNames.push(cssModule['fa-inverse']) 61 | flip && classNames.push(cssModule['fa-flip-' + flip]) 62 | rotate && classNames.push(cssModule['fa-rotate-' + rotate]) 63 | stack && classNames.push(cssModule['fa-stack-' + stack]) 64 | } else { 65 | classNames.push('fa') 66 | classNames.push('fa-' + name) 67 | size && classNames.push('fa-' + size) 68 | spin && classNames.push('fa-spin') 69 | pulse && classNames.push('fa-pulse') 70 | border && classNames.push('fa-border') 71 | fixedWidth && classNames.push('fa-fw') 72 | inverse && classNames.push('fa-inverse') 73 | flip && classNames.push('fa-flip-' + flip) 74 | rotate && classNames.push('fa-rotate-' + rotate) 75 | stack && classNames.push('fa-stack-' + stack) 76 | } 77 | 78 | // Add any custom class names at the end. 79 | className && classNames.push(className) 80 | return React.createElement(tag, { 81 | ...props, 82 | ...ariaProps, 83 | className: classNames.join(' '), 84 | }) 85 | } 86 | } 87 | 88 | FontAwesome.propTypes = { 89 | ariaLabel: PropTypes.string, 90 | border: PropTypes.bool, 91 | className: PropTypes.string, 92 | cssModule: PropTypes.object, 93 | fixedWidth: PropTypes.bool, 94 | flip: PropTypes.oneOf(['horizontal', 'vertical']), 95 | inverse: PropTypes.bool, 96 | name: PropTypes.string.isRequired, 97 | pulse: PropTypes.bool, 98 | rotate: PropTypes.oneOf([90, 180, 270]), 99 | size: PropTypes.oneOf(['lg', '2x', '3x', '4x', '5x']), 100 | spin: PropTypes.bool, 101 | stack: PropTypes.oneOf(['1x', '2x']), 102 | tag: PropTypes.string, 103 | } 104 | 105 | export default FontAwesome 106 | -------------------------------------------------------------------------------- /test/helper.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai') 2 | 3 | global.expect = chai.expect 4 | -------------------------------------------------------------------------------- /test/index-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import jsdom from 'mocha-jsdom' 4 | import FontAwesome from '../src' 5 | 6 | describe('react-fontawesome', () => { 7 | let component 8 | let classes 9 | let props 10 | 11 | // Use mocha-jsdom. 12 | jsdom({ html: '
', url: 'http://localhost/' }) 13 | 14 | beforeEach(() => { 15 | props = { 16 | border: true, 17 | className: 'my-custom-class', 18 | fixedWidth: true, 19 | flip: 'vertical', 20 | inverse: true, 21 | name: 'rocket', 22 | size: 'lg', 23 | spin: true, 24 | pulse: true, 25 | rotate: 180, 26 | stack: '1x', 27 | } 28 | component = ReactDOM.render(, document.getElementById('root')) 29 | classes = ReactDOM.findDOMNode(component).className.split(' ') 30 | }) 31 | 32 | it('the proper class names should get set', () => { 33 | const expectedClasses = [ 34 | 'fa', 35 | 'fa-border', 36 | 'fa-flip-vertical', 37 | 'fa-fw', 38 | 'fa-inverse', 39 | 'fa-lg', 40 | 'fa-rocket', 41 | 'fa-pulse', 42 | 'fa-rotate-180', 43 | 'fa-spin', 44 | 'fa-stack-1x', 45 | 'my-custom-class', 46 | ] 47 | expectedClasses.forEach(name => expect(classes).to.include(name)) 48 | }) 49 | 50 | it('the "name" prop is not rendered in the markup', () => { 51 | expect(ReactDOM.findDOMNode(component).name).to.be.undefined 52 | }) 53 | 54 | context('CSS module support', () => { 55 | let cssModuleComponent 56 | let cssModuleClasses 57 | 58 | beforeEach(() => { 59 | const cssModule = { 60 | fa: 'fa_1', 61 | 'fa-border': 'fa-border_1', 62 | 'fa-flip-vertical': 'fa-flip-vertical_1', 63 | 'fa-fw': 'fa-fw_1', 64 | 'fa-inverse': 'fa-inverse_1', 65 | 'fa-lg': 'fa-lg_1', 66 | 'fa-rocket': 'fa-rocket_1', 67 | 'fa-pulse': 'fa-pulse_1', 68 | 'fa-rotate-180': 'fa-rotate-180_1', 69 | 'fa-spin': 'fa-spin_1', 70 | 'fa-stack-1x': 'fa-stack-1x_1', 71 | } 72 | 73 | cssModuleComponent = ReactDOM.render( 74 | , 75 | document.getElementById('root') 76 | ) 77 | cssModuleClasses = ReactDOM.findDOMNode(cssModuleComponent).className.split(' ') 78 | }) 79 | 80 | it('correct class names get set using cssModule style', () => { 81 | const expectedClasses = [ 82 | 'fa_1', 83 | 'fa-border_1', 84 | 'fa-flip-vertical_1', 85 | 'fa-fw_1', 86 | 'fa-inverse_1', 87 | 'fa-lg_1', 88 | 'fa-rocket_1', 89 | 'fa-pulse_1', 90 | 'fa-rotate-180_1', 91 | 'fa-spin_1', 92 | 'fa-stack-1x_1', 93 | 'my-custom-class', 94 | ] 95 | expectedClasses.forEach(className => { 96 | expect(cssModuleClasses).to.include(className) 97 | }) 98 | }) 99 | 100 | it('the "name" and "cssModule" prop is not rendered in the markup using cssModule style', () => { 101 | expect(ReactDOM.findDOMNode(cssModuleComponent).name).to.be.undefined 102 | expect(ReactDOM.findDOMNode(cssModuleComponent).cssModule).to.be.undefined 103 | }) 104 | }) 105 | 106 | context('Using tag prop', () => { 107 | it('should render span tag if tag prop is not specified', () => { 108 | props = { name: 'rocket' } 109 | component = ReactDOM.render(, document.getElementById('root')) 110 | expect(ReactDOM.findDOMNode(component).tagName).to.be.equal('SPAN') 111 | }) 112 | 113 | it('should render tag specified in tag prop', () => { 114 | props = { tag: 'i', name: 'rocket' } 115 | component = ReactDOM.render( 116 |
117 | 118 |
, 119 | document.getElementById('root') 120 | ) 121 | expect(ReactDOM.findDOMNode(component).children[0].tagName).to.be.equal('I') 122 | }) 123 | }) 124 | 125 | context('Using ariaLabel prop', () => { 126 | it('should render with ariaHidden attribute if ariaLabel prop is not specified', () => { 127 | component = ReactDOM.render(, document.getElementById('root')) 128 | 129 | const ariaHidden = ReactDOM.findDOMNode(component).getAttribute('aria-hidden') 130 | const ariaLabel = ReactDOM.findDOMNode(component).getAttribute('aria-label') 131 | expect(ariaHidden).to.equal('true') 132 | expect(ariaLabel).to.be.null 133 | }) 134 | 135 | it('should render without ariaHidden attribute if ariaLabel prop is specified', () => { 136 | props = { ariaLabel: 'foobar', name: 'rocket' } 137 | component = ReactDOM.render(, document.getElementById('root')) 138 | 139 | const ariaHidden = ReactDOM.findDOMNode(component).getAttribute('aria-hidden') 140 | const ariaLabel = ReactDOM.findDOMNode(component).getAttribute('aria-label') 141 | expect(ariaHidden).to.be.null 142 | expect(ariaLabel).to.equal(props.ariaLabel) 143 | }) 144 | }) 145 | }) 146 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ./test/helper.js 2 | --require babel-core/register 3 | --reporter list 4 | --ui bdd 5 | --------------------------------------------------------------------------------