├── .gitignore ├── History.md ├── Makefile ├── Readme.md ├── example └── index.js ├── index.js ├── lib ├── bus.js ├── fill.js ├── go.js ├── location.js ├── match.js └── route.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules 3 | .DS_Store 4 | components 5 | build 6 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 1.0.3 / 2015-09-24 3 | ================== 4 | 5 | * add react as a peer dependency 6 | 7 | 1.0.2 / 2015-09-18 8 | ================== 9 | 10 | * add: Route.match(path). fix: make example 11 | * add example 12 | 13 | 1.0.1 / 2015-06-08 14 | ================== 15 | 16 | * remove logging 17 | 18 | 1.0.0 / 2015-06-08 19 | ================== 20 | 21 | * Initial commit 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | example: 2 | @PORT=5000 ./node_modules/.bin/roo react example/index.js --live 3 | 4 | .PHONY: example 5 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # react-route 2 | 3 | Simple, tiny router for React. 4 | 5 | ```jsx 6 |
7 | 8 |
Index /
9 |
10 | 11 | About me 12 | 13 | 14 | 15 | 16 | Hi amy! 17 | 18 | 19 |
20 | ``` 21 | 22 | ## Features 23 | 24 | - Parameter support via `props.params` 25 | - Simple API for navigating pages 26 | - HTML5 History Support 27 | - No wrapping handlers 28 | - Nesting 29 | 30 | ## Installation 31 | 32 | ```js 33 | npm install react-route 34 | ``` 35 | 36 | ## API 37 | 38 | ### `` 39 | 40 | Specify an express-style path. For a list of possibilities check out: https://github.com/pillarjs/path-to-regexp 41 | 42 | Any child components will receive a `params` property based on the pathname and keys provided. 43 | 44 | ```js 45 |

46 | Welcome user {this.props.params.user} 47 |

48 | ``` 49 | 50 | ### Route.go(path) 51 | 52 | Navigate to `path` and re-render the routes. 53 | 54 | ```js 55 | onclick () { 56 | Route.go('/user/amy'); 57 | } 58 | ``` 59 | 60 | ## License 61 | 62 | MIT 63 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module Dependencies 3 | */ 4 | 5 | var React = require('react') 6 | var Route = require('..') 7 | 8 | /** 9 | * Example Component 10 | */ 11 | 12 | export default class Example extends React.Component { 13 | constructor (props) { 14 | super(props) 15 | } 16 | 17 | render () { 18 | return ( 19 |
20 | 21 |

index

22 |
23 | 24 |

dashboard

25 |
26 |
27 | ) 28 | } 29 | } 30 | 31 | if (typeof window !== 'undefined') { 32 | var component = React.createElement(Example, {}) 33 | React.render(component, document.body) 34 | } 35 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Export `react-route` 3 | */ 4 | 5 | exports = module.exports = require('./lib/route'); 6 | exports.go = require('./lib/go'); 7 | exports.match = require('./lib/match'); 8 | -------------------------------------------------------------------------------- /lib/bus.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Export `bus` 3 | */ 4 | 5 | module.exports = require('component-emitter')({}); 6 | -------------------------------------------------------------------------------- /lib/fill.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module Dependencies 3 | */ 4 | 5 | var Regexp = require('path-to-regexp') 6 | var location = require('./location'); 7 | 8 | /** 9 | * Export `match` 10 | */ 11 | 12 | module.exports = match; 13 | 14 | /** 15 | * Check if this route matches `path`, if so 16 | * populate `params`. 17 | * 18 | * @param {String} path 19 | * @param {Object} params 20 | * @return {Boolean} 21 | * @api private 22 | */ 23 | 24 | function match(path, params, pathname) { 25 | var keys = []; 26 | var regexp = Regexp(path, keys); 27 | var m = regexp.exec(pathname || location.pathname); 28 | 29 | if (!m) return false; 30 | else if (!params) return true; 31 | 32 | for (var i = 1, len = m.length; i < len; ++i) { 33 | var key = keys[i - 1]; 34 | var val = 'string' == typeof m[i] ? decodeURIComponent(m[i]) : m[i]; 35 | if (key) params[key.name] = val; 36 | } 37 | 38 | return true; 39 | } 40 | -------------------------------------------------------------------------------- /lib/go.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module Dependencies 3 | */ 4 | 5 | var location = require('./location'); 6 | var bus = require('./bus'); 7 | 8 | /** 9 | * Export `Go` 10 | */ 11 | 12 | module.exports = Go; 13 | 14 | /** 15 | * Go 16 | */ 17 | 18 | function Go(path, state) { 19 | if (arguments.length) { 20 | window.history.pushState(state, null, path); 21 | bus.emit('pushstate', path); 22 | } else { 23 | var params = {}; 24 | var m = match(location.pathname, params); 25 | return m && params; 26 | } 27 | } 28 | 29 | /** 30 | * Setup the "popstate" events 31 | */ 32 | 33 | function onpopstate() { 34 | var loaded = false; 35 | if ('undefined' === typeof window) return; 36 | if (document.readyState === 'complete') { 37 | loaded = true; 38 | } else { 39 | window.addEventListener('load', function() { 40 | setTimeout(function() { 41 | loaded = true; 42 | }, 0); 43 | }); 44 | } 45 | 46 | return function _onpopstate(e) { 47 | if (!loaded) return; 48 | bus.emit('popstate', location.pathname); 49 | } 50 | } 51 | 52 | /** 53 | * Start listening for the "popstate" event 54 | */ 55 | 56 | window.addEventListener('popstate', onpopstate()); 57 | -------------------------------------------------------------------------------- /lib/location.js: -------------------------------------------------------------------------------- 1 | /** 2 | * To work properly with the URL 3 | * history.location generated polyfill in https://github.com/devote/HTML5-History-API 4 | */ 5 | 6 | module.exports = ('undefined' !== typeof window) && (window.history.location || window.location); 7 | -------------------------------------------------------------------------------- /lib/match.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module Dependencies 3 | */ 4 | 5 | var fill = require('./fill') 6 | 7 | /** 8 | * 9 | */ 10 | 11 | module.exports = match 12 | 13 | /** 14 | * Match against a path 15 | */ 16 | 17 | function match (path, location) { 18 | location = location || window.location.pathname 19 | var params = {} 20 | return fill(path, params, location) && params 21 | } 22 | -------------------------------------------------------------------------------- /lib/route.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module Dependencies 3 | */ 4 | 5 | var assign = require('object-assign'); 6 | var fill = require('./fill'); 7 | var React = require('react'); 8 | var bus = require('./bus'); 9 | 10 | /** 11 | * Export `Route` 12 | */ 13 | 14 | module.exports = React.createClass({ 15 | 16 | displayName: 'Route', 17 | 18 | setInitialState: function () { 19 | return { 20 | pathname: location.pathname 21 | } 22 | }, 23 | 24 | componentDidMount: function () { 25 | var self = this; 26 | 27 | bus.on('pushstate', function(pathname) { 28 | self.setState({ pathname: pathname }); 29 | }) 30 | 31 | bus.on('popstate', function(pathname) { 32 | self.setState({ pathname: pathname }); 33 | }) 34 | }, 35 | 36 | render: function(props) { 37 | var props = this.props; 38 | var path = props.path; 39 | var params = {}; 40 | 41 | var m = fill(path, params); 42 | if (!m) return null; 43 | 44 | var children = React.Children.map(this.props.children, function(child) { 45 | return child.type 46 | ? React.cloneElement(child, assign({ params: params }, child.props)) 47 | : React.createElement('span', {}, child); 48 | }) 49 | 50 | return React.createElement('div', { className: 'Route'}, children); 51 | } 52 | }); 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-route", 3 | "version": "1.0.3", 4 | "description": "tiny react router thats less opinionated than react-router", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "make test" 8 | }, 9 | "keywords": [ 10 | "react", 11 | "router", 12 | "tiny", 13 | "mini", 14 | "small" 15 | ], 16 | "author": "Matthew Mueller", 17 | "license": "MIT", 18 | "dependencies": { 19 | "component-emitter": "^1.2.0", 20 | "object-assign": "^3.0.0", 21 | "path-to-regexp": "^1.2.0" 22 | }, 23 | "devDependencies": { 24 | "roo": "^0.4.5" 25 | }, 26 | "peerDependencies": { 27 | "react": "^0.13.3 || ^0.14.0-rc1" 28 | } 29 | } --------------------------------------------------------------------------------