UNPKG

@uirouter/core

Version:

UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps

171 lines 8.7 kB
"use strict"; 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