├── .babelrc ├── .circleci └── config.yml ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .nvrmrc ├── README.md ├── animate └── style.css ├── docs ├── App.js ├── assets │ ├── fonts │ │ └── Lazer84.woff2 │ ├── images │ │ └── driver.jpg │ ├── select.css │ └── styles.css ├── bundle.js ├── index.html ├── package.json └── webpack.config.babel.js ├── package.json ├── react-motions ├── index.js ├── package.json ├── react-motions.min.js ├── src │ ├── bounce │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── bounce-test.js.snap │ │ │ │ └── withBounce-test.js.snap │ │ │ ├── bounce-test.js │ │ │ └── withBounce-test.js │ │ ├── bounce.css │ │ ├── bounce.js │ │ ├── index.js │ │ ├── styles.js │ │ └── withBounce.js │ ├── fadeIn │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── fadeIn-test.js.snap │ │ │ │ └── withFadeIn-test.js.snap │ │ │ ├── fadeIn-test.js │ │ │ └── withFadeIn-test.js │ │ ├── fadeIn.css │ │ ├── fadeIn.js │ │ ├── index.js │ │ ├── styles.js │ │ └── withFadeIn.js │ ├── fadeOut │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── fadeOut-test.js.snap │ │ │ │ └── withFadeOut-test.js.snap │ │ │ ├── fadeOut-test.js │ │ │ └── withFadeOut-test.js │ │ ├── fadeOut.css │ │ ├── fadeOut.js │ │ ├── index.js │ │ ├── styles.js │ │ └── withFadeOut.js │ ├── flash │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── flash-test.js.snap │ │ │ │ └── withFlash-test.js.snap │ │ │ ├── flash-test.js │ │ │ └── withFlash-test.js │ │ ├── flash.css │ │ ├── flash.js │ │ ├── index.js │ │ ├── styles.js │ │ └── withFlash.js │ ├── injectStyles.js │ ├── jello │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── jello-test.js.snap │ │ │ │ └── withJello-test.js.snap │ │ │ ├── jello-test.js │ │ │ └── withJello-test.js │ │ ├── index.js │ │ ├── jello.css │ │ ├── jello.js │ │ ├── styles.js │ │ └── withJello.js │ ├── pulse │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── pulse-test.js.snap │ │ │ │ └── withPulse-test.js.snap │ │ │ ├── pulse-test.js │ │ │ └── withPulse-test.js │ │ ├── index.js │ │ ├── pulse.css │ │ ├── pulse.js │ │ ├── styles.js │ │ └── withPulse.js │ ├── rubberBand │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── rubberBand-test.js.snap │ │ │ │ └── withRubberBand-test.js.snap │ │ │ ├── rubberBand-test.js │ │ │ └── withRubberBand-test.js │ │ ├── index.js │ │ ├── rubberBand.css │ │ ├── rubberBand.js │ │ ├── styles.js │ │ └── withRubberBand.js │ ├── shake │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── shake-test.js.snap │ │ │ │ └── withShake-test.js.snap │ │ │ ├── shake-test.js │ │ │ └── withShake-test.js │ │ ├── index.js │ │ ├── shake.css │ │ ├── shake.js │ │ ├── styles.js │ │ └── withShake.js │ ├── swing │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── swing-test.js.snap │ │ │ │ └── withSwing-test.js.snap │ │ │ ├── swing-test.js │ │ │ └── withSwing-test.js │ │ ├── index.js │ │ ├── styles.js │ │ ├── swing.css │ │ ├── swing.js │ │ └── withSwing.js │ ├── tada │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── tada-test.js.snap │ │ │ │ └── withTada-test.js.snap │ │ │ ├── tada-test.js │ │ │ └── withTada-test.js │ │ ├── index.js │ │ ├── styles.js │ │ ├── tada.css │ │ ├── tada.js │ │ └── withTada.js │ ├── withInfinite.js │ └── wobble │ │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── withWobble-test.js.snap │ │ │ └── wobble-test.js.snap │ │ ├── withWobble-test.js │ │ └── wobble-test.js │ │ ├── index.js │ │ ├── styles.js │ │ ├── withWobble.js │ │ ├── wobble.css │ │ └── wobble.js └── webpack.config.babel.js ├── test └── setup.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":[ 3 | "env", "react" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:8 6 | 7 | working_directory: ~/repo 8 | 9 | steps: 10 | - checkout 11 | 12 | # Versions Check 13 | - run: 14 | name: Node version 15 | command: node -v 16 | - run: 17 | name: Yarn version 18 | command: yarn --version 19 | 20 | - restore_cache: 21 | keys: 22 | - v1-dependencies-{{ checksum "package.json" }} 23 | - v1-dependencies- 24 | 25 | - run: 26 | name: Install base packages 27 | command: yarn install 28 | 29 | - save_cache: 30 | paths: 31 | - node_modules 32 | key: v1-dependencies-{{ checksum "package.json" }} 33 | 34 | - run: 35 | name: Lint and Test packages 36 | command: yarn test 37 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.nvrmrc: -------------------------------------------------------------------------------- 1 | v8 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Motions 2 | 3 | [![CircleCI](https://circleci.com/gh/raphamorim/react-motions/tree/master.svg?style=svg)](https://circleci.com/gh/raphamorim/react-motions/tree/master) 4 | 5 | > Compose React Animations using High-Order Functions or Components 6 | 7 | React-Motions is a mix of ideas from [Recompose](https://github.com/acdlite/recompose) and [Animate.css](https://github.com/daneden/animate.css). In fact, `react-motions` is a set of pure functions entirely based on animation purpose. 8 | 9 | ```bash 10 | yarn add react-motions --dev 11 | ``` 12 | 13 | # Usage 14 | 15 | Using HOF 16 | 17 | ```jsx 18 | import { withBounce, withShake, withInfinite, withSequence } from 'react-motions' 19 | 20 | const Component =
How can I look beautiful
21 | 22 | const ComponentWithShake = withShake(Component) 23 | const ComponentWithShakeAndBounce = withShake(withBounce(Component)) 24 | const ComponentWithInfiniteBounce = withInfinite(withBounce(Component)) 25 | const ComponentWithShakeThenBounce = withSequence(withShake(withBounce(Component))) 26 | ``` 27 | 28 | HOF - Based on Compositions 29 | 30 | You can add compose animations (even custom animations) based on functions. Here is an example: 31 | 32 | ```jsx 33 | import { withShake, withFadeOut, withInfine } from 'react-motions' 34 | 35 | const Component = () => ( 36 | withInfinite( 37 | withFadeOut( 38 | withInfinite( 39 | withShake( 40 |

Bouncing and Fading Out infinitely!!

41 | ) 42 | ) 43 | ) 44 | ) 45 | ) 46 | ``` 47 | 48 | Using Components 49 | 50 | ```jsx 51 | import { Bounce, Shake } from 'react-motions' 52 | 53 | const ComponentWithShake = () => ( 54 | 55 |
How can I look beautiful
56 |
57 | ) 58 | 59 | const ComponentWithBounce = () => ( 60 | 61 |
How can I look beautiful
62 |
63 | ) 64 | ``` 65 | 66 | React-Motions was created to be agnostic to the renderer: 67 | 68 | | React Renderer | Available for use | Version | 69 | | :--- | :--- | :--- | 70 | | [React-DOM](github.com/facebook/react) | ✔️ | `^16` | 71 | | [React-Native](https://github.com/facebook/react-native) | ✖️ | ✖️ | 72 | | [React-TV](https://github.com/raphamorim/react-tv) | ✔️ | `^0.3` 73 | 74 | # API 75 | 76 | ## withInfinite 77 | 78 | Set last animation with `infinity` property. 79 | 80 | ```jsx 81 | import { withInfinite, withBounce } from 'react-motions' 82 | 83 | const DoNotStopBouncing = withInfinite(withBounce(
Let's bounce without stop!
)) 84 | ``` 85 | 86 | ## withSequence 87 | 88 | Execute next animation only after previous animation be finished. 89 | 90 | ```jsx 91 | import { withSequence, withShake, withJello } from 'react-motions' 92 | 93 | const SequencialAnimations = withSequence( 94 | withShake, 95 | withJello, 96 |
First shake it then jello!
97 | ) 98 | ``` 99 | 100 | ## compose 101 | 102 | Execute all animations in the same time. 103 | 104 | ```jsx 105 | import { compose, withFlash, withPulse } from 'react-motions' 106 | 107 | const VividAnimation = compose( 108 | withFlash, 109 | withPulse, 110 |
Flash and Pulse!
111 | ) 112 | ``` 113 | 114 | ## Bounce 115 | ### Component 116 | 117 | Render a React Component with Bounce animation (`2s` duration and iterationCount `infinite`) 118 | 119 | ```jsx 120 | import { Bounce } from 'react-motions' 121 | 122 | const ComponentBounce = ( 123 | 124 | Let's bounce here 125 | 126 | ) 127 | ``` 128 | 129 | ### Function 130 | 131 | Return a React Component with Bounce animation (`1s` duration) 132 | 133 | ```jsx 134 | import { withBounce } from 'react-motions' 135 | 136 | const ComponentWithBounce = withBounce(
Let's bounce here
) 137 | ``` 138 | 139 | ## FadeIn 140 | ### Component 141 | 142 | Render a React Component with FadeIn animation (`2s` duration and iterationCount `infinite`) 143 | 144 | ```jsx 145 | import { FadeIn } from 'react-motions' 146 | 147 | const ComponentFadeIn = ( 148 | 149 | Let's fadeIn here 150 | 151 | ) 152 | ``` 153 | ### Function 154 | 155 | Return a React Component with FadeIn animation (`1s` duration) 156 | 157 | ```jsx 158 | import { withFadeIn } from 'react-motions' 159 | 160 | const ComponentWithFadeIn = withFadeIn(
Let's fadeIn here
) 161 | ``` 162 | 163 | ## FadeOut 164 | ### Component 165 | 166 | Render a React Component with FadeOut animation (`2s` duration and iterationCount `infinite`) 167 | 168 | ```jsx 169 | import { FadeOut } from 'react-motions' 170 | 171 | const ComponentFadeOut = ( 172 | 173 | Let's fadeOut here 174 | 175 | ) 176 | ``` 177 | ### Function 178 | 179 | Return a React Component with FadeOut animation (`1s` duration) 180 | 181 | ```jsx 182 | import { withFadeOut } from 'react-motions' 183 | 184 | const ComponentWithFadeOut = withFadeOut(
fadeOut here
) 185 | ``` 186 | 187 | ## Flash 188 | ### Component 189 | 190 | Render a React Component with Flash animation (`2s` duration and iterationCount `infinite`) 191 | 192 | ```jsx 193 | import { Flash } from 'react-motions' 194 | 195 | const ComponentFlash = ( 196 | 197 | Let's flash here 198 | 199 | ) 200 | ``` 201 | ### Function 202 | 203 | Return a React Component with Flash animation (`1s` duration) 204 | 205 | ```jsx 206 | import { withFlash } from 'react-motions' 207 | 208 | const ComponentWithFlash = withFlash(
Flash! Flash!
) 209 | ``` 210 | 211 | ## Jello 212 | ### Component 213 | 214 | Render a React Component with Jello animation (`2s` duration and iterationCount `infinite`) 215 | 216 | ```jsx 217 | import { Jello } from 'react-motions' 218 | 219 | const ComponentJello = ( 220 | 221 | Let's jello here 222 | 223 | ) 224 | ``` 225 | ### Function 226 | 227 | Return a React Component with Jello animation (`1s` duration) 228 | 229 | ```jsx 230 | import { withJello } from 'react-motions' 231 | 232 | const ComponentWithJello = withJello(
Jelloooool
) 233 | ``` 234 | 235 | ## Pulse 236 | ### Component 237 | 238 | Render a React Component with Pulse animation (`2s` duration and iterationCount `infinite`) 239 | 240 | ```jsx 241 | import { Pulse } from 'react-motions' 242 | 243 | const ComponentPulse = ( 244 | 245 | Let's pulse here 246 | 247 | ) 248 | ``` 249 | ### Function 250 | 251 | Return a React Component with Pulse animation (`1s` duration) 252 | 253 | ```jsx 254 | import { withPulse } from 'react-motions' 255 | 256 | const ComponentWithPulse = withPulse(
Let's pulse here
) 257 | ``` 258 | 259 | ## RubberBand 260 | ### Component 261 | 262 | Render a React Component with RubberBand animation (`2s` duration and iterationCount `infinite`) 263 | 264 | ```jsx 265 | import { RubberBand } from 'react-motions' 266 | 267 | const ComponentRubberBand = ( 268 | 269 | Let's rubberBand here 270 | 271 | ) 272 | ``` 273 | ### Function 274 | 275 | Return a React Component with rubberBand animation (`1s` duration) 276 | 277 | ```jsx 278 | import { withRubberBand } from 'react-motions' 279 | 280 | const ComponentWithRubberBand = withRubberBand(
rubberBand!
) 281 | ``` 282 | 283 | ## Shake 284 | ### Component 285 | 286 | Render a React Component with Shake animation (`2s` duration and iterationCount `infinite`) 287 | 288 | ```jsx 289 | import { Shake } from 'react-motions' 290 | 291 | const ComponentShake = ( 292 | 293 | Let's shake here 294 | 295 | ) 296 | ``` 297 | ### Function 298 | 299 | Return a React Component with Shake animation (`1s` duration) 300 | 301 | ```jsx 302 | import { withShake } from 'react-motions' 303 | 304 | const ComponentWithShake = withShake(
Let's shake here
) 305 | ``` 306 | ## Swing 307 | ### Component 308 | 309 | Render a React Component with Swing animation (`2s` duration and iterationCount `infinite`) 310 | 311 | ```jsx 312 | import { Swing } from 'react-motions' 313 | 314 | const ComponentSwing = ( 315 | 316 | Let's swing here 317 | 318 | ) 319 | ``` 320 | ### Function 321 | 322 | Return a React Component with Swing animation (`1s` duration) 323 | 324 | ```jsx 325 | import { withSwing } from 'react-motions' 326 | 327 | const ComponentWithSwing = withSwing(
Swing!
) 328 | ``` 329 | ## Tada 330 | ### Component 331 | 332 | Render a React Component with Tada animation (`2s` duration and iterationCount `infinite`) 333 | 334 | ```jsx 335 | import { Tada } from 'react-motions' 336 | 337 | const ComponentTada = ( 338 | 339 | Let's tada here 340 | 341 | ) 342 | ``` 343 | 344 | ### Function 345 | 346 | Return a React Component with Tada animation (`1s` duration) 347 | 348 | ```jsx 349 | import { withTada } from 'react-motions' 350 | 351 | const ComponentWithTada = withTada(
Tadaaaan!
) 352 | ``` 353 | ## Wobble 354 | ### Component 355 | 356 | Render a React Component with Wobble animation (`2s` duration and iterationCount `infinite`) 357 | 358 | ```jsx 359 | import { Wobble } from 'react-motions' 360 | 361 | const ComponentWobble = ( 362 | 363 | Let's wobble here 364 | 365 | ) 366 | ``` 367 | ### Function 368 | 369 | Return a React Component with Wobble animation (`1s` duration) 370 | 371 | ```jsx 372 | import { withWobble } from 'react-motions' 373 | 374 | const ComponentWithWobble = withWobble(
Wobble!
) 375 | ``` 376 | 377 | # Roadmap 378 | 379 | - [ ] `withSequence` 380 | - [ ] `compose` 381 | - [ ] Create handler props on Components for bind Animation Hooks 382 | - [ ] Allows to configure animation property on HOC 383 | 384 | # Credits 385 | 386 | A thanks to [Animate.css](https://github.com/daneden/animate.css) for all animations. 387 | 388 | Created by [Raphael Amorim](https://twitter.com/raphamorims). 389 | -------------------------------------------------------------------------------- /docs/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { 4 | withBounce, 5 | Bounce, 6 | withPulse, 7 | withShake, 8 | withInfinite, 9 | withJello, 10 | Jello, 11 | withTada, 12 | withWobble, 13 | withFlash, 14 | withFadeIn, 15 | withFadeOut, 16 | } from 'react-motions'; 17 | import Select from 'react-select'; 18 | 19 | const Poster = () => ( 20 |
21 | 22 |
23 | ) 24 | 25 | const MOTIONS = { 26 | withBounce, 27 | withPulse, 28 | withShake, 29 | withFlash, 30 | withTada, 31 | withWobble, 32 | withJello, 33 | withFadeIn, 34 | withFadeOut, 35 | withBounceInfinite: Component => withInfinite(withBounce(Component)), 36 | withPulseInfinite: Component => withInfinite(withPulse(Component)), 37 | withShakeInfinite: Component => withInfinite(withShake(Component)), 38 | withFlashInfinite: Component => withInfinite(withFlash(Component)), 39 | withTadaInfinite: Component => withInfinite(withTada(Component)), 40 | withWobbleInfinite: Component => withInfinite(withWobble(Component)), 41 | withJelloInfinite: Component => withInfinite(withJello(Component)), 42 | }; 43 | 44 | const OPTIONS = [ 45 | { label: 'withBounce(Component)', value: 'withBounce' }, 46 | { label: 'withPulse(Component)', value: 'withPulse' }, 47 | { label: 'withShake(Component)', value: 'withShake' }, 48 | { label: 'withFadeIn(Component)', value: 'withFadeIn' }, 49 | { label: 'withFadeOut(Component)', value: 'withFadeOut' }, 50 | { label: 'withFlash(Component)', value: 'withFlash' }, 51 | { label: 'withTada(Component)', value: 'withTada' }, 52 | { label: 'withWobble(Component)', value: 'withWobble' }, 53 | { label: 'withJello(Component)', value: 'withJello' }, 54 | { label: '', value: 'Bounce duration={3}' }, 55 | { label: '', value: 'Jello infinite' }, 56 | { label: 'withInfinite(withBounce(Component))', value: 'withBounceInfinite' }, 57 | { label: 'withInfinite(withPulse(Component))', value: 'withPulseInfinite' }, 58 | { label: 'withInfinite(withShake(Component))', value: 'withShakeInfinite' }, 59 | { label: 'withInfinite(withFlash(Component))', value: 'withFlashInfinite' }, 60 | { label: 'withInfinite(withTada(Component))', value: 'withTadaInfinite' }, 61 | { label: 'withInfinite(withWobble(Component))', value: 'withWobbleInfinite' }, 62 | { label: 'withInfinite(withJello(Component))', value: 'withJelloInfinite' }, 63 | ]; 64 | 65 | class Sandbox extends React.Component { 66 | constructor(props) { 67 | super() 68 | this.state = { 69 | value: 'withJello', 70 | example: withJello(Poster()), 71 | code: this.generateCode('withJello') 72 | } 73 | } 74 | 75 | // unproud of this method 76 | generateCode(method) { 77 | method = [ method, `${method}(Component)` ]; 78 | 79 | if (method[0].indexOf('with') <= -1) { 80 | const ComponentName = method[0].replace(/ .*/,'') 81 | method = [ ComponentName, `<${method[0]}>` ] 82 | } 83 | 84 | if (method[0].indexOf('withInfinite') > -1) { 85 | const effect = method[0].replace('Infinite', '') 86 | method = [ `withInfinite, ${effect}`, `withInfinite(${effect}(Component))` ] 87 | } 88 | 89 | return ` 90 | import React from 'react'; 91 | import { render } from 'react-dom'; 92 | import { ${method[0]} } from 'react-motions'; 93 | 94 | const Component = () => ( 95 |
96 | 97 |
98 | ); 99 | 100 | render( 101 | ${method[1]}, 102 | document.querySelector('#root') 103 | );` 104 | } 105 | 106 | onChange(value) { 107 | let example; 108 | 109 | if (value.indexOf('with') <= -1) { 110 | const ComponentName = value.replace(/ .*/,'') 111 | if (ComponentName === 'Bounce') { 112 | example = {Poster()} 113 | } else if (ComponentName === 'Jello') { 114 | example = {Poster()} 115 | } 116 | } else { 117 | example = MOTIONS[value](Poster()); 118 | } 119 | 120 | this.setState({ 121 | value, 122 | example, 123 | code: this.generateCode(value), 124 | }); 125 | } 126 | 127 | render() { 128 | return ( 129 |
130 |