├── .dependabot └── config.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── 1-bug-report.md │ └── 2-feature-request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .storybook ├── addons.js ├── config.js └── webpack.config.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── azure-pipelines.yml ├── babel.config.js ├── docs └── images │ └── repo-banner.gif ├── examples ├── README.md └── server-side-rendering │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package.json │ ├── screenshot.gif │ ├── src │ ├── App.tsx │ ├── client │ │ └── index.tsx │ └── server │ │ └── index.tsx │ ├── webpack.config.js │ └── yarn.lock ├── package.json ├── rollup.config.js ├── src ├── MDSpinner.tsx ├── constants.ts ├── index.ts ├── ssr-behavior.tsx ├── styles │ ├── get-styles.ts │ └── keyframes.ts └── utils │ └── manipulation.ts ├── stories ├── __snapshots__ │ └── index.stories.storyshot └── index.stories.tsx ├── test ├── MDSpinner.test.tsx └── storyshots.test.js ├── tsconfig.json └── yarn.lock /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | - package_manager: "javascript" 4 | directory: "/" 5 | update_schedule: "live" 6 | 7 | default_assignees: 8 | - "tsuyoshiwada" 9 | 10 | default_labels: 11 | - "dependencies" 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = false 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /storybook-static 3 | node_modules 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | parserOptions: { 4 | sourceType: "module", 5 | project: "./tsconfig.json", 6 | ecmaFeatures: { 7 | jsx: true 8 | } 9 | }, 10 | plugins: ["@typescript-eslint", "react"], 11 | extends: [ 12 | "eslint:recommended", 13 | "plugin:@typescript-eslint/recommended", 14 | "prettier", 15 | "prettier/@typescript-eslint" 16 | ], 17 | env: { 18 | node: true, 19 | browser: true, 20 | jest: true 21 | }, 22 | globals: { 23 | page: true, 24 | browser: true, 25 | context: true, 26 | jestPuppeteer: true 27 | }, 28 | settings: { 29 | react: { 30 | version: "detect" 31 | } 32 | }, 33 | rules: { 34 | "@typescript-eslint/no-explicit-any": "off", 35 | "@typescript-eslint/no-unused-vars": "off", 36 | "@typescript-eslint/explicit-function-return-type": "off", 37 | "react/display-name": "off", 38 | "react/prop-types": "off" 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: Bugs, missing documentation, or unexpected behavior. 4 | --- 5 | 6 | 7 | 8 | ## Expected Behavior 9 | 10 | {Please write here} 11 | 12 | ## Actual Behavior 13 | 14 | {Please write here} 15 | 16 | ## Steps to Reproduce (including precondition) 17 | 18 | {Please write here} 19 | 20 | ## Screenshot on This Problem (if possible) 21 | 22 | {Please write here} 23 | 24 | ## Your Environment 25 | 26 | - OS: {Please write here} 27 | - react-md-spinner version: {Please write here} 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: Suggest an idea for this project. 4 | --- 5 | 6 | 7 | 8 | ## Description 9 | 10 | {Please write here} 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## What does this do / why do we need it? 4 | 5 | {Please write here} 6 | 7 | ## How this PR fixes the problem? 8 | 9 | {Please write here} 10 | 11 | ## What should your reviewer look out for in this PR? 12 | 13 | {Please write here} 14 | 15 | ## Check lists 16 | 17 | - [ ] Test passed 18 | - [ ] Coding style (indentation, etc) 19 | 20 | ## Additional Comments (if any) 21 | 22 | {Please write here} 23 | 24 | ## Which issue(s) does this PR fix? 25 | 26 | 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /storybook-static 3 | /tmp 4 | 5 | # Created by https://www.gitignore.io/api/osx,windows,node 6 | # Edit at https://www.gitignore.io/?templates=osx,windows,node 7 | 8 | ### Node ### 9 | # Logs 10 | logs 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | lerna-debug.log* 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 19 | 20 | # Runtime data 21 | pids 22 | *.pid 23 | *.seed 24 | *.pid.lock 25 | 26 | # Directory for instrumented libs generated by jscoverage/JSCover 27 | lib-cov 28 | 29 | # Coverage directory used by tools like istanbul 30 | coverage 31 | 32 | # nyc test coverage 33 | .nyc_output 34 | 35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 36 | .grunt 37 | 38 | # Bower dependency directory (https://bower.io/) 39 | bower_components 40 | 41 | # node-waf configuration 42 | .lock-wscript 43 | 44 | # Compiled binary addons (https://nodejs.org/api/addons.html) 45 | build/Release 46 | 47 | # Dependency directories 48 | node_modules/ 49 | jspm_packages/ 50 | 51 | # TypeScript v1 declaration files 52 | typings/ 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional REPL history 61 | .node_repl_history 62 | 63 | # Output of 'npm pack' 64 | *.tgz 65 | 66 | # Yarn Integrity file 67 | .yarn-integrity 68 | 69 | # dotenv environment variables file 70 | .env 71 | .env.test 72 | 73 | # parcel-bundler cache (https://parceljs.org/) 74 | .cache 75 | 76 | # next.js build output 77 | .next 78 | 79 | # nuxt.js build output 80 | .nuxt 81 | 82 | # vuepress build output 83 | .vuepress/dist 84 | 85 | # Serverless directories 86 | .serverless/ 87 | 88 | # FuseBox cache 89 | .fusebox/ 90 | 91 | # DynamoDB Local files 92 | .dynamodb/ 93 | 94 | ### OSX ### 95 | # General 96 | .DS_Store 97 | .AppleDouble 98 | .LSOverride 99 | 100 | # Icon must end with two \r 101 | Icon 102 | 103 | # Thumbnails 104 | ._* 105 | 106 | # Files that might appear in the root of a volume 107 | .DocumentRevisions-V100 108 | .fseventsd 109 | .Spotlight-V100 110 | .TemporaryItems 111 | .Trashes 112 | .VolumeIcon.icns 113 | .com.apple.timemachine.donotpresent 114 | 115 | # Directories potentially created on remote AFP share 116 | .AppleDB 117 | .AppleDesktop 118 | Network Trash Folder 119 | Temporary Items 120 | .apdisk 121 | 122 | ### Windows ### 123 | # Windows thumbnail cache files 124 | Thumbs.db 125 | ehthumbs.db 126 | ehthumbs_vista.db 127 | 128 | # Dump file 129 | *.stackdump 130 | 131 | # Folder config file 132 | [Dd]esktop.ini 133 | 134 | # Recycle Bin used on file shares 135 | $RECYCLE.BIN/ 136 | 137 | # Windows Installer files 138 | *.cab 139 | *.msi 140 | *.msix 141 | *.msm 142 | *.msp 143 | 144 | # Windows shortcuts 145 | *.lnk 146 | 147 | # End of https://www.gitignore.io/api/osx,windows,node 148 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import "@storybook/addon-actions/register"; 2 | import "@storybook/addon-links/register"; 3 | import "@storybook/addon-storysource/register"; 4 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from "@storybook/react"; 2 | import requireContext from "require-context.macro"; 3 | 4 | // automatically import all files ending in *.stories.tsx 5 | const req = requireContext("../stories", true, /\.stories\.tsx$/); 6 | 7 | function loadStories() { 8 | req.keys().forEach(req); 9 | } 10 | 11 | configure(loadStories, module); 12 | -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = ({ config }) => { 4 | config.module.rules.push({ 5 | test: /\.(ts|tsx)$/, 6 | include: [ 7 | path.resolve(__dirname, "../src"), 8 | path.resolve(__dirname, "../stories") 9 | ], 10 | exclude: /node_modules/, 11 | use: [ 12 | { 13 | loader: require.resolve("babel-loader") 14 | }, 15 | { 16 | loader: require.resolve("@storybook/addon-storysource/loader"), 17 | options: { 18 | parser: "typescript" 19 | } 20 | } 21 | ] 22 | }); 23 | 24 | config.resolve.extensions.push(".ts", ".tsx"); 25 | 26 | return config; 27 | }; 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 1.0.0 (2019-06-09) 4 | 5 | ### New Features 6 | 7 | - Rewrite with TypeScript! 8 | - Small bundle size!! 9 | - Build process using rollup and babel. (support `module` field) 10 | - Storybook examples. 11 | 12 | ### Breaking Changes 13 | 14 | - Remove `useAgent` props. (always vendor prefixes) 15 | - Remove `useAgent` argument on `ssrBehavior` API. 16 | 17 | Changed to use `stylis` instead of `inline-style-prefixer`. Along with that, we now always have a vendor prefix for styles in `@keyframes`. 18 | 19 | These changes have the benefit of reducing the bundle size. 20 | 21 | ### Internal Changes 22 | 23 | - TSLint -> ESLint. 24 | - Using Prettier. 25 | - Using Dependabot. 26 | 27 | ## 0.4.0 (2019-06-01) 28 | 29 | - Replace deprecated lifecycle hook. Thanks [@ChrisBrownie55](https://github.com/ChrisBrownie55) ! 30 | 31 | ## 0.3.0 (2018-07-08) 32 | 33 | - Add `borderSize` props. 34 | Thanks [@dbalas](https://github.com/dbalas) ! 35 | 36 | ## 0.2.5 (2017-07-22) 37 | 38 | - Changes unused Component types from `undefined` to `{}` 39 | Thanks [@nbgraham](https://github.com/nbgraham) ! 40 | 41 | ## 0.2.4 (2017-05-22) 42 | 43 | - Add type declaration file for typescript [#9](https://github.com/tsuyoshiwada/react-md-spinner/pull/9) 44 | Thanks [@devholic](https://github.com/devholic) !! 45 | 46 | ## 0.2.3 (2017-05-08) 47 | 48 | - [rofrischmann/inline-style-prefixer](https://github.com/rofrischmann/inline-style-prefixer) update to `3.0.3`. [#8](https://github.com/tsuyoshiwada/react-md-spinner/pull/8) 49 | Thanks [@MichaelDeBoey](https://github.com/MichaelDeBoey). 50 | - Bump 'react-highlight' dependency. 51 | - Add dependencies [caniuse-api](https://github.com/nyalab/caniuse-api) package. 52 | 53 | ## 0.2.2 (2017-04-21) 54 | 55 | - Use 'prop-types' package instead of React.PropTypes. ([#6](https://github.com/tsuyoshiwada/react-md-spinner/pull/6)) 56 | Thanks [@MichaelDeBoey](https://github.com/MichaelDeBoey). 57 | 58 | ## 0.2.1 (2017-03-09) 59 | 60 | - Update dev/dependencies. 61 | - [rofrischmann/inline-style-prefixer](https://github.com/rofrischmann/inline-style-prefixer) update to `3.0.1`. 62 | 63 | ## 0.2.0 (2017-02-02) 64 | 65 | ### New features 66 | 67 | - Full support for Server-Side Rendering. [#3](https://github.com/tsuyoshiwada/react-md-spinner/issues/3). 68 | - Thanks [@cescoferraro](https://github.com/cescoferraro)! 69 | - Add `ssrBehavior` utilities. 70 | - Please checkout [examples](./examples/) directory for details. 71 | 72 | ### Minor changes 73 | 74 | - Add [examples](./examples/). 75 | - Update docs. 76 | - Add this ChangeLog. 77 | - Change to `docs` from `demo` for gh-pages. 78 | - Update dependencies. 79 | 80 | ## 0.1.0 (2016-09-23) 81 | 82 | ### New features 83 | 84 | - Add `userAgent` props. (for Server-Side Rendering) 85 | - Thanks [@ryan-codingintrigue](https://github.com/ryan-codingintrigue)! 86 | 87 | ### Minor changes 88 | 89 | - Update dependencies. 90 | 91 | ## 0.0.3 (2016-07-19) 92 | 93 | - Fix specification of the numeric string on size prop. 94 | - Update dependencies. 95 | 96 | ## 0.0.2 (2016-07-03) 97 | 98 | - Fix npm files in package.json. 99 | 100 | ## 0.0.1 (2016-07-03) 101 | 102 | - First release. 103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 tsuyoshiwada 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 | # react-md-spinner 2 | 3 | ![Screenshot](./docs/images/repo-banner.gif) 4 | 5 | [![Build Status](https://dev.azure.com/wadackel/react-md-spinner/_apis/build/status/tsuyoshiwada.react-md-spinner?branchName=master)](https://dev.azure.com/wadackel/react-md-spinner/_build/latest?definitionId=1&branchName=master) 6 | [![npm version](https://img.shields.io/npm/v/react-md-spinner.svg)](https://www.npmjs.com/package/react-md-spinner) 7 | 8 | > Material Design spinner components for React.js. 9 | 10 | Live example: https://tsuyoshiwada.github.io/react-md-spinner/ 11 | 12 | ## Table of Contents 13 | 14 | - [Installation](#installation) 15 | - [Features](#features) 16 | - [Getting Started](#getting-started) 17 | - [Basic Usage](#basic-usage) 18 | - [Server-Side Rendering](#server-side-rendering) 19 | - [Example](#example) 20 | - [Props](#props) 21 | - [`size`](#size) 22 | - [`borderSize`](#bordersize) 23 | - [`duration`](#duration) 24 | - [`color1`](#color1) 25 | - [`color2`](#color2) 26 | - [`color3`](#color3) 27 | - [`color4`](#color4) 28 | - [`singleColor`](#singlecolor) 29 | - [API](#api) 30 | - [`ssrBehavior`](#ssrbehavior) 31 | - [As string output](#as-string-output) 32 | - [As React Components](#as-react-components) 33 | - [ChangeLog](#changelog) 34 | - [Contributing](#contributing) 35 | - [Available Scripts](#available-scripts) 36 | - [`yarn test`](#yarn-test) 37 | - [`yarn lint`](#yarn-lint) 38 | - [`yarn format`](#yarn-format) 39 | - [`yarn build`](#yarn-build) 40 | - [`yarn storybook`](#yarn-storybook) 41 | - [License](#license) 42 | 43 | ## Installation 44 | 45 | You can install the [react-md-spinner](https://www.npmjs.com/package/react-md-spinner) from [npm](https://www.npmjs.com/). 46 | 47 | ```bash 48 | $ npm i -S react-md-spinner 49 | # or 50 | $ yarn add react-md-spinner 51 | ``` 52 | 53 | ## Features 54 | 55 | - :rocket: You can start using with zero configuration! 56 | - :wrench: Support to change of color, size, border and animation speed. 57 | - :sparkling_heart: It can also be used in single color. 58 | - :globe_with_meridians: Support Server-Side Rendering. 59 | 60 | ## Getting Started 61 | 62 | ### Basic Usage 63 | 64 | Because it is made of 100% inline styles, you can start using it right away without setting. 65 | 66 | ```typescript 67 | import React from "react"; 68 | import MDSpinner from "react-md-spinner"; 69 | 70 | export const SpinnerExample: React.FC = () => ( 71 |
72 | 73 |
74 | ); 75 | ``` 76 | 77 | ### Server-Side Rendering 78 | 79 | The following is an example of Server-Side Rendering. 80 | Please checkout [examples](./examples/) directory for details. 81 | 82 | The point is to use `ssrBehavior`. 83 | 84 | #### Example 85 | 86 | **Note:** The following is pseudo code. 87 | 88 | **Client-Side:** 89 | 90 | ```typescript 91 | import React from "react"; 92 | import { render } from "react-dom"; 93 | import App from "./App"; 94 | 95 | render(, document.getElementById("app")); 96 | ``` 97 | 98 | **Server-Side:** 99 | 100 | ```typescript 101 | import { ssrBehavior } from "react-md-spinner"; 102 | 103 | // ... 104 | 105 | const html = (root: JSX.Element) => ` 106 | 107 | 108 | 109 | ${ssrBehavior.getStylesheetString()} 110 | 111 | 112 |
${renderToString(root)}
113 | 114 | 115 | `; 116 | 117 | app.get("/", (_req, res) => { 118 | res.status(200).send(`${renderer()}`); 119 | }); 120 | ``` 121 | 122 | **App:** 123 | 124 | ```typescript 125 | import React from "react"; 126 | import MDSpinner from "react-md-spinner"; 127 | 128 | export const App: React.FC = () => ( 129 |
130 | 131 |
132 | ); 133 | ``` 134 | 135 | ## Props 136 | 137 | You can use the following Props. All Props are Optional! 138 | 139 | ### `size` 140 | 141 | **type:** `number` 142 | **default:** `28` 143 | 144 | Set the size (diameter) of the spinner circle. 145 | 146 | ### `borderSize` 147 | 148 | **type:** `number` 149 | **default:** `undefined` 150 | 151 | Set the spinner border size of. By default, the appropriate size is calculated according to the value of `size`. 152 | 153 | ### `duration` 154 | 155 | **type:** `number` 156 | **default:** `1333` 157 | 158 | Set the animation duration (ms) of the spinner. 159 | 160 | ### `color1` 161 | 162 | **type:** `string` 163 | **default:** !`rgb(66, 165, 245)` 164 | 165 | The color of the spinner. Can be set to any valid CSS string (hex, rgb, rgba). 166 | 167 | ### `color2` 168 | 169 | **type:** `string` 170 | **default:** `rgb(239, 83, 80)` 171 | 172 | Same as above. 173 | 174 | ### `color3` 175 | 176 | **type:** `string` 177 | **default:** `rgb(253, 216, 53)` 178 | 179 | Same as above. 180 | 181 | ### `color4` 182 | 183 | **type:** `string` 184 | **default:** `rgb(76, 175, 80)` 185 | 186 | Same as above. 187 | 188 | ### `singleColor` 189 | 190 | **type:** `string` 191 | **default:** `undefined` 192 | 193 | Same as above. Use this if the spinner should be in only one single color. The settings (props) for `color1` ~ `4` will be ignored by setting this `singleColor` property. 194 | 195 | ## API 196 | 197 | ### `ssrBehavior` 198 | 199 | In Server-Side Rendering you need to inject `@keyframes` inside the ``. 200 | `react-md-spinner` provides utilities to handle them. 201 | 202 | - `ssrBehavior.getStylesheetString(): string` 203 | - `ssrBehavior.getStylesheetComponent(): React.ReactNode` 204 | 205 | #### As string output 206 | 207 | ```typescript 208 | import { ssrBehavior } from "react-md-spinner"; 209 | 210 | const html = () => ` 211 | 212 | ${ssrBehavior.getStylesheetString()} 213 | 214 | 215 |
216 | // React stuff here 217 |
218 | 219 | `; 220 | ``` 221 | 222 | #### As React Components 223 | 224 | ```typescript 225 | import React from "react"; 226 | import { ssrBehavior } from "react-md-spinner"; 227 | 228 | const Html: React.FC = () => ( 229 | 230 | {ssrBehavior.getStylesheetComponent()} 231 | 232 |
{/* React stuff here */}
233 | 234 | 235 | ); 236 | ``` 237 | 238 | ## ChangeLog 239 | 240 | See [CHANGELOG.md](./CHANGELOG.md) 241 | 242 | ## Contributing 243 | 244 | We are always welcoming your contribution :clap: 245 | 246 | 1. Fork (https://github.com/tsuyoshiwada/react-md-spinner) :tada: 247 | 1. Create a feature branch :coffee: 248 | 1. Run test suite with the `$ yarn test` command and confirm that it passes :zap: 249 | 1. Commit your changes :memo: 250 | 1. Rebase your local changes against the `master` branch :bulb: 251 | 1. Create new Pull Request :love_letter: 252 | 253 | ## Available Scripts 254 | 255 | ### `yarn test` 256 | 257 | Run unit test using Jest. 258 | 259 | ### `yarn lint` 260 | 261 | Run Lint of source code using ESLint. 262 | 263 | ### `yarn format` 264 | 265 | Run formatting using Prettier and ESLint's Fixer. 266 | 267 | ### `yarn build` 268 | 269 | Run build of TypeScript code. 270 | 271 | ### `yarn storybook` 272 | 273 | Run Storybook. 274 | 275 | ## License 276 | 277 | [MIT © tsuyoshiwada](./LICENSE) 278 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | pool: 2 | vmImage: 'ubuntu-latest' 3 | 4 | steps: 5 | - task: NodeTool@0 6 | inputs: 7 | versionSpec: '10.x' 8 | displayName: 'Install Node.js' 9 | 10 | - script: | 11 | yarn --pure-lockfile 12 | yarn test 13 | yarn lint 14 | yarn format:prettier && git diff --exit-code || exit 1 15 | displayName: 'yarn install and build' 16 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const { NODE_ENV: env } = process.env; 2 | 3 | const presets = [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: "> 0.25%, last 2 versions, not ie < 11", 8 | modules: env === "test" ? "commonjs" : false 9 | } 10 | ], 11 | "@babel/preset-react", 12 | "@babel/preset-typescript" 13 | ]; 14 | 15 | const plugins = ["@babel/plugin-proposal-class-properties", "macros"]; 16 | 17 | module.exports = { 18 | presets, 19 | plugins 20 | }; 21 | -------------------------------------------------------------------------------- /docs/images/repo-banner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wadackel/react-md-spinner/1242f3fc797822e11894f7092dd6e94acd25d200/docs/images/repo-banner.gif -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | The following example can be run locally. 4 | 5 | - [Server-Side Rendering](./server-side-rendering/) 6 | -------------------------------------------------------------------------------- /examples/server-side-rendering/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /examples/server-side-rendering/README.md: -------------------------------------------------------------------------------- 1 | # Example: Server-Side rendering 2 | 3 | An example of spinner in Server-Side Rendering. 4 | 5 | ![Screenshot](./screenshot.gif) 6 | 7 | ## Example 8 | 9 | The point is to use `ssrBehavior`. 10 | 11 | ```javascript 12 | import { ssrBehavior } from "react-md-spinner"; 13 | 14 | const html = (root: JSX.Element) => ` 15 | 16 | 17 | 18 | ${ssrBehavior.getStylesheetString()} 19 | 20 | 21 |
${renderToString(root)}
22 | 23 | 24 | `; 25 | 26 | app.get("/", (_req, res) => { 27 | res.status(200).send(`${renderer()}`); 28 | }); 29 | ``` 30 | 31 | ### App 32 | 33 | ```javascript 34 | import React, { useState, useEffect } from "react"; 35 | import MDSpinner from "react-md-spinner"; 36 | 37 | export const App: React.FC = () => { 38 | const [mounted, setMounted] = useState(false); 39 | 40 | useEffect(() => { 41 | setMounted(true); 42 | }, []); 43 | 44 | return ( 45 |
46 |

{mounted ? "Mounted" : "Loading..."}

47 | 48 |
49 | ); 50 | }; 51 | ``` 52 | 53 | ## Available Scripts 54 | 55 | In the project directory, you can run: 56 | 57 | ### `$ npm start` 58 | 59 | Runs the app. 60 | Open http://localhost:8080 to view it in the browser. 61 | 62 | ### `$ npm run build` 63 | 64 | Build the client side and server side code. 65 | -------------------------------------------------------------------------------- /examples/server-side-rendering/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("../../babel.config"); 2 | -------------------------------------------------------------------------------- /examples/server-side-rendering/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "react-md-spinner-server-side-rendering", 4 | "scripts": { 5 | "serve": "nodemon dist/server.js", 6 | "build": "webpack", 7 | "clean": "rimraf dist", 8 | "postinstall": "yarn build", 9 | "prebuild": "yarn clean" 10 | }, 11 | "author": "tsuyoshiwada", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "@babel/core": "^7.4.5", 15 | "@babel/preset-env": "^7.4.5", 16 | "@babel/preset-typescript": "^7.3.3", 17 | "@types/express": "^4.16.1", 18 | "@types/react": "^16.8.19", 19 | "@types/react-dom": "^16.8.4", 20 | "babel-loader": "^8.0.6", 21 | "nodemon": "^1.19.1", 22 | "rimraf": "^2.6.3", 23 | "typescript": "^3.5.1", 24 | "webpack": "^4.32.2", 25 | "webpack-cli": "^3.3.2", 26 | "webpack-node-externals": "^1.7.2" 27 | }, 28 | "dependencies": { 29 | "express": "^4.17.1", 30 | "react": "^16.8.6", 31 | "react-dom": "^16.8.6" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/server-side-rendering/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wadackel/react-md-spinner/1242f3fc797822e11894f7092dd6e94acd25d200/examples/server-side-rendering/screenshot.gif -------------------------------------------------------------------------------- /examples/server-side-rendering/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import MDSpinner from "../../../src"; 3 | 4 | export const App: React.FC = () => { 5 | const [mounted, setMounted] = useState(false); 6 | 7 | useEffect(() => { 8 | setMounted(true); 9 | }, []); 10 | 11 | return ( 12 |
13 |

{mounted ? "Mounted" : "Loading..."}

14 | 15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /examples/server-side-rendering/src/client/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "react-dom"; 3 | import { App } from "../App"; 4 | 5 | render(, document.getElementById("app")); 6 | -------------------------------------------------------------------------------- /examples/server-side-rendering/src/server/index.tsx: -------------------------------------------------------------------------------- 1 | import * as path from "path"; 2 | import express from "express"; 3 | import React from "react"; 4 | import { renderToString } from "react-dom/server"; 5 | import { ssrBehavior } from "../../../../src"; 6 | import { App } from "../App"; 7 | 8 | // You can try out the output of the component if setting it to `true`. 9 | const USE_COMPONENT = false; 10 | 11 | const PORT = 8080; 12 | 13 | // for rendering as string. 14 | const html = (root: JSX.Element) => ` 15 | 16 | 17 | 18 | ${ssrBehavior.getStylesheetString()} 19 | 20 | 21 |
${renderToString(root)}
22 | 23 | 24 | `; 25 | 26 | // for rendering as component. 27 | const Html = (root: JSX.Element) => 28 | renderToString( 29 | 30 | 31 | 32 | 33 | {ssrBehavior.getStylesheetComponent()} 34 | 35 | 36 |
{root}
37 |