react-mini-router-hook
Version:
Mini Router for React using hooks
134 lines (102 loc) • 4.12 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
(factory((global['react-mini-router-hook'] = {}),global.React));
}(this, (function (exports,React) { 'use strict';
var React__default = 'default' in React ? React['default'] : React;
var Regexp = require('path-to-regexp');
function RouteBuild (routes) {
return function routeBuild (location, props) {
props = props || {};
var params = {};
for (var route in routes) {
var m = match(route, params, location);
var fn = routes[route];
if (m) {
if (typeof fn !== 'function') { return fn }
else { return fn(params, props) }
}
}
return null
}
}
function match(path, params, pathname) {
var keys = [];
var regexp = Regexp(path, keys);
var m = regexp.exec(pathname);
if (!m) { return false; }
else if (!params) { return true; }
for (var i = 1, len = m.length; i < len; ++i) {
var key = keys[i - 1];
var val = 'string' == typeof m[i] ? decodeURIComponent(m[i]) : m[i];
if (key) { params[key.name] = val; }
}
return true;
}
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
var routes = {};
function RouterRender(props) {
function addRoute(el, parent) {
var ref = el.props;
var path = ref.path;
var component = ref.component;
var children = ref.children;
var rest = objectWithoutProperties( ref, ["path", "component", "children"] );
var routeProps = rest;
var render = function (params, renderProps) {
var finalProps = Object.assign({}, props, routeProps, renderProps, {params: params});
var children = React.createElement(component, finalProps);
return parent ? parent.render(params, { children: children }) : children;
};
var route = normalizeRoute(path, parent).replace(/\/\//g, '/');
routes[route] = render;
if (children) { addRoutes(children, { route: route, render: render }); }
}
function addRoutes(routes, parent) {
React.Children.forEach(routes, function (r) { return addRoute(r, parent); });
}
addRoutes(props.children);
var router = RouteBuild(routes);
return router(props.location, { children: null });
}
var RouterContext = React__default.createContext({ path: undefined, setPath: function () { return null; } });
function Router(props) {
var ref = React.useState(props.location);
var path = ref[0];
var setState = ref[1];
function setPath(p, pathTitle, pathState) {
if ( pathTitle === void 0 ) pathTitle = '';
if ( pathState === void 0 ) pathState = {};
window.history.pushState(pathState, pathTitle, p);
setState(p);
}
function updateOnBrowserButtons() {
if (window.location.pathname !== path) {
setState(window.location.pathname);
}
}
React.useEffect(function () {
window.addEventListener('popstate', updateOnBrowserButtons);
return function () {
window.removeEventListener('popstate', updateOnBrowserButtons);
};
});
var contextState = { path: path, setPath: setPath };
return (
React__default.createElement( RouterContext.Provider, { value: contextState },
React__default.createElement( RouterRender, Object.assign({}, props, { location: path || props.location }))
)
);
}
function Route() {}
function normalizeRoute(path, parent) {
if (!path) { return parent ? parent.route : '/'; }
if (path[0] === '/') { return path; }
if (parent == null) { return path; }
return ((parent.route) + "/" + path);
}
exports.Route = Route;
exports.Router = Router;
exports.RouterContext = RouterContext;
Object.defineProperty(exports, '__esModule', { value: true });
})));