├── .babelrc
├── src
├── index.js
├── native.js
└── components.js
├── examples
└── demos
│ ├── index.js
│ ├── index.html
│ ├── app.js
│ └── reset.css
├── .eslintrc
├── .gitignore
├── server.js
├── lib
├── index.js
├── native.js
└── components.js
├── package.json
├── webpack.config.js
└── README.md
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import components from './components';
3 |
4 | module.exports = components(React);
5 |
--------------------------------------------------------------------------------
/src/native.js:
--------------------------------------------------------------------------------
1 | import React from 'react-native';
2 | import components from './components';
3 |
4 | module.exports = components(React);
5 |
--------------------------------------------------------------------------------
/examples/demos/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {App} from './app';
3 | React.render(, document.getElementById('container'));
4 | window.React = React;
5 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "rules" :{
4 | "quotes": [1, "single"],
5 | "no-unused-vars": [1, {"vars": "all", "args": "all"}],
6 | "strict": true
7 | },
8 | "env":{
9 | "browser": true,
10 | "node" : true
11 | }
12 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # osx noise
2 | .DS_Store
3 | profile
4 |
5 | # xcode noise
6 | build/*
7 | *.mode1
8 | *.mode1v3
9 | *.mode2v3
10 | *.perspective
11 | *.perspectivev3
12 | *.pbxuser
13 | *.xcworkspace
14 | xcuserdata
15 |
16 | # svn & cvs
17 | .svn
18 | CVS
19 | node_modules
20 |
--------------------------------------------------------------------------------
/examples/demos/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | react-springs
5 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | import WebpackDevServer from 'webpack-dev-server';
3 | import config from './webpack.config';
4 |
5 | const isHot = !!process.env.HOT;
6 |
7 | new WebpackDevServer(webpack(config), {
8 | publicPath: config.output.publicPath,
9 | hot: isHot,
10 | historyApiFallback: true
11 | }).listen(3000, 'localhost', err => console.log(err || 'webpack at localhost:3000'));
12 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _react = require('react');
6 |
7 | var _react2 = _interopRequireDefault(_react);
8 |
9 | var _components = require('./components');
10 |
11 | var _components2 = _interopRequireDefault(_components);
12 |
13 | module.exports = (0, _components2['default'])(_react2['default']);
--------------------------------------------------------------------------------
/lib/native.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _reactNative = require('react-native');
6 |
7 | var _reactNative2 = _interopRequireDefault(_reactNative);
8 |
9 | var _components = require('./components');
10 |
11 | var _components2 = _interopRequireDefault(_components);
12 |
13 | module.exports = (0, _components2['default'])(_reactNative2['default']);
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-springs",
3 | "version": "1.1.0",
4 | "description": "ooh lookit the wow",
5 | "main": "./lib/index.js",
6 | "scripts": {
7 | "test": "mocha",
8 | "build": "rm -rf lib && babel src -d lib",
9 | "start": "HOT=1 babel-node server.js",
10 | "dev": "babel-node server.js"
11 | },
12 | "keywords": [
13 | "animation",
14 | "react",
15 | "rebound",
16 | "spring"
17 | ],
18 | "author": "Sunil Pai",
19 | "license": "ISC",
20 | "devDependencies": {
21 | "babel": "^5.5.4",
22 | "babel-core": "^5.5.4",
23 | "babel-eslint": "^3.1.15",
24 | "babel-loader": "^5.1.4",
25 | "eslint": "^0.22.1",
26 | "eslint-plugin-react": "^2.5.0",
27 | "node-libs-browser": "^0.5.2",
28 | "react": "^0.13.3",
29 | "react-hot-loader": "^1.2.7",
30 | "rebound": "0.0.13",
31 | "webpack": "^1.9.10",
32 | "webpack-dev-server": "^1.9.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | // import path from 'path';
3 |
4 | let config = {
5 | devtool: 'source-map',
6 | target: 'web',
7 | entry: {
8 | demos: ['./examples/demos/index.js']
9 | },
10 | output: {
11 | path: __dirname,
12 | filename: 'examples/[name]/bundle.js',
13 | publicPath: '/'
14 | },
15 | module: {
16 | loaders: [{
17 | test: /\.js$/,
18 | exclude: /node_modules/,
19 | loaders: ['babel-loader']
20 | }]
21 | },
22 | resolve: {
23 | extensions: ['', '.js', '.jsx']
24 | },
25 | plugins: [new webpack.DefinePlugin({
26 | 'process.env': {
27 | 'NODE_ENV': `"${process.env.NODE_ENV || 'development'}"`
28 | }
29 | })],
30 | externals: ['react-native']
31 | };
32 |
33 | if(process.env.HOT){
34 | config = {
35 | ...config,
36 | devtool: 'eval-source-map',
37 | entry: Object.keys(config.entry).reduce((o, key) => ({...o, [key]: [
38 | 'webpack-dev-server/client?http://localhost:3000', // WebpackDevServer host and port
39 | 'webpack/hot/only-dev-server'
40 | ].concat(config.entry[key])}), {}),
41 | module: {...config.module,
42 | loaders: [{
43 | ...config.module.loaders[0],
44 | loaders: [
45 | 'react-hot'
46 | ].concat(config.module.loaders[0].loaders)
47 | }]
48 | },
49 | plugins: [
50 | new webpack.HotModuleReplacementPlugin(),
51 | new webpack.NoErrorsPlugin()
52 | ].concat(config.plugins)
53 | };
54 | }
55 |
56 | module.exports = config;
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | react-springs
2 | ---
3 |
4 | (bring your family and friends)
5 |
6 | `npm install react-springs react rebound --save`
7 |
8 | Dynamic animations for [react](https://facebook.github.io/react/)/[react-native](https://facebook.github.io/react-native/), powered by [rebound](https://github.com/facebook/rebound-js).
9 |
10 | (if you're looking for something more conventional, consider [react-ease](https://github.com/threepointone/react-ease))
11 |
12 | ```js
13 | // output floats gradually from 0 to 10
14 |
15 | {val => {val}
} // yes, children is a function.
16 |
17 |
18 | // you can compose multiple springs
19 |
20 | {val => }
21 |
22 |
23 | // alternately, if you want control on each spring
24 | {x =>
25 | {y =>
26 | }
27 | }
28 |
29 |
30 | // and if you'd rather not use the child-function pattern
31 |
32 |
this.setState({ value: spring.getCurrentValue() })} />
33 | moving box
34 |
35 | ```
36 |
37 | props
38 | ---
39 |
40 | - to (Spring): *number* : sets end value for the spring. if `atRest` is `true`, then the spring immediately snaps to `to`.
41 | - to (Springs): *obj* : similar to `Spring`, but accepts a map of key-values.
42 | - from: *number* : sets start value for a spring. changing it while a spring is in motion will set its current value to `from`, and continue to `to`
43 | - atRest: *boolean*
44 | - friction: *number*
45 | - tension: *number*
46 | - overshootClamping: *boolean*
47 | - onSpringUpdate (Spring): *function* : optional callback to be notified on every spring movement. 'returns' the spring.
48 | - onSpringUpdate (Springs): *function* : like `Spring`, but 'returns' `key, spring`
49 | - springSystem: *SpringSystem* : optional instance of rebound's SpringSystem. useful for perf/custom loopers/etc.
50 |
51 | dev
52 | ---
53 |
54 | `npm install`
55 |
56 | `npm start`
57 |
58 | notes
59 | ---
60 |
61 | - don't forget about the ridiculous performance boost you get from React when NODE_ENV=production
62 | - open to ideas on how to set 'velocity' for flings, etc
--------------------------------------------------------------------------------
/src/components.js:
--------------------------------------------------------------------------------
1 | // springs, all that
2 | import rebound from 'rebound';
3 |
4 | const noop = () => {}; // default onSpringUpdate
5 |
6 | const setters = {
7 | friction(spring, props){
8 | spring.getSpringConfig().friction =
9 | rebound.OrigamiValueConverter.frictionFromOrigamiValue(props.friction);
10 | },
11 | tension(spring, props){
12 | spring.getSpringConfig().tension =
13 | rebound.OrigamiValueConverter.frictionFromOrigamiValue(props.tension);
14 | },
15 | // from(spring, props){
16 | // spring.setCurrentValue(props.from, true).setEndValue(spring.getEndValue());
17 | // },
18 | overShootClamping(spring, props){
19 | spring.setOvershootClampingEnabled(props.overShootClamping);
20 | },
21 | to(spring, props){
22 | if(props.atRest){
23 | spring.setCurrentValue(props.to).setAtRest();
24 | }
25 | else{
26 | spring.setEndValue(props.to);
27 | }
28 | }
29 | };
30 |
31 | export default function components(React){
32 | class Spring extends React.Component{
33 | static defaultProps = {
34 | // we use a common 'global' springSystem for perf, but you can pass in your own
35 | springSystem: new rebound.SpringSystem(),
36 |
37 | // from and to are analogous to setCurrentValue() and setEndValue()
38 | from: 0,
39 | to: 0,
40 |
41 | // more rebound options
42 | tension: 50,
43 | friction: 3,
44 | overShootClamping: false,
45 | atRest: false,
46 | onSpringUpdate: noop,
47 | children: () => null
48 |
49 | // todo - velocity?
50 | }
51 |
52 | static propTypes = {
53 | from: React.PropTypes.number,
54 | friction: React.PropTypes.number,
55 | tension: React.PropTypes.number,
56 | to: React.PropTypes.number,
57 | atRest: React.PropTypes.bool,
58 | overShootClamping: React.PropTypes.bool,
59 | children: React.PropTypes.func,
60 | onSpringUpdate: React.PropTypes.func
61 | }
62 |
63 | accept(props, initial){
64 | Object.keys(props).forEach(k => {
65 | if(setters[k] && (initial || (props[k] !== this.props[k]))){
66 | setters[k](this.spring, props);
67 | }
68 | });
69 | }
70 |
71 | state = {
72 | value: this.props.from
73 | }
74 |
75 | shouldComponentUpdate(){
76 | return true;
77 | // components with 'render callbacks' can/should render 'through'.
78 | }
79 |
80 | componentWillMount() {
81 | // create the spring on mounting.
82 | this.spring = this.props.springSystem.createSpring(this.props.tension, this.props.friction);
83 |
84 | this.spring.addListener({
85 | onSpringUpdate: () => {
86 | this.setState({ value: this.spring.getCurrentValue() });
87 | this.props.onSpringUpdate(this.spring);
88 | }
89 | });
90 |
91 | this.spring.setCurrentValue(this.props.from, true);
92 |
93 | this.accept(this.props, true);
94 | }
95 |
96 | componentWillReceiveProps(nextProps) {
97 | this.accept(nextProps, false);
98 | }
99 |
100 | componentWillUnmount() {
101 | // ...and destroy on onmounting
102 | this.spring.destroy();
103 | delete this.spring;
104 | }
105 |
106 | render(){
107 | return this.props.children(this.state.value, this.spring);
108 | }
109 | }
110 |
111 | /////////////////////////////////////////
112 |
113 | class Springs extends React.Component{
114 | static defaultProps = {
115 | onSpringUpdate: noop,
116 | children: () => null
117 | }
118 |
119 | static propTypes: {
120 | onSpringUpdate: React.PropTypes.func,
121 | children: React.PropTypes.func
122 | }
123 |
124 | shouldComponentUpdate(){
125 | return true;
126 | // like above
127 | }
128 | onSpringUpdate(key, spring){
129 | this.setState({
130 | [key]: spring.getCurrentValue()
131 | });
132 | this.props.onSpringUpdate(key, spring);
133 | }
134 |
135 | to(pos, keys, index, value, springs){
136 | if(index === -1){
137 | return this.props.children(value, springs);
138 | }
139 | const key = keys[index];
140 | return this.onSpringUpdate(key, spring)}>
141 | {(val, spring) => this.to(pos, keys, index - 1, (value[key] = val, value), (springs[key] = spring, springs))}
142 | ;
143 | }
144 |
145 | // todo - sort keys alphabetically?
146 | render() {
147 | // what we do here, is break `to` into key value pairs, and then return a nest of s
148 | // React takes care of the boring bits (caching, state, etc)
149 | const {to} = this.props, keys = Object.keys(to);
150 | return this.to(to, keys, keys.length - 1, {}, {});
151 | }
152 | }
153 |
154 | return {Spring, Springs};
155 | }
156 |
157 |
--------------------------------------------------------------------------------
/examples/demos/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Spring, Springs} from '../../src';
3 | import rebound from 'rebound';
4 |
5 | function times (n, fn){
6 | var arr = [];
7 | for(var i = 0; i < n; i++){ arr.push(fn(i)); }
8 | return arr;
9 | }
10 |
11 | let styles = {};
12 |
13 | styles.slideshow = {
14 | wrap: { width: 400, height: 400, outline: '1px solid #ccc' },
15 | bar: { flexDirection: 'row', height: 60, position: 'absolute' },
16 | slide: { flex: 1, fontSize: 200, alignItems: 'center', justifyContent: 'center' },
17 | thumb: { justifyContent: 'center', alignItems: 'center', flex: 1, cursor: 'pointer' }
18 | };
19 |
20 |
21 | // ICK
22 | var win; let winset = () => (win = { width: document.body.offsetWidth }); window.addEventListener('resize', winset); window.addEventListener('load', winset); winset();
23 | // END ICK
24 |
25 | export const Slideshow = React.createClass({
26 | getInitialState() {
27 | return {
28 | x: 0, y: 0, hover: -1, active: 0, opacity: 0, selected: 1
29 | };
30 | },
31 | getDefaultProps(){
32 | return {n: 100};
33 | },
34 | convert(x, y){
35 | return Slideshow.convert(this.props.n * 60, 400, 60, 400, x, y);
36 | },
37 |
38 | render() {
39 | return (
40 | this.setState({x: e.pageX - ((win.width - 400) / 2), y: e.pageY - ((this.props.pos * 420) + 20)})}
42 | onMouseEnter={() => this.setState({opacity: 1})}
43 | onMouseLeave={() => this.setState({opacity: 0})}>
44 |
{bg =>
45 |
46 | {this.state.active}
47 |
}
48 |
49 |
{val =>
50 | this.setState({hover: -1})}>
51 | {times(this.props.n, i =>
52 |
{ bg =>
53 | this.setState({hover: i})}
55 | onClick={()=> this.setState({active: i, selected: (Math.random() / 100)})}>
56 | {i}
57 |
58 | }
59 | )}
60 |
61 | }
62 |
63 | );
64 | },
65 | statics: {
66 | convert(W, w, H, h, x, y){
67 | return {
68 | left: -1 * ((W - w) / w) * x, // < - memoization target
69 | top: (h - H) + (((H - h) / h) * y) // < - memoization target
70 | };
71 | }
72 | }
73 | });
74 |
75 | styles.followers = {
76 | wrap: { width: 400, height: 400, outline: '1px solid #ccc', marginTop: 20 },
77 | box: { width: 20, height: 20, position: 'absolute', borderRadius: 10 },
78 | blue: { backgroundColor: 'blue' },
79 | red: { backgroundColor: 'red' }
80 | };
81 |
82 | export const Followers = React.createClass({
83 | getInitialState() {
84 | return {
85 | x: 0, y: 0
86 | };
87 | },
88 | onMouseMove(e){
89 | this.setState({x: Math.min(400, Math.max(0, e.pageX - ((win.width - 400) / 2))), y: Math.min(400, Math.max(0, e.pageY - ((this.props.pos * 420) + 20)))});
90 | },
91 | render() {
92 | return
93 |
94 | {vals => }
95 |
96 |
97 |
{x =>
98 | {y =>
99 | }
100 | }
101 |
102 |
;
103 | }
104 | });
105 |
106 | styles.unlock = {
107 | wrap: { width: 400, height: 400, outline: '1px solid #ccc', marginTop: 20, justifyContent: 'center' },
108 | lockscreen: { width: 200, height: 50, backgroundColor: '#ccc', position: 'absolute', top: '50%', marginTop: -25, left: '50%',
109 | marginLeft: -100, justifyContent: 'center', alignItems: 'center', borderRadius: 30 },
110 | key: { width: 50, height: 50, position: 'absolute', top: 0, backgroundColor: '#fff', cursor: 'pointer', alignItems: 'center',
111 | justifyContent: 'center', borderRadius: 30, boxShadow: '2px 2px 10px #aaa' },
112 | main: { backgroundColor: 'black', justifyContent: 'center', alignItems: 'center', color: 'white', flex: 1 },
113 | lock: { cursor: 'pointer' },
114 | noSelect: { 'WebkitTouchCallout': 'none', 'WebkitUserSelect': 'none', 'KhtmlUserSelect': 'none',
115 | 'MozUserSelect': 'none', 'MsUserSelect': 'none', 'UserSelect': 'none' }
116 | };
117 |
118 | export const SlideToUnlock = React.createClass({
119 | getInitialState() {
120 | return {
121 | x: 0,
122 | unlocking: false,
123 | opacity: 0,
124 | delta: 0
125 |
126 | };
127 | },
128 | onMouseMove(e){
129 | this.setState({x: this.state.unlocking ? Math.min(200, Math.max(0, e.pageX - ((win.width - 200) / 2))) : this.state.x});
130 | },
131 | onKeyMouseDown(e){
132 | let x = Math.min(200, Math.max(0, e.pageX - ((win.width - 200) / 2))) - document.getElementById('keyElement').offsetLeft;
133 | this.setState({
134 | unlocking: true,
135 | x: x,
136 | delta: x
137 | });
138 | },
139 | onMouseUp(){
140 | this.setState({
141 | unlocking: false,
142 | opacity: this.state.x > 190 ? 1 : 0,
143 | ...(this.state.x > 190 ? {} : {x: 0, delta: 0})
144 | });
145 | },
146 | render() {
147 | return { val =>
148 |
149 |
150 | slide
151 |
>
152 |
153 |
154 |
this.setState({opacity: 0, x: 0, delta: 0})}>
155 | click
156 |
157 |
158 |
159 | };
160 |
161 | }
162 | });
163 |
164 |
165 | styles.root = { alignItems: 'center', paddingTop: 20, paddingBottom: 20 };
166 |
167 | export const App = React.createClass({
168 | render() {
169 | return
170 |
171 |
172 |
173 |
;
174 | }
175 | });
176 |
--------------------------------------------------------------------------------
/lib/components.js:
--------------------------------------------------------------------------------
1 | // springs, all that
2 | 'use strict';
3 |
4 | Object.defineProperty(exports, '__esModule', {
5 | value: true
6 | });
7 |
8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
9 |
10 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
11 |
12 | exports['default'] = components;
13 |
14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
15 |
16 | function _defineProperty(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); }
17 |
18 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
19 |
20 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
21 |
22 | var _rebound = require('rebound');
23 |
24 | var _rebound2 = _interopRequireDefault(_rebound);
25 |
26 | var noop = function noop() {}; // default onSpringUpdate
27 |
28 | var setters = {
29 | friction: function friction(spring, props) {
30 | spring.getSpringConfig().friction = _rebound2['default'].OrigamiValueConverter.frictionFromOrigamiValue(props.friction);
31 | },
32 | tension: function tension(spring, props) {
33 | spring.getSpringConfig().tension = _rebound2['default'].OrigamiValueConverter.frictionFromOrigamiValue(props.tension);
34 | },
35 | // from(spring, props){
36 | // spring.setCurrentValue(props.from, true).setEndValue(spring.getEndValue());
37 | // },
38 | overShootClamping: function overShootClamping(spring, props) {
39 | spring.setOvershootClampingEnabled(props.overShootClamping);
40 | },
41 | to: function to(spring, props) {
42 | if (props.atRest) {
43 | spring.setCurrentValue(props.to).setAtRest();
44 | } else {
45 | spring.setEndValue(props.to);
46 | }
47 | }
48 | };
49 |
50 | function components(React) {
51 | var Spring = (function (_React$Component) {
52 | function Spring() {
53 | _classCallCheck(this, Spring);
54 |
55 | if (_React$Component != null) {
56 | _React$Component.apply(this, arguments);
57 | }
58 |
59 | this.state = {
60 | value: this.props.from
61 | };
62 | }
63 |
64 | _inherits(Spring, _React$Component);
65 |
66 | _createClass(Spring, [{
67 | key: 'accept',
68 | value: function accept(props, initial) {
69 | var _this = this;
70 |
71 | Object.keys(props).forEach(function (k) {
72 | if (setters[k] && (initial || props[k] !== _this.props[k])) {
73 | setters[k](_this.spring, props);
74 | }
75 | });
76 | }
77 | }, {
78 | key: 'shouldComponentUpdate',
79 | value: function shouldComponentUpdate() {
80 | return true;
81 | // components with 'render callbacks' can/should render 'through'.
82 | }
83 | }, {
84 | key: 'componentWillMount',
85 | value: function componentWillMount() {
86 | var _this2 = this;
87 |
88 | // create the spring on mounting.
89 | this.spring = this.props.springSystem.createSpring(this.props.tension, this.props.friction).addListener({
90 | onSpringUpdate: function onSpringUpdate() {
91 | _this2.setState({ value: _this2.spring.getCurrentValue() });
92 | _this2.props.onSpringUpdate(_this2.spring);
93 | }
94 | }).setCurrentValue(this.props.from, true);
95 |
96 | this.accept(this.props, true);
97 | }
98 | }, {
99 | key: 'componentWillReceiveProps',
100 | value: function componentWillReceiveProps(nextProps) {
101 | this.accept(nextProps, false);
102 | }
103 | }, {
104 | key: 'componentWillUnmount',
105 | value: function componentWillUnmount() {
106 | // ...and destroy on onmounting
107 | this.spring.destroy();
108 | delete this.spring;
109 | }
110 | }, {
111 | key: 'render',
112 | value: function render() {
113 | return this.props.children(this.state.value, this.spring);
114 | }
115 | }], [{
116 | key: 'defaultProps',
117 | value: {
118 | // we use a common 'global' springSystem for perf, but you can pass in your own
119 | springSystem: new _rebound2['default'].SpringSystem(),
120 |
121 | // from and to are analogous to setCurrentValue() and setEndValue()
122 | from: 0,
123 | to: 0,
124 |
125 | // more rebound options
126 | tension: 50,
127 | friction: 3,
128 | overShootClamping: false,
129 | atRest: false,
130 | onSpringUpdate: noop,
131 | children: function children() {
132 | return null
133 |
134 | // todo - velocity?
135 | ;
136 | } },
137 | enumerable: true
138 | }, {
139 | key: 'propTypes',
140 | value: {
141 | from: React.PropTypes.number,
142 | friction: React.PropTypes.number,
143 | tension: React.PropTypes.number,
144 | to: React.PropTypes.number,
145 | atRest: React.PropTypes.bool,
146 | overShootClamping: React.PropTypes.bool,
147 | children: React.PropTypes.func,
148 | onSpringUpdate: React.PropTypes.func
149 | },
150 | enumerable: true
151 | }]);
152 |
153 | return Spring;
154 | })(React.Component);
155 |
156 | var Springs = (function (_React$Component2) {
157 | function Springs() {
158 | _classCallCheck(this, Springs);
159 |
160 | if (_React$Component2 != null) {
161 | _React$Component2.apply(this, arguments);
162 | }
163 | }
164 |
165 | _inherits(Springs, _React$Component2);
166 |
167 | _createClass(Springs, [{
168 | key: 'shouldComponentUpdate',
169 | value: function shouldComponentUpdate() {
170 | return true;
171 | // like above
172 | }
173 | }, {
174 | key: 'onSpringUpdate',
175 | value: function onSpringUpdate(key, spring) {
176 | this.setState(_defineProperty({}, key, spring.getCurrentValue()));
177 | this.props.onSpringUpdate(key, spring);
178 | }
179 | }, {
180 | key: 'to',
181 | value: function to(pos, keys, index, value, springs) {
182 | var _this3 = this;
183 |
184 | if (index === -1) {
185 | return this.props.children(value, springs);
186 | }
187 | var key = keys[index];
188 | return React.createElement(
189 | Spring,
190 | _extends({}, this.props, { key: key, to: pos[key], onSpringUpdate: function (spring) {
191 | return _this3.onSpringUpdate(key, spring);
192 | } }),
193 | function (val, spring) {
194 | return _this3.to(pos, keys, index - 1, (value[key] = val, value), (springs[key] = spring, springs));
195 | }
196 | );
197 | }
198 | }, {
199 | key: 'render',
200 |
201 | // todo - sort keys alphabetically?
202 | value: function render() {
203 | // what we do here, is break `to` into key value pairs, and then return a nest of s
204 | // React takes care of the boring bits (caching, state, etc)
205 | var to = this.props.to;var keys = Object.keys(to);
206 | return this.to(to, keys, keys.length - 1, {}, {});
207 | }
208 | }], [{
209 | key: 'defaultProps',
210 | value: {
211 | onSpringUpdate: noop,
212 | children: function children() {
213 | return null;
214 | }
215 | },
216 | enumerable: true
217 | }]);
218 |
219 | return Springs;
220 | })(React.Component);
221 |
222 | return { Spring: Spring, Springs: Springs };
223 | }
224 |
225 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/examples/demos/reset.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.1 | MIT License | git.io/normalize */
2 |
3 | // * 1. Set default font family to sans-serif.
4 | // * 2. Prevent iOS text size adjust after orientation change, without disabling user zoom.
5 | html {
6 | font-family: sans-serif;
7 | -ms-text-size-adjust: 100%;
8 | -webkit-text-size-adjust: 100%;
9 | }
10 |
11 | // Remove default margin.
12 | body { margin: 0 }
13 |
14 | // HTML5 display definitions ==========================================================================
15 | // * Correct `block` display not defined for any HTML5 element in IE 8/9.
16 | // * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
17 | // * Correct `block` display not defined for `main` in IE 11.
18 | article,
19 | aside,
20 | details,
21 | figcaption,
22 | figure,
23 | footer,
24 | header,
25 | hgroup,
26 | main,
27 | nav,
28 | section,
29 | summary {
30 | display: block;
31 | }
32 |
33 | // * 1. Correct `inline-block` display not defined in IE 8/9.
34 | // * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
35 | audio,
36 | canvas,
37 | progress,
38 | video {
39 | display: inline-block;
40 | vertical-align: baseline;
41 | }
42 |
43 | // * Prevent modern browsers from displaying `audio` without controls.
44 | // * Remove excess height in iOS 5 devices.
45 | audio:not([controls]) {
46 | display: none;
47 | height: 0;
48 | }
49 |
50 | // * Address `[hidden]` styling not present in IE 8/9/10.
51 | // * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
52 | [hidden],
53 | template {
54 | display: none;
55 | }
56 |
57 | // Links ==========================================================================
58 | // * Remove the gray background color from active links in IE 10.
59 | a {
60 | background: transparent;
61 | // * Improve readability when focused and also mouse hovered in all browsers.
62 | &:active,
63 | &:hover {
64 | outline: 0;
65 | }
66 | }
67 |
68 | // Text-level semantics ==========================================================================
69 |
70 | // * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
71 | abbr[title] { border-bottom: 1px dotted; }
72 |
73 | // * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
74 | b,
75 | strong {
76 | font-weight: bold;
77 | }
78 |
79 | // * Address styling not present in Safari and Chrome.
80 | dfn { font-style: italic; }
81 |
82 | // * Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari, and Chrome.
83 | h1 {
84 | font-size: 2em;
85 | margin: 0.67em 0;
86 | }
87 |
88 | // * Address styling not present in IE 8/9.
89 | mark {
90 | background: #ff0;
91 | color: #000;
92 | }
93 |
94 | // * Address inconsistent and variable font size in all browsers.
95 | small { font-size: 80%; }
96 |
97 | // * Prevent `sub` and `sup` affecting `line-height` in all browsers.
98 | sub,
99 | sup {
100 | font-size: 75%;
101 | line-height: 0;
102 | position: relative;
103 | vertical-align: baseline;
104 | }
105 |
106 | sup { top: -0.5em; }
107 | sub { bottom: -0.25em; }
108 |
109 | // Embedded content ==========================================================================
110 | // * Remove border when inside `a` element in IE 8/9/10.
111 | img { border: 0; }
112 |
113 | // * Correct overflow not hidden in IE 9/10/11.
114 | svg:not(:root) { overflow: hidden; }
115 |
116 | // Grouping content ==========================================================================
117 | // * Address margin not present in IE 8/9 and Safari.
118 | figure { margin: 1em 40px; }
119 |
120 | // * Address differences between Firefox and other browsers.
121 | hr {
122 | -moz-box-sizing: content-box;
123 | box-sizing: content-box;
124 | height: 0;
125 | }
126 |
127 | // * Contain overflow in all browsers.
128 | pre { overflow: auto; }
129 |
130 | // * Address odd `em`-unit font size rendering in all browsers.
131 | code,
132 | kbd,
133 | pre,
134 | samp {
135 | font-family: monospace, monospace;
136 | font-size: 1em;
137 | }
138 |
139 | // Forms ==========================================================================
140 | // * Known limitation: by default, Chrome and Safari on OS X allow very limited
141 | // * styling of `select`, unless a `border` property is set.
142 |
143 | // * 1. Correct color not being inherited.
144 | // * Known issue: affects color of disabled elements.
145 | // * 2. Correct font properties not being inherited.
146 | // * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
147 | button,
148 | input,
149 | optgroup,
150 | select,
151 | textarea {
152 | color: inherit;
153 | font: inherit;
154 | margin: 0;
155 | }
156 |
157 | // * Address `overflow` set to `hidden` in IE 8/9/10/11.
158 | button { overflow: visible;}
159 |
160 | // * Address inconsistent `text-transform` inheritance for `button` and `select`.
161 | // * All other form control elements do not inherit `text-transform` values.
162 | // * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
163 | // * Correct `select` style inheritance in Firefox.
164 | button,
165 | select {
166 | text-transform: none;
167 | }
168 |
169 | // * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls.
170 | // * 2. Correct inability to style clickable `input` types in iOS.
171 | // * 3. Improve usability and consistency of cursor style between image-type `input` and others.
172 | button,
173 | html input[type="button"] {
174 | -webkit-appearance: button;
175 | cursor: pointer;
176 | }
177 |
178 | // * Re-set default cursor for disabled elements.
179 | button[disabled],
180 | html input[disabled] {
181 | cursor: default;
182 | }
183 |
184 | // * Remove inner padding and border in Firefox 4+.
185 | button
186 | input {
187 | &::-moz-focus-inner {
188 | border: 0;
189 | padding: 0;
190 | }
191 | }
192 |
193 | // * Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet.
194 | input {
195 | line-height: normal;
196 | &[type="reset"],
197 | &[type="submit"] {
198 | -webkit-appearance: button;
199 | cursor: pointer;
200 | }
201 |
202 | // * It's recommended that you don't attempt to style these elements.
203 | // * Firefox's implementation doesn't respect box-sizing, padding, or width.
204 | // * 1. Address box sizing set to `content-box` in IE 8/9/10.
205 | // * 2. Remove excess padding in IE 8/9/10.
206 | &[type="checkbox"],
207 | &[type="radio"] {
208 | box-sizing: border-box;
209 | padding: 0;
210 | }
211 |
212 | // * Fix the cursor style for Chrome's increment/decrement buttons. For certain
213 | // * `font-size` values of the `input`, it causes the cursor style of the
214 | // * decrement button to change from `default` to `text`.
215 | &[type="number"] {
216 | &::-webkit-inner-spin-button,
217 | &::-webkit-outer-spin-button {
218 | height: auto;
219 | }
220 | }
221 |
222 | // * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
223 | // * 2. Address `box-sizing` set to `border-box` in Safari and Chrome (include `-moz` to future-proof).
224 | &[type="search"] {
225 | -webkit-appearance: textfield;
226 | -moz-box-sizing: content-box;
227 | -webkit-box-sizing: content-box;
228 | box-sizing: content-box;
229 |
230 | // * Remove inner padding and search cancel button in Safari and Chrome on OS X.
231 | // * Safari (but not Chrome) clips the cancel button when the search input has
232 | // * padding (and `textfield` appearance).
233 | &::-webkit-search-cancel-button,
234 | &::-webkit-search-decoration {
235 | -webkit-appearance: none;
236 | }
237 | }
238 |
239 | }
240 |
241 | // * Define consistent border, margin, and padding.
242 | fieldset {
243 | border: 1px solid #c0c0c0;
244 | margin: 0 2px;
245 | padding: 0.35em 0.625em 0.75em;
246 | }
247 |
248 | // * 1. Correct `color` not being inherited in IE 8/9/10/11.
249 | // * 2. Remove padding so people aren't caught out if they zero out fieldsets.
250 | legend {
251 | border: 0;
252 | padding: 0;
253 | }
254 |
255 | // * Remove default vertical scrollbar in IE 8/9/10/11.
256 | textarea { overflow: auto; }
257 |
258 | // * Don't inherit the `font-weight` (applied by a rule above).
259 | // * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
260 | optgroup { font-weight: bold; }
261 |
262 | // Tables ==========================================================================
263 | // * Remove most spacing between table cells.
264 | table {
265 | border-collapse: collapse;
266 | border-spacing: 0;
267 | }
268 |
269 | td,
270 | th {
271 | padding: 0;
272 | }
273 |
274 | body{
275 | font-family:helvetica, sans-serif;
276 | }
277 |
278 |
279 | html, body{
280 | position:relative;
281 | display:block;
282 | height:100%;
283 | width:100%;
284 | padding:0;
285 | margin:0;
286 | }
287 |
288 | /* css-layout defaults */
289 | div, span, html, body{
290 | box-sizing: border-box;
291 | position: relative;
292 |
293 | display: flex;
294 | flex-direction: column;
295 | align-items: stretch;
296 | flex-shrink: 0;
297 |
298 | border: 0 solid black;
299 | margin: 0;
300 | padding: 0;
301 | }
302 |
303 | /* stretch out container */
304 | #container{
305 | flex:1;
306 | }
--------------------------------------------------------------------------------