├── .babelrc
├── .eslintrc
├── .gitignore
├── .npmignore
├── README.md
├── modules
├── Bounce
│ ├── index.jsx
│ └── readme.md
├── Fade
│ ├── index.jsx
│ └── readme.md
├── Parallax
│ ├── index.jsx
│ └── readme.md
├── Plate
│ ├── index.jsx
│ └── readme.md
├── PopUp
│ ├── index.jsx
│ ├── readme.md
│ └── styles.js
└── index.js
├── package.json
├── styleguide.config.js
└── template.html
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0,
3 | "optional": ["es7.decorators"],
4 | "env": {
5 | "development": {
6 | "plugins": [
7 | "react-transform",
8 | "react-autoprefix"
9 | ],
10 | "extra": {
11 | "react-transform": {
12 | "transforms": [{
13 | "transform": "react-transform-hmr",
14 | "imports": ["react"],
15 | "locals": ["module"]
16 | }, {
17 | "transform": "react-transform-catch-errors",
18 | "imports": ["react", "redbox-react"]
19 | }]
20 | }
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | parser: "babel-eslint"
2 |
3 | extends: 'airbnb'
4 |
5 | env:
6 | browser: true
7 | node: true
8 | es6: true
9 | mocha: true
10 |
11 | rules:
12 | object-curly-spacing: [2, 'always']
13 | indent: [2, 'tab']
14 | semi: [2, 'never']
15 | jsx-quotes: [2, 'prefer-single']
16 | id-length: 0
17 |
18 | ecmaFeatures:
19 | jsx: true
20 | module: true
21 |
22 | plugins:
23 | - react
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /lib/
2 | /build/
3 | /index.html
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /build
2 | /index.html
3 | /styleguide.config.js
4 | /.eslintrc
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-motion-pack
2 | **• work in progress •**
3 |
4 | Library of React animated components
5 | [Demo](http://nitive.github.io/react-motion-pack/)
6 |
7 | ### Main idea:
8 | * Rule behaivor not appearance
9 | * As easy as possible - just wrap your block into component to get animation
10 |
11 | ### Dependences
12 | * [react](https://github.com/facebook/react)
13 | * [react-motion](https://github.com/chenglou/react-motion)
14 |
15 | ### Installation
16 | `npm install --save react-motion-pack react react-motion`
17 |
--------------------------------------------------------------------------------
/modules/Bounce/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { Motion, spring } from 'react-motion'
3 |
4 | export default class Bounce extends React.Component {
5 |
6 | static propTypes = {
7 | children: PropTypes.node.isRequired,
8 | type: PropTypes.oneOf(['in', 'out']),
9 | side: PropTypes.oneOf(['left', 'right', 'up', 'down', 'none']),
10 | offset: PropTypes.number,
11 | }
12 |
13 | static defaultProps = {
14 | type: 'in',
15 | side: 'none',
16 | offset: 0,
17 | }
18 |
19 | render() {
20 | const { type, side, offset, children } = this.props
21 |
22 | const config = {
23 | opacity: [80, 11],
24 | translate: [350, 12],
25 | scale: [300, 8],
26 | }
27 |
28 | const getContent = ({ opacity, translateX, translateY, scaleX, scaleY }) => {
29 | const style = {
30 | opacity,
31 | transform: `scale(${scaleX}, ${scaleY})translate3d(${translateX}px, ${translateY}px, 0)`,
32 | }
33 | return React.cloneElement(children, { style })
34 | }
35 |
36 | let x = side === 'left' ? -offset : 0
37 | x = side === 'right' ? offset : x
38 |
39 | let y = side === 'up' ? offset : 0
40 | y = side === 'down' ? -offset : y
41 |
42 |
43 | const hideStyle = {
44 | opacity: spring(0),
45 | translateX: spring(x),
46 | translateY: spring(y),
47 | scaleX: spring(0.8),
48 | scaleY: spring(0.8),
49 | }
50 |
51 | const showStyle = {
52 | opacity: spring(1, config.opacity),
53 | translateX: spring(0, config.translate),
54 | translateY: spring(0, config.translate),
55 | scaleX: spring(1, config.scale),
56 | scaleY: spring(1, config.scale),
57 | }
58 |
59 | return (
60 |
64 | {interpolated => getContent(interpolated)}
65 |
66 | )
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/modules/Bounce/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/modules/Fade/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { Motion, spring } from 'react-motion'
3 |
4 | export default class Fade extends React.Component {
5 |
6 | static propTypes = {
7 | children: PropTypes.node.isRequired,
8 | type: PropTypes.oneOf(['in', 'out']),
9 | side: PropTypes.oneOf(['left', 'right', 'up', 'down', 'none']),
10 | offset: PropTypes.number,
11 | }
12 |
13 | static defaultProps = {
14 | type: 'in',
15 | side: 'none',
16 | offset: 0,
17 | }
18 |
19 | render() {
20 | const { type, side, offset, children } = this.props
21 |
22 | const getContent = ({ opacity, translateX, translateY }) => {
23 | const style = {
24 | opacity,
25 | transform: `translate3d(${translateX}px, ${translateY}px, 0)`,
26 | }
27 | return React.cloneElement(children, { style })
28 | }
29 |
30 | let x = side === 'left' ? -offset : 0
31 | x = side === 'right' ? offset : x
32 |
33 | let y = side === 'up' ? offset : 0
34 | y = side === 'down' ? -offset : y
35 |
36 | const hideStyle = {
37 | opacity: spring(0),
38 | translateX: spring(x),
39 | translateY: spring(y),
40 | }
41 |
42 | const showStyle = {
43 | opacity: spring(1, [80, 11]),
44 | translateY: spring(0),
45 | translateX: spring(0),
46 | }
47 |
48 | return (
49 |
53 | { interpolated => getContent(interpolated) }
54 |
55 | )
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/modules/Fade/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/modules/Parallax/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 |
3 | export default class Parallax extends React.Component {
4 |
5 | static propTypes = {
6 | children: PropTypes.node.isRequired,
7 | scope: PropTypes.number,
8 | speed: PropTypes.number,
9 | offset: PropTypes.number,
10 | }
11 |
12 | static defaultProps = {
13 | speed: 1,
14 | scope: 100,
15 | offset: 0,
16 | }
17 |
18 |
19 | componentWillMount() {
20 | this.setState({
21 | position: this.getPosition(),
22 | })
23 | }
24 |
25 |
26 | componentDidMount() {
27 | const ref = this.refs.node
28 | const node = React.version.slice(0, 4) === '0.13' ? ref.getDOMNode() : ref
29 | this.startOffset = node.offsetTop
30 | window.addEventListener('scroll', this.scrollHandler)
31 | }
32 |
33 |
34 | componentWillUnmount() {
35 | window.removeEventListener('scroll', this.scrollHandler)
36 | }
37 |
38 | getPosition = () => {
39 | const { scope, offset, speed } = this.props
40 | const position = ((window.pageYOffset - this.startOffset) * speed)
41 | return Math.min(-Math.min(scope - offset, position), scope + offset)
42 | }
43 |
44 | scrollHandler = () => {
45 | this.setState({
46 | position: this.getPosition(),
47 | })
48 | }
49 |
50 |
51 | render() {
52 | const style = {
53 | transform: `translateY(${this.state.position}px)`,
54 | }
55 |
56 | return React.cloneElement(this.props.children, { style, ref: 'node' })
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/modules/Parallax/readme.md:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 | default
25 |
26 |
27 |
28 |
29 | offset = 200
30 |
31 |
32 |
33 |
34 | scope = 50
35 |
36 |
37 |
38 |
39 | speed = 2
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/modules/Plate/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { Motion, spring } from 'react-motion'
3 |
4 | const configs = {
5 | down: {
6 | origin: 'center top',
7 | axis: 'X',
8 | coef: -1,
9 | },
10 | up: {
11 | origin: 'center bottom',
12 | axis: 'X',
13 | coef: 1,
14 | },
15 | left: {
16 | origin: 'left center',
17 | axis: 'Y',
18 | coef: 1,
19 | },
20 | right: {
21 | origin: 'right center',
22 | axis: 'Y',
23 | coef: -1,
24 | },
25 | }
26 |
27 | export default class Plate extends React.Component {
28 |
29 | static propTypes = {
30 | children: PropTypes.node.isRequired,
31 | type: PropTypes.oneOf(['in', 'out']),
32 | side: PropTypes.oneOf(['left', 'right', 'up', 'down']),
33 | move: PropTypes.oneOf(['pull', 'push']),
34 | perspective: PropTypes.number,
35 | }
36 |
37 | static defaultProps = {
38 | type: 'in',
39 | side: 'down',
40 | move: 'pull',
41 | perspective: 300,
42 | }
43 |
44 | render() {
45 | const { type, side, move, perspective, children } = this.props
46 |
47 | const config = configs[side] || configs.down
48 |
49 | const getContent = ({ rotate }) => {
50 | const style = {
51 | backfaceVisibility: 'hidden',
52 | transformStyle: 'preserve-3d',
53 | transformOrigin: config.origin,
54 | transform: `perspective(${perspective}px)rotate${config.axis}(${rotate}deg)`,
55 | }
56 | return React.cloneElement(children, { style })
57 | }
58 |
59 | const hideStyle = {
60 | rotate: spring(120 * config.coef * (move !== 'push' ? 1 : -1)),
61 | }
62 |
63 | const showStyle = {
64 | rotate: spring(0, [80, 6]),
65 | }
66 |
67 | return (
68 |
72 | {interpolated => getContent(interpolated)}
73 |
74 | )
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/modules/Plate/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/modules/PopUp/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { Motion, spring } from 'react-motion'
3 | import { wrapper, content } from './styles'
4 |
5 |
6 | export default class PopUp extends React.Component {
7 |
8 | static propTypes = {
9 | children: PropTypes.node.isRequired,
10 | show: PropTypes.bool,
11 | position: PropTypes.oneOf(['static', 'relative', 'absolute', 'fixed']),
12 | className: PropTypes.string,
13 | style: PropTypes.object,
14 | }
15 |
16 | static defaultProps = {
17 | show: true,
18 | position: 'fixed',
19 | }
20 |
21 |
22 | render() {
23 | const {
24 | show,
25 | style,
26 | className,
27 | position,
28 | } = this.props
29 |
30 | const enterConfig = [120, 11]
31 | const leaveConfig = [300, 28]
32 |
33 | const getContent = interpolated => (
34 |
35 |
40 | {this.props.children}
41 |
42 |
43 | )
44 |
45 | return (
46 |
50 | {interpolated => getContent(interpolated)}
51 |
52 | )
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/modules/PopUp/readme.md:
--------------------------------------------------------------------------------
1 |
44 |
45 | **Basic PopUp:**
46 | Change `show` property to see animation
47 |
48 |
49 | You must specify show property to hide element with animation
50 | instead to disable rendering. Otherwise you will lose animation.
51 |
52 |
53 |
57 |
58 | Lorem ipsum dolor sit amet, consectetur adipisicing elit.
59 | Accusantium ea deleniti alias voluptatum, dolorum ullam eos dolores
60 | itaque harum adipisci maiores praesentium magni beatae officiis
61 | at accusamus facere modi vero.
62 |
63 |
64 |
65 |
66 |
67 | **Fixed PopUp (Default):**
68 | Change `show` property to unhide
69 |
70 |
73 |
74 | Sed ut perspiciatis unde omnis iste natus error sit voluptatem
75 | accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
76 | quae ab illo inventore veritatis et quasi architecto beatae vitae
77 | dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit
78 | aspernatur aut odit aut fugit, sed quia consequuntur magni dolores
79 | eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est,
80 | qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit,
81 | sed quia non numquam eius modi tempora incidunt ut labore et dolore
82 | magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis
83 | nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut
84 | aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit
85 | qui in ea voluptate velit esse quam nihil molestiae consequatur,
86 | vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
87 |
88 |
89 |
--------------------------------------------------------------------------------
/modules/PopUp/styles.js:
--------------------------------------------------------------------------------
1 | export const content = {
2 | marginRight: 'auto',
3 | marginLeft: 'auto',
4 | backgroundColor: 'initial',
5 | }
6 |
7 | export const wrapper = {
8 | display: 'flex',
9 | flexDirection: 'column',
10 | justifyContent: 'center',
11 |
12 | position: 'fixed',
13 | top: 0,
14 | left: 0,
15 | right: 0,
16 | bottom: 0,
17 | zIndex: 99999,
18 |
19 | height: '100%',
20 | backgroundColor: 'transparent',
21 | pointerEvents: 'none',
22 | }
23 |
--------------------------------------------------------------------------------
/modules/index.js:
--------------------------------------------------------------------------------
1 | export PopUp from './PopUp'
2 | export Parallax from './Parallax'
3 | export Fade from './Fade'
4 | export Bounce from './Bounce'
5 | export Plate from './Plate'
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-motion-pack",
3 | "version": "0.1.9",
4 | "description": "Library of react components with beautiful animation",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "build": "gulp",
8 | "prepublish": "npm run build",
9 | "watch": "gulp watch",
10 | "lint": "eslint modules",
11 | "test": "karma start",
12 | "server": "styleguidist server",
13 | "static": "styleguidist build",
14 | "pages": "git checkout gh-pages; git reset --hard master; npm run static; git add -f index.html build; git commit --allow-empty-message -m ''; git push origin +gh-pages; git checkout master"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/Nitive/react-motion-pack.git"
19 | },
20 | "keywords": [
21 | "react",
22 | "react-motion",
23 | "react-component",
24 | "animation"
25 | ],
26 | "author": "Maxim Samoilov ",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/Nitive/react-motion-pack/issues"
30 | },
31 | "homepage": "https://github.com/Nitive/react-motion-pack#readme",
32 | "peerDependencies": {
33 | "react": ">=0.13.0",
34 | "react-motion": "^0.3.1"
35 | },
36 | "devDependencies": {
37 | "babel": "^5.8.23",
38 | "babel-eslint": "^4.1.3",
39 | "eslint": "^1.7.1",
40 | "eslint-config-airbnb": "^0.1.0",
41 | "eslint-plugin-react": "^3.6.0",
42 | "gulp": "^3.9.0",
43 | "gulp-babel": "^5.3.0",
44 | "gulp-watch": "^4.3.5",
45 | "mocha": "^2.3.3",
46 | "react": "^0.13.3",
47 | "react-motion": "^0.3.1",
48 | "react-styleguidist": "^0.2.1",
49 | "webpack": "^1.12.2"
50 | },
51 | "dependencies": {
52 | "babel-plugin-react-autoprefix": "^0.2.6"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/styleguide.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: 'React Motion Pack',
3 | rootDir: './modules',
4 | components: './**/*.jsx',
5 | styleguideDir: '.',
6 | serverPort: 3589,
7 | template: './template.html',
8 | }
9 |
--------------------------------------------------------------------------------
/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {%=o.htmlWebpackPlugin.options.title%}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------