reduxen
Version:
Redux-first router
209 lines (164 loc) • 5.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stringifyUrl = require("./stringifyUrl.js");
var _stringifyUrl2 = _interopRequireDefault(_stringifyUrl);
var _parseUrl3 = require("./parseUrl.js");
var _parseUrl4 = _interopRequireDefault(_parseUrl3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var createHistoryRouter = function createHistoryRouter() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var prefix = opts.prefix || "ROUTER__";
var selectRouter = opts.selectRouter || function (_ref) {
var router = _ref.router;
return router;
};
var initialUrl = opts.initialUrl || null;
var redirectCallback = opts.redirectCallback || null;
/*
REDUCER
*/
var initialState = { path: "", query: {}, hash: "" };
var reducer = function reducer() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
var action = arguments[1];
if (action.type === prefix + "ENTERED") {
var _action$payload = action.payload,
path = _action$payload.path,
query = _action$payload.query,
hash = _action$payload.hash;
return { path: path, query: query, hash: hash };
}
return state;
};
/*
MIDDLEWARE
*/
var middleware = function middleware(_ref2) {
var dispatch = _ref2.dispatch,
getState = _ref2.getState;
var window = global.window || null;
var history = window ? window.history : null;
var location = window ? window.location : null;
// dispatch left & entered actions
var dispatchTransition = function dispatchTransition(from, to) {
if (from) {
dispatch({
type: prefix + "LEFT",
payload: { path: from.path, query: from.query, hash: from.hash, to: to }
});
}
dispatch({
type: prefix + "ENTERED",
payload: {
path: to.path,
query: to.query,
hash: to.hash,
from: from || { path: "", query: {}, hash: "" }
}
});
};
// subscribe to popstate
if (window) {
window.addEventListener("popstate", function () {
var router = selectRouter(getState());
var _parseUrl = (0, _parseUrl4.default)(location.pathname + location.search + location.hash),
path = _parseUrl.path,
query = _parseUrl.query,
hash = _parseUrl.hash;
dispatchTransition(router, {
path: path,
query: query || {},
hash: hash || ""
});
});
}
// dispatch initial route
setImmediate(function () {
var router = selectRouter(getState());
if (!router.path) {
var url = initialUrl || location.pathname + location.search + location.hash;
var _parseUrl2 = (0, _parseUrl4.default)(url),
path = _parseUrl2.path,
query = _parseUrl2.query,
hash = _parseUrl2.hash;
dispatchTransition(null, {
path: path,
query: query || {},
hash: hash || ""
});
}
});
// handle incoming actions
return function (next) {
return function (action) {
switch (action.type) {
case prefix + "PUSH":
case prefix + "REPLACE":
{
var payload = action.payload;
var router = selectRouter(getState());
var finalUrlObject = void 0;
if ("path" in payload) {
finalUrlObject = {
path: payload.path,
query: payload.query || {},
hash: payload.hash || ""
};
} else {
if ("query" in payload) {
finalUrlObject = {
path: router.path,
query: payload.query,
hash: payload.hash || ""
};
} else {
if ("hash" in payload) {
finalUrlObject = {
path: router.path,
query: router.query,
hash: payload.hash
};
} else {
break;
}
}
}
var stringifiedUrl = (0, _stringifyUrl2.default)(finalUrlObject);
if (redirectCallback) {
redirectCallback(stringifiedUrl);
}
if (history) {
if (action.type === prefix + "PUSH") {
history.pushState(null, null, stringifiedUrl);
} else {
history.replaceState(null, null, stringifiedUrl);
}
dispatchTransition(router, finalUrlObject);
}
}
break;
case prefix + "BACK":
if (history) {
history.back();
}
break;
case prefix + "FORWARD":
if (history) {
history.forward();
}
break;
case prefix + "GO":
if (history) {
history.go(action.payload.entries);
}
break;
}
return next(action);
};
};
};
return { middleware: middleware, reducer: reducer };
};
exports.default = createHistoryRouter;