UNPKG

react-history-switch

Version:

Self-hosted context-free Switch routing component for History.js library (React). The library was created to transfer navigation responsibility from a view into Mobx state container (MVC). Also can be used separately as a self-hosted router

713 lines (602 loc) 19 kB
var React = require('react'); var history = require('history'); var pathToRegexp = require('path-to-regexp'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n['default'] = e; return n; } var React__namespace = /*#__PURE__*/_interopNamespace(React); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); function _extends() { _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; }; return _extends.apply(this, arguments); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } var Context = React.createContext(history.createMemoryHistory()); var HistoryContext = function HistoryContext(_ref) { var children = _ref.children, history = _ref.history; return React__namespace.createElement(Context.Provider, { value: history }, children); }; var useHistoryContext = function useHistoryContext() { return React.useContext(Context); }; var _excluded$1 = ["to"]; var Link = function Link(_ref) { var to = _ref.to, otherProps = _objectWithoutPropertiesLoose(_ref, _excluded$1); var history = useHistoryContext(); return React__namespace.createElement("a", Object.assign({}, otherProps, { href: '#', onClick: function onClick() { return history.push(to); } })); }; var Error = function Error() { return React__default['default'].createElement("p", null, "500"); }; var queued = function queued(promise) { var lastPromise = Promise.resolve(); var wrappedFn = function wrappedFn() { var _arguments = arguments; lastPromise = lastPromise.then(function () { return promise.apply(void 0, [].slice.call(_arguments)); })["finally"](function () { return wrappedFn.clear(); }); return lastPromise; }; wrappedFn.clear = function () { lastPromise = Promise.resolve(); }; return wrappedFn; }; function _catch(body, recover) { try { var result = body(); } catch (e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } function _finallyRethrows(body, finalizer) { try { var result = body(); } catch (e) { return finalizer(true, e); } if (result && result.then) { return result.then(finalizer.bind(null, false), finalizer.bind(null, true)); } return finalizer(false, result); } var Async = function Async(_ref) { var children = _ref.children, _ref$Loader = _ref.Loader, Loader = _ref$Loader === void 0 ? function () { return null; } : _ref$Loader, _ref$Error = _ref.Error, Error = _ref$Error === void 0 ? function () { return null; } : _ref$Error, onLoadStart = _ref.onLoadStart, onLoadEnd = _ref.onLoadEnd, payload = _ref.payload, _ref$deps = _ref.deps, deps = _ref$deps === void 0 ? [] : _ref$deps; var _useState = React.useState(''), child = _useState[0], setChild = _useState[1]; var _useState2 = React.useState(false), loading = _useState2[0], setLoading = _useState2[1]; var _useState3 = React.useState(false), error = _useState3[0], setError = _useState3[1]; var execute = React.useMemo(function () { return queued(function (payload) { try { var _exit2; var isOk = true; setLoading(true); setError(false); onLoadStart && onLoadStart(); var _temp2 = _finallyRethrows(function () { return _catch(function () { var result = children(payload); if (result instanceof Promise) { _exit2 = 1; return Promise.resolve(result).then(function (_result2) { return _result2 || null; }); } else { _exit2 = 1; return result || null; } }, function () { isOk = false; }); }, function (_wasThrown, _result) { setLoading(false); setError(!isOk); onLoadEnd && onLoadEnd(isOk); if (_wasThrown) throw _result; return _result; }); return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function (_result) { return _exit2 ? _result : null; }) : _exit2 ? _temp2 : null); } catch (e) { return Promise.reject(e); } }); }, []); React.useEffect(function () { var process = function process() { try { return Promise.resolve(execute(payload)).then(function (result) { setChild(result); }); } catch (e) { return Promise.reject(e); } }; process(); }, [payload].concat(deps)); if (loading) { return React__namespace.createElement(Loader, null); } else if (error) { return React__namespace.createElement(Error, null); } else { return React__namespace.createElement(React__namespace.Fragment, null, child); } }; var Loader = function Loader() { return React__default['default'].createElement("p", null, "Loading"); }; var _excluded = ["Loader", "Error", "onLoadEnd", "onLoadStart", "children", "state", "payload"]; var FetchView = function FetchView(_ref) { var _ref$Loader = _ref.Loader, Loader$1 = _ref$Loader === void 0 ? Loader : _ref$Loader, _ref$Error = _ref.Error, Error$1 = _ref$Error === void 0 ? Error : _ref$Error, onLoadEnd = _ref.onLoadEnd, onLoadStart = _ref.onLoadStart, children = _ref.children, state = _ref.state, payload = _ref.payload, otherProps = _objectWithoutPropertiesLoose(_ref, _excluded); var handleData = function handleData(payload) { try { if (Array.isArray(state)) { return Promise.resolve(Promise.all(state.map(function (item) { return item(payload); }))); } else { return Promise.resolve(state(payload)).then(function (_state) { return [_state]; }); } } catch (e) { return Promise.reject(e); } }; return React__default['default'].createElement(Async, Object.assign({}, otherProps, { Loader: Loader$1, Error: Error$1, onLoadStart: onLoadStart, onLoadEnd: onLoadEnd, payload: payload }), function (payload) { try { return Promise.resolve(handleData(payload)).then(function (data) { return children.apply(void 0, data); }); } catch (e) { return Promise.reject(e); } }); }; var Forbidden = function Forbidden() { return React__default['default'].createElement("p", null, "Forbidden"); }; var NotFound = function NotFound() { return React__default['default'].createElement("p", null, "Not found"); }; var createWindowHistory = function createWindowHistory() { if (window.location.protocol === 'file:') { return history.createMemoryHistory(); } else { return history.createBrowserHistory(); } }; var sleep = function sleep(timeout) { if (timeout === void 0) { timeout = 1000; } return new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, timeout); }); }; var _iteratorSymbol = typeof Symbol !== "undefined" ? Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator")) : "@@iterator"; function _settle(pact, state, value) { if (!pact.s) { if (value instanceof _Pact) { if (value.s) { if (state & 1) { state = value.s; } value = value.v; } else { value.o = _settle.bind(null, pact, state); return; } } if (value && value.then) { value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2)); return; } pact.s = state; pact.v = value; var observer = pact.o; if (observer) { observer(pact); } } } var _Pact = /*#__PURE__*/function () { function _Pact() {} _Pact.prototype.then = function (onFulfilled, onRejected) { var result = new _Pact(); var state = this.s; if (state) { var callback = state & 1 ? onFulfilled : onRejected; if (callback) { try { _settle(result, 1, callback(this.v)); } catch (e) { _settle(result, 2, e); } return result; } else { return this; } } this.o = function (_this) { try { var value = _this.v; if (_this.s & 1) { _settle(result, 1, onFulfilled ? onFulfilled(value) : value); } else if (onRejected) { _settle(result, 1, onRejected(value)); } else { _settle(result, 2, value); } } catch (e) { _settle(result, 2, e); } }; return result; }; return _Pact; }(); function _isSettledPact(thenable) { return thenable instanceof _Pact && thenable.s & 1; } function _forTo(array, body, check) { var i = -1, pact, reject; function _cycle(result) { try { while (++i < array.length && (!check || !check())) { result = body(i); if (result && result.then) { if (_isSettledPact(result)) { result = result.v; } else { result.then(_cycle, reject || (reject = _settle.bind(null, pact = new _Pact(), 2))); return; } } } if (pact) { _settle(pact, 1, result); } else { pact = result; } } catch (e) { _settle(pact || (pact = new _Pact()), 2, e); } } _cycle(); return pact; } var canActivate = function canActivate(item) { try { var _item$guard = item.guard, guard = _item$guard === void 0 ? function () { return true; } : _item$guard; var isAvailable = guard(); if (isAvailable instanceof Promise) { return Promise.resolve(isAvailable); } else { return Promise.resolve(isAvailable); } } catch (e) { return Promise.reject(e); } }; function _forOf(target, body, check) { if (typeof target[_iteratorSymbol] === "function") { var _cycle = function _cycle(result) { try { while (!(step = iterator.next()).done && (!check || !check())) { result = body(step.value); if (result && result.then) { if (_isSettledPact(result)) { result = result.v; } else { result.then(_cycle, reject || (reject = _settle.bind(null, pact = new _Pact(), 2))); return; } } } if (pact) { _settle(pact, 1, result); } else { pact = result; } } catch (e) { _settle(pact || (pact = new _Pact()), 2, e); } }; var iterator = target[_iteratorSymbol](), step, pact, reject; _cycle(); if (iterator["return"]) { var _fixup = function _fixup(value) { try { if (!step.done) { iterator["return"](); } } catch (e) {} return value; }; if (pact && pact.then) { return pact.then(_fixup, function (e) { throw _fixup(e); }); } _fixup(); } return pact; } // No support for Symbol.iterator // No support for Symbol.iterator if (!("length" in target)) { throw new TypeError("Object is not iterable"); } // Handle live collections properly // Handle live collections properly var values = []; for (var i = 0; i < target.length; i++) { values.push(target[i]); } return _forTo(values, function (i) { return body(values[i]); }, check); } var DEFAULT_HISTORY = createWindowHistory(); var Fragment = function Fragment() { return React__default['default'].createElement(React__default['default'].Fragment, null); }; var Switch = function Switch(_ref) { var _ref$Loader = _ref.Loader, Loader$1 = _ref$Loader === void 0 ? Loader : _ref$Loader, _ref$Forbidden = _ref.Forbidden, Forbidden$1 = _ref$Forbidden === void 0 ? Forbidden : _ref$Forbidden, _ref$NotFound = _ref.NotFound, NotFound$1 = _ref$NotFound === void 0 ? NotFound : _ref$NotFound, _ref$Error = _ref.Error, Error$1 = _ref$Error === void 0 ? Error : _ref$Error, _ref$history = _ref.history, history = _ref$history === void 0 ? DEFAULT_HISTORY : _ref$history, items = _ref.items, onLoadStart = _ref.onLoadStart, onLoadEnd = _ref.onLoadEnd; var unloadRef = React.useRef(null); var _useState = React.useState(_extends({}, history.location)), location = _useState[0], setLocation = _useState[1]; React.useEffect(function () { var handleLocation = function handleLocation(update) { if (update.location.pathname !== location.pathname) { var newLocation = _extends({}, update.location); setLocation(newLocation); } }; return history.listen(handleLocation); }, [history, location]); var handleState = React.useMemo(function () { return function (url) { try { var _temp8 = function _temp8(_unloadRef$current) { var _exit; function _temp5(_result3) { return _exit ? _result3 : { element: NotFound$1 }; } _unloadRef$current; var _temp4 = _forOf(items, function (item) { var _item$element = item.element, element = _item$element === void 0 ? Fragment : _item$element, redirect = item.redirect, prefetch = item.prefetch, unload = item.unload, path = item.path; var params = {}; var keys = []; var reg = pathToRegexp.pathToRegexp(path, keys); var match = reg.test(url); var buildParams = function buildParams() { var tokens = reg.exec(url); tokens && keys.forEach(function (key, i) { params[key.name] = tokens[i + 1]; }); }; var provideUnloadRef = function provideUnloadRef() { if (unload) { unloadRef.current = function () { try { return Promise.resolve(Promise.resolve(unload(params))).then(function () { unloadRef.current = null; }); } catch (e) { return Promise.reject(e); } }; } }; return function () { if (match) { var _exit4; return Promise.resolve(canActivate(item)).then(function (_canActivate) { var _exit3; function _temp3(_result2) { if (_exit3) ; _exit = 1; return { element: Forbidden$1 }; } var _temp2 = function () { if (_canActivate) { var _temp7 = function _temp7(_prefetch) { prefetch && Object.assign(params, _prefetch); provideUnloadRef(); if (typeof redirect === 'string') { setLocation(function (location) { return _extends({}, location, { pathname: redirect }); }); _exit = 1; return { element: Fragment }; } if (typeof redirect === 'function') { var result = redirect(params); if (result !== null) { setLocation(function (location) { return _extends({}, location, { pathname: result }); }); _exit = 1; return { element: Fragment }; } } _exit = 1; return { element: element, params: params }; }; buildParams(); return prefetch ? Promise.resolve(prefetch(params)).then(_temp7) : _temp7(prefetch); } }(); return _temp2 && _temp2.then ? _temp2.then(_temp3) : _temp3(_temp2); }); } }(); }, function () { return _exit; }); return _temp4 && _temp4.then ? _temp4.then(_temp5) : _temp5(_temp4); }; var _unloadRef$current3 = unloadRef.current; return Promise.resolve(_unloadRef$current3 ? Promise.resolve(unloadRef.current()).then(_temp8) : _temp8(_unloadRef$current3)); } catch (e) { return Promise.reject(e); } }; }, [location]); return React__default['default'].createElement(HistoryContext, { history: history }, React__default['default'].createElement(FetchView, { state: handleState, Loader: Loader$1, Error: Error$1, payload: location.pathname, onLoadStart: onLoadStart, onLoadEnd: onLoadEnd }, function (data) { try { var _data$element = data.element, Element = _data$element === void 0 ? Fragment : _data$element, params = data.params; /* delay to prevent sync execution for appear animation */ return Promise.resolve(sleep(0)).then(function () { return React__default['default'].createElement(Element, Object.assign({}, params)); }); } catch (e) { return Promise.reject(e); } })); }; exports.Link = Link; exports.Switch = Switch; //# sourceMappingURL=index.js.map