@uirouter/core
Version:
UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps
155 lines • 6.98 kB
JavaScript
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
;