react-view-router
Version:
react-view-router
320 lines (317 loc) • 11.2 kB
JavaScript
import "core-js/modules/es6.symbol.js";
import "core-js/modules/es6.array.filter.js";
import "core-js/modules/es7.object.get-own-property-descriptors.js";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import "core-js/modules/es6.regexp.search.js";
import { Action, HistoryType } from './types';
import { createPath, freeze, createEvents, parsePath, createKey, allowTx, allowTxWithParams, copyOwnProperties } from './utils';
// const BeforeUnloadEventType = 'beforeunload';
export var HashChangeEventType = 'hashchange';
export var PopStateEventType = 'popstate';
export function createHistory(options) {
var _window = options.window,
type = options.type,
getLocationPath = options.getLocationPath,
createHref = options.createHref;
var globalHistory = _window.history;
function getIndexAndLocation() {
var _getLocationPath = getLocationPath(),
_getLocationPath$path = _getLocationPath.pathname,
pathname = _getLocationPath$path === void 0 ? '/' : _getLocationPath$path,
_getLocationPath$sear = _getLocationPath.search,
search = _getLocationPath$sear === void 0 ? '' : _getLocationPath$sear,
_getLocationPath$hash = _getLocationPath.hash,
hash = _getLocationPath$hash === void 0 ? '' : _getLocationPath$hash;
var state = globalHistory.state || {};
return [state.idx, freeze({
pathname,
search,
hash,
state: state.usr || null,
key: state.key || 'default'
})];
}
var action = Action.Push;
var _getIndexAndLocation = getIndexAndLocation(),
_getIndexAndLocation2 = _slicedToArray(_getIndexAndLocation, 2),
index = _getIndexAndLocation2[0],
location = _getIndexAndLocation2[1];
var listeners = createEvents();
var blockers = createEvents();
function getIndex(delta) {
var ret = index;
if (delta) ret = Math.max(index + delta, 0);
return ret;
}
function getNextLocation(to, state = null) {
return freeze(copyOwnProperties(copyOwnProperties(_objectSpread({}, location), typeof to === 'string' ? parsePath(to) : to, true), {
state,
key: createKey()
}, true));
}
function getHistoryState(nextLocation, index) {
return {
usr: nextLocation.state,
key: nextLocation.key,
idx: index
};
}
function getHistoryStateAndUrl(nextLocation, index) {
return [getHistoryState(nextLocation, index), createHref(nextLocation)];
}
function applyTx(nextAction, payload) {
action = nextAction;
var prevIndex = index;
var _getIndexAndLocation3 = getIndexAndLocation();
var _getIndexAndLocation4 = _slicedToArray(_getIndexAndLocation3, 2);
index = _getIndexAndLocation4[0];
location = _getIndexAndLocation4[1];
if (index == null && prevIndex != null) {
index = nextAction === Action.Push ? prevIndex + 1 : nextAction === Action.Replace ? prevIndex : prevIndex - 1;
}
listeners.call({
action,
index,
location
}, payload);
}
function pushHistoryState(location, index) {
var _getHistoryStateAndUr = getHistoryStateAndUrl(location, index),
_getHistoryStateAndUr2 = _slicedToArray(_getHistoryStateAndUr, 2),
historyState = _getHistoryStateAndUr2[0],
url = _getHistoryStateAndUr2[1];
// TODO: Support forced reloading
// try...catch because iOS limits us to 100 pushState calls :/
try {
globalHistory.pushState(historyState, '', url);
} catch (error) {
// They are going to lose state here, but there is no real
// way to warn them about it since the page will refresh...
_window.location.assign(url);
}
return index;
}
function replaceHistoryState(location, index) {
var _getHistoryStateAndUr3 = getHistoryStateAndUrl(location, index),
_getHistoryStateAndUr4 = _slicedToArray(_getHistoryStateAndUr3, 2),
historyState = _getHistoryStateAndUr4[0],
url = _getHistoryStateAndUr4[1];
// TODO: Support forced reloading
globalHistory.replaceState(historyState, '', url);
return index;
}
var blockedPopTx = null;
var blockedPopAp = null;
var blockedPopDc = null;
function go(delta) {
blockedPopTx = null;
globalHistory.go(delta);
}
function handlePop(e) {
var index = getIndex();
var _getIndexAndLocation5 = getIndexAndLocation(),
_getIndexAndLocation6 = _slicedToArray(_getIndexAndLocation5, 2),
nextIndex = _getIndexAndLocation6[0],
nextLocation = _getIndexAndLocation6[1];
if (nextIndex == null) {
if (index == null || isNaN(index)) index = 0;
nextIndex = createPath(nextLocation) === createPath(location) ? index : index + 1;
replaceHistoryState(nextLocation, nextIndex);
if (!blockedPopAp && !blockedPopTx && nextIndex === index) return;
}
var delta = index - nextIndex;
var nextAction = !delta ? Action.Replace : delta > 0 ? Action.Pop : Action.Push;
if (blockedPopDc) {
blockedPopDc({
index: nextIndex,
location: nextLocation
});
blockedPopDc = null;
} else if (blockedPopAp) {
if (nextIndex === blockedPopAp.prevIndex) {
go(blockedPopAp.delta);
return;
}
blockedPopAp.cb && blockedPopAp.cb();
blockedPopAp = null;
} else if (blockers.length && delta) {
var seed = 0;
var callback = (ok, payload) => {
if (!blockedPopTx) return;
if (ok) {
blockedPopTx = null;
applyTx(nextAction, payload);
return;
}
blockedPopTx.backCallback(seed);
};
nextLocation.fromEvent = true;
blockedPopTx = {
seed,
index,
nextIndex,
action: nextAction,
location: nextLocation,
callback,
backCallback(seed) {
if (this.seed !== seed) return;
blockedPopTx = null;
blockedPopAp = {
action,
index,
location,
prevIndex: nextIndex,
delta
};
go(blockedPopAp.delta);
}
};
allowTxWithParams(blockers, blockedPopTx);
} else {
applyTx(nextAction);
}
}
_window.addEventListener(PopStateEventType, handlePop);
if (type === HistoryType.hash) {
// popstate does not fire on hashchange in IE 11 and old (trident) Edge
// https://developer.mozilla.org/de/docs/Web/API/Window/popstate_event
_window.addEventListener(HashChangeEventType, e => {
if (blockedPopTx || blockedPopAp) return;
var _getIndexAndLocation7 = getIndexAndLocation(),
_getIndexAndLocation8 = _slicedToArray(_getIndexAndLocation7, 2),
nextLocation = _getIndexAndLocation8[1];
// Ignore extraneous hashchange events.
if (createPath(nextLocation) !== createPath(location)) {
handlePop(e);
}
});
}
if (index == null) {
index = 0;
globalHistory.replaceState(_objectSpread(_objectSpread({}, globalHistory.state), {}, {
idx: index
}), '');
}
function push(to, state) {
var nextAction = Action.Push;
var nextLocation = getNextLocation(to, state);
var seed = blockedPopTx ? ++blockedPopTx.seed : -1;
var callback = (ok, payload) => {
if (!ok) {
if (blockedPopTx) blockedPopTx.backCallback(seed);
return;
}
if (blockedPopTx && blockedPopTx.seed === seed) {
blockedPopTx = null;
}
var _cb = index => {
pushHistoryState(nextLocation, index + 1);
applyTx(nextAction, payload);
};
if (typeof to !== 'string' && to.delta) {
blockedPopDc = ({
index
}) => _cb(index);
go(to.delta);
return;
}
if (blockedPopAp) blockedPopAp.cb = () => _cb(index);else _cb(index);
};
if (allowTx(blockers, nextAction, nextLocation, index, getIndex(typeof to !== 'string' ? to.delta : undefined) + 1, callback)) {
callback(true, to);
}
}
function replace(to, state) {
var nextAction = Action.Replace;
var nextLocation = getNextLocation(to, state);
var seed = blockedPopTx ? ++blockedPopTx.seed : -1;
var callback = (ok, payload) => {
if (!ok) {
if (blockedPopTx) blockedPopTx.backCallback(seed);
return;
}
if (blockedPopTx && blockedPopTx.seed === seed) {
blockedPopTx = null;
}
var _cb = index => {
replaceHistoryState(nextLocation, index);
applyTx(nextAction, payload);
};
if (typeof to !== 'string' && to.delta) {
blockedPopDc = ({
index
}) => _cb(index);
go(to.delta);
return;
}
if (blockedPopAp) blockedPopAp.cb = () => _cb(index);else _cb(index);
};
if (allowTx(blockers, nextAction, nextLocation, index, getIndex(typeof to !== 'string' ? to.delta : undefined), callback)) {
callback(true);
}
}
var history = {
get extra() {
return options.extra;
},
get type() {
return type;
},
get action() {
return action;
},
get location() {
return location;
},
get index() {
return index;
},
get length() {
return globalHistory.length;
},
get state() {
return getHistoryState(location, index).usr;
},
get realtimeLocation() {
var _getIndexAndLocation9 = getIndexAndLocation(),
_getIndexAndLocation0 = _slicedToArray(_getIndexAndLocation9, 2),
current = _getIndexAndLocation0[1];
return current.pathname === location.pathname && current.search === location.search && current.hash === location.hash ? location : current;
},
createHref,
getIndexAndLocation,
push,
replace,
replaceState(state) {
var historyState = getHistoryState(location, index);
historyState.usr = state;
globalHistory.replaceState(historyState, '');
return state;
},
refresh() {
var _getIndexAndLocation1 = getIndexAndLocation();
var _getIndexAndLocation10 = _slicedToArray(_getIndexAndLocation1, 2);
index = _getIndexAndLocation10[0];
location = _getIndexAndLocation10[1];
return [index, location];
},
go,
back() {
go(-1);
},
forward() {
go(1);
},
listen(listener) {
return listeners.push(listener);
},
block(blocker) {
return blockers.push(blocker);
}
};
return history;
}
//# sourceMappingURL=history.js.map