Repository: chenglou/react-motion
Branch: master
Commit: 9e3ce95bacaa
Files: 68
Total size: 183.5 KB
Directory structure:
gitextract_zo4f_ak9/
├── .babelrc
├── .eslintignore
├── .eslintrc
├── .flowconfig
├── .gitignore
├── .npmignore
├── .size-snapshot.json
├── .travis.yml
├── AUTHORS
├── HISTORY.md
├── LICENSE
├── README.md
├── bower.json
├── demos/
│ ├── README.md
│ ├── demo0-simple-transition/
│ │ ├── Demo.jsx
│ │ ├── index.html
│ │ └── index.jsx
│ ├── demo1-chat-heads/
│ │ ├── Demo.jsx
│ │ ├── index.html
│ │ └── index.jsx
│ ├── demo2-draggable-balls/
│ │ ├── Demo.jsx
│ │ ├── index.html
│ │ └── index.jsx
│ ├── demo3-todomvc-list-transition/
│ │ ├── Demo.jsx
│ │ ├── index.css
│ │ ├── index.html
│ │ └── index.jsx
│ ├── demo4-photo-gallery/
│ │ ├── Demo.jsx
│ │ ├── index.html
│ │ └── index.jsx
│ ├── demo5-spring-parameters-chooser/
│ │ ├── Demo.jsx
│ │ ├── index.html
│ │ └── index.jsx
│ ├── demo7-water-ripples/
│ │ ├── Demo.jsx
│ │ ├── index.html
│ │ └── index.jsx
│ └── demo8-draggable-list/
│ ├── Demo.jsx
│ ├── index.html
│ └── index.jsx
├── karma.conf.js
├── package.json
├── rollup.config.js
├── server.js
├── src/
│ ├── Motion.js
│ ├── StaggeredMotion.js
│ ├── TransitionMotion.js
│ ├── Types.js
│ ├── mapToZero.js
│ ├── mergeDiff.js
│ ├── presets.js
│ ├── react-motion.js
│ ├── reorderKeys.js
│ ├── shouldStopAnimation.js
│ ├── spring.js
│ ├── stepper.js
│ └── stripStyle.js
├── test/
│ ├── Motion-test.js
│ ├── StaggeredMotion-test.js
│ ├── TransitionMotion-test.js
│ ├── createMockRaf.js
│ ├── index.js
│ ├── integration/
│ │ ├── README.md
│ │ ├── bower.html
│ │ ├── bower.json
│ │ └── package.json
│ ├── mergeDiff-test.js
│ └── stripStyle-test.js
└── webpack.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [
["@babel/env", { "modules": "commonjs", "loose": true }],
"@babel/flow",
"@babel/react"
],
"plugins": [
["@babel/proposal-class-properties", { "loose": true }],
["transform-react-remove-prop-types", { "mode": "unsafe-wrap" }]
],
"env": {
"test": {
"plugins": [
"@babel/transform-modules-commonjs"
]
}
}
}
================================================
FILE: .eslintignore
================================================
build
coverage
lib
node_modules
**/*/all.js
webpack.*.js
server.js
karma.*.js
test/integration
demos/demo6/babel.js
demos/*/Demo.jsx
================================================
FILE: .eslintrc
================================================
{
"parser": "babel-eslint",
"extends": ["airbnb", "prettier"],
"env": {
"browser": true,
"es6": true,
"jasmine": true
},
"rules": {
"eqeqeq": [2, "allow-null"],
"id-length": 0,
"no-console": 0, // use it for warnings
"no-nested-ternary": 0,
"prefer-const": 0,
"no-multiple-empty-lines": 0,
"no-useless-escape": 0,
"no-else-return": 0,
"comma-dangle": 0,
"lines-between-class-members": 0,
"indent": 0,
"operator-linebreak": 0,
"object-curly-newline": 0,
"function-paren-newline": 0,
"prefer-destructuring": 0,
"camelcase": ["error", {"allow": ["^UNSAFE_"]}],
"react/jsx-wrap-multilines": 0,
"react/jsx-one-expression-per-line": 0,
"react/no-unused-state": 0,
"react/require-default-props": 0,
"react/destructuring-assignment": 0,
"react/no-did-mount-set-state": 2,
"react/no-multi-comp": 0,
"react/jsx-boolean-value": [2, "always"],
"react/sort-comp": [
2, {
"order": [
"displayName",
"propTypes",
"contextTypes",
"childContextTypes",
"mixins",
"statics",
"defaultProps",
"getDefaultProps",
"getInitialState",
"getChildContext",
"componentWillMount",
"UNSAFE_componentWillMount",
"componentDidMount",
"componentWillReceiveProps",
"UNSAFE_componentWillReceiveProps",
"shouldComponentUpdate",
"componentWillUpdate",
"UNSAFE_componentWillUpdate",
"componentDidUpdate",
"componentWillUnmount",
"/^on.+$/",
"/^get.+$/",
"/^render.+$/",
"/^.+$/", // All other methods go here
"render"
]
}
],
"max-len": 0,
"no-mixed-operators": 0,
"no-continue": 0,
"no-restricted-syntax": 0,
"no-plusplus": 0,
"no-confusing-arrow": 0,
"arrow-parens": 0,
"arrow-body-style": 0,
"react/jsx-indent": 0,
"react/jsx-indent-props": 0,
"react/jsx-closing-bracket-location": 0,
"react/prefer-es6-class": 0,
"react/jsx-filename-extension": 0,
"react/prefer-stateless-function": 0,
"object-curly-spacing": 0,
"import/imports-first": 0,
"import/no-unresolved": 0,
"import/no-extraneous-dependencies": 0,
"import/order": 0,
"import/no-webpack-loader-syntax": 0,
}
}
================================================
FILE: .flowconfig
================================================
[ignore]
.*/node_modules/fbjs/lib/PromiseMap.js
.*/node_modules/fbjs/lib/fetchWithRetries.js
.*/node_modules/fbjs/lib/Deferred.js.flow
.*/node_modules/fbjs/lib/equalsSet.js.flow
.*/node_modules/fbjs/lib/shallowEqual.js.flow
.*/node_modules/fbjs/lib/someSet.js.flow
.*/node_modules/fbjs/lib/everySet.js.flow
.*/node_modules/fbjs/lib/UnicodeBidi.js.flow
.*/node_modules/fbjs/lib/UnicodeBidiService.js.flow
.*/node_modules/kefir/kefir.js.flow
.*/node_modules/kefir/dist/kefir.js.flow
.*/test/.*
.*/node_modules/@webassemblyjs/.*
.*/node_modules/eslint-plugin-jsx-a11y/.*
.*/node_modules/rollup-plugin-size-snapshot/.*
.*/node_modules/babel-plugin-transform-react-remove-prop-types
[include]
[libs]
[options]
================================================
FILE: .gitignore
================================================
logs
*.log
pids
*.pid
*.seed
coverage
node_modules
bower_components
.DS_Store
/demos/**/all.*
/build/
/lib/
================================================
FILE: .npmignore
================================================
/.*
/bower_components/
/coverage/
/demos/
/test/
/karma.conf.js
/webpack.*
/server.js
# sublime
/*.sublime-project
/*.sublime-workspace
/rollup.config.js
================================================
FILE: .size-snapshot.json
================================================
{
"build/react-motion.js": {
"bundled": 77059,
"minified": 22596,
"gzipped": 6616
},
"build/react-motion.min.js": {
"bundled": 52481,
"minified": 15210,
"gzipped": 4446
},
"lib/react-motion.esm.js": {
"bundled": 43290,
"minified": 14594,
"gzipped": 3583,
"treeshaked": {
"rollup": {
"code": 6381,
"import_statements": 196
},
"webpack": {
"code": 7588
}
}
}
}
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- 10
script:
- npm run -s lint
- npm run -s flow_check
- npm run -s test:travis
================================================
FILE: AUTHORS
================================================
Adrian le Bas
Amadeus Junqueira
Benjamin San Souci
Bishop Zareh
Brenton Simpson
Cesar Andreu
Cheng Lou
Dan Abramov
Daniel Dunderfelt
Dustan Kasten
Frederick Fogerty
Gaëtan Renaudeau
Google, Inc.
Henry Zhu
Ivan Starkov
Jeroen van Aert
Jesper Petersson
Jevgeni Geimanen
Joe Lencioni
John Amiah Ford
Jon Lebensold
Justin Morris
Kyle Mathews
Ludovico Fischer
Michael J Hoffman
Mirko Mariani
Neil Kistner
Nik Butenko
Nikhil Baradwaj
Olivier Tassinari
Paolo Moretti
Raymond Zhou
Robert Haritonov
Sorin Iclanzan
Stefan Dombrowski
Stephen J. Collings
Sundeep Malladi
Sunil Pai
Travis Arnold
Wilfred Denton
================================================
FILE: HISTORY.md
================================================
Legend:
- [B]: Breaking
- [F]: Fix
- [I]: Improvement
### 0.5.1 (August 28th 2017)
- [F] New flow definitions, fixes children typing.
### 0.5.0 (April 26th 2017)
- [B] Dropping support for older React. Currently supported versions are `^0.14.9` || `^15.3.0`
- [I] Upgraded all React components to use ES6 classes
- [I] Replace React.PropTypes with prop-types package
### 0.4.8 (April 17th 2017)
- [I] Externalize stripStyle #452 by @bearcott
- [I] Migrated deprecated React.PropTypes and React.createClass #446 by @Andarist
- [F] Fix link to TypeScript types #443 by @pshrmn
- [F] Refactored demo and fixed flow check errors #435 by @therewillbecode
- [F] Fix broken link #430 by @codler
- [F] Unmounted component setState fix #420 by @alleycat-at-git
### 0.4.7 (December 15th 2016)
- [I] `didLeave` for `TransitionMotion`! Please check the README for more.
### 0.4.4 (June 4th 2016)
- [F] Small fix to component unmounting bug (https://github.com/chenglou/react-motion/commit/49ea396041b0031b95f4941cc7efce200fcca454). It's not clear why this is erroring, but people want the temp fix.
### 0.4.3 (April 19th 2016)
- [F] `TransitionMotion` `styles` function not being passed `defaultStyles` value upon first call. #296
- [I] `onRest` callback for `Motion`!
### 0.4.2 (January 30th 2016)
- [F] `TransitionMotion` keys merging bug. #264
- [F] `TransitionMotion` rare stale read bug. [https://github.com/chenglou/react-motion/commit/f20dc1b9c8de7b387927b24afdb73e0a5ea0d0a6](https://github.com/chenglou/react-motion/commit/f20dc1b9c8de7b387927b24afdb73e0a5ea0d0a6)
### 0.4.1 (January 26th 2016)
- [F] Made a mistake while publishing the bower package; fixed.
### 0.4.0 (January 26th 2016)
- [B] `spring` helper's format has changed from `spring(10, [120, 12])` to `spring(10, {stiffness: 120, damping: 12})`.
- [B] `style`, `styles` and `styles` of the three respective components now only accept either a number to interpolate, or a `spring` configuration to interpolate. Previously, it accepted (and ignored) random key/value pairs mixed in, such as `{x: spring(0), y: 'helloWorld'}`. `y` Doesn't belong there and should be placed elsewhere, e.g. directly on the (actual react) style of the component you're assigning the interpolating values on.
- [B] `TransitionMotion` got an all-around clearer API. See the [upgrade guide](https://github.com/chenglou/react-motion/wiki) and [README section](https://github.com/chenglou/react-motion/blob/9877c311cc4a22099eb56fe7c76bad9753519ddb/README.md#transitionmotion-) for more.
- [B] `Motion`'s' `defaultStyle`, informally accepted the format `{x: spring(0)}`. This is now officially unsupported. The correct format has always been `{x: 0}`. Setting a default style of `{x: spring(whatever)}` did not make sense; the configuration only applies for a `style`, aka destination value. Same modification applies to `StaggeredMotion` and `TransitionMotion`'s `defaultStyles` & `willEnter`.
- [B] `TransitionMotion`'s `willEnter`/`willLeave`'s signature has changed.
- [B] The `reorderKeys` helper is no longer needed thanks to the changes to `TransitionMotion`. It's now removed.
- [B] React-Native specific build gone. RN 0.18+ uses the vanilla Npm React package, so there's no more need for us to export a wrapper.
- [F] Bunch of bugs gone: #225, #212, #179, #157, #90, #88.
- [I] `spring` has acquired a new field as part of the new signature: [precision tuning](https://github.com/chenglou/react-motion/blob/9877c311cc4a22099eb56fe7c76bad9753519ddb/README.md#--spring-val-number-config-springhelperconfig--opaqueconfig)!
- [I] [Fully typed](https://github.com/chenglou/react-motion/blob/05d76f5ec7e9722dbca0237a97c41267e297eb2c/src/Types.js) via [Flow types](http://flowtype.org).
- [I] Performance improvements.
### 0.3.1 (October 14th 2015)
- [F] Handle `null` and `undefined` in `style`/`styles`. #181
- [I] Library's now partially annotated with [Flow](http://flowtype.org).
- [I] Related to above, the `src/` folder is now exposed on npm so that you can take advantage of Flow by using: `import {Motion} from 'react-motion/src/react-motion'` directly, instead of the old, prebuilt `import {Motion} from 'react-motion'`. **This is experimental** and intentionally undocumented. You'll have to adjust your webpack/browserify configurations to require these original source files correctly. No harm trying of course. It's just some type annotations =).
### 0.3.0 (September 30th 2015)
- [B] API revamp! See [https://github.com/chenglou/react-motion/wiki](https://github.com/chenglou/react-motion/wiki) for more details. Thanks!
### 0.2.7 (August 6th 2015)
- [F] Small bug where nested springs don't animate. #123
- [I] Support for all React 0.14.0 betas.
### 0.2.6 (July 31th 2015)
- [F] React-native warning's now gone, but also put into a separate file path. To require react-motion on react-native, do `require('react-motion/native')`.
- [I] Support for React 0.14.0-beta1.
### 0.2.4 (July 29th 2015)
- [I] React-native support!
- [I] Allow returning `null` from children function. #101
- [I] `defaultValue` for specifying a... default value, upon mounting.
- [I] `TransitionSpring`'s `willLeave` API got simplified and now asks for an object as a return value instead of `null`. `null` is still supported, but is deprecated and will be removed in the next version. See the new docs on it [here](https://github.com/chenglou/react-motion/blob/24d6a7284ef61268c0ead67fe43d7e40bf45d381/README.md#transitionspring-).
- [I] Exposed a few tasteful default spring configurations under the new exported `presets`.
### 0.2.2 (July 24th 2015)
- [F] Import some internal modules correctly for Ubuntu/Linux node (case-sensitive for them).
- [F] Nested springs work again.
### 0.2.0 (July 22th 2015)
- [B] `willLeave` returning `false` will now keep the key. Only `null` and `undefined` will serve as a signal to kill the disappeared key.
- [B] `willLeave` previously failed to expose the second argument `correspondingValueOfKeyThatJustLeft`. It's now exposed correctly.
- [F] Definitively fix the previous problem of mis-detecting React Element as object.
- [F] `willLeave` is now called only once per disappearing key. It was called more than once previously as a implementation detail. Though you should never have put side-effects in `willLeave`. It's still discouraged now.
- [F] If you have some `this.props.handlerThatSetStateAndUnmountsSpringInOwnerRender()` in `Spring`'s `endValue`, Spring's already scheduled `requestAnimationFrame` will no longer cause an extra `setState` since it's unmounted. But in general, _please_ don't put side-effect in `endValue`.
- [I] Stabilize the spring algorithm. No more erratic behavior with a big amount of animated items or tab switching (which usually slows down `requestAnimationFrame`). #57
- [I] Partial (total?) support for IE9 by using a `requestAnimationFrame` polyfill.
### 0.1.0 (July 14th 2015)
- [B] Breaking API: `TransitionSpring`'s `willEnter`'s callback signature is now `(keyThatEnters, correspondingValue, endValueYouJustSpecified, currentInterpolatedValue, currentSpeed)` (added `correspondingValue` as the second argument). Same for `willLeave`.
- [B] `Spring` is now no longer exposed as a default, but simply as "Spring": `require('react-motion').Spring`. Or `import {Spring} from 'react-motion'`.
- [B] `Spring` and `TransitionSpring`'s `children` function now expect a ReactElement. The components will no longer wrap the return value in a `div` for you. #44 #20
- [I] Move React to from dependencies to peerDependencies. #35
- [I] Internal cleanups + tests, for happier contributors.
- [F] Mis-detecting React Element as object.
- [F] Accidentally updating values at the first level of `endValue` without `{val: ...}` wrapper.
### 0.0.3 (July 9th 2015)
- [I] Initial release.
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 React Motion authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# React-Motion
[](https://travis-ci.org/chenglou/react-motion)
[](https://www.npmjs.com/package/react-motion)
[](http://badge.fury.io/bo/react-motion)
[](https://discordapp.com/invite/0ZcbPKXt5bYzmcI0)
```js
import {Motion, spring} from 'react-motion';
// In your render...
{value =>
{value.x}
}
```
Animate a counter from `0` to `10`. For more advanced usage, see below.
### Install
- Npm: `npm install --save react-motion`
- Bower: **do not install with `bower install react-motion`, it won't work**. Use `bower install --save https://unpkg.com/react-motion/bower.zip`. Or in `bower.json`:
```json
{
"dependencies": {
"react-motion": "https://unpkg.com/react-motion/bower.zip"
}
}
```
then include as
```html
```
- 1998 Script Tag:
```html
(Module exposed as `ReactMotion`)
```
**Works with React-Native v0.18+**.
### Demos
- [Simple Transition](http://chenglou.github.io/react-motion/demos/demo0-simple-transition)
- [Chat Heads](http://chenglou.github.io/react-motion/demos/demo1-chat-heads)
- [Draggable Balls](http://chenglou.github.io/react-motion/demos/demo2-draggable-balls)
- [TodoMVC List Transition](http://chenglou.github.io/react-motion/demos/demo3-todomvc-list-transition)
- [Photo Gallery](http://chenglou.github.io/react-motion/demos/demo4-photo-gallery)
- [Spring Parameters Chooser](http://chenglou.github.io/react-motion/demos/demo5-spring-parameters-chooser)
- [Water Ripples](http://chenglou.github.io/react-motion/demos/demo7-water-ripples)
- [Draggable List](http://chenglou.github.io/react-motion/demos/demo8-draggable-list)
[Check the wiki for more!](https://github.com/chenglou/react-motion/wiki/Gallery-of-third-party-React-Motion-demos)
### Try the Demos Locally
```sh
git clone https://github.com/chenglou/react-motion.git
cd react-motion
npm install
```
- With hot reloading (**slow, development version**): run `npm start`.
- Without hot reloading (**faster, production version**): run `npm run build-demos` and open the static `demos/demo_name/index.html` file directly. **Don't forget to use production mode when testing your animation's performance**!
To build the repo yourself: `npm run prepublish`.
## What does this library try to solve?
[My React-Europe talk](https://www.youtube.com/watch?v=1tavDv5hXpo)
For 95% of use-cases of animating components, we don't have to resort to using hard-coded easing curves and duration. Set up a stiffness and damping for your UI element, and let the magic of physics take care of the rest. This way, you don't have to worry about petty situations such as interrupted animation behavior. It also greatly simplifies the API.
This library also provides an alternative, more powerful API for React's `TransitionGroup`.
## API
Exports:
- `spring`
- `Motion`
- `StaggeredMotion`
- `TransitionMotion`
- `presets`
[Here](https://github.com/chenglou/react-motion/blob/9cb90eca20ecf56e77feb816d101a4a9110c7d70/src/Types.js)'s the well-annotated public [Flow type](http://flowtype.org) definition file (you don't have to use Flow with React-motion, but the types help document the API below).
P.S. using TypeScript? [Here](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-motion/index.d.ts) are the React-motion TypeScript definitions!
---
### Helpers
##### - spring: (val: number, config?: SpringHelperConfig) => OpaqueConfig
Used in conjunction with the components below. Specifies the how to animate to the destination value, e.g. `spring(10, {stiffness: 120, damping: 17})` means "animate to value 10, with a spring of stiffness 120 and damping 17".
- `val`: the value.
- `config`: optional, for further adjustments. Possible fields:
- `stiffness`: optional, defaults to `170`.
- `damping`: optional, defaults to `26`.
- `precision`: optional, defaults to `0.01`. Specifies both the rounding of the interpolated value and the speed (internal).
It's normal not to feel how stiffness and damping affect your spring; use [Spring Parameters Chooser](http://chenglou.github.io/react-motion/demos/demo5-spring-parameters-chooser) to get a feeling. **Usually**, you'd just use the list of tasteful stiffness/damping presets below.
##### - Presets for `{stiffness, damping}`
Commonly used spring configurations used like so: `spring(10, presets.wobbly)` or `spring(20, {...presets.gentle, precision: 0.1})`. [See here](https://github.com/chenglou/react-motion/blob/9cb90eca20ecf56e77feb816d101a4a9110c7d70/src/presets.js).
---
### <Motion />
#### Usage
```jsx
{interpolatingStyle => }
```
#### Props
##### - style: Style
Required. The `Style` type is an object that maps to either a `number` or an `OpaqueConfig` returned by `spring()` above. Must keep the same keys throughout component's existence. The meaning of the values:
- an `OpaqueConfig` returned from `spring(x)`: interpolate to `x`.
- a `number` `x`: jump to `x`, do not interpolate.
##### - defaultStyle?: PlainStyle
Optional. The `PlainStyle` type maps to `number`s. Defaults to an object with the same keys as `style` above, whose values are the initial numbers you're interpolating on. **Note that during subsequent renders, this prop is ignored. The values will interpolate from the current ones to the destination ones (specified by `style`)**.
##### - children: (interpolatedStyle: PlainStyle) => ReactElement
Required **function**.
- `interpolatedStyle`: the interpolated style object passed back to you. E.g. if you gave `style={{x: spring(10), y: spring(20)}}`, you'll receive as `interpolatedStyle`, at a certain time, `{x: 5.2, y: 12.1}`, which you can then apply on your `div` or something else.
- Return: must return **one** React element to render.
##### - onRest?: () => void
Optional. The callback that fires when the animation comes to a rest.
---
### <StaggeredMotion />
Animates a collection of (**fixed length**) items whose values depend on each other, creating a natural, springy, "staggering" effect [like so](http://chenglou.github.io/react-motion/demos/demo1-chat-heads). This is preferred over hard-coding a delay for an array of `Motions` to achieve a similar (but less natural-looking) effect.
#### Usage
```jsx
prevInterpolatedStyles.map((_, i) => {
return i === 0
? {h: spring(100)}
: {h: spring(prevInterpolatedStyles[i - 1].h)}
})}>
{interpolatingStyles =>
{interpolatingStyles.map((style, i) =>
)
}
}
```
Aka "the current spring's destination value is the interpolating value of the previous spring". Imagine a spring dragging another. Physics, it works!
#### Props
##### - styles: (previousInterpolatedStyles: ?Array<PlainStyle>) => Array<Style>
Required **function**. **Don't forget the "s"**!
- `previousInterpolatedStyles`: the previously interpolating (array of) styles (`undefined` at first render, unless `defaultStyles` is provided).
- Return: must return an array of `Style`s containing the destination values, e.g. `[{x: spring(10)}, {x: spring(20)}]`.
##### - defaultStyles?: Array<PlainStyle>
Optional. Similar to `Motion`'s `defaultStyle`, but an array of them.
##### - children: (interpolatedStyles: Array<PlainStyle>) => ReactElement
Required **function**. Similar to `Motion`'s `children`, but accepts the array of interpolated styles instead, e.g. `[{x: 5}, {x: 6.4}, {x: 8.1}]`
(No `onRest` for StaggeredMotion because we haven't found a good semantics for it yet. Voice your support in the issues section.)
---
### <TransitionMotion />
**Helps you to do mounting and unmounting animation**.
#### Usage
You have items `a`, `b`, `c`, with their respective style configuration, given to `TransitionMotion`'s `styles`. In its `children` function, you're passed the three interpolated styles as params; you map over them and produce three components. All is good.
During next render, you give only `a` and `b`, indicating that you want `c` gone, but that you'd like to animate it reaching value `0`, before killing it for good.
Fortunately, `TransitionMotion` has kept `c` around and still passes it into the `children` function param. So when you're mapping over these three interpolated styles, you're still producing three components. It'll keep interpolating, while checking `c`'s current value at every frame. Once `c` reaches the specified `0`, `TransitionMotion` will remove it for good (from the interpolated styles passed to your `children` function).
This time, when mapping through the two remaining interpolated styles, you'll produce only two components. `c` is gone for real.
```jsx
import createReactClass from 'create-react-class';
const Demo = createReactClass({
getInitialState() {
return {
items: [{key: 'a', size: 10}, {key: 'b', size: 20}, {key: 'c', size: 30}],
};
},
componentDidMount() {
this.setState({
items: [{key: 'a', size: 10}, {key: 'b', size: 20}], // remove c.
});
},
willLeave() {
// triggered when c's gone. Keeping c until its width/height reach 0.
return {width: spring(0), height: spring(0)};
},
render() {
return (
({
key: item.key,
style: {width: item.size, height: item.size},
}))}>
{interpolatedStyles =>
// first render: a, b, c. Second: still a, b, c! Only last one's a, b.
{interpolatedStyles.map(config => {
return
})}
}
);
},
});
```
#### Props
First, two type definitions to ease the comprehension.
- `TransitionStyle`: an object of the format `{key: string, data?: any, style: Style}`.
- `key`: required. The ID that `TransitionMotion` uses to track which configuration is which across renders, even when things are reordered. Typically reused as the component `key` when you map over the interpolated styles.
- `data`: optional. Anything you'd like to carry along. This is so that when the previous section example's `c` disappears, you still get to access `c`'s related data, such as the text to display along with it.
- `style`: required. The actual starting style configuration, similar to what you provide for `Motion`'s `style`. Maps keys to either a number or an `OpaqueConfig` returned by `spring()`.
- `TransitionPlainStyle`: similar to above, except the `style` field's value is of type `PlainStyle`, aka an object that maps to numbers.
##### - styles: Array<TransitionStyle> | (previousInterpolatedStyles: ?Array<TransitionPlainStyle>) => Array<TransitionStyle>
Required. Accepts either:
- an array of `TransitionStyle` configs, e.g. `[{key: 'a', style: {x: spring(0)}}, {key: 'b', style: {x: spring(10)}}]`.
- a function similar to `StaggeredMotion`, taking the previously interpolating styles (`undefined` at first call, unless `defaultStyles` is provided), and returning the previously mentioned array of configs. __You can do staggered mounting animation with this__.
##### - defaultStyles?: Array<TransitionPlainStyle>
Optional. Similar to the other components' `defaultStyle`/`defaultStyles`.
##### - children: (interpolatedStyles: Array<TransitionPlainStyle>) => ReactElement
Required **function**. Similar to other two components' `children`. Receive back an array similar to what you provided for `defaultStyles`, only that each `style` object's number value represent the currently interpolating value.
##### - willLeave?: (styleThatLeft: TransitionStyle) => ?Style
Optional. Defaults to `() => null`. **The magic sauce property**.
- `styleThatLeft`: the e.g. `{key: ..., data: ..., style: ...}` object from the `styles` array, identified by `key`, that was present during a previous render, and that is now absent, thus triggering the call to `willLeave`. Note that the style property is exactly what you passed in `styles`, and is not interpolated. For example, if you passed a spring for `x` you will receive an object like `{x: {stiffness, damping, val, precision}}`.
- Return: `null` to indicate you want the `TransitionStyle` gone immediately. A `Style` object to indicate you want to reach transition to the specified value(s) before killing the `TransitionStyle`.
##### - didLeave?: (styleThatLeft: `{key: string, data?: any}`) => void
Optional. Defaults to `() => {}`.
- `styleThatLeft`: the `{key:..., data:...}` that was removed after the finished transition.
##### - willEnter?: (styleThatEntered: TransitionStyle) => PlainStyle
Optional. Defaults to `styleThatEntered => stripStyle(styleThatEntered.style)`. Where `stripStyle` turns `{x: spring(10), y: spring(20)}` into `{x: 10, y: 20}`.
- `styleThatEntered`: similar to `willLeave`'s, except the `TransitionStyle` represents the object whose `key` value was absent during the last `render`, and that is now present.
- Return: a `defaultStyle`-like `PlainStyle` configuration, e.g. `{x: 0, y: 0}`, that serves as the starting values of the animation. Under this light, the default provided means "a style config that has the same starting values as the destination values".
**Note** that `willEnter` and `defaultStyles` serve different purposes. `willEnter` only triggers when a previously inexistent `TransitionStyle` inside `styles` comes into the new render.
(No `onRest` for TransitionMotion because we haven't found a good semantics for it yet. Voice your support in the issues section.)
---
## FAQ
- How do I set the duration of my animation?
[Hard-coded duration goes against fluid interfaces](https://twitter.com/andy_matuschak/status/566736015188963328). If your animation is interrupted mid-way, you'd get a weird completion animation if you hard-coded the time. That being said, in the demo section there's a great [Spring Parameters Chooser](http://chenglou.github.io/react-motion/demos/demo5-spring-parameters-chooser) for you to have a feel of what spring is appropriate, rather than guessing a duration in the dark.
- How do I unmount the `TransitionMotion` container itself?
You don't. Unless you put it in another `TransitionMotion`...
- How do I do staggering/chained animation where items animate in one after another?
See [`StaggeredMotion`](#staggeredmotion-)
- My `ref` doesn't work in the children function.
React string refs won't work:
```jsx
{currentValue => }
```
This is how React works. Here's the [callback ref solution](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs).
================================================
FILE: bower.json
================================================
{
"name": "react-motion",
"version": "0.5.1",
"homepage": "https://github.com/chenglou/react-motion",
"authors": [
"chenglou"
],
"description": "A spring that solves your animation problems.",
"main": [
"build/react-motion.js",
"build/react-motion.map"
],
"dependencies": {
"react": "^0.14.9 || ^15.3.0"
},
"keywords": [
"react",
"component",
"react-component",
"transitiongroup",
"spring",
"tween",
"motion",
"animation",
"transition",
"ui"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"test",
"demo*",
"server.js",
"src",
"webpack.config.js",
"webpack.prod.config.js",
"karma.conf.js",
"package.json"
]
}
================================================
FILE: demos/README.md
================================================
## Demos folder
**Note**: since this is the master branch, the demos might be a bit ahead of the current stable API. [This commit](https://github.com/chenglou/react-motion/tree/0627243316c564f6c2f480bf615b82135f649a0a/demos) contains the stable demos.
================================================
FILE: demos/demo0-simple-transition/Demo.jsx
================================================
import React from 'react';
import {Motion, spring} from '../../src/react-motion';
export default class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
};
handleMouseDown = () => {
this.setState({open: !this.state.open});
};
handleTouchStart = (e) => {
e.preventDefault();
this.handleMouseDown();
};
render() {
return (
{({x}) =>
// children is a callback which should accept the current value of
// `style`
}
);
};
}
================================================
FILE: demos/demo0-simple-transition/index.html
================================================
Toggle
================================================
FILE: demos/demo0-simple-transition/index.jsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import Demo from './Demo';
ReactDOM.render(, document.querySelector('#content'));
================================================
FILE: demos/demo1-chat-heads/Demo.jsx
================================================
import React from 'react';
import {StaggeredMotion, spring, presets} from '../../src/react-motion';
import range from 'lodash.range';
export default class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {x: 250, y: 300};
};
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove);
window.addEventListener('touchmove', this.handleTouchMove);
};
handleMouseMove = ({pageX: x, pageY: y}) => {
this.setState({x, y});
};
handleTouchMove = ({touches}) => {
this.handleMouseMove(touches[0]);
};
getStyles = (prevStyles) => {
// `prevStyles` is the interpolated value of the last tick
const endValue = prevStyles.map((_, i) => {
return i === 0
? this.state
: {
x: spring(prevStyles[i - 1].x, presets.gentle),
y: spring(prevStyles[i - 1].y, presets.gentle),
};
});
return endValue;
};
render() {
return (
({x: 0, y: 0}))}
styles={this.getStyles}>
{balls =>