From a831d15bf7b01232ba0b06c673066441df706669 Mon Sep 17 00:00:00 2001 From: Eugene Yemelin Date: Fri, 27 Oct 2017 08:44:21 +0300 Subject: [PATCH 1/4] v0.3.0 refactoring --- index.html | 15 ------ package.json | 39 ++++---------- postcss.config.js | 5 -- .../Flipper/index.js | 21 +++++--- src/Countdown/Flipper/schema.js | 17 ++++++ .../Flipper/style.scss | 2 +- src/{components => }/Countdown/index.js | 36 +++++++------ src/Countdown/schema.js | 14 +++++ src/{components => }/Countdown/style.scss | 0 src/components/Countdown/schema.js | 15 ------ src/components/Flipper/schema.js | 17 ------ src/index.js | 7 --- webpack.config.js | 54 ------------------- 13 files changed, 74 insertions(+), 168 deletions(-) delete mode 100644 index.html delete mode 100644 postcss.config.js rename src/{components => Countdown}/Flipper/index.js (77%) create mode 100644 src/Countdown/Flipper/schema.js rename src/{components => Countdown}/Flipper/style.scss (97%) rename src/{components => }/Countdown/index.js (68%) create mode 100644 src/Countdown/schema.js rename src/{components => }/Countdown/style.scss (100%) delete mode 100644 src/components/Countdown/schema.js delete mode 100644 src/components/Flipper/schema.js delete mode 100644 src/index.js delete mode 100644 webpack.config.js diff --git a/index.html b/index.html deleted file mode 100644 index 1514442..0000000 --- a/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - webpack react kit - - - - -
- - - - diff --git a/package.json b/package.json index 42df54d..3b1d946 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,15 @@ { - "name": "box-kit", - "version": "1.0.0", - "description": "Webpack + React start kit", - "main": "index.js", - "scripts": { - "test": "test", - "build": "webpack --progress", - "dev": "webpack-dev-server" - }, + "name": "react-flip-counter", + "version": "0.3.0-alpha1", + "description": "React flip countdown timer", + "main": "src/Countdown/index.js", "author": "Eugene Yemelin", "license": "ISC", - "babel": { - "presets": [ - "es2015", - "react" - ] - }, - "devDependencies": { - "babel-core": "^6.18.2", - "babel-loader": "^6.2.7", - "babel-preset-es2015": "^6.18.0", - "babel-preset-react": "^6.16.0", - "css-loader": "^0.26.0", - "extract-text-webpack-plugin": "^1.0.1", - "node-sass": "^3.13.0", - "postcss-loader": "^1.1.1", - "sass-loader": "^4.0.2", - "webpack": "^1.13.3", - "webpack-dev-server": "^1.16.2" - }, "dependencies": { - "react": "^15.4.1", - "react-dom": "^15.4.1" + "classnames": "^2.2.5", + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^16.0.0" } } diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index 88752c6..0000000 --- a/postcss.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - plugins: [ - require('autoprefixer') - ] -} diff --git a/src/components/Flipper/index.js b/src/Countdown/Flipper/index.js similarity index 77% rename from src/components/Flipper/index.js rename to src/Countdown/Flipper/index.js index c6b168c..bf48b2e 100644 --- a/src/components/Flipper/index.js +++ b/src/Countdown/Flipper/index.js @@ -1,8 +1,9 @@ import React from 'react'; +import cn from 'classnames'; import schema from './schema.js'; -import './style.scss'; +import st from './style.scss'; -class Flipper extends React.PureComponent { +class Flipper extends React.Component { constructor(props) { super(props); @@ -11,7 +12,7 @@ class Flipper extends React.PureComponent { * @type {object} * @property {object} toggle - flag for switching index of current digit index */ - this.state = { toggle: false } + this.state = {}; } /** @@ -71,14 +72,18 @@ class Flipper extends React.PureComponent { * @return {ReactElement} markup */ render() { - return
+ return
{this.getRange(this.props.now).map((val, i) => { return
-
- {['front', 'back'].map(key =>
-
+ className={cn(st.card, this.props.cardClassName, { + [st.now]: val == this.props.now + })}> +
+ {['front', 'back'].map(key =>
+
{key == 'front' ? val : this.getCount(val, 'next')}
)} diff --git a/src/Countdown/Flipper/schema.js b/src/Countdown/Flipper/schema.js new file mode 100644 index 0000000..0d68f95 --- /dev/null +++ b/src/Countdown/Flipper/schema.js @@ -0,0 +1,17 @@ +import { bool, number } from 'prop-types'; + +export default { + types: { + reverse: bool, + now: number, + min: number, + max: number + }, + + defaults: { + reverse: false, + now: 0, + min: 0, + max: 9 + } +}; diff --git a/src/components/Flipper/style.scss b/src/Countdown/Flipper/style.scss similarity index 97% rename from src/components/Flipper/style.scss rename to src/Countdown/Flipper/style.scss index 9b07c3b..05a0148 100644 --- a/src/components/Flipper/style.scss +++ b/src/Countdown/Flipper/style.scss @@ -66,7 +66,7 @@ .side-num { height: 200%; font-size: 100px; - line-height: 1.1; + line-height: 0.93; // my bad.. vertical-align: middle; text-align: center; box-sizing: border-box; diff --git a/src/components/Countdown/index.js b/src/Countdown/index.js similarity index 68% rename from src/components/Countdown/index.js rename to src/Countdown/index.js index bcb392a..0c4c3e3 100644 --- a/src/components/Countdown/index.js +++ b/src/Countdown/index.js @@ -1,9 +1,10 @@ import React from 'react'; -import Flipper from '../Flipper'; +import cn from 'classnames'; +import Flipper from './Flipper'; import schema from './schema.js'; -import './style.scss'; +import st from './style.scss'; -class Countdown extends React.PureComponent { +class Countdown extends React.Component { constructor(props) { super(props); @@ -14,7 +15,7 @@ class Countdown extends React.PureComponent { */ this.state = { diff: this.getDiffObject() - } + }; } /** @@ -78,19 +79,22 @@ class Countdown extends React.PureComponent { seconds: [ [0,5], [0,9] ] }; - return
+ return
{Object.keys(this.state.diff).map(key =>
- {Array(2).fill(0).map((_, i) => )} -
- )} + key={key} + className={cn(st[`countdown-${key}`], this.props.slotClassName)}> + {Array(2).fill(0).map((_, i) => )} +
)}
; } }; diff --git a/src/Countdown/schema.js b/src/Countdown/schema.js new file mode 100644 index 0000000..9d09392 --- /dev/null +++ b/src/Countdown/schema.js @@ -0,0 +1,14 @@ +import { instanceOf, func } from 'prop-types'; + +export default { + + types: { + stop: instanceOf(Date), + onStart: func, + onStop: func + }, + + defaults: { + stop: new Date("Mon Nov 30 2020 00:00:00 GMT+0300 (MSK)") + } +}; diff --git a/src/components/Countdown/style.scss b/src/Countdown/style.scss similarity index 100% rename from src/components/Countdown/style.scss rename to src/Countdown/style.scss diff --git a/src/components/Countdown/schema.js b/src/components/Countdown/schema.js deleted file mode 100644 index 3896da1..0000000 --- a/src/components/Countdown/schema.js +++ /dev/null @@ -1,15 +0,0 @@ -import { PropTypes as types} from 'react'; - -export default { - - types: { - stop: types.instanceOf(Date), - onStart: types.func, - onStop: types.func - }, - - - defaults: { - stop: new Date("Mon Nov 30 2020 00:00:00 GMT+0300 (MSK)") - } -}; diff --git a/src/components/Flipper/schema.js b/src/components/Flipper/schema.js deleted file mode 100644 index fa2a7e1..0000000 --- a/src/components/Flipper/schema.js +++ /dev/null @@ -1,17 +0,0 @@ -import { PropTypes as types} from 'react'; - -export default { - types: { - reverse: types.bool, - now: types.number.isRequired, - min: types.number, - max: types.number - }, - - defaults: { - reverse: false, - now: 0, - min: 0, - max: 9 - } -}; diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 07e69f3..0000000 --- a/src/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; -import { render } from 'react-dom'; -import Countdown from './components/Countdown'; - -render(, document.getElementById('application-wrapper') ); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 0e6a82c..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,54 +0,0 @@ -var webpack = require('webpack'), - extractPlugin = require('extract-text-webpack-plugin'), - - deps = require('./package.json'), - - env = process.env.NODE_ENV, - isDev = env == 'dev'; - -module.exports = { - entry: { - app: './src/index.js', - libs: Object.keys(deps.dependencies) - }, - module: { - loaders: [ - { - test: /\.js$/, - include: /src/, - loader: 'babel' - } , - { - test: /\.scss$/, - include: /src/, - loader: extractPlugin.extract('css!sass!postcss') - } - ] - }, - plugins: [ - !isDev && (new webpack.optimize.UglifyJsPlugin({ - compress: { warnings: false }, - output: { comments: isDev } - })), - - isDev && new webpack.HotModuleReplacementPlugin(), - - new webpack.NoErrorsPlugin(), - new extractPlugin('[name].css'), - new webpack.optimize.CommonsChunkPlugin('libs', null, 2), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(env) - }) - ].filter(function(item) { return !!item }), - output: { - publicPath: '/dist/', - path: './dist', - filename: '[name].js' - }, - devServer: isDev && { - inline: true, - hot: true, - host: 'localhost', - port: 8080 - } -}; From 676d750899a83147bd428f6c35418ea904c8558d Mon Sep 17 00:00:00 2001 From: Eugene Yemelin Date: Wed, 15 Nov 2017 16:49:48 +0300 Subject: [PATCH 2/4] Update Readme --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8094b22..0673d08 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,66 @@ -# flip-timer +# react-flip-counter -React flip counter. Docs in progress, checkout example https://jeka1985.github.io/ +> React countdown timer, like an 80-s flip clocks +May be useful for stuff like promos, sales, launch landings and so on. + +## Install +``` +npm i --save react-flip-counter +``` + +## Webpack configuation + +As react-flip-counter contains JSX syntax and has CSS resources, +it must be parsed with babel and CSS loader. + +You may have a list of such UI modules, so it might be useful +create array with such types of modules names and use it as +loader includes with main src folder + +``` +var uiModules = ['react-flip-counter'], + includes = uiModules.reduce((res, name) => { + res.push(path.resolve(root, 'node_modules/' + name)); + + return res; + }, [path.resolve(root, 'src/')]); +``` + +Then you need to update loaders configuration +and use include instead exclude property + +``` +rules: [ + { + test: /\.js$/, + include: includes, + use: { + loader: 'babel', + ... + } + }, + { + test: /\.css$/, + include: includes, + use: { + loader: 'css', + ... + } + } + ... +] +``` + +## Usage +``` + alert('stopped')} + stop={new Date('Wed Nov 15 2017 15:57:38 GMT+0300 (MSK)')}/> +``` + +## Props +* `onStop` +Function to be called on time over + +* `stop` +Time when counter shod stop and show all zeros. expect Date From c574721b800aea36116f82f73be7f80d372a7225 Mon Sep 17 00:00:00 2001 From: Eugene Yemelin Date: Wed, 15 Nov 2017 16:50:37 +0300 Subject: [PATCH 3/4] Add onStop callback feature, stop count on time over --- src/Countdown/index.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Countdown/index.js b/src/Countdown/index.js index 0c4c3e3..ba88b38 100644 --- a/src/Countdown/index.js +++ b/src/Countdown/index.js @@ -22,7 +22,22 @@ class Countdown extends React.Component { * Create second interval */ componentDidMount() { - this.interval = window.setInterval(() => this.updateTime(), 1000); + if (!this.isTimeOver(this.state.diff)) { + this.interval = window.setInterval(() => { + this.setState({ diff: this.getDiffObject() }); + this.isTimeOver() && this.stopCount(); + }, 1000); + } else { + this.stopCount(); + } + } + + /** + * Clears interval and drop notification + */ + stopCount() { + window.clearInterval(this.interval); + this.props.onStop && this.props.onStop(); } /** @@ -37,7 +52,7 @@ class Countdown extends React.Component { * @return {Object} formatted value */ getDiffObject() { - var ms = Math.abs(this.props.stop - (new Date()).getTime()), + var ms = Math.abs(this.props.stop.getTime() - (new Date()).getTime()), s = Math.floor(ms / 1000), m = Math.floor(s / 60), h = Math.floor(m / 60), @@ -52,10 +67,11 @@ class Countdown extends React.Component { } /** - * Update state with calcualted diff object + * Return flag stop date reached + * @return {Boolean} */ - updateTime() { - this.setState({ diff: this.getDiffObject() }); + isTimeOver() { + return (new Date()).getTime() > this.props.stop.getTime(); } /** @@ -77,7 +93,8 @@ class Countdown extends React.Component { hours: [ [0,2], [0,4] ], minutes: [ [0,5], [0,9] ], seconds: [ [0,5], [0,9] ] - }; + }, + isOver = this.isTimeOver(); return
{Object.keys(this.state.diff).map(key =>
)}
)} From 052579e717d8d63e229a84ffad5464f1f4fc509f Mon Sep 17 00:00:00 2001 From: Eugene Yemelin Date: Wed, 15 Nov 2017 16:51:02 +0300 Subject: [PATCH 4/4] Update deps, Bump version v0.4.0 --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3b1d946..a19e263 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-flip-counter", - "version": "0.3.0-alpha1", + "version": "0.4.0", "description": "React flip countdown timer", "main": "src/Countdown/index.js", "author": "Eugene Yemelin", @@ -10,6 +10,7 @@ "prop-types": "^15.6.0" }, "peerDependencies": { - "react": "^16.0.0" + "react": "^16.1.0", + "react-dom": "^16.1.0" } }