├── .gitignore ├── README.md ├── css-color-names-es2015 ├── assets │ ├── dist │ │ ├── app.js │ │ └── app.js.map │ └── src │ │ └── app.js ├── gulp │ ├── config.js │ └── tasks │ │ └── browserify.js ├── gulpfile.js ├── index.html └── package.json └── css-color-names ├── assets ├── css │ └── app.css └── js │ ├── JSXTransformer.js │ ├── app-color.jsx │ ├── app-header.jsx │ ├── app.jsx │ ├── director.js │ ├── react-with-addons.js │ └── utils.js └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-demo 2 | React demo web apps. 3 | -------------------------------------------------------------------------------- /css-color-names-es2015/assets/src/app.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | class Page extends React.Component { 5 | render() { 6 | return ( 7 |
8 | Hello World 9 |
10 | ) 11 | } 12 | } 13 | 14 | ReactDOM.render( 15 | , document.getElementById('page') 16 | ) 17 | 18 | -------------------------------------------------------------------------------- /css-color-names-es2015/gulp/config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | js: { 5 | src: './assets/src/app.js', 6 | dest: './assets/dist/' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /css-color-names-es2015/gulp/tasks/browserify.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var watchify = require('watchify'); 4 | var browserify = require('browserify'); 5 | var babelify = require('babelify'); 6 | var gulp = require('gulp'); 7 | var source = require('vinyl-source-stream'); 8 | var buffer = require('vinyl-buffer'); 9 | var gutil = require('gulp-util'); 10 | var uglify = require('gulp-uglify'); 11 | var sourcemaps = require('gulp-sourcemaps'); 12 | var config = require('../config').js; 13 | 14 | var opts = { 15 | entries: [config.src], 16 | debug: true 17 | }; 18 | var b; 19 | 20 | function bundle() { 21 | b.transform("babelify", {presets: ["es2015", "react"]}) 22 | return b.bundle() 23 | .on('error', gutil.log.bind(gutil, 'Browserify Error')) 24 | .pipe(source('app.js')) 25 | .pipe(buffer()) 26 | .pipe(sourcemaps.init({loadMaps: true})) 27 | .pipe(uglify()) 28 | .pipe(sourcemaps.write('./')) 29 | .pipe(gulp.dest(config.dest)); 30 | } 31 | 32 | gulp.task('js', function(){ 33 | b = browserify(opts); 34 | b.on('log', gutil.log); 35 | return bundle(); 36 | }); 37 | 38 | gulp.task('js:watch', function(){ 39 | b = watchify(browserify(opts)); 40 | b.on('log', gutil.log); 41 | b.on('update', bundle); 42 | return bundle(); 43 | }); 44 | -------------------------------------------------------------------------------- /css-color-names-es2015/gulpfile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var requireDir = require('require-dir'); 4 | requireDir('./gulp/tasks'); 5 | -------------------------------------------------------------------------------- /css-color-names-es2015/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CSS Color Names v.03 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /css-color-names-es2015/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-color-names-es2015", 3 | "version": "1.0.0", 4 | "description": "CSS Color Names v.03 -- with ES2015", 5 | "main": "assets/dist/app.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/hazmi/gulp-collections/browserify-react-es2015" 9 | }, 10 | "scripts": {}, 11 | "author": { 12 | "name": "Hazmi Abdun Nazir", 13 | "email": "hello@hazmi.id", 14 | "url": "http://hazmi.id" 15 | }, 16 | "devDependencies": { 17 | "babel-preset-es2015": "^6.1.18", 18 | "babel-preset-react": "^6.1.18", 19 | "babelify": "^7.2.0", 20 | "browserify": "^12.0.1", 21 | "gulp": "^3.9.0", 22 | "gulp-sourcemaps": "^1.6.0", 23 | "gulp-uglify": "^1.5.1", 24 | "gulp-util": "^3.0.7", 25 | "react": "^0.14.3", 26 | "react-dom": "^0.14.3", 27 | "require-dir": "^0.3.0", 28 | "vinyl-buffer": "^1.0.0", 29 | "vinyl-source-stream": "^1.1.0", 30 | "watchify": "^3.6.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /css-color-names/assets/css/app.css: -------------------------------------------------------------------------------- 1 | #color-app{ 2 | position: relative; 3 | width: 365px; 4 | padding: 15px 15px 0; 5 | border: 1px solid #e6e9f2; 6 | border-radius: 4px; 7 | font: 12px/1 "Open Sans", sans-serif; 8 | background: #fff; 9 | } 10 | #color-list{ 11 | position: relative; 12 | width: 100%; 13 | transition: height .2s ease-in-out; 14 | } 15 | #color-header{ 16 | margin-bottom: 15px; 17 | } 18 | #color-header h1{ 19 | padding: 5px 0 0; 20 | margin: 0; 21 | font-size: 15px; 22 | color: #5b9bd1; 23 | text-transform: uppercase; 24 | } 25 | #color-header p{ 26 | padding: 5px 0 0; 27 | margin: 0; 28 | font-size: 12px; 29 | color: #888; 30 | } 31 | #color-header input{ 32 | width: 326px; 33 | height: 25px; 34 | margin: 15px 0 0; 35 | border-radius: 5px; 36 | padding: 2px 26px 3px 10px; 37 | font-size: 13px; 38 | background-color: #F1F3F8; 39 | border: 1px solid #F1F3F8; 40 | outline: none; 41 | } 42 | #color-header .title{ 43 | float: left; 44 | } 45 | #color-header #action{ 46 | float: right; 47 | padding-top: 10px; 48 | } 49 | #color-app .label-sort{ 50 | display: inline-block; 51 | padding: 0 5px 0 10px; 52 | font-size: 11px; 53 | color: #888; 54 | } 55 | #color-app .btn { 56 | display: inline-block; 57 | padding: 5px 10px; 58 | margin: 0; 59 | border: 1px solid #e6e9f2; 60 | border-radius: 14px; 61 | outline: none; 62 | cursor: pointer; 63 | font-size: 11px; 64 | line-height: 1; 65 | text-decoration: none; 66 | color: #666; 67 | background: #fff; 68 | } 69 | #color-app .btn-sort-date{ 70 | padding-right: 5px; 71 | border-top-right-radius: 0; 72 | border-bottom-right-radius: 0; 73 | } 74 | #color-app .btn-sort-name{ 75 | padding-left: 5px; 76 | border-left: 0; 77 | border-top-left-radius: 0; 78 | border-bottom-left-radius: 0; 79 | } 80 | #color-app .btn-add{ 81 | margin-left: 10px; 82 | border-color: #4db3a4; 83 | color: #fff; 84 | background: #4db3a4; 85 | } 86 | #color-app .btn-remove{ 87 | position: absolute; 88 | left: -7px; 89 | top: -7px; 90 | display: block; 91 | width: 22px; 92 | padding: 5px 0; 93 | opacity: 0; 94 | border: 1px solid #e6e9f2; 95 | border-radius: 10; 96 | font-size: 9px; 97 | text-transform: uppercase; 98 | color: #fff; 99 | background: #F3565D; 100 | transition: opacity .1s ease-in; 101 | } 102 | #color-app .date .btn-sort-date, 103 | #color-app .name .btn-sort-name{ 104 | color: #fff; 105 | cursor: default; 106 | background: #8895a9; 107 | } 108 | #color-app .content-item:hover .btn-remove{ 109 | opacity: .9; 110 | } 111 | #color-app .content-item{ 112 | position: absolute; 113 | display: block; 114 | left: 0; 115 | top: 0; 116 | width: 80px; 117 | text-align: center; 118 | transition: all 0.4s ease-in-out; 119 | } 120 | #color-app .content-item .color-preview{ 121 | display: block; 122 | width: 80px; 123 | height: 80px; 124 | border-radius: 10px; 125 | border: 1px solid #e6e9f2; 126 | } 127 | #color-app .content-item .color-name{ 128 | cursor: default; 129 | display: block; 130 | overflow: hidden; 131 | width: 60px; 132 | padding: 5px 10px; 133 | margin-top: 40px; 134 | border-style: solid; 135 | border-color: #e6e9f2; 136 | border-width: 1px 0; 137 | font-size: 9px; 138 | color: #fff; 139 | text-transform: uppercase; 140 | text-overflow: ellipsis; 141 | white-space: nowrap; 142 | background: #428bca; 143 | } 144 | #color-app .items-enter { 145 | opacity: 0; 146 | transform: scale(0) rotate(-90deg); 147 | } 148 | #color-app .items-enter.items-enter-active { 149 | opacity: 1; 150 | transform: scale(1) rotate(0deg); 151 | } 152 | #color-app .items-leave { 153 | opacity: 1; 154 | transform: scale(1) rotate(0deg); 155 | } 156 | #color-app .items-leave.items-leave-active, 157 | .content-item-hide { 158 | opacity: 0; 159 | transform: scale(1) rotate(0deg); 160 | } -------------------------------------------------------------------------------- /css-color-names/assets/js/app-color.jsx: -------------------------------------------------------------------------------- 1 | var App = App || {}; 2 | 3 | App.ColorItem = (function(){ 4 | var self = React.createClass({ 5 | getInitialState: function(){ 6 | return { 7 | display: this.props.display, 8 | order: this.props.order 9 | } 10 | }, 11 | componentWillReceiveProps: function(nextProps){ 12 | this.setState({ 13 | display: nextProps.display, 14 | order: nextProps.order 15 | }); 16 | }, 17 | shouldComponentUpdate: function(nextProps, nextState){ 18 | return (this.state.display === nextProps.display && this.state.order === nextProps.order) ? false : true; 19 | }, 20 | render: function(){ 21 | var curColumn = Math.ceil((this.props.order + 1) / App.MAX_ROW); 22 | var curRow = this.props.order % 4; 23 | var colorStyle = { 24 | backgroundColor: this.props.colorName 25 | }; 26 | var positionStyle = { 27 | top : App.ITEM_HEIGHT * (curColumn - 1), 28 | left : App.ITEM_WIDTH * curRow 29 | }; 30 | var cx = React.addons.classSet; 31 | var classes = cx({ 32 | 'content-item': true, 33 | 'content-item-hide': !this.props.display 34 | }); 35 | return ( 36 | 37 | 38 | 39 | {this.props.colorName} 40 | 41 | 42 | ) 43 | } 44 | }); 45 | return self; 46 | })(); -------------------------------------------------------------------------------- /css-color-names/assets/js/app-header.jsx: -------------------------------------------------------------------------------- 1 | var App = App || {}; 2 | 3 | App.ColorHeader = (function(){ 4 | var self = React.createClass({ 5 | render: function(){ 6 | return ( 7 |
8 |
9 |

CSS Color Names

10 |

Displaying {this.props.displayCount} of {this.props.total}

11 |
12 |
13 | Sort by: 14 | Date 15 | Name 16 | Add 17 |
18 | 19 |
20 | ) 21 | } 22 | }); 23 | return self; 24 | })(); -------------------------------------------------------------------------------- /css-color-names/assets/js/app.jsx: -------------------------------------------------------------------------------- 1 | var App = App || {}; 2 | 3 | App.ColorApp = (function(){ 4 | 5 | App.MAX_ROW = 4; 6 | App.ITEM_WIDTH = 95; 7 | App.ITEM_HEIGHT = 95; 8 | App.NUM_INIT_ITEM = 10; 9 | App.SORT_NAME = 'name'; 10 | App.SORT_DATE = 'date'; 11 | App.COLORS = []; 12 | App.TARGET_HTML_ID = 'color-app'; 13 | 14 | var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; 15 | var ColorHeader = App.ColorHeader; 16 | var ColorFooter = App.ColorFooter; 17 | var ColorItem = App.ColorItem; 18 | 19 | var ColorApp = React.createClass({ 20 | refreshData: function(keyword, data){ 21 | keyword = (keyword !== null) ? keyword : this.state.searchKeyword; 22 | data = (data !== null) ? data : this.state.data; 23 | filterInfo = App.Utils.filterDisplayInfo(data, keyword); 24 | this.setState({ 25 | displayCount: filterInfo.count, 26 | data: App.Utils.setupSortOrder(filterInfo.data), 27 | searchKeyword: keyword 28 | }); 29 | }, 30 | handleChange: function(e){ 31 | this.refreshData(e.target.value, null); 32 | }, 33 | handleAdd: function(){ 34 | var data = this.state.data; 35 | var newData = App.Utils.getColor(); 36 | newData.order.date = this.state.data.length; 37 | data.push(newData); 38 | this.refreshData(this.state.searchKeyword, data); 39 | }, 40 | handleRemove: function(index){ 41 | var data = this.state.data; 42 | data.splice(index, 1); 43 | data = App.Utils.setupSortOrder(data); 44 | this.refreshData(this.state.searchKeyword, data); 45 | }, 46 | getInitialState: function() { 47 | return { 48 | data: [], 49 | displayCount: 0, 50 | order: 'date', 51 | searchKeyword: '' 52 | }; 53 | }, 54 | componentDidMount: function() { 55 | var setState = this.setState; 56 | var router = Router({ 57 | '/date': setState.bind(this, {order: 'date'}), 58 | '/name': setState.bind(this, {order: 'name'}) 59 | }); 60 | router.init('/date'); 61 | this.setState({ 62 | data: this.props.colors, 63 | displayCount: this.props.colors.length 64 | }); 65 | }, 66 | getColorListStyle: function(){ 67 | var numColumn = Math.ceil(this.state.displayCount / App.MAX_ROW); 68 | var wrapperHeight = App.ITEM_HEIGHT * numColumn; 69 | return { 70 | height: wrapperHeight 71 | }; 72 | }, 73 | render: function(){ 74 | var colorListStyle = this.getColorListStyle(); 75 | 76 | var items = this.state.data.map(function(color, index) { 77 | var order = color.order[this.state.order]; 78 | return ( 79 | 87 | ); 88 | }.bind(this)); 89 | 90 | return ( 91 |
92 | 99 |
100 | 101 | {items} 102 | 103 |
104 |
105 | ); 106 | } 107 | }); 108 | 109 | var self = { 110 | render: function( colors ){ 111 | App.COLORS = colors; 112 | var intialColors = App.Utils.getInitialRandomColors( App.NUM_INIT_ITEM ); 113 | 114 | React.render( 115 | , 118 | document.getElementById( App.TARGET_HTML_ID ) 119 | ); 120 | } 121 | }; 122 | return self; 123 | })(); 124 | 125 | var colors = ['black','silver','gray','white','maroon','red','purple','fuchsia','green','lime','olive','yellow','navy','blue','teal','aqua','orange','aliceblue','antiquewhite','aquamarine','azure','beige','bisque','blanchedalmond','blueviolet','brown','burlywood','cadetblue','chartreuse','chocolate','coral','cornflowerblue','cornsilk','crimson','darkblue','darkcyan','darkgoldenrod','darkgray','darkgreen','darkgrey','darkkhaki','darkmagenta','darkolivegreen','darkorange','darkorchid','darkred','darksalmon','darkseagreen','darkslateblue','darkslategray','darkslategrey','darkturquoise','darkviolet','deeppink','deepskyblue','dimgray','dimgrey','dodgerblue','firebrick','floralwhite','forestgreen','gainsboro','ghostwhite','gold','goldenrod','greenyellow','grey','honeydew','hotpink','indianred','indigo','ivory','khaki','lavender','lavenderblush','lawngreen','lemonchiffon','lightblue','lightcoral','lightcyan','lightgoldenrodyellow','lightgray','lightgreen','lightgrey','lightpink','lightsalmon','lightseagreen','lightskyblue','lightslategray','lightslategrey','lightsteelblue','lightyellow','limegreen','linen','mediumaquamarine','mediumblue','mediumorchid','mediumpurple','mediumseagreen','mediumslateblue','mediumspringgreen','mediumturquoise','mediumvioletred','midnightblue','mintcream','mistyrose','moccasin','navajowhite','oldlace','olivedrab','orangered','orchid','palegoldenrod','palegreen','paleturquoise','palevioletred','papayawhip','peachpuff','peru','pink','plum','powderblue','rosybrown','royalblue','saddlebrown','salmon','sandybrown','seagreen','seashell','sienna','skyblue','slateblue','slategray','slategrey','snow','springgreen','steelblue','tan','thistle','tomato','turquoise','violet','wheat','whitesmoke','yellowgreen','rebeccapurple']; 126 | 127 | App.ColorApp.render(colors); -------------------------------------------------------------------------------- /css-color-names/assets/js/director.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 4 | // Generated on Tue Dec 16 2014 12:13:47 GMT+0100 (CET) by Charlie Robbins, Paolo Fragomeni & the Contributors (Using Codesurgeon). 5 | // Version 1.2.6 6 | // 7 | 8 | (function (exports) { 9 | 10 | /* 11 | * browser.js: Browser specific functionality for director. 12 | * 13 | * (C) 2011, Charlie Robbins, Paolo Fragomeni, & the Contributors. 14 | * MIT LICENSE 15 | * 16 | */ 17 | 18 | var dloc = document.location; 19 | 20 | function dlocHashEmpty() { 21 | // Non-IE browsers return '' when the address bar shows '#'; Director's logic 22 | // assumes both mean empty. 23 | return dloc.hash === '' || dloc.hash === '#'; 24 | } 25 | 26 | var listener = { 27 | mode: 'modern', 28 | hash: dloc.hash, 29 | history: false, 30 | 31 | check: function () { 32 | var h = dloc.hash; 33 | if (h != this.hash) { 34 | this.hash = h; 35 | this.onHashChanged(); 36 | } 37 | }, 38 | 39 | fire: function () { 40 | if (this.mode === 'modern') { 41 | this.history === true ? window.onpopstate() : window.onhashchange(); 42 | } 43 | else { 44 | this.onHashChanged(); 45 | } 46 | }, 47 | 48 | init: function (fn, history) { 49 | var self = this; 50 | this.history = history; 51 | 52 | if (!Router.listeners) { 53 | Router.listeners = []; 54 | } 55 | 56 | function onchange(onChangeEvent) { 57 | for (var i = 0, l = Router.listeners.length; i < l; i++) { 58 | Router.listeners[i](onChangeEvent); 59 | } 60 | } 61 | 62 | //note IE8 is being counted as 'modern' because it has the hashchange event 63 | if ('onhashchange' in window && (document.documentMode === undefined 64 | || document.documentMode > 7)) { 65 | // At least for now HTML5 history is available for 'modern' browsers only 66 | if (this.history === true) { 67 | // There is an old bug in Chrome that causes onpopstate to fire even 68 | // upon initial page load. Since the handler is run manually in init(), 69 | // this would cause Chrome to run it twise. Currently the only 70 | // workaround seems to be to set the handler after the initial page load 71 | // http://code.google.com/p/chromium/issues/detail?id=63040 72 | setTimeout(function() { 73 | window.onpopstate = onchange; 74 | }, 500); 75 | } 76 | else { 77 | window.onhashchange = onchange; 78 | } 79 | this.mode = 'modern'; 80 | } 81 | else { 82 | // 83 | // IE support, based on a concept by Erik Arvidson ... 84 | // 85 | var frame = document.createElement('iframe'); 86 | frame.id = 'state-frame'; 87 | frame.style.display = 'none'; 88 | document.body.appendChild(frame); 89 | this.writeFrame(''); 90 | 91 | if ('onpropertychange' in document && 'attachEvent' in document) { 92 | document.attachEvent('onpropertychange', function () { 93 | if (event.propertyName === 'location') { 94 | self.check(); 95 | } 96 | }); 97 | } 98 | 99 | window.setInterval(function () { self.check(); }, 50); 100 | 101 | this.onHashChanged = onchange; 102 | this.mode = 'legacy'; 103 | } 104 | 105 | Router.listeners.push(fn); 106 | 107 | return this.mode; 108 | }, 109 | 110 | destroy: function (fn) { 111 | if (!Router || !Router.listeners) { 112 | return; 113 | } 114 | 115 | var listeners = Router.listeners; 116 | 117 | for (var i = listeners.length - 1; i >= 0; i--) { 118 | if (listeners[i] === fn) { 119 | listeners.splice(i, 1); 120 | } 121 | } 122 | }, 123 | 124 | setHash: function (s) { 125 | // Mozilla always adds an entry to the history 126 | if (this.mode === 'legacy') { 127 | this.writeFrame(s); 128 | } 129 | 130 | if (this.history === true) { 131 | window.history.pushState({}, document.title, s); 132 | // Fire an onpopstate event manually since pushing does not obviously 133 | // trigger the pop event. 134 | this.fire(); 135 | } else { 136 | dloc.hash = (s[0] === '/') ? s : '/' + s; 137 | } 138 | return this; 139 | }, 140 | 141 | writeFrame: function (s) { 142 | // IE support... 143 | var f = document.getElementById('state-frame'); 144 | var d = f.contentDocument || f.contentWindow.document; 145 | d.open(); 146 | d.write(" 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | --------------------------------------------------------------------------------