"use strict"; exports.__esModule = true; exports.globalHistory = exports.redirectTo = exports.navigate = exports.isRedirect = exports.createMemorySource = exports.createHistory = exports.ServerLocation = exports.Router = exports.Redirect = exports.Match = exports.LocationProvider = exports.Location = exports.Link = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _warning = require("warning"); var _warning2 = _interopRequireDefault(_warning); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _invariant = require("invariant"); var _invariant2 = _interopRequireDefault(_invariant); var _createReactContext = require("create-react-context"); var _createReactContext2 = _interopRequireDefault(_createReactContext); var _reactLifecyclesCompat = require("react-lifecycles-compat"); var _utils = require("./lib/utils"); var _history = require("./lib/history"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* eslint-disable jsx-a11y/anchor-has-content */ //////////////////////////////////////////////////////////////////////////////// var createNamedContext = function createNamedContext(name, defaultValue) { var Ctx = (0, _createReactContext2.default)(defaultValue); Ctx.Consumer.displayName = name + ".Consumer"; Ctx.Provider.displayName = name + ".Provider"; return Ctx; }; //////////////////////////////////////////////////////////////////////////////// // Location Context/Provider var LocationContext = createNamedContext("Location"); // sets up a listener if there isn't one already so apps don't need to be // wrapped in some top level provider var Location = function Location(_ref) { var children = _ref.children; return _react2.default.createElement( LocationContext.Consumer, null, function (context) { return context ? children(context) : _react2.default.createElement( LocationProvider, null, children ); } ); }; var LocationProvider = function (_React$Component) { _inherits(LocationProvider, _React$Component); function LocationProvider() { var _temp, _this, _ret; _classCallCheck(this, LocationProvider); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.state = { context: _this.getContext(), refs: { unlisten: null } }, _temp), _possibleConstructorReturn(_this, _ret); } LocationProvider.prototype.getContext = function getContext() { var _props$history = this.props.history, navigate = _props$history.navigate, location = _props$history.location; return { navigate: navigate, location: location }; }; LocationProvider.prototype.componentDidCatch = function componentDidCatch(error, info) { if (isRedirect(error)) { var _navigate = this.props.history.navigate; _navigate(error.uri, { replace: true }); } else { throw error; } }; LocationProvider.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { if (prevState.context.location !== this.state.context.location) { this.props.history._onTransitionComplete(); } }; LocationProvider.prototype.componentDidMount = function componentDidMount() { var _this2 = this; var refs = this.state.refs, history = this.props.history; refs.unlisten = history.listen(function () { Promise.resolve().then(function () { // TODO: replace rAF with react deferred update API when it's ready https://github.com/facebook/react/issues/13306 requestAnimationFrame(function () { if (!_this2.unmounted) { _this2.setState(function () { return { context: _this2.getContext() }; }); } }); }); }); }; LocationProvider.prototype.componentWillUnmount = function componentWillUnmount() { var refs = this.state.refs; this.unmounted = true; refs.unlisten(); }; LocationProvider.prototype.render = function render() { var context = this.state.context, children = this.props.children; return _react2.default.createElement( LocationContext.Provider, { value: context }, typeof children === "function" ? children(context) : children || null ); }; return LocationProvider; }(_react2.default.Component); //////////////////////////////////////////////////////////////////////////////// LocationProvider.defaultProps = { history: _history.globalHistory }; process.env.NODE_ENV !== "production" ? LocationProvider.propTypes = { history: _propTypes2.default.object.isRequired } : void 0; var ServerLocation = function ServerLocation(_ref2) { var url = _ref2.url, children = _ref2.children; return _react2.default.createElement( LocationContext.Provider, { value: { location: { pathname: url, search: "", hash: "" }, navigate: function navigate() { throw new Error("You can't call navigate on the server."); } } }, children ); }; //////////////////////////////////////////////////////////////////////////////// // Sets baseuri and basepath for nested routers and links var BaseContext = createNamedContext("Base", { baseuri: "/", basepath: "/" }); //////////////////////////////////////////////////////////////////////////////// // The main event, welcome to the show everybody. var Router = function Router(props) { return _react2.default.createElement( BaseContext.Consumer, null, function (baseContext) { return _react2.default.createElement( Location, null, function (locationContext) { return _react2.default.createElement(RouterImpl, _extends({}, baseContext, locationContext, props)); } ); } ); }; var RouterImpl = function (_React$PureComponent) { _inherits(RouterImpl, _React$PureComponent); function RouterImpl() { _classCallCheck(this, RouterImpl); return _possibleConstructorReturn(this, _React$PureComponent.apply(this, arguments)); } RouterImpl.prototype.render = function render() { var _props = this.props, location = _props.location, _navigate2 = _props.navigate, basepath = _props.basepath, primary = _props.primary, children = _props.children, baseuri = _props.baseuri, _props$component = _props.component, component = _props$component === undefined ? "div" : _props$component, domProps = _objectWithoutProperties(_props, ["location", "navigate", "basepath", "primary", "children", "baseuri", "component"]); var routes = _react2.default.Children.map(children, createRoute(basepath)); var pathname = location.pathname; var match = (0, _utils.pick)(routes, pathname); if (match) { var params = match.params, uri = match.uri, route = match.route, element = match.route.value; // remove the /* from the end for child routes relative paths basepath = route.default ? basepath : route.path.replace(/\*$/, ""); var props = _extends({}, params, { uri: uri, location: location, navigate: function navigate(to, options) { return _navigate2((0, _utils.resolve)(to, uri), options); } }); var clone = _react2.default.cloneElement(element, props, element.props.children ? _react2.default.createElement( Router, { primary: primary }, element.props.children ) : undefined); // using 'div' for < 16.3 support var FocusWrapper = primary ? FocusHandler : component; // don't pass any props to 'div' var wrapperProps = primary ? _extends({ uri: uri, location: location, component: component }, domProps) : domProps; return _react2.default.createElement( BaseContext.Provider, { value: { baseuri: uri, basepath: basepath } }, _react2.default.createElement( FocusWrapper, wrapperProps, clone ) ); } else { // Not sure if we want this, would require index routes at every level // warning( // false, // `\n\nNothing matched:\n\t${ // location.pathname // }\n\nPaths checked: \n\t${routes // .map(route => route.path) // .join( // "\n\t" // )}\n\nTo get rid of this warning, add a default NotFound component as child of Router: // \n\tlet NotFound = () =>
Not Found!
// \n\t\n\t \n\t {/* ... */}\n\t` // ); return null; } }; return RouterImpl; }(_react2.default.PureComponent); RouterImpl.defaultProps = { primary: true }; var FocusContext = createNamedContext("Focus"); var FocusHandler = function FocusHandler(_ref3) { var uri = _ref3.uri, location = _ref3.location, component = _ref3.component, domProps = _objectWithoutProperties(_ref3, ["uri", "location", "component"]); return _react2.default.createElement( FocusContext.Consumer, null, function (requestFocus) { return _react2.default.createElement(FocusHandlerImpl, _extends({}, domProps, { component: component, requestFocus: requestFocus, uri: uri, location: location })); } ); }; // don't focus on initial render var initialRender = true; var focusHandlerCount = 0; var FocusHandlerImpl = function (_React$Component2) { _inherits(FocusHandlerImpl, _React$Component2); function FocusHandlerImpl() { var _temp2, _this4, _ret2; _classCallCheck(this, FocusHandlerImpl); for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return _ret2 = (_temp2 = (_this4 = _possibleConstructorReturn(this, _React$Component2.call.apply(_React$Component2, [this].concat(args))), _this4), _this4.state = {}, _this4.requestFocus = function (node) { if (!_this4.state.shouldFocus) { node.focus(); } }, _temp2), _possibleConstructorReturn(_this4, _ret2); } FocusHandlerImpl.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) { var initial = prevState.uri == null; if (initial) { return _extends({ shouldFocus: true }, nextProps); } else { var myURIChanged = nextProps.uri !== prevState.uri; var navigatedUpToMe = prevState.location.pathname !== nextProps.location.pathname && nextProps.location.pathname === nextProps.uri; return _extends({ shouldFocus: myURIChanged || navigatedUpToMe }, nextProps); } }; FocusHandlerImpl.prototype.componentDidMount = function componentDidMount() { focusHandlerCount++; this.focus(); }; FocusHandlerImpl.prototype.componentWillUnmount = function componentWillUnmount() { focusHandlerCount--; if (focusHandlerCount === 0) { initialRender = true; } }; FocusHandlerImpl.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { if (prevProps.location !== this.props.location && this.state.shouldFocus) { this.focus(); } }; FocusHandlerImpl.prototype.focus = function focus() { if (process.env.NODE_ENV === "test") { // getting cannot read property focus of null in the tests // and that bit of global `initialRender` state causes problems // should probably figure it out! return; } var requestFocus = this.props.requestFocus; if (requestFocus) { requestFocus(this.node); } else { if (initialRender) { initialRender = false; } else { // React polyfills [autofocus] and it fires earlier than cDM, // so we were stealing focus away, this line prevents that. if (!this.node.contains(document.activeElement)) { this.node.focus(); } } } }; FocusHandlerImpl.prototype.render = function render() { var _this5 = this; var _props2 = this.props, children = _props2.children, style = _props2.style, requestFocus = _props2.requestFocus, _props2$role = _props2.role, role = _props2$role === undefined ? "group" : _props2$role, _props2$component = _props2.component, Comp = _props2$component === undefined ? "div" : _props2$component, uri = _props2.uri, location = _props2.location, domProps = _objectWithoutProperties(_props2, ["children", "style", "requestFocus", "role", "component", "uri", "location"]); return _react2.default.createElement( Comp, _extends({ style: _extends({ outline: "none" }, style), tabIndex: "-1", role: role, ref: function ref(n) { return _this5.node = n; } }, domProps), _react2.default.createElement( FocusContext.Provider, { value: this.requestFocus }, this.props.children ) ); }; return FocusHandlerImpl; }(_react2.default.Component); (0, _reactLifecyclesCompat.polyfill)(FocusHandlerImpl); var k = function k() {}; //////////////////////////////////////////////////////////////////////////////// var forwardRef = _react2.default.forwardRef; if (typeof forwardRef === "undefined") { forwardRef = function forwardRef(C) { return C; }; } var Link = forwardRef(function (_ref4, ref) { var innerRef = _ref4.innerRef, props = _objectWithoutProperties(_ref4, ["innerRef"]); return _react2.default.createElement( BaseContext.Consumer, null, function (_ref5) { var basepath = _ref5.basepath, baseuri = _ref5.baseuri; return _react2.default.createElement( Location, null, function (_ref6) { var location = _ref6.location, navigate = _ref6.navigate; var to = props.to, state = props.state, replace = props.replace, _props$getProps = props.getProps, getProps = _props$getProps === undefined ? k : _props$getProps, anchorProps = _objectWithoutProperties(props, ["to", "state", "replace", "getProps"]); var href = (0, _utils.resolve)(to, baseuri); var isCurrent = location.pathname === href; var isPartiallyCurrent = (0, _utils.startsWith)(location.pathname, href); return _react2.default.createElement("a", _extends({ ref: ref || innerRef, "aria-current": isCurrent ? "page" : undefined }, anchorProps, getProps({ isCurrent: isCurrent, isPartiallyCurrent: isPartiallyCurrent, href: href, location: location }), { href: href, onClick: function onClick(event) { if (anchorProps.onClick) anchorProps.onClick(event); if (shouldNavigate(event)) { event.preventDefault(); navigate(href, { state: state, replace: replace }); } } })); } ); } ); }); //////////////////////////////////////////////////////////////////////////////// function RedirectRequest(uri) { this.uri = uri; } var isRedirect = function isRedirect(o) { return o instanceof RedirectRequest; }; var redirectTo = function redirectTo(to) { throw new RedirectRequest(to); }; var RedirectImpl = function (_React$Component3) { _inherits(RedirectImpl, _React$Component3); function RedirectImpl() { _classCallCheck(this, RedirectImpl); return _possibleConstructorReturn(this, _React$Component3.apply(this, arguments)); } // Support React < 16 with this hook RedirectImpl.prototype.componentDidMount = function componentDidMount() { var _props3 = this.props, navigate = _props3.navigate, to = _props3.to, from = _props3.from, _props3$replace = _props3.replace, replace = _props3$replace === undefined ? true : _props3$replace, state = _props3.state, noThrow = _props3.noThrow, props = _objectWithoutProperties(_props3, ["navigate", "to", "from", "replace", "state", "noThrow"]); Promise.resolve().then(function () { navigate((0, _utils.insertParams)(to, props), { replace: replace, state: state }); }); }; RedirectImpl.prototype.render = function render() { var _props4 = this.props, navigate = _props4.navigate, to = _props4.to, from = _props4.from, replace = _props4.replace, state = _props4.state, noThrow = _props4.noThrow, props = _objectWithoutProperties(_props4, ["navigate", "to", "from", "replace", "state", "noThrow"]); if (!noThrow) redirectTo((0, _utils.insertParams)(to, props)); return null; }; return RedirectImpl; }(_react2.default.Component); var Redirect = function Redirect(props) { return _react2.default.createElement( Location, null, function (locationContext) { return _react2.default.createElement(RedirectImpl, _extends({}, locationContext, props)); } ); }; process.env.NODE_ENV !== "production" ? Redirect.propTypes = { from: _propTypes2.default.string, to: _propTypes2.default.string.isRequired } : void 0; //////////////////////////////////////////////////////////////////////////////// var Match = function Match(_ref7) { var path = _ref7.path, children = _ref7.children; return _react2.default.createElement( BaseContext.Consumer, null, function (_ref8) { var baseuri = _ref8.baseuri; return _react2.default.createElement( Location, null, function (_ref9) { var navigate = _ref9.navigate, location = _ref9.location; var resolvedPath = (0, _utils.resolve)(path, baseuri); var result = (0, _utils.match)(resolvedPath, location.pathname); return children({ navigate: navigate, location: location, match: result ? _extends({}, result.params, { uri: result.uri, path: path }) : null }); } ); } ); }; //////////////////////////////////////////////////////////////////////////////// // Junk var stripSlashes = function stripSlashes(str) { return str.replace(/(^\/+|\/+$)/g, ""); }; var createRoute = function createRoute(basepath) { return function (element) { if (!element) { return null; } !(element.props.path || element.props.default || element.type === Redirect) ? process.env.NODE_ENV !== "production" ? (0, _invariant2.default)(false, ": Children of must have a `path` or `default` prop, or be a ``. None found on element type `" + element.type + "`") : (0, _invariant2.default)(false) : void 0; !!(element.type === Redirect && (!element.props.from || !element.props.to)) ? process.env.NODE_ENV !== "production" ? (0, _invariant2.default)(false, " requires both \"from\" and \"to\" props when inside a .") : (0, _invariant2.default)(false) : void 0; !!(element.type === Redirect && !(0, _utils.validateRedirect)(element.props.from, element.props.to)) ? process.env.NODE_ENV !== "production" ? (0, _invariant2.default)(false, " has mismatched dynamic segments, ensure both paths have the exact same dynamic segments.") : (0, _invariant2.default)(false) : void 0; if (element.props.default) { return { value: element, default: true }; } var elementPath = element.type === Redirect ? element.props.from : element.props.path; var path = elementPath === "/" ? basepath : stripSlashes(basepath) + "/" + stripSlashes(elementPath); return { value: element, default: element.props.default, path: element.props.children ? stripSlashes(path) + "/*" : path }; }; }; var shouldNavigate = function shouldNavigate(event) { return !event.defaultPrevented && event.button === 0 && !(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); }; //////////////////////////////////////////////////////////////////////// exports.Link = Link; exports.Location = Location; exports.LocationProvider = LocationProvider; exports.Match = Match; exports.Redirect = Redirect; exports.Router = Router; exports.ServerLocation = ServerLocation; exports.createHistory = _history.createHistory; exports.createMemorySource = _history.createMemorySource; exports.isRedirect = isRedirect; exports.navigate = _history.navigate; exports.redirectTo = redirectTo; exports.globalHistory = _history.globalHistory;