├── .gitignore ├── README.md ├── index.js ├── package.json └── store.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | logs 3 | *.log 4 | npm-debug.log* 5 | .DS_Store 6 | 7 | dist/ 8 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bar-component [![stability][0]][1] 2 | [![npm version][2]][3] [![build status][4]][5] 3 | [![downloads][8]][9] [![js-standard-style][10]][11] 4 | 5 | tiny loading bar component 6 | 7 | ## Installation 8 | 9 | ``` 10 | $ npm install bar-component 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | // index.js 17 | var choo = require('choo') 18 | var html = require('choo/html') 19 | var Bar = require('bar-component') 20 | var bar = new Bar() 21 | 22 | var app = choo() 23 | 24 | app.use(require('bar-component/store')()) 25 | 26 | app.route('/', (state, emit) => { 27 | return html` 28 |

Hello

29 | ${bar.render(state.__progress)} 30 | ` 31 | }) 32 | 33 | app.mount('body') 34 | ``` 35 | 36 | [0]: https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square 37 | [1]: https://nodejs.org/api/documentation.html#documentation_stability_index 38 | [2]: https://img.shields.io/npm/v/bar-component.svg?style=flat-square 39 | [3]: https://npmjs.org/package/bar-component 40 | [4]: https://img.shields.io/travis/s3ththompson/bar-component/master.svg?style=flat-square 41 | [5]: https://travis-ci.org/s3ththompson/bar-component 42 | [8]: http://img.shields.io/npm/dm/bar-component.svg?style=flat-square 43 | [9]: https://npmjs.org/package/bar-component 44 | [10]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square 45 | [11]: https://github.com/feross/standard 46 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var Nanocomponent = require('nanocomponent') 2 | var html = require('bel') 3 | var xtend = require('xtend') 4 | 5 | module.exports = Bar 6 | 7 | function Bar () { 8 | if (!(this instanceof Bar)) return new Bar() 9 | Nanocomponent.call(this) 10 | } 11 | 12 | Bar.prototype = Object.create(Nanocomponent.prototype) 13 | 14 | Bar.identity = function () { 15 | return 'unique' 16 | } 17 | 18 | Bar.prototype.createElement = function (progress, color, height) { 19 | return html`
` 20 | } 21 | 22 | Bar.prototype.update = function (progress, color, height) { 23 | if (this.element) { 24 | this.element.setAttribute('style', css(progress, color, height)) 25 | } 26 | return false 27 | } 28 | 29 | function css (progress, color, height) { 30 | var styles = `transition: all 200ms ease; 31 | position: fixed; 32 | z-index: 9999; 33 | top: 0; 34 | left: 0; 35 | width: 100%;` 36 | if (progress == null) return styles + 'transition: none; ' + translate(-100) 37 | if (!color) color = '#000' 38 | if (!height) height = '2px' 39 | if (Number.isInteger(height)) height += 'px' 40 | return ( 41 | styles + 42 | translate(100 * (progress - 1)) + 43 | ` background-color: ${color}; height: ${height};` 44 | ) 45 | } 46 | 47 | function translate (percentage) { 48 | return `-webkit-transform: translate3d(${percentage}%, 0px, 0px); 49 | -ms-transform: translate3d(${percentage}%, 0px, 0px); 50 | transform: translate3d(${percentage}%, 0px, 0px);` 51 | } 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bar-component", 3 | "version": "1.0.1", 4 | "description": "tiny loading bar component", 5 | "main": "index.js", 6 | "scripts": { 7 | "fmt": "prettier-standard '**/*.js'", 8 | "test": "npm run fmt" 9 | }, 10 | "author": "Seth Thompson (https://seththompson.org)", 11 | "repository": "s3ththompson/bar-component", 12 | "license": "MIT", 13 | "dependencies": { 14 | "bel": "^5.1.5", 15 | "nanocomponent": "^6.5.0", 16 | "xtend": "^4.0.1" 17 | }, 18 | "devDependencies": { 19 | "prettier-standard": "^8.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /store.js: -------------------------------------------------------------------------------- 1 | var TRICKLE_SPEED = 200 2 | var _trickle 3 | 4 | module.exports = function () { 5 | return function (state, emitter) { 6 | emitter.on('progress:start', start) 7 | emitter.on('progress:done', done) 8 | emitter.on('progress:remove', remove) 9 | emitter.on('progress:set', set) 10 | emitter.on('progress:inc', inc) 11 | 12 | function start () { 13 | set(0) 14 | 15 | _trickle = setInterval(function () { 16 | inc() 17 | }, TRICKLE_SPEED) 18 | } 19 | 20 | function done () { 21 | inc(0.3 + 0.5 * Math.random()) 22 | set(1) 23 | } 24 | 25 | function remove () { 26 | state.__progress = null 27 | render() 28 | } 29 | 30 | function set (n) { 31 | n = clamp(n, 0, 1) 32 | state.__progress = n 33 | render() 34 | if (n == 1) { 35 | clearInterval(_trickle) 36 | // wait for animation to finish then clear 37 | setTimeout(function () { 38 | state.__progress = null 39 | render() 40 | }, 200) 41 | } 42 | } 43 | 44 | function inc (amount) { 45 | var n = state.__progress 46 | if (n == null) { 47 | return start() 48 | } else if (n == 1) { 49 | } else { 50 | // trickle amounts from NProgress, (c) 2013, 2014 Rico Sta. Cruz 51 | // http://ricostacruz.com/nprogress 52 | if (typeof amount !== 'number') { 53 | if (n >= 0 && n < 0.2) { 54 | amount = 0.1 55 | } else if (n >= 0.2 && n < 0.5) { 56 | amount = 0.04 57 | } else if (n >= 0.5 && n < 0.8) { 58 | amount = 0.02 59 | } else if (n >= 0.8 && n < 0.99) { 60 | amount = 0.005 61 | } else { 62 | amount = 0 63 | } 64 | } 65 | n = clamp(n + amount, 0, 0.994) 66 | return set(n) 67 | } 68 | } 69 | 70 | function render () { 71 | emitter.emit('render') 72 | } 73 | } 74 | } 75 | 76 | function clamp (n, min, max) { 77 | if (n < min) return min 78 | if (n > max) return max 79 | return n 80 | } 81 | --------------------------------------------------------------------------------