UNPKG

6.98 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.makeEvent = exports.RegisteredHook = exports.matchState = void 0;
4var common_1 = require("../common");
5var interface_1 = require("./interface");
6/**
7 * Determines if the given state matches the matchCriteria
8 *
9 * @internal
10 *
11 * @param state a State Object to test against
12 * @param criterion
13 * - If a string, matchState uses the string as a glob-matcher against the state name
14 * - If an array (of strings), matchState uses each string in the array as a glob-matchers against the state name
15 * and returns a positive match if any of the globs match.
16 * - If a function, matchState calls the function with the state and returns true if the function's result is truthy.
17 * @returns {boolean}
18 */
19function matchState(state, criterion, transition) {
20 var toMatch = common_1.isString(criterion) ? [criterion] : criterion;
21 function matchGlobs(_state) {
22 var globStrings = toMatch;
23 for (var i = 0; i < globStrings.length; i++) {
24 var glob = new common_1.Glob(globStrings[i]);
25 if ((glob && glob.matches(_state.name)) || (!glob && globStrings[i] === _state.name)) {
26 return true;
27 }
28 }
29 return false;
30 }
31 var matchFn = (common_1.isFunction(toMatch) ? toMatch : matchGlobs);
32 return !!matchFn(state, transition);
33}
34exports.matchState = matchState;
35/**
36 * The registration data for a registered transition hook
37 */
38var RegisteredHook = /** @class */ (function () {
39 function RegisteredHook(tranSvc, eventType, callback, matchCriteria, removeHookFromRegistry, options) {
40 if (options === void 0) { options = {}; }
41 this.tranSvc = tranSvc;
42 this.eventType = eventType;
43 this.callback = callback;
44 this.matchCriteria = matchCriteria;
45 this.removeHookFromRegistry = removeHookFromRegistry;
46 this.invokeCount = 0;
47 this._deregistered = false;
48 this.priority = options.priority || 0;
49 this.bind = options.bind || null;
50 this.invokeLimit = options.invokeLimit;
51 }
52 /**
53 * Gets the matching [[PathNode]]s
54 *
55 * Given an array of [[PathNode]]s, and a [[HookMatchCriterion]], returns an array containing
56 * the [[PathNode]]s that the criteria matches, or `null` if there were no matching nodes.
57 *
58 * Returning `null` is significant to distinguish between the default
59 * "match-all criterion value" of `true` compared to a `() => true` function,
60 * when the nodes is an empty array.
61 *
62 * This is useful to allow a transition match criteria of `entering: true`
63 * to still match a transition, even when `entering === []`. Contrast that
64 * with `entering: (state) => true` which only matches when a state is actually
65 * being entered.
66 */
67 RegisteredHook.prototype._matchingNodes = function (nodes, criterion, transition) {
68 if (criterion === true)
69 return nodes;
70 var matching = nodes.filter(function (node) { return matchState(node.state, criterion, transition); });
71 return matching.length ? matching : null;
72 };
73 /**
74 * Gets the default match criteria (all `true`)
75 *
76 * Returns an object which has all the criteria match paths as keys and `true` as values, i.e.:
77 *
78 * ```js
79 * {
80 * to: true,
81 * from: true,
82 * entering: true,
83 * exiting: true,
84 * retained: true,
85 * }
86 */
87 RegisteredHook.prototype._getDefaultMatchCriteria = function () {
88 return common_1.mapObj(this.tranSvc._pluginapi._getPathTypes(), function () { return true; });
89 };
90 /**
91 * Gets matching nodes as [[IMatchingNodes]]
92 *
93 * Create a IMatchingNodes object from the TransitionHookTypes that is roughly equivalent to:
94 *
95 * ```js
96 * let matches: IMatchingNodes = {
97 * to: _matchingNodes([tail(treeChanges.to)], mc.to),
98 * from: _matchingNodes([tail(treeChanges.from)], mc.from),
99 * exiting: _matchingNodes(treeChanges.exiting, mc.exiting),
100 * retained: _matchingNodes(treeChanges.retained, mc.retained),
101 * entering: _matchingNodes(treeChanges.entering, mc.entering),
102 * };
103 * ```
104 */
105 RegisteredHook.prototype._getMatchingNodes = function (treeChanges, transition) {
106 var _this = this;
107 var criteria = common_1.extend(this._getDefaultMatchCriteria(), this.matchCriteria);
108 var paths = common_1.values(this.tranSvc._pluginapi._getPathTypes());
109 return paths.reduce(function (mn, pathtype) {
110 // STATE scope criteria matches against every node in the path.
111 // TRANSITION scope criteria matches against only the last node in the path
112 var isStateHook = pathtype.scope === interface_1.TransitionHookScope.STATE;
113 var path = treeChanges[pathtype.name] || [];
114 var nodes = isStateHook ? path : [common_1.tail(path)];
115 mn[pathtype.name] = _this._matchingNodes(nodes, criteria[pathtype.name], transition);
116 return mn;
117 }, {});
118 };
119 /**
120 * Determines if this hook's [[matchCriteria]] match the given [[TreeChanges]]
121 *
122 * @returns an IMatchingNodes object, or null. If an IMatchingNodes object is returned, its values
123 * are the matching [[PathNode]]s for each [[HookMatchCriterion]] (to, from, exiting, retained, entering)
124 */
125 RegisteredHook.prototype.matches = function (treeChanges, transition) {
126 var matches = this._getMatchingNodes(treeChanges, transition);
127 // Check if all the criteria matched the TreeChanges object
128 var allMatched = common_1.values(matches).every(common_1.identity);
129 return allMatched ? matches : null;
130 };
131 RegisteredHook.prototype.deregister = function () {
132 this.removeHookFromRegistry(this);
133 this._deregistered = true;
134 };
135 return RegisteredHook;
136}());
137exports.RegisteredHook = RegisteredHook;
138/** Return a registration function of the requested type. */
139function makeEvent(registry, transitionService, eventType) {
140 // Create the object which holds the registered transition hooks.
141 var _registeredHooks = (registry._registeredHooks = registry._registeredHooks || {});
142 var hooks = (_registeredHooks[eventType.name] = []);
143 var removeHookFn = common_1.removeFrom(hooks);
144 // Create hook registration function on the IHookRegistry for the event
145 registry[eventType.name] = hookRegistrationFn;
146 function hookRegistrationFn(matchObject, callback, options) {
147 if (options === void 0) { options = {}; }
148 var registeredHook = new RegisteredHook(transitionService, eventType, callback, matchObject, removeHookFn, options);
149 hooks.push(registeredHook);
150 return registeredHook.deregister.bind(registeredHook);
151 }
152 return hookRegistrationFn;
153}
154exports.makeEvent = makeEvent;
155//# sourceMappingURL=hookRegistry.js.map
\No newline at end of file