@uirouter/core
Version:
UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps
171 lines • 8.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.PathUtils = void 0;
var common_1 = require("../common/common");
var hof_1 = require("../common/hof");
var targetState_1 = require("../state/targetState");
var pathNode_1 = require("./pathNode");
/**
* This class contains functions which convert TargetStates, Nodes and paths from one type to another.
*/
var PathUtils = /** @class */ (function () {
function PathUtils() {
}
/** Given a PathNode[], create an TargetState */
PathUtils.makeTargetState = function (registry, path) {
var state = common_1.tail(path).state;
return new targetState_1.TargetState(registry, state, path.map(hof_1.prop('paramValues')).reduce(common_1.mergeR, {}), {});
};
PathUtils.buildPath = function (targetState) {
var toParams = targetState.params();
return targetState.$state().path.map(function (state) { return new pathNode_1.PathNode(state).applyRawParams(toParams); });
};
/** Given a fromPath: PathNode[] and a TargetState, builds a toPath: PathNode[] */
PathUtils.buildToPath = function (fromPath, targetState) {
var toPath = PathUtils.buildPath(targetState);
if (targetState.options().inherit) {
return PathUtils.inheritParams(fromPath, toPath, Object.keys(targetState.params()));
}
return toPath;
};
/**
* Creates ViewConfig objects and adds to nodes.
*
* On each [[PathNode]], creates ViewConfig objects from the views: property of the node's state
*/
PathUtils.applyViewConfigs = function ($view, path, states) {
// Only apply the viewConfigs to the nodes for the given states
path
.filter(function (node) { return common_1.inArray(states, node.state); })
.forEach(function (node) {
var viewDecls = common_1.values(node.state.views || {});
var subPath = PathUtils.subPath(path, function (n) { return n === node; });
var viewConfigs = viewDecls.map(function (view) { return $view.createViewConfig(subPath, view); });
node.views = viewConfigs.reduce(common_1.unnestR, []);
});
};
/**
* Given a fromPath and a toPath, returns a new to path which inherits parameters from the fromPath
*
* For a parameter in a node to be inherited from the from path:
* - The toPath's node must have a matching node in the fromPath (by state).
* - The parameter name must not be found in the toKeys parameter array.
*
* Note: the keys provided in toKeys are intended to be those param keys explicitly specified by some
* caller, for instance, $state.transitionTo(..., toParams). If a key was found in toParams,
* it is not inherited from the fromPath.
*/
PathUtils.inheritParams = function (fromPath, toPath, toKeys) {
if (toKeys === void 0) { toKeys = []; }
function nodeParamVals(path, state) {
var node = common_1.find(path, hof_1.propEq('state', state));
return common_1.extend({}, node && node.paramValues);
}
var noInherit = fromPath
.map(function (node) { return node.paramSchema; })
.reduce(common_1.unnestR, [])
.filter(function (param) { return !param.inherit; })
.map(hof_1.prop('id'));
/**
* Given an [[PathNode]] "toNode", return a new [[PathNode]] with param values inherited from the
* matching node in fromPath. Only inherit keys that aren't found in "toKeys" from the node in "fromPath""
*/
function makeInheritedParamsNode(toNode) {
// All param values for the node (may include default key/vals, when key was not found in toParams)
var toParamVals = common_1.extend({}, toNode && toNode.paramValues);
// limited to only those keys found in toParams
var incomingParamVals = common_1.pick(toParamVals, toKeys);
toParamVals = common_1.omit(toParamVals, toKeys);
var fromParamVals = common_1.omit(nodeParamVals(fromPath, toNode.state) || {}, noInherit);
// extend toParamVals with any fromParamVals, then override any of those those with incomingParamVals
var ownParamVals = common_1.extend(toParamVals, fromParamVals, incomingParamVals);
return new pathNode_1.PathNode(toNode.state).applyRawParams(ownParamVals);
}
// The param keys specified by the incoming toParams
return toPath.map(makeInheritedParamsNode);
};
/**
* Computes the tree changes (entering, exiting) between a fromPath and toPath.
*/
PathUtils.treeChanges = function (fromPath, toPath, reloadState) {
var max = Math.min(fromPath.length, toPath.length);
var keep = 0;
var nodesMatch = function (node1, node2) { return node1.equals(node2, PathUtils.nonDynamicParams); };
while (keep < max && fromPath[keep].state !== reloadState && nodesMatch(fromPath[keep], toPath[keep])) {
keep++;
}
/** Given a retained node, return a new node which uses the to node's param values */
function applyToParams(retainedNode, idx) {
var cloned = retainedNode.clone();
cloned.paramValues = toPath[idx].paramValues;
return cloned;
}
var from, retained, exiting, entering, to;
from = fromPath;
retained = from.slice(0, keep);
exiting = from.slice(keep);
// Create a new retained path (with shallow copies of nodes) which have the params of the toPath mapped
var retainedWithToParams = retained.map(applyToParams);
entering = toPath.slice(keep);
to = retainedWithToParams.concat(entering);
return { from: from, to: to, retained: retained, retainedWithToParams: retainedWithToParams, exiting: exiting, entering: entering };
};
/**
* Returns a new path which is: the subpath of the first path which matches the second path.
*
* The new path starts from root and contains any nodes that match the nodes in the second path.
* It stops before the first non-matching node.
*
* Nodes are compared using their state property and their parameter values.
* If a `paramsFn` is provided, only the [[Param]] returned by the function will be considered when comparing nodes.
*
* @param pathA the first path
* @param pathB the second path
* @param paramsFn a function which returns the parameters to consider when comparing
*
* @returns an array of PathNodes from the first path which match the nodes in the second path
*/
PathUtils.matching = function (pathA, pathB, paramsFn) {
var done = false;
var tuples = common_1.arrayTuples(pathA, pathB);
return tuples.reduce(function (matching, _a) {
var nodeA = _a[0], nodeB = _a[1];
done = done || !nodeA.equals(nodeB, paramsFn);
return done ? matching : matching.concat(nodeA);
}, []);
};
/**
* Returns true if two paths are identical.
*
* @param pathA
* @param pathB
* @param paramsFn a function which returns the parameters to consider when comparing
* @returns true if the the states and parameter values for both paths are identical
*/
PathUtils.equals = function (pathA, pathB, paramsFn) {
return pathA.length === pathB.length && PathUtils.matching(pathA, pathB, paramsFn).length === pathA.length;
};
/**
* Return a subpath of a path, which stops at the first matching node
*
* Given an array of nodes, returns a subset of the array starting from the first node,
* stopping when the first node matches the predicate.
*
* @param path a path of [[PathNode]]s
* @param predicate a [[Predicate]] fn that matches [[PathNode]]s
* @returns a subpath up to the matching node, or undefined if no match is found
*/
PathUtils.subPath = function (path, predicate) {
var node = common_1.find(path, predicate);
var elementIdx = path.indexOf(node);
return elementIdx === -1 ? undefined : path.slice(0, elementIdx + 1);
};
PathUtils.nonDynamicParams = function (node) {
return node.state.parameters({ inherit: false }).filter(function (param) { return !param.dynamic; });
};
/** Gets the raw parameter values from a path */
PathUtils.paramValues = function (path) { return path.reduce(function (acc, node) { return common_1.extend(acc, node.paramValues); }, {}); };
return PathUtils;
}());
exports.PathUtils = PathUtils;
//# sourceMappingURL=pathUtils.js.map
;