Skip to content

Commit 1009f35

Browse files
committed
initial commit
0 parents  commit 1009f35

File tree

11 files changed

+297
-0
lines changed

11 files changed

+297
-0
lines changed

.eslintrc.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": ["standard", "standard-react"],
3+
"parser": "babel-eslint",
4+
"plugins": ["react"],
5+
"rules": {
6+
"yoda": 0,
7+
"semi": [2, "always"],
8+
"no-extra-semi": 2,
9+
"semi-spacing": [2, { "before": false, "after": true }],
10+
"no-shadow": [2, {"builtinGlobals": true, "hoist": "functions"}]
11+
}
12+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
build

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This is a dummy Makefile.
2+
# For cross-platform support, we use Gulp instead.
3+
# See:
4+
# - List: $ npm run gulp help
5+
# - Edit: $ vi gulpfile.js
6+
# - Docs: https://github.com/gulpjs/gulp
7+
8+
all:
9+
@npm run gulp
10+
11+
test:
12+
@npm test
13+
14+
.PHONY: test

Readme.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# React Keyframes
2+
3+
## Credits
4+
5+
- Copyright © 2016 Zeit, Inc and project authors.
6+
- Licensed under MIT.
7+
-

gulpfile.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const gulp = require('gulp');
2+
const del = require('del');
3+
const babel = require('gulp-babel');
4+
const eslint = require('gulp-eslint');
5+
const help = require('gulp-task-listing');
6+
7+
gulp.task('help', help);
8+
9+
gulp.task('compile', function () {
10+
return gulp.src('lib/**/*.js')
11+
.pipe(babel({
12+
presets: [
13+
'es2015',
14+
'react'
15+
],
16+
plugins: [
17+
'syntax-async-functions',
18+
'transform-async-to-generator',
19+
'transform-runtime'
20+
]
21+
}))
22+
.pipe(gulp.dest('build/lib'));
23+
});
24+
25+
gulp.task('lint', function () {
26+
return gulp.src([
27+
'gulpfile.js',
28+
'test/*.js',
29+
'lib/**/*.js'
30+
])
31+
.pipe(eslint())
32+
.pipe(eslint.format())
33+
.pipe(eslint.failAfterError());
34+
});
35+
36+
gulp.task('clean', function () {
37+
return del(['build']);
38+
});
39+
40+
gulp.task('default', ['lint', 'compile']);

lib/frame.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React, { PropTypes } from 'react';
2+
3+
export default class Frame extends React.Component {
4+
componentDidMount () {
5+
this.props.onRender();
6+
}
7+
8+
componentDidUpdate () {
9+
this.props.onRender();
10+
}
11+
12+
render () {
13+
const { component } = this.props;
14+
return React.createElement(component, null, this.props.children);
15+
}
16+
}
17+
18+
Frame.propTypes = {
19+
children: PropTypes.element.isRequired,
20+
component: PropTypes.string,
21+
delay: PropTypes.number,
22+
onRender: PropTypes.func
23+
};
24+
25+
Frame.defaultProps = {
26+
component: null,
27+
delay: 0,
28+
onRender: () => {}
29+
};

lib/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as Keyframes } from './keyframes';
2+
export { default as Frame } from './frame';

lib/keyframes.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import React, { PropTypes } from 'react';
2+
3+
const noop = () => {};
4+
5+
export default class Keyframes extends React.Component {
6+
constructor (props) {
7+
super(props);
8+
this.state = { frameNum: -1 };
9+
this.delayTimer = null;
10+
}
11+
12+
shouldComponentUpdate (nextProps, nextState) {
13+
const { frameNum } = nextState;
14+
if (this.state.frameNum === frameNum) return false;
15+
return 0 <= frameNum && frameNum < this.props.children.length;
16+
}
17+
18+
componentWillMount () {
19+
const frameNum = this.state.frameNum + 1;
20+
const frame = this.getFrame(frameNum);
21+
22+
// render the first frame if it has no delay
23+
if (frame && !frame.props.delay) {
24+
this.setState({ frameNum });
25+
}
26+
}
27+
28+
componentDidMount () {
29+
this.requestNextFrame();
30+
}
31+
32+
componentDidUpdate () {
33+
this.requestNextFrame();
34+
}
35+
36+
componentWillUnmount () {
37+
clearTimeout(this.delayTimer);
38+
}
39+
40+
render () {
41+
const frame = this.getFrame();
42+
if (!frame) return null;
43+
44+
const component = frame.props.component || this.props.component;
45+
return React.cloneElement(frame, { component });
46+
}
47+
48+
requestNextFrame () {
49+
const frameNum = this.state.frameNum + 1;
50+
const frame = this.getFrame(frameNum);
51+
if (!frame) {
52+
this.props.onEnd();
53+
return;
54+
}
55+
56+
const { delay } = frame.props;
57+
58+
clearTimeout(this.delayTimer);
59+
this.delayTimer = setTimeout(() => {
60+
if (0 === frameNum) {
61+
this.props.onStart();
62+
}
63+
this.setState({ frameNum });
64+
}, delay);
65+
}
66+
67+
getFrame (frameNum = this.state.frameNum) {
68+
return this.props.children[frameNum];
69+
}
70+
}
71+
72+
Keyframes.propTypes = {
73+
children: PropTypes.element.isRequired,
74+
component: PropTypes.string,
75+
onStart: PropTypes.func,
76+
onEnd: PropTypes.func
77+
};
78+
79+
Keyframes.defaultProps = {
80+
component: 'span',
81+
onStart: noop,
82+
onEnd: noop
83+
};

package.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"name": "react-keyframes",
3+
"version": "0.0.1",
4+
"description": "",
5+
"main": "./build/lib",
6+
"files": [
7+
"build"
8+
],
9+
"dependencies": {
10+
"babel-runtime": "6.6.1"
11+
},
12+
"devDependencies": {
13+
"ava": "0.13.0",
14+
"babel-eslint": "5.0.0",
15+
"babel-plugin-syntax-async-functions": "6.5.0",
16+
"babel-plugin-transform-async-to-generator": "6.7.0",
17+
"babel-plugin-transform-runtime": "6.6.0",
18+
"babel-preset-es2015": "6.6.0",
19+
"babel-preset-react": "6.5.0",
20+
"babel-register": "6.7.2",
21+
"del": "2.2.0",
22+
"eslint-config-standard": "4.4.0",
23+
"eslint-config-standard-jsx": "1.1.1",
24+
"eslint-config-standard-react": "2.3.0",
25+
"eslint-plugin-react": "4.2.1",
26+
"eslint-plugin-standard": "1.3.2",
27+
"gulp": "3.9.1",
28+
"gulp-babel": "6.1.2",
29+
"gulp-eslint": "1.1.1",
30+
"gulp-task-listing": "1.0.1",
31+
"jsdom": "8.1.0",
32+
"lolex": "1.4.0",
33+
"react": "0.14.7",
34+
"react-dom": "0.14.7"
35+
},
36+
"scripts": {
37+
"gulp": "gulp",
38+
"test": "ava"
39+
},
40+
"babel": {
41+
"presets": [
42+
"es2015",
43+
"react"
44+
],
45+
"plugins": [
46+
"transform-runtime",
47+
"syntax-async-functions",
48+
"transform-async-to-generator"
49+
]
50+
},
51+
"ava": {
52+
"failFast": true,
53+
"files": [
54+
"test/*.js"
55+
],
56+
"require": [
57+
"babel-register",
58+
"./test/helpers/setup-browser-env.js"
59+
],
60+
"babel": "inherit"
61+
}
62+
}

test/helpers/setup-browser-env.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import jsdom from 'jsdom';
2+
3+
global.document = jsdom.jsdom('<body></body>');
4+
global.window = document.defaultView;
5+
global.navigator = window.navigator;

0 commit comments

Comments
 (0)