UNPKG

@uirouter/core

Version:

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

155 lines 6.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeEvent = exports.RegisteredHook = exports.matchState = void 0; var common_1 = require("../common"); var interface_1 = require("./interface"); /** * Determines if the given state matches the matchCriteria * * @internal * * @param state a State Object to test against * @param criterion * - If a string, matchState uses the string as a glob-matcher against the state name * - If an array (of strings), matchState uses each string in the array as a glob-matchers against the state name * and returns a positive match if any of the globs match. * - If a function, matchState calls the function with the state and returns true if the function's result is truthy. * @returns {boolean} */ function matchState(state, criterion, transition) { var toMatch = common_1.isString(criterion) ? [criterion] : criterion; function matchGlobs(_state) { var globStrings = toMatch; for (var i = 0; i < globStrings.length; i++) { var glob = new common_1.Glob(globStrings[i]); if ((glob && glob.matches(_state.name)) || (!glob && globStrings[i] === _state.name)) { return true; } } return false; } var matchFn = (common_1.isFunction(toMatch) ? toMatch : matchGlobs); return !!matchFn(state, transition); } exports.matchState = matchState; /** * The registration data for a registered transition hook */ var RegisteredHook = /** @class */ (function () { function RegisteredHook(tranSvc, eventType, callback, matchCriteria, removeHookFromRegistry, options) { if (options === void 0) { options = {}; } this.tranSvc = tranSvc; this.eventType = eventType; this.callback = callback; this.matchCriteria = matchCriteria; this.removeHookFromRegistry = removeHookFromRegistry; this.invokeCount = 0; this._deregistered = false; this.priority = options.priority || 0; this.bind = options.bind || null; this.invokeLimit = options.invokeLimit; } /** * Gets the matching [[PathNode]]s * * Given an array of [[PathNode]]s, and a [[HookMatchCriterion]], returns an array containing * the [[PathNode]]s that the criteria matches, or `null` if there were no matching nodes. * * Returning `null` is significant to distinguish between the default * "match-all criterion value" of `true` compared to a `() => true` function, * when the nodes is an empty array. * * This is useful to allow a transition match criteria of `entering: true` * to still match a transition, even when `entering === []`. Contrast that * with `entering: (state) => true` which only matches when a state is actually * being entered. */ RegisteredHook.prototype._matchingNodes = function (nodes, criterion, transition) { if (criterion === true) return nodes; var matching = nodes.filter(function (node) { return matchState(node.state, criterion, transition); }); return matching.length ? matching : null; }; /** * Gets the default match criteria (all `true`) * * Returns an object which has all the criteria match paths as keys and `true` as values, i.e.: * * ```js * { * to: true, * from: true, * entering: true, * exiting: true, * retained: true, * } */ RegisteredHook.prototype._getDefaultMatchCriteria = function () { return common_1.mapObj(this.tranSvc._pluginapi._getPathTypes(), function () { return true; }); }; /** * Gets matching nodes as [[IMatchingNodes]] * * Create a IMatchingNodes object from the TransitionHookTypes that is roughly equivalent to: * * ```js * let matches: IMatchingNodes = { * to: _matchingNodes([tail(treeChanges.to)], mc.to), * from: _matchingNodes([tail(treeChanges.from)], mc.from), * exiting: _matchingNodes(treeChanges.exiting, mc.exiting), * retained: _matchingNodes(treeChanges.retained, mc.retained), * entering: _matchingNodes(treeChanges.entering, mc.entering), * }; * ``` */ RegisteredHook.prototype._getMatchingNodes = function (treeChanges, transition) { var _this = this; var criteria = common_1.extend(this._getDefaultMatchCriteria(), this.matchCriteria); var paths = common_1.values(this.tranSvc._pluginapi._getPathTypes()); return paths.reduce(function (mn, pathtype) { // STATE scope criteria matches against every node in the path. // TRANSITION scope criteria matches against only the last node in the path var isStateHook = pathtype.scope === interface_1.TransitionHookScope.STATE; var path = treeChanges[pathtype.name] || []; var nodes = isStateHook ? path : [common_1.tail(path)]; mn[pathtype.name] = _this._matchingNodes(nodes, criteria[pathtype.name], transition); return mn; }, {}); }; /** * Determines if this hook's [[matchCriteria]] match the given [[TreeChanges]] * * @returns an IMatchingNodes object, or null. If an IMatchingNodes object is returned, its values * are the matching [[PathNode]]s for each [[HookMatchCriterion]] (to, from, exiting, retained, entering) */ RegisteredHook.prototype.matches = function (treeChanges, transition) { var matches = this._getMatchingNodes(treeChanges, transition); // Check if all the criteria matched the TreeChanges object var allMatched = common_1.values(matches).every(common_1.identity); return allMatched ? matches : null; }; RegisteredHook.prototype.deregister = function () { this.removeHookFromRegistry(this); this._deregistered = true; }; return RegisteredHook; }()); exports.RegisteredHook = RegisteredHook; /** Return a registration function of the requested type. */ function makeEvent(registry, transitionService, eventType) { // Create the object which holds the registered transition hooks. var _registeredHooks = (registry._registeredHooks = registry._registeredHooks || {}); var hooks = (_registeredHooks[eventType.name] = []); var removeHookFn = common_1.removeFrom(hooks); // Create hook registration function on the IHookRegistry for the event registry[eventType.name] = hookRegistrationFn; function hookRegistrationFn(matchObject, callback, options) { if (options === void 0) { options = {}; } var registeredHook = new RegisteredHook(transitionService, eventType, callback, matchObject, removeHookFn, options); hooks.push(registeredHook); return registeredHook.deregister.bind(registeredHook); } return hookRegistrationFn; } exports.makeEvent = makeEvent; //# sourceMappingURL=hookRegistry.js.map