├── .babelrc ├── .editorconfig ├── .eslintrc ├── .github └── workflows │ └── npmpublish.yml ├── .gitignore ├── .npmignore ├── .storybook ├── addons.js ├── config.js └── manager-head.html ├── .vscode └── settings.json ├── Contributing.md ├── LICENSE ├── README.md ├── _config.yml ├── example ├── .env ├── .gitignore ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.css │ ├── App.js │ ├── index.css │ └── index.js └── yarn.lock ├── index.js ├── package-lock.json ├── package.json ├── react-loader-spinner.bak.png ├── react-loader-spinner.png ├── scripts └── mocha_runner.js ├── src ├── __tests__ │ └── index.js ├── index.js └── loader │ ├── Audio.js │ ├── BallTriangle.js │ ├── Bars.js │ ├── Circles.js │ ├── CradleLoader.js │ ├── Grid.js │ ├── Hearts.js │ ├── MutatingDots.js │ ├── Oval.js │ ├── Plane.js │ ├── Puff.js │ ├── RevolvingDot.js │ ├── Rings.js │ ├── TailSpin.js │ ├── ThreeDots.js │ ├── Triangle.js │ ├── Watch.js │ ├── css │ ├── CradleLoader.css │ ├── Plane.css │ ├── Triangle.css │ └── react-spinner-loader.css │ └── index.js ├── stories └── index.stories.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "stage-2", "react"] 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "prettier", "prettier/react"], 3 | "rules": { 4 | "import/prefer-default-export": "off", 5 | "import/no-extraneous-dependencies": "off", 6 | "global-require": "off", 7 | "consistent-return": "off", 8 | "react/destructuring-assignment": "off", 9 | "no-use-before-define": ["error", { "functions": true, "classes": true, "variables": false }], 10 | "react/prop-types": ["error", { "ignore": ["navigation", "children"] }], 11 | "react/jsx-filename-extension": [ 12 | 1, 13 | { 14 | "extensions": [".js", ".jsx"] 15 | } 16 | ], 17 | "prettier/prettier": [ 18 | "error", 19 | { 20 | "printWidth": 100 21 | } 22 | ] 23 | }, 24 | "plugins": ["prettier"], 25 | "parser": "babel-eslint" 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v1 10 | - uses: actions/setup-node@v1 11 | with: 12 | node-version: 12 13 | 14 | publish-npm: 15 | needs: build 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v1 19 | - uses: actions/setup-node@v1 20 | with: 21 | node-version: 12 22 | registry-url: https://registry.npmjs.org/ 23 | - run: npm install 24 | - run: npm publish 25 | env: 26 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | *.iml 4 | .*.haste_cache.* 5 | .DS_Store 6 | .idea 7 | npm-debug.log 8 | node_modules 9 | .yarn.lock 10 | dist 11 | example/node_modules 12 | example/build 13 | 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | *.iml 4 | .*.haste_cache.* 5 | .DS_Store 6 | .idea 7 | .babelrc 8 | .eslintrc 9 | npm-debug.log 10 | lib 11 | .storybook 12 | stories 13 | .gitignore 14 | docs 15 | src 16 | scripts 17 | .vscode 18 | _config.yml 19 | .editorconfig 20 | example 21 | 22 | 23 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; 3 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { addParameters, configure } from '@storybook/react'; 2 | 3 | 4 | // automatically import all files ending in *.stories.js 5 | const req = require.context('../stories', true, /\.stories\.js$/); 6 | function loadStories() { 7 | req.keys().forEach(filename => req(filename)); 8 | } 9 | 10 | addParameters({ 11 | options: { 12 | name: 'React Spinner', 13 | /** 14 | * show story component as full screen 15 | * @type {Boolean} 16 | */ 17 | isFullscreen: false, 18 | /** 19 | * display panel that shows a list of stories 20 | * @type {Boolean} 21 | */ 22 | showNav: true, 23 | /** 24 | * display panel that shows addon configurations 25 | * @type {Boolean} 26 | */ 27 | showPanel: false, 28 | /** 29 | * where to show the addon panel 30 | * @type {('bottom'|'right')} 31 | */ 32 | panelPosition: 'bottom', 33 | /** 34 | * regex for finding the hierarchy separator 35 | * @example: 36 | * null - turn off hierarchy 37 | * /\// - split by `/` 38 | * /\./ - split by `.` 39 | * /\/|\./ - split by `/` or `.` 40 | * @type {Regex} 41 | */ 42 | hierarchySeparator: /\/|\./, 43 | /** 44 | * regex for finding the hierarchy root separator 45 | * @example: 46 | * null - turn off multiple hierarchy roots 47 | * /\|/ - split by `|` 48 | * @type {Regex} 49 | */ 50 | hierarchyRootSeparator: /\|/, 51 | /** 52 | * sidebar tree animations 53 | * @type {Boolean} 54 | */ 55 | sidebarAnimations: true, 56 | /** 57 | * enable/disable shortcuts 58 | * @type {Boolean} 59 | */ 60 | enableShortcuts: true, 61 | /** 62 | * show/hide tool bar 63 | * @type {Boolean} 64 | */ 65 | isToolshown: false, 66 | /** 67 | * theme storybook, see link below 68 | */ 69 | theme: undefined, 70 | }, 71 | }); 72 | 73 | 74 | configure(loadStories, module); 75 | -------------------------------------------------------------------------------- /.storybook/manager-head.html: -------------------------------------------------------------------------------- 1 | 4 | 13 | 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "xmlns" 4 | ] 5 | } -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Mohan Pd. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | title 4 |

5 |
6 | 7 | `react-spinner-loader` provides simple React SVG spinner component which can be implemented for async await operation before data loads to the view. 8 | 9 | ### Installation 10 | 11 | ##### Using NPM: 12 | 13 | # 14 | 15 | ```sh 16 | $ npm install react-loader-spinner --save 17 | ``` 18 | 19 | ##### Using yarn 20 | 21 | # 22 | 23 | ```sh 24 | $ yarn add react-loader-spinner 25 | ``` 26 | 27 | ##### Import required css 28 | 29 | # 30 | 31 | ```js 32 | import "react-loader-spinner/dist/loader/css/react-spinner-loader.css"; 33 | ``` 34 | 35 | # Demo 36 | 37 | [View in page] 38 | 39 | ### Usage 40 | 41 | ```js 42 | import Loader from "react-loader-spinner"; 43 | export default class App extends React.Component { 44 | //other logic 45 | render() { 46 | return ( 47 | 54 | ); 55 | } 56 | } 57 | ``` 58 | 59 | ### If webpack throws issue with css. (For older version of this package) 60 | 61 | Change webpack config as: 62 | ` test: /\.scss$/ to test: /\.s?css$/` 63 |

64 | Newer version just import css file from node modules to app.js 65 | 66 | ### Types of Spinner 67 | 68 | react-loader-spinner component has the following types of spinners. 69 | 70 | | Spinner Type | Implementation | 71 | | ------------- | ----------------------------------------------------------------------- | 72 | | Audio | ` ` | 73 | | Ball-Triangle | `` | 74 | | Bars | `` | 75 | | Circles | `` | 76 | | Grid | `` | 77 | | Hearts | `` | 78 | | Oval | `` | 79 | | Puff | `` | 80 | | Rings | `` | 81 | | TailSpin | `` | 82 | | ThreeDots | `` | 83 | 84 | > There are more. View [demo] to see the full list. 85 | 86 | ### PropTypes Available 87 | 88 | react-loader-spinner component accepts the following props. Instructions on how to use them are below. 89 | 90 | | name | types | default | Detail | 91 | | -------------- | ----------------- | ------------ | ------------------------------------------------------------------------------- | 92 | | visible | String or boolean | false | Show/ Hide the loader as required. | 93 | | type | String | "Audio" | Type of spinner you want to display. View the type in Types of Spinner section. | 94 | | height | Number | 80 | Height props define the height of the svg spinner. Default height is 80px. | 95 | | width | Number | 80 | Width props define the width of the spinner. | 96 | | color | String | "Blue" | color props is add color to the spinner | 97 | | secondaryColor | String | "Grey" | secondaryColor props for now is available on Plane and MutatingDots loaders | 98 | | timeout | Number | 0 | Duration in miliseconds after which spinner is disabled | 99 | | radius | Number | value varies | Set radius if the loader has a circle element in it | 100 | 101 | ### Here are the list of the task for which we want PR: 102 | 103 | - Optimize css implementation 104 | - Add support for Typescript. 105 | - Optimization for multiple color support. 106 | 107 | ## License 108 | 109 | MIT 110 | 111 | [svg-loader]: 112 | [here]: 113 | [View in page]: https://mhnpd.github.io/react-loader-spinner/ 114 | [storybook]: https://mhnpd.github.io/react-loader-spinner/ 115 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /example/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": "https://mhnpd.github.io/react-loader-spinner/", 6 | "dependencies": { 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.3.2", 9 | "@testing-library/user-event": "^7.1.2", 10 | "bootstrap": "4.4.1", 11 | "react": "^16.13.1", 12 | "react-dom": "^16.13.1", 13 | "react-loader-spinner": "^3.1.13", 14 | "react-scripts": "3.4.1" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /example/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codemaster730/react-loader-spinner/b096cb2e36906832ea81c60ea9b9d8638835fd06/example/public/favicon.ico -------------------------------------------------------------------------------- /example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React Spinner 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /example/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | .spinner_item { 32 | border: 2px solid #00BFFF; 33 | } 34 | 35 | @keyframes App-logo-spin { 36 | from { 37 | transform: rotate(0deg); 38 | } 39 | to { 40 | transform: rotate(360deg); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /example/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Loader from "react-loader-spinner"; 3 | import "./App.css"; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 |

React Spinner

10 |
11 |
12 |
13 | 14 |
15 |
16 | 17 |
18 |
19 | 25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 | 55 |
56 |
57 | 63 |
64 |
65 | 66 |
67 |
68 |
69 |
70 | 76 |
77 |
78 | 84 |
85 |
86 | 92 |
93 |
97 |
98 |
99 |
100 |
101 | ); 102 | } 103 | 104 | export default App; 105 | -------------------------------------------------------------------------------- /example/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /example/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import "bootstrap/dist/css/bootstrap.min.css" 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | 15 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist/index'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-loader-spinner", 3 | "version": "3.1.14", 4 | "description": " react-spinner-loader provides simple React.js spinner component which can be implemented for async wait operation before data load to the view.", 5 | "unpkg": "dist/index.js", 6 | "jsdelivr": "dist/index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/mhnpd/react-loader-spinner" 10 | }, 11 | "author": { 12 | "name": "Mohan Upadhyay", 13 | "url": "https://thecodersblog.com" 14 | }, 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/mhnpd/react-loader-spinner" 18 | }, 19 | "homepage": "https://mhnpd.github.io/react-loader-spinner/", 20 | "keywords": [ 21 | "react-component", 22 | "loader", 23 | "spinner", 24 | "react" 25 | ], 26 | "company": { 27 | "name": "The Coders Blog", 28 | "url": "https://thecodersblog.com", 29 | "feed": "https://thecodersblog.com/feed" 30 | }, 31 | "options": { 32 | "mocha": "--require scripts/mocha_runner src/**/__tests__/**/*.js" 33 | }, 34 | "scripts": { 35 | "prepublish": "babel --plugins transform-es2015-modules-umd src --ignore __tests__ --out-dir ./dist --copy-files", 36 | "build": "babel --plugins transform-es2015-modules-umd src --ignore __tests__ --out-dir ./dist --copy-files", 37 | "lint": "eslint ./src", 38 | "lintfix": "eslint ./src --fix", 39 | "testonly": "mocha $npm_package_options_mocha", 40 | "test": "npm run lint && npm run testonly", 41 | "test-watch": "npm run testonly -- --watch --watch-extensions js", 42 | "storybook": "start-storybook -p 6006", 43 | "build-storybook": "build-storybook --output-dir ./docs", 44 | "deploy": "gh-pages -d ./example/build" 45 | }, 46 | "devDependencies": { 47 | "@storybook/addon-actions": "^5.1.10", 48 | "@storybook/addon-centered": "^5.1.10", 49 | "@storybook/addon-links": "^5.1.10", 50 | "@storybook/addons": "^5.1.10", 51 | "@storybook/react": "^5.1.10", 52 | "babel-cli": "^6.6.4", 53 | "babel-core": "^6.7.4", 54 | "babel-eslint": "^10.0.2", 55 | "babel-loader": "^7.1.5", 56 | "babel-plugin-transform-es2015-modules-umd": "^6.6.5", 57 | "babel-polyfill": "^6.7.4", 58 | "babel-preset-env": "^1.7.0", 59 | "babel-preset-react": "^6.5.0", 60 | "babel-preset-stage-2": "^6.5.0", 61 | "chai": "^4.1.2", 62 | "enzyme": "^3.3.0", 63 | "eslint": "*", 64 | "eslint-config-airbnb": "^17.0.0", 65 | "eslint-config-prettier": "*", 66 | "eslint-plugin-babel": "^5.3.0", 67 | "eslint-plugin-import": "^2.13.0", 68 | "eslint-plugin-jsx-a11y": "^6.1.1", 69 | "eslint-plugin-prettier": "*", 70 | "eslint-plugin-react": "^7.10.0", 71 | "gh-pages": "^2.2.0", 72 | "mocha": "^6.2.0", 73 | "nodemon": "^1.17.2", 74 | "prettier": "*", 75 | "redux-logger": "*", 76 | "sinon": "^7.3.2" 77 | }, 78 | "peerDependencies": { 79 | "prop-types": "^15.7.2", 80 | "react": "^16.8.6", 81 | "react-dom": "^16.8.6" 82 | }, 83 | "dependencies": { 84 | "babel-runtime": "^6.26.0", 85 | "prop-types": "^15.7.2" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /react-loader-spinner.bak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codemaster730/react-loader-spinner/b096cb2e36906832ea81c60ea9b9d8638835fd06/react-loader-spinner.bak.png -------------------------------------------------------------------------------- /react-loader-spinner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codemaster730/react-loader-spinner/b096cb2e36906832ea81c60ea9b9d8638835fd06/react-loader-spinner.png -------------------------------------------------------------------------------- /scripts/mocha_runner.js: -------------------------------------------------------------------------------- 1 | var jsdom = require('jsdom').jsdom; 2 | 3 | var exposedProperties = ['window', 'navigator', 'document']; 4 | 5 | global.document = jsdom(''); 6 | global.window = document.defaultView; 7 | Object.keys(document.defaultView).forEach((property) => { 8 | if (typeof global[property] === 'undefined') { 9 | exposedProperties.push(property); 10 | global[property] = document.defaultView[property]; 11 | } 12 | }); 13 | 14 | global.navigator = { 15 | userAgent: 'node.js' 16 | }; 17 | 18 | documentRef = document; 19 | 20 | require('babel-core/register'); 21 | require('babel-polyfill'); -------------------------------------------------------------------------------- /src/__tests__/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {shallow, mount, render} from 'enzyme'; 4 | import {expect} from 'chai'; 5 | import sinon from 'sinon'; 6 | 7 | import MyComponent from '../index'; 8 | 9 | // Demo tests 10 | 11 | // Shallow Rendering 12 | // https://github.com/airbnb/enzyme/blob/master/docs/api/shallow.md 13 | describe('Shallow Rendering', () => { 14 | 15 | it('to have three `.icon-test`s', () => { 16 | const wrapper = shallow(); 17 | expect(wrapper.find('.icon-test')).to.have.length(3); 18 | }); 19 | 20 | it('simulates click events', () => { 21 | const buttonClick = sinon.spy(); 22 | const wrapper = shallow( 23 | 24 | ); 25 | wrapper.find('button').simulate('click'); 26 | expect(buttonClick.calledOnce).to.equal(true); 27 | }); 28 | 29 | }); 30 | 31 | // Full DOM Rendering 32 | // https://github.com/airbnb/enzyme/blob/master/docs/api/mount.md 33 | describe('Full DOM Rendering', () => { 34 | 35 | it('allows us to set props', () => { 36 | const wrapper = mount(); 37 | expect(wrapper.props().bar).to.equal('baz'); 38 | wrapper.setProps({ bar: 'foo' }); 39 | expect(wrapper.props().bar).to.equal('foo'); 40 | }); 41 | 42 | it('calls componentDidMount', () => { 43 | sinon.spy(MyComponent.prototype, 'componentDidMount'); 44 | const wrapper = mount(); 45 | expect(MyComponent.prototype.componentDidMount.calledOnce).to.be.true; 46 | MyComponent.prototype.componentDidMount.restore(); 47 | }); 48 | 49 | }); 50 | 51 | // Static Rendered Markup 52 | // https://github.com/airbnb/enzyme/blob/master/docs/api/render.md 53 | describe('Static Rendered Markup', () => { 54 | 55 | it('renders three `.icon-test`s', () => { 56 | const wrapper = render(); 57 | expect(wrapper.find('.icon-test').length).to.equal(3); 58 | }); 59 | 60 | }); -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Spinner } from "./loader"; 4 | 5 | const componentNames = [ 6 | "Audio", 7 | "BallTriangle", 8 | "Bars", 9 | "Circles", 10 | "Grid", 11 | "Hearts", 12 | "Oval", 13 | "Puff", 14 | "Rings", 15 | "TailSpin", 16 | "ThreeDots", 17 | "Watch", 18 | "RevolvingDot", 19 | "Triangle", 20 | "Plane", 21 | "MutatingDots", 22 | "CradleLoader" 23 | ]; 24 | 25 | function componentName(type) { 26 | if (componentNames.includes(type)) { 27 | return Spinner[type]; 28 | } 29 | return Spinner.Audio; 30 | } 31 | 32 | /** 33 | * @return {null} 34 | */ 35 | export default function Loader(props) { 36 | const [display, setDisplay] = useState(true); 37 | 38 | useEffect(() => { 39 | let timer; 40 | if (props.timeout && props.timeout > 0) { 41 | timer = setTimeout(() => { 42 | setDisplay(false); 43 | }, props.timeout); 44 | } 45 | 46 | return () => { 47 | if (timer) clearTimeout(timer); 48 | }; 49 | }); 50 | 51 | if (!props.visible || props.visible === "false") { 52 | return null; 53 | } 54 | return display ? ( 55 |
56 | {React.createElement(componentName(props.type), { ...props })} 57 |
58 | ) : null; 59 | } 60 | 61 | Loader.propTypes = { 62 | type: PropTypes.oneOf([...componentNames]), 63 | style: PropTypes.objectOf(PropTypes.string), 64 | className: PropTypes.string, 65 | visible: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), 66 | timeout: PropTypes.number 67 | }; 68 | 69 | Loader.defaultProps = { 70 | type: "Audio", 71 | style: {}, 72 | className: "", 73 | visible: true, 74 | timeout: 0 75 | }; 76 | -------------------------------------------------------------------------------- /src/loader/Audio.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Audio = props => ( 5 | 13 | 14 | 15 | 23 | 24 | 25 | 33 | 34 | 35 | 43 | 44 | 45 | 53 | 54 | 55 | 56 | ); 57 | 58 | Audio.propTypes = { 59 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 60 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 61 | color: PropTypes.string, 62 | label: PropTypes.string 63 | }; 64 | 65 | Audio.defaultProps = { 66 | height: 80, 67 | width: 80, 68 | color: "green", 69 | label: "audio-loading" 70 | }; 71 | -------------------------------------------------------------------------------- /src/loader/BallTriangle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const BallTriangle = props => ( 5 | 13 | 14 | 15 | 16 | 24 | 32 | 33 | 34 | 44 | 54 | 55 | 56 | 64 | 74 | 75 | 76 | 77 | 78 | ); 79 | 80 | BallTriangle.propTypes = { 81 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 82 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 83 | color: PropTypes.string, 84 | label: PropTypes.string, 85 | radius: PropTypes.number 86 | }; 87 | 88 | BallTriangle.defaultProps = { 89 | height: 80, 90 | width: 80, 91 | color: "green", 92 | radius: 5, 93 | label: "audio-loading" 94 | }; 95 | -------------------------------------------------------------------------------- /src/loader/Bars.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Bars = props => ( 5 | 13 | 14 | 22 | 30 | 31 | 32 | 40 | 48 | 49 | 50 | 58 | 66 | 67 | 68 | 76 | 84 | 85 | 86 | 94 | 102 | 103 | 104 | ); 105 | 106 | Bars.propTypes = { 107 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 108 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 109 | color: PropTypes.string, 110 | label: PropTypes.string 111 | }; 112 | 113 | Bars.defaultProps = { 114 | height: 80, 115 | width: 80, 116 | color: "green", 117 | label: "audio-loading" 118 | }; 119 | -------------------------------------------------------------------------------- /src/loader/Circles.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Circles = props => ( 5 | 13 | 14 | 22 | 23 | 24 | 32 | 33 | 34 | ); 35 | 36 | Circles.propTypes = { 37 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 38 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 39 | color: PropTypes.string, 40 | label: PropTypes.string 41 | }; 42 | 43 | Circles.defaultProps = { 44 | height: 80, 45 | width: 80, 46 | color: "green", 47 | label: "audio-loading" 48 | }; 49 | -------------------------------------------------------------------------------- /src/loader/CradleLoader.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const CradleLoader = props => ( 5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ); 26 | 27 | CradleLoader.propTypes = { 28 | label: PropTypes.string 29 | }; 30 | 31 | CradleLoader.defaultProps = { 32 | label: "audio-loading" 33 | }; 34 | -------------------------------------------------------------------------------- /src/loader/Grid.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Grid = props => ( 5 | 12 | 13 | 21 | 22 | 23 | 31 | 32 | 33 | 41 | 42 | 43 | 51 | 52 | 53 | 61 | 62 | 63 | 71 | 72 | 73 | 81 | 82 | 83 | 91 | 92 | 93 | 101 | 102 | 103 | ); 104 | 105 | Grid.propTypes = { 106 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 107 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 108 | color: PropTypes.string, 109 | label: PropTypes.string, 110 | radius:PropTypes.number 111 | }; 112 | 113 | Grid.defaultProps = { 114 | height: 80, 115 | width: 80, 116 | color: "green", 117 | radius:12.5, 118 | label: "audio-loading" 119 | }; 120 | -------------------------------------------------------------------------------- /src/loader/Hearts.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Hearts = props => ( 5 | 13 | 19 | 27 | 28 | 34 | 42 | 43 | 44 | 45 | ); 46 | 47 | Hearts.propTypes = { 48 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 49 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 50 | color: PropTypes.string, 51 | label: PropTypes.string 52 | }; 53 | 54 | Hearts.defaultProps = { 55 | height: 80, 56 | width: 80, 57 | color: "green", 58 | label: "audio-loading" 59 | }; 60 | -------------------------------------------------------------------------------- /src/loader/MutatingDots.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const MutatingDots = props => ( 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 27 | 28 | 39 | 40 | 41 | 52 | 53 | 54 | 55 | ); 56 | 57 | MutatingDots.propTypes = { 58 | width: PropTypes.number, 59 | secondaryColor: PropTypes.string, 60 | height:PropTypes.number, 61 | color: PropTypes.string, 62 | radius:PropTypes.number, 63 | label: PropTypes.string 64 | }; 65 | 66 | MutatingDots.defaultProps = { 67 | width: 80, 68 | height:90, 69 | color: "green", 70 | radius:11, 71 | secondaryColor: "green", 72 | label: "audio-loading" 73 | }; 74 | -------------------------------------------------------------------------------- /src/loader/Oval.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Oval = props => ( 5 | 13 | 14 | 15 | 16 | 17 | 25 | 26 | 27 | 28 | 29 | ); 30 | 31 | Oval.propTypes = { 32 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 33 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 34 | color: PropTypes.string, 35 | label: PropTypes.string, 36 | radius: PropTypes.number 37 | }; 38 | 39 | Oval.defaultProps = { 40 | height: 80, 41 | width: 80, 42 | color: "green", 43 | label: "audio-loading", 44 | radius:18 45 | }; 46 | -------------------------------------------------------------------------------- /src/loader/Plane.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Plane = props => ( 5 | 12 | Plane animation. Loading 13 | 25 | 31 | 32 | ); 33 | 34 | Plane.propTypes = { 35 | secondaryColor: PropTypes.string, 36 | color: PropTypes.string, 37 | label: PropTypes.string 38 | }; 39 | 40 | Plane.defaultProps = { 41 | secondaryColor: "grey", 42 | color: "#FFA500", 43 | label: "async-loading" 44 | }; 45 | -------------------------------------------------------------------------------- /src/loader/Puff.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Puff = props => ( 5 | 13 | 14 | 15 | 25 | 35 | 36 | 37 | 47 | 57 | 58 | 59 | 60 | ); 61 | 62 | 63 | Puff.propTypes = { 64 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 65 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 66 | color: PropTypes.string, 67 | label: PropTypes.string, 68 | radius: PropTypes.number 69 | }; 70 | 71 | Puff.defaultProps = { 72 | height: 80, 73 | width: 80, 74 | color: "green", 75 | label: "audio-loading", 76 | radius:1 77 | }; 78 | -------------------------------------------------------------------------------- /src/loader/RevolvingDot.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const RevolvingDot = props => ( 5 | 14 | 23 | 24 | 32 | 33 | 34 | ); 35 | 36 | RevolvingDot.propTypes = { 37 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 38 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 39 | color: PropTypes.string, 40 | label: PropTypes.string, 41 | radius: PropTypes.number 42 | }; 43 | 44 | RevolvingDot.defaultProps = { 45 | height: 80, 46 | width: 80, 47 | color: "green", 48 | label: "audio-loading", 49 | radius: 6 50 | }; 51 | -------------------------------------------------------------------------------- /src/loader/Rings.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Rings = props => ( 5 | 13 | 14 | 15 | 23 | 31 | 39 | 40 | 41 | 49 | 57 | 65 | 66 | 67 | 75 | 76 | 77 | 78 | ); 79 | 80 | Rings.propTypes = { 81 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 82 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 83 | color: PropTypes.string, 84 | label: PropTypes.string, 85 | radius: PropTypes.number 86 | }; 87 | 88 | Rings.defaultProps = { 89 | height: 80, 90 | width: 80, 91 | color: "green", 92 | radius: 6, 93 | label: "audio-loading" 94 | }; 95 | -------------------------------------------------------------------------------- /src/loader/TailSpin.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const TailSpin = props => ( 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 44 | ); 45 | 46 | TailSpin.propTypes = { 47 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 48 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 49 | color: PropTypes.string, 50 | label: PropTypes.string, 51 | radius: PropTypes.number 52 | }; 53 | 54 | TailSpin.defaultProps = { 55 | height: 80, 56 | width: 80, 57 | color: "green", 58 | radius: 1, 59 | label: "audio-loading" 60 | }; 61 | -------------------------------------------------------------------------------- /src/loader/ThreeDots.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const ThreeDots = props => ( 5 | 13 | 14 | 24 | 34 | 35 | 43 | 53 | 63 | 64 | 65 | 75 | 85 | 86 | 87 | ); 88 | 89 | ThreeDots.propTypes = { 90 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 91 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 92 | color: PropTypes.string, 93 | label: PropTypes.string, 94 | radius: PropTypes.number 95 | }; 96 | 97 | ThreeDots.defaultProps = { 98 | height: 80, 99 | width: 80, 100 | color: "green", 101 | label: "audio-loading", 102 | radius: 9 103 | }; 104 | -------------------------------------------------------------------------------- /src/loader/Triangle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Triangle = props => ( 5 |
6 | 13 | 14 | 15 |
16 | ); 17 | 18 | Triangle.propTypes = { 19 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 20 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 21 | color: PropTypes.string, 22 | label: PropTypes.string 23 | }; 24 | 25 | Triangle.defaultProps = { 26 | height: 80, 27 | width: 80, 28 | color: "green", 29 | label: "audio-loading" 30 | }; 31 | -------------------------------------------------------------------------------- /src/loader/Watch.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export const Watch = props => ( 5 | 18 | 27 | 38 | 46 | 47 | 58 | 66 | 67 | 68 | ); 69 | 70 | Watch.propTypes = { 71 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 72 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 73 | color: PropTypes.string, 74 | label: PropTypes.string, 75 | radius: PropTypes.number 76 | }; 77 | 78 | Watch.defaultProps = { 79 | height: 80, 80 | width: 80, 81 | color: "green", 82 | label: "audio-loading", 83 | radius: 48 84 | }; 85 | -------------------------------------------------------------------------------- /src/loader/css/CradleLoader.css: -------------------------------------------------------------------------------- 1 | .react-spinner-loader-swing div { 2 | border-radius: 50%; 3 | float: left; 4 | height: 1em; 5 | width: 1em; 6 | } 7 | .react-spinner-loader-swing div:nth-of-type(1) { 8 | background: -webkit-linear-gradient(left, #385c78 0%, #325774 100%); 9 | background: linear-gradient(to right, #385c78 0%, #325774 100%); 10 | } 11 | .react-spinner-loader-swing div:nth-of-type(2) { 12 | background: -webkit-linear-gradient(left, #325774 0%, #47536a 100%); 13 | background: linear-gradient(to right, #325774 0%, #47536a 100%); 14 | } 15 | .react-spinner-loader-swing div:nth-of-type(3) { 16 | background: -webkit-linear-gradient(left, #4a5369 0%, #6b4d59 100%); 17 | background: linear-gradient(to right, #4a5369 0%, #6b4d59 100%); 18 | } 19 | .react-spinner-loader-swing div:nth-of-type(4) { 20 | background: -webkit-linear-gradient(left, #744c55 0%, #954646 100%); 21 | background: linear-gradient(to right, #744c55 0%, #954646 100%); 22 | } 23 | .react-spinner-loader-swing div:nth-of-type(5) { 24 | background: -webkit-linear-gradient(left, #9c4543 0%, #bb4034 100%); 25 | background: linear-gradient(to right, #9c4543 0%, #bb4034 100%); 26 | } 27 | .react-spinner-loader-swing div:nth-of-type(6) { 28 | background: -webkit-linear-gradient(left, #c33f31 0%, #d83b27 100%); 29 | background: linear-gradient(to right, #c33f31 0%, #d83b27 100%); 30 | } 31 | .react-spinner-loader-swing div:nth-of-type(7) { 32 | background: -webkit-linear-gradient(left, #da3b26 0%, #db412c 100%); 33 | background: linear-gradient(to right, #da3b26 0%, #db412c 100%); 34 | } 35 | .react-spinner-loader-shadow { 36 | clear: left; 37 | padding-top: 1.5em; 38 | } 39 | .react-spinner-loader-shadow div { 40 | -webkit-filter: blur(1px); 41 | filter: blur(1px); 42 | float: left; 43 | width: 1em; 44 | height: .25em; 45 | border-radius: 50%; 46 | background: #e3dbd2; 47 | } 48 | .react-spinner-loader-shadow .react-spinner-loader-shadow-l { 49 | background: #d5d8d6; 50 | } 51 | .react-spinner-loader-shadow .react-spinner-loader-shadow-r { 52 | background: #eed3ca; 53 | } 54 | @-webkit-keyframes ball-l { 55 | 0%, 50% { 56 | -webkit-transform: rotate(0) translateX(0); 57 | transform: rotate(0) translateX(0); 58 | } 59 | 100% { 60 | -webkit-transform: rotate(50deg) translateX(-2.5em); 61 | transform: rotate(50deg) translateX(-2.5em); 62 | } 63 | } 64 | @keyframes ball-l { 65 | 0%, 50% { 66 | -webkit-transform: rotate(0) translate(0); 67 | transform: rotate(0) translateX(0); 68 | } 69 | 100% { 70 | -webkit-transform: rotate(50deg) translateX(-2.5em); 71 | transform: rotate(50deg) translateX(-2.5em); 72 | } 73 | } 74 | @-webkit-keyframes ball-r { 75 | 0% { 76 | -webkit-transform: rotate(-50deg) translateX(2.5em); 77 | transform: rotate(-50deg) translateX(2.5em); 78 | } 79 | 50%, 80 | 100% { 81 | -webkit-transform: rotate(0) translateX(0); 82 | transform: rotate(0) translateX(0); 83 | } 84 | } 85 | @keyframes ball-r { 86 | 0% { 87 | -webkit-transform: rotate(-50deg) translateX(2.5em); 88 | transform: rotate(-50deg) translateX(2.5em); 89 | } 90 | 50%, 91 | 100% { 92 | -webkit-transform: rotate(0) translateX(0); 93 | transform: rotate(0) translateX(0) 94 | } 95 | } 96 | @-webkit-keyframes shadow-l-n { 97 | 0%, 50% { 98 | opacity: .5; 99 | -webkit-transform: translateX(0); 100 | transform: translateX(0); 101 | } 102 | 100% { 103 | opacity: .125; 104 | -webkit-transform: translateX(-1.57em); 105 | transform: translateX(-1.75em); 106 | } 107 | } 108 | @keyframes shadow-l-n { 109 | 0%, 50% { 110 | opacity: .5; 111 | -webkit-transform: translateX(0); 112 | transform: translateX(0); 113 | } 114 | 100% { 115 | opacity: .125; 116 | -webkit-transform: translateX(-1.75); 117 | transform: translateX(-1.75em); 118 | } 119 | } 120 | @-webkit-keyframes shadow-r-n { 121 | 0% { 122 | opacity: .125; 123 | -webkit-transform: translateX(1.75em); 124 | transform: translateX(1.75em); 125 | } 126 | 50%, 127 | 100% { 128 | opacity: .5; 129 | -webkit-transform: translateX(0); 130 | transform: translateX(0); 131 | } 132 | } 133 | @keyframes shadow-r-n { 134 | 0% { 135 | opacity: .125; 136 | -webkit-transform: translateX(1.75em); 137 | transform: translateX(1.75em); 138 | } 139 | 50%, 140 | 100% { 141 | opacity: .5; 142 | -webkit-transform: translateX(0); 143 | transform: translateX(0); 144 | } 145 | } 146 | .react-spinner-loader-swing-l { 147 | -webkit-animation: ball-l .425s ease-in-out infinite alternate; 148 | animation: ball-l .425s ease-in-out infinite alternate; 149 | } 150 | .react-spinner-loader-swing-r { 151 | -webkit-animation: ball-r .425s ease-in-out infinite alternate; 152 | animation: ball-r .425s ease-in-out infinite alternate; 153 | } 154 | .react-spinner-loader-shadow-l { 155 | -webkit-animation: shadow-l-n .425s ease-in-out infinite alternate; 156 | animation: shadow-l-n .425s ease-in-out infinite alternate; 157 | } 158 | .react-spinner-loader-shadow-r { 159 | -webkit-animation: shadow-r-n .425s ease-in-out infinite alternate; 160 | animation: shadow-r-n .425s ease-in-out infinite alternate; 161 | } 162 | -------------------------------------------------------------------------------- /src/loader/css/Plane.css: -------------------------------------------------------------------------------- 1 | 2 | .react-spinner-loader-svg-calLoader { 3 | width: 230px; 4 | height: 230px; 5 | transform-origin: 115px 115px; 6 | animation: 1.4s linear infinite loader-spin; 7 | } 8 | 9 | .react-spinner-loader-svg-cal-loader__path { 10 | 11 | animation: 1.4s ease-in-out infinite loader-path; 12 | } 13 | 14 | @keyframes loader-spin { 15 | to { 16 | transform: rotate(360deg); 17 | } 18 | } 19 | @keyframes loader-path { 20 | 0% { 21 | stroke-dasharray: 0, 580, 0, 0, 0, 0, 0, 0, 0; 22 | } 23 | 50% { 24 | stroke-dasharray: 0, 450, 10, 30, 10, 30, 10, 30, 10; 25 | } 26 | 100% { 27 | stroke-dasharray: 0, 580, 0, 0, 0, 0, 0, 0, 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/loader/css/Triangle.css: -------------------------------------------------------------------------------- 1 | 2 | .react-spinner-loader-svg svg { 3 | -webkit-transform-origin: 50% 65%; 4 | transform-origin: 50% 65%; 5 | } 6 | 7 | .react-spinner-loader-svg svg polygon { 8 | stroke-dasharray: 17; 9 | -webkit-animation: dash 2.5s cubic-bezier(0.35, 0.04, 0.63, 0.95) infinite; 10 | animation: dash 2.5s cubic-bezier(0.35, 0.04, 0.63, 0.95) infinite; 11 | } 12 | 13 | @-webkit-keyframes dash { 14 | to { 15 | stroke-dashoffset: 136; 16 | } 17 | } 18 | 19 | @keyframes dash { 20 | to { 21 | stroke-dashoffset: 136; 22 | } 23 | } 24 | @-webkit-keyframes rotate { 25 | 100% { 26 | -webkit-transform: rotate(360deg); 27 | transform: rotate(360deg); 28 | } 29 | } 30 | @keyframes rotate { 31 | 100% { 32 | -webkit-transform: rotate(360deg); 33 | transform: rotate(360deg); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/loader/css/react-spinner-loader.css: -------------------------------------------------------------------------------- 1 | @import"./CradleLoader.css"; 2 | @import"./Plane.css"; 3 | @import"./Triangle.css"; 4 | -------------------------------------------------------------------------------- /src/loader/index.js: -------------------------------------------------------------------------------- 1 | import { Circles } from "./Circles"; 2 | import { Watch } from "./Watch"; 3 | import { Audio } from "./Audio"; 4 | import { BallTriangle } from "./BallTriangle"; 5 | import { Bars } from "./Bars"; 6 | import { CradleLoader } from "./CradleLoader"; 7 | import { Grid } from "./Grid"; 8 | import { Hearts } from "./Hearts"; 9 | import { MutatingDots } from "./MutatingDots"; 10 | import { Oval } from "./Oval"; 11 | import { Plane } from "./Plane"; 12 | import { Puff } from "./Puff"; 13 | import { RevolvingDot } from "./RevolvingDot"; 14 | import { Rings } from "./Rings"; 15 | import { TailSpin } from "./TailSpin"; 16 | import { ThreeDots } from "./ThreeDots"; 17 | import { Triangle } from "./Triangle"; 18 | 19 | export const Spinner = { 20 | Circles, 21 | Audio, 22 | BallTriangle, 23 | Bars, 24 | CradleLoader, 25 | Grid, 26 | Hearts, 27 | MutatingDots, 28 | Oval, 29 | Plane, 30 | Puff, 31 | RevolvingDot, 32 | Rings, 33 | TailSpin, 34 | ThreeDots, 35 | Triangle, 36 | Watch 37 | }; 38 | -------------------------------------------------------------------------------- /stories/index.stories.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { storiesOf } from "@storybook/react"; 3 | import centered from "@storybook/addon-centered/react"; 4 | import Loader from "../src/index"; 5 | import "../src/loader/css/react-spinner-loader.css"; 6 | 7 | storiesOf("Loader", module) 8 | .addDecorator(centered) 9 | .add("Audio", () => ) 10 | .add("Ball Triangle", () => ( 11 | 12 | )) 13 | .add("Bars", () => ) 14 | .add("Circles", () => ) 15 | .add("Grid", () => ) 16 | .add("Hearts", () => ) 17 | .add("Oval", () => ) 18 | .add("Puff", () => ) 19 | .add("Rings", () => ) 20 | .add("TailSpin", () => ) 21 | .add("ThreeDots", () => ) 22 | .add("Watch", () => ) 23 | .add("RevolvingDot", () => ) 24 | .add("Triangle", () => ) 25 | .add("Plane", () => ) 26 | .add("Mutating Dots", () => ( 27 | 28 | )) 29 | 30 | .add("CradleLoader", () => ) 31 | .add("None", () => ) 32 | .add("NotSpecified", () => ); 33 | --------------------------------------------------------------------------------