UNPKG

react-mini-router-hook

Version:
134 lines (102 loc) 4.12 kB
(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 }); })));