UNPKG

@uirouter/core

Version:

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

115 lines 5.65 kB
import { extend, assertPredicate, unnestR, identity } from '../common/common'; import { isArray } from '../common/predicates'; import { TransitionHookPhase, TransitionHookScope, } from './interface'; import { TransitionHook } from './transitionHook'; /** * This class returns applicable TransitionHooks for a specific Transition instance. * * Hooks ([[RegisteredHook]]) may be registered globally, e.g., $transitions.onEnter(...), or locally, e.g. * myTransition.onEnter(...). The HookBuilder finds matching RegisteredHooks (where the match criteria is * determined by the type of hook) * * The HookBuilder also converts RegisteredHooks objects to TransitionHook objects, which are used to run a Transition. * * The HookBuilder constructor is given the $transitions service and a Transition instance. Thus, a HookBuilder * instance may only be used for one specific Transition object. (side note: the _treeChanges accessor is private * in the Transition class, so we must also provide the Transition's _treeChanges) */ var HookBuilder = /** @class */ (function () { function HookBuilder(transition) { this.transition = transition; } HookBuilder.prototype.buildHooksForPhase = function (phase) { var _this = this; var $transitions = this.transition.router.transitionService; return $transitions._pluginapi ._getEvents(phase) .map(function (type) { return _this.buildHooks(type); }) .reduce(unnestR, []) .filter(identity); }; /** * Returns an array of newly built TransitionHook objects. * * - Finds all RegisteredHooks registered for the given `hookType` which matched the transition's [[TreeChanges]]. * - Finds [[PathNode]] (or `PathNode[]`) to use as the TransitionHook context(s) * - For each of the [[PathNode]]s, creates a TransitionHook * * @param hookType the type of the hook registration function, e.g., 'onEnter', 'onFinish'. */ HookBuilder.prototype.buildHooks = function (hookType) { var transition = this.transition; var treeChanges = transition.treeChanges(); // Find all the matching registered hooks for a given hook type var matchingHooks = this.getMatchingHooks(hookType, treeChanges, transition); if (!matchingHooks) return []; var baseHookOptions = { transition: transition, current: transition.options().current, }; var makeTransitionHooks = function (hook) { // Fetch the Nodes that caused this hook to match. var matches = hook.matches(treeChanges, transition); // Select the PathNode[] that will be used as TransitionHook context objects var matchingNodes = matches[hookType.criteriaMatchPath.name]; // Return an array of HookTuples return matchingNodes.map(function (node) { var _options = extend({ bind: hook.bind, traceData: { hookType: hookType.name, context: node }, }, baseHookOptions); var state = hookType.criteriaMatchPath.scope === TransitionHookScope.STATE ? node.state.self : null; var transitionHook = new TransitionHook(transition, state, hook, _options); return { hook: hook, node: node, transitionHook: transitionHook }; }); }; return matchingHooks .map(makeTransitionHooks) .reduce(unnestR, []) .sort(tupleSort(hookType.reverseSort)) .map(function (tuple) { return tuple.transitionHook; }); }; /** * Finds all RegisteredHooks from: * - The Transition object instance hook registry * - The TransitionService ($transitions) global hook registry * * which matched: * - the eventType * - the matchCriteria (to, from, exiting, retained, entering) * * @returns an array of matched [[RegisteredHook]]s */ HookBuilder.prototype.getMatchingHooks = function (hookType, treeChanges, transition) { var isCreate = hookType.hookPhase === TransitionHookPhase.CREATE; // Instance and Global hook registries var $transitions = this.transition.router.transitionService; var registries = isCreate ? [$transitions] : [this.transition, $transitions]; return registries .map(function (reg) { return reg.getHooks(hookType.name); }) // Get named hooks from registries .filter(assertPredicate(isArray, "broken event named: " + hookType.name)) // Sanity check .reduce(unnestR, []) // Un-nest RegisteredHook[][] to RegisteredHook[] array .filter(function (hook) { return hook.matches(treeChanges, transition); }); // Only those satisfying matchCriteria }; return HookBuilder; }()); export { HookBuilder }; /** * A factory for a sort function for HookTuples. * * The sort function first compares the PathNode depth (how deep in the state tree a node is), then compares * the EventHook priority. * * @param reverseDepthSort a boolean, when true, reverses the sort order for the node depth * @returns a tuple sort function */ function tupleSort(reverseDepthSort) { if (reverseDepthSort === void 0) { reverseDepthSort = false; } return function nodeDepthThenPriority(l, r) { var factor = reverseDepthSort ? -1 : 1; var depthDelta = (l.node.state.path.length - r.node.state.path.length) * factor; return depthDelta !== 0 ? depthDelta : r.hook.priority - l.hook.priority; }; } //# sourceMappingURL=hookBuilder.js.map