@uirouter/core
Version:
UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps
672 lines • 30.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transition = void 0;
var trace_1 = require("../common/trace");
var coreservices_1 = require("../common/coreservices");
var strings_1 = require("../common/strings");
var common_1 = require("../common/common");
var predicates_1 = require("../common/predicates");
var hof_1 = require("../common/hof");
var interface_1 = require("./interface"); // has or is using
var transitionHook_1 = require("./transitionHook");
var hookRegistry_1 = require("./hookRegistry");
var hookBuilder_1 = require("./hookBuilder");
var pathUtils_1 = require("../path/pathUtils");
var param_1 = require("../params/param");
var resolvable_1 = require("../resolve/resolvable");
var resolveContext_1 = require("../resolve/resolveContext");
var rejectFactory_1 = require("./rejectFactory");
var common_2 = require("../common");
/** @internal */
var stateSelf = hof_1.prop('self');
/**
* Represents a transition between two states.
*
* When navigating to a state, we are transitioning **from** the current state **to** the new state.
*
* This object contains all contextual information about the to/from states, parameters, resolves.
* It has information about all states being entered and exited as a result of the transition.
*/
var Transition = /** @class */ (function () {
/**
* Creates a new Transition object.
*
* If the target state is not valid, an error is thrown.
*
* @internal
*
* @param fromPath The path of [[PathNode]]s from which the transition is leaving. The last node in the `fromPath`
* encapsulates the "from state".
* @param targetState The target state and parameters being transitioned to (also, the transition options)
* @param router The [[UIRouter]] instance
* @internal
*/
function Transition(fromPath, targetState, router) {
var _this = this;
/** @internal */
this._deferred = coreservices_1.services.$q.defer();
/**
* This promise is resolved or rejected based on the outcome of the Transition.
*
* When the transition is successful, the promise is resolved
* When the transition is unsuccessful, the promise is rejected with the [[Rejection]] or javascript error
*/
this.promise = this._deferred.promise;
/** @internal Holds the hook registration functions such as those passed to Transition.onStart() */
this._registeredHooks = {};
/** @internal */
this._hookBuilder = new hookBuilder_1.HookBuilder(this);
/** Checks if this transition is currently active/running. */
this.isActive = function () { return _this.router.globals.transition === _this; };
this.router = router;
this._targetState = targetState;
if (!targetState.valid()) {
throw new Error(targetState.error());
}
// current() is assumed to come from targetState.options, but provide a naive implementation otherwise.
this._options = common_1.extend({ current: hof_1.val(this) }, targetState.options());
this.$id = router.transitionService._transitionCount++;
var toPath = pathUtils_1.PathUtils.buildToPath(fromPath, targetState);
this._treeChanges = pathUtils_1.PathUtils.treeChanges(fromPath, toPath, this._options.reloadState);
this.createTransitionHookRegFns();
var onCreateHooks = this._hookBuilder.buildHooksForPhase(interface_1.TransitionHookPhase.CREATE);
transitionHook_1.TransitionHook.invokeHooks(onCreateHooks, function () { return null; });
this.applyViewConfigs(router);
}
/** @internal */
Transition.prototype.onBefore = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onStart = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onExit = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onRetain = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onEnter = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onFinish = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onSuccess = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
Transition.prototype.onError = function (criteria, callback, options) {
return;
};
/** @internal
* Creates the transition-level hook registration functions
* (which can then be used to register hooks)
*/
Transition.prototype.createTransitionHookRegFns = function () {
var _this = this;
this.router.transitionService._pluginapi
._getEvents()
.filter(function (type) { return type.hookPhase !== interface_1.TransitionHookPhase.CREATE; })
.forEach(function (type) { return hookRegistry_1.makeEvent(_this, _this.router.transitionService, type); });
};
/** @internal */
Transition.prototype.getHooks = function (hookName) {
return this._registeredHooks[hookName];
};
Transition.prototype.applyViewConfigs = function (router) {
var enteringStates = this._treeChanges.entering.map(function (node) { return node.state; });
pathUtils_1.PathUtils.applyViewConfigs(router.transitionService.$view, this._treeChanges.to, enteringStates);
};
/**
* @internal
* @returns the internal from [State] object
*/
Transition.prototype.$from = function () {
return common_1.tail(this._treeChanges.from).state;
};
/**
* @internal
* @returns the internal to [State] object
*/
Transition.prototype.$to = function () {
return common_1.tail(this._treeChanges.to).state;
};
/**
* Returns the "from state"
*
* Returns the state that the transition is coming *from*.
*
* @returns The state declaration object for the Transition's ("from state").
*/
Transition.prototype.from = function () {
return this.$from().self;
};
/**
* Returns the "to state"
*
* Returns the state that the transition is going *to*.
*
* @returns The state declaration object for the Transition's target state ("to state").
*/
Transition.prototype.to = function () {
return this.$to().self;
};
/**
* Gets the Target State
*
* A transition's [[TargetState]] encapsulates the [[to]] state, the [[params]], and the [[options]] as a single object.
*
* @returns the [[TargetState]] of this Transition
*/
Transition.prototype.targetState = function () {
return this._targetState;
};
/**
* Determines whether two transitions are equivalent.
* @deprecated
*/
Transition.prototype.is = function (compare) {
if (compare instanceof Transition) {
// TODO: Also compare parameters
return this.is({ to: compare.$to().name, from: compare.$from().name });
}
return !((compare.to && !hookRegistry_1.matchState(this.$to(), compare.to, this)) ||
(compare.from && !hookRegistry_1.matchState(this.$from(), compare.from, this)));
};
Transition.prototype.params = function (pathname) {
if (pathname === void 0) { pathname = 'to'; }
return Object.freeze(this._treeChanges[pathname].map(hof_1.prop('paramValues')).reduce(common_1.mergeR, {}));
};
Transition.prototype.paramsChanged = function () {
var fromParams = this.params('from');
var toParams = this.params('to');
// All the parameters declared on both the "to" and "from" paths
var allParamDescriptors = []
.concat(this._treeChanges.to)
.concat(this._treeChanges.from)
.map(function (pathNode) { return pathNode.paramSchema; })
.reduce(common_2.flattenR, [])
.reduce(common_2.uniqR, []);
var changedParamDescriptors = param_1.Param.changed(allParamDescriptors, fromParams, toParams);
return changedParamDescriptors.reduce(function (changedValues, descriptor) {
changedValues[descriptor.id] = toParams[descriptor.id];
return changedValues;
}, {});
};
/**
* Creates a [[UIInjector]] Dependency Injector
*
* Returns a Dependency Injector for the Transition's target state (to state).
* The injector provides resolve values which the target state has access to.
*
* The `UIInjector` can also provide values from the native root/global injector (ng1/ng2).
*
* #### Example:
* ```js
* .onEnter({ entering: 'myState' }, trans => {
* var myResolveValue = trans.injector().get('myResolve');
* // Inject a global service from the global/native injector (if it exists)
* var MyService = trans.injector().get('MyService');
* })
* ```
*
* In some cases (such as `onBefore`), you may need access to some resolve data but it has not yet been fetched.
* You can use [[UIInjector.getAsync]] to get a promise for the data.
* #### Example:
* ```js
* .onBefore({}, trans => {
* return trans.injector().getAsync('myResolve').then(myResolveValue =>
* return myResolveValue !== 'ABORT';
* });
* });
* ```
*
* If a `state` is provided, the injector that is returned will be limited to resolve values that the provided state has access to.
* This can be useful if both a parent state `foo` and a child state `foo.bar` have both defined a resolve such as `data`.
* #### Example:
* ```js
* .onEnter({ to: 'foo.bar' }, trans => {
* // returns result of `foo` state's `myResolve` resolve
* // even though `foo.bar` also has a `myResolve` resolve
* var fooData = trans.injector('foo').get('myResolve');
* });
* ```
*
* If you need resolve data from the exiting states, pass `'from'` as `pathName`.
* The resolve data from the `from` path will be returned.
* #### Example:
* ```js
* .onExit({ exiting: 'foo.bar' }, trans => {
* // Gets the resolve value of `myResolve` from the state being exited
* var fooData = trans.injector(null, 'from').get('myResolve');
* });
* ```
*
*
* @param state Limits the resolves provided to only the resolves the provided state has access to.
* @param pathName Default: `'to'`: Chooses the path for which to create the injector. Use this to access resolves for `exiting` states.
*
* @returns a [[UIInjector]]
*/
Transition.prototype.injector = function (state, pathName) {
if (pathName === void 0) { pathName = 'to'; }
var path = this._treeChanges[pathName];
if (state)
path = pathUtils_1.PathUtils.subPath(path, function (node) { return node.state === state || node.state.name === state; });
return new resolveContext_1.ResolveContext(path).injector();
};
/**
* Gets all available resolve tokens (keys)
*
* This method can be used in conjunction with [[injector]] to inspect the resolve values
* available to the Transition.
*
* This returns all the tokens defined on [[StateDeclaration.resolve]] blocks, for the states
* in the Transition's [[TreeChanges.to]] path.
*
* #### Example:
* This example logs all resolve values
* ```js
* let tokens = trans.getResolveTokens();
* tokens.forEach(token => console.log(token + " = " + trans.injector().get(token)));
* ```
*
* #### Example:
* This example creates promises for each resolve value.
* This triggers fetches of resolves (if any have not yet been fetched).
* When all promises have all settled, it logs the resolve values.
* ```js
* let tokens = trans.getResolveTokens();
* let promise = tokens.map(token => trans.injector().getAsync(token));
* Promise.all(promises).then(values => console.log("Resolved values: " + values));
* ```
*
* Note: Angular 1 users whould use `$q.all()`
*
* @param pathname resolve context's path name (e.g., `to` or `from`)
*
* @returns an array of resolve tokens (keys)
*/
Transition.prototype.getResolveTokens = function (pathname) {
if (pathname === void 0) { pathname = 'to'; }
return new resolveContext_1.ResolveContext(this._treeChanges[pathname]).getTokens();
};
/**
* Dynamically adds a new [[Resolvable]] (i.e., [[StateDeclaration.resolve]]) to this transition.
*
* Allows a transition hook to dynamically add a Resolvable to this Transition.
*
* Use the [[Transition.injector]] to retrieve the resolved data in subsequent hooks ([[UIInjector.get]]).
*
* If a `state` argument is provided, the Resolvable is processed when that state is being entered.
* If no `state` is provided then the root state is used.
* If the given `state` has already been entered, the Resolvable is processed when any child state is entered.
* If no child states will be entered, the Resolvable is processed during the `onFinish` phase of the Transition.
*
* The `state` argument also scopes the resolved data.
* The resolved data is available from the injector for that `state` and any children states.
*
* #### Example:
* ```js
* transitionService.onBefore({}, transition => {
* transition.addResolvable({
* token: 'myResolve',
* deps: ['MyService'],
* resolveFn: myService => myService.getData()
* });
* });
* ```
*
* @param resolvable a [[ResolvableLiteral]] object (or a [[Resolvable]])
* @param state the state in the "to path" which should receive the new resolve (otherwise, the root state)
*/
Transition.prototype.addResolvable = function (resolvable, state) {
if (state === void 0) { state = ''; }
resolvable = hof_1.is(resolvable_1.Resolvable)(resolvable) ? resolvable : new resolvable_1.Resolvable(resolvable);
var stateName = typeof state === 'string' ? state : state.name;
var topath = this._treeChanges.to;
var targetNode = common_1.find(topath, function (node) { return node.state.name === stateName; });
var resolveContext = new resolveContext_1.ResolveContext(topath);
resolveContext.addResolvables([resolvable], targetNode.state);
};
/**
* Gets the transition from which this transition was redirected.
*
* If the current transition is a redirect, this method returns the transition that was redirected.
*
* #### Example:
* ```js
* let transitionA = $state.go('A').transition
* transitionA.onStart({}, () => $state.target('B'));
* $transitions.onSuccess({ to: 'B' }, (trans) => {
* trans.to().name === 'B'; // true
* trans.redirectedFrom() === transitionA; // true
* });
* ```
*
* @returns The previous Transition, or null if this Transition is not the result of a redirection
*/
Transition.prototype.redirectedFrom = function () {
return this._options.redirectedFrom || null;
};
/**
* Gets the original transition in a redirect chain
*
* A transition might belong to a long chain of multiple redirects.
* This method walks the [[redirectedFrom]] chain back to the original (first) transition in the chain.
*
* #### Example:
* ```js
* // states
* registry.register({ name: 'A', redirectTo: 'B' });
* registry.register({ name: 'B', redirectTo: 'C' });
* registry.register({ name: 'C', redirectTo: 'D' });
* registry.register({ name: 'D' });
*
* let transitionA = $state.go('A').transition
*
* $transitions.onSuccess({ to: 'D' }, (trans) => {
* trans.to().name === 'D'; // true
* trans.redirectedFrom().to().name === 'C'; // true
* trans.originalTransition() === transitionA; // true
* trans.originalTransition().to().name === 'A'; // true
* });
* ```
*
* @returns The original Transition that started a redirect chain
*/
Transition.prototype.originalTransition = function () {
var rf = this.redirectedFrom();
return (rf && rf.originalTransition()) || this;
};
/**
* Get the transition options
*
* @returns the options for this Transition.
*/
Transition.prototype.options = function () {
return this._options;
};
/**
* Gets the states being entered.
*
* @returns an array of states that will be entered during this transition.
*/
Transition.prototype.entering = function () {
return common_1.map(this._treeChanges.entering, hof_1.prop('state')).map(stateSelf);
};
/**
* Gets the states being exited.
*
* @returns an array of states that will be exited during this transition.
*/
Transition.prototype.exiting = function () {
return common_1.map(this._treeChanges.exiting, hof_1.prop('state')).map(stateSelf).reverse();
};
/**
* Gets the states being retained.
*
* @returns an array of states that are already entered from a previous Transition, that will not be
* exited during this Transition
*/
Transition.prototype.retained = function () {
return common_1.map(this._treeChanges.retained, hof_1.prop('state')).map(stateSelf);
};
/**
* Get the [[ViewConfig]]s associated with this Transition
*
* Each state can define one or more views (template/controller), which are encapsulated as `ViewConfig` objects.
* This method fetches the `ViewConfigs` for a given path in the Transition (e.g., "to" or "entering").
*
* @param pathname the name of the path to fetch views for:
* (`'to'`, `'from'`, `'entering'`, `'exiting'`, `'retained'`)
* @param state If provided, only returns the `ViewConfig`s for a single state in the path
*
* @returns a list of ViewConfig objects for the given path.
*/
Transition.prototype.views = function (pathname, state) {
if (pathname === void 0) { pathname = 'entering'; }
var path = this._treeChanges[pathname];
path = !state ? path : path.filter(hof_1.propEq('state', state));
return path.map(hof_1.prop('views')).filter(common_1.identity).reduce(common_1.unnestR, []);
};
Transition.prototype.treeChanges = function (pathname) {
return pathname ? this._treeChanges[pathname] : this._treeChanges;
};
/**
* Creates a new transition that is a redirection of the current one.
*
* This transition can be returned from a [[TransitionService]] hook to
* redirect a transition to a new state and/or set of parameters.
*
* @internal
*
* @returns Returns a new [[Transition]] instance.
*/
Transition.prototype.redirect = function (targetState) {
var redirects = 1, trans = this;
// tslint:disable-next-line:no-conditional-assignment
while ((trans = trans.redirectedFrom()) != null) {
if (++redirects > 20)
throw new Error("Too many consecutive Transition redirects (20+)");
}
var redirectOpts = { redirectedFrom: this, source: 'redirect' };
// If the original transition was caused by URL sync, then use { location: 'replace' }
// on the new transition (unless the target state explicitly specifies location: false).
// This causes the original url to be replaced with the url for the redirect target
// so the original url disappears from the browser history.
if (this.options().source === 'url' && targetState.options().location !== false) {
redirectOpts.location = 'replace';
}
var newOptions = common_1.extend({}, this.options(), targetState.options(), redirectOpts);
targetState = targetState.withOptions(newOptions, true);
var newTransition = this.router.transitionService.create(this._treeChanges.from, targetState);
var originalEnteringNodes = this._treeChanges.entering;
var redirectEnteringNodes = newTransition._treeChanges.entering;
// --- Re-use resolve data from original transition ---
// When redirecting from a parent state to a child state where the parent parameter values haven't changed
// (because of the redirect), the resolves fetched by the original transition are still valid in the
// redirected transition.
//
// This allows you to define a redirect on a parent state which depends on an async resolve value.
// You can wait for the resolve, then redirect to a child state based on the result.
// The redirected transition does not have to re-fetch the resolve.
// ---------------------------------------------------------
var nodeIsReloading = function (reloadState) { return function (node) {
return reloadState && node.state.includes[reloadState.name];
}; };
// Find any "entering" nodes in the redirect path that match the original path and aren't being reloaded
var matchingEnteringNodes = pathUtils_1.PathUtils.matching(redirectEnteringNodes, originalEnteringNodes, pathUtils_1.PathUtils.nonDynamicParams).filter(hof_1.not(nodeIsReloading(targetState.options().reloadState)));
// Use the existing (possibly pre-resolved) resolvables for the matching entering nodes.
matchingEnteringNodes.forEach(function (node, idx) {
node.resolvables = originalEnteringNodes[idx].resolvables;
});
return newTransition;
};
/** @internal If a transition doesn't exit/enter any states, returns any [[Param]] whose value changed */
Transition.prototype._changedParams = function () {
var tc = this._treeChanges;
/** Return undefined if it's not a "dynamic" transition, for the following reasons */
// If user explicitly wants a reload
if (this._options.reload)
return undefined;
// If any states are exiting or entering
if (tc.exiting.length || tc.entering.length)
return undefined;
// If to/from path lengths differ
if (tc.to.length !== tc.from.length)
return undefined;
// If the to/from paths are different
var pathsDiffer = common_1.arrayTuples(tc.to, tc.from)
.map(function (tuple) { return tuple[0].state !== tuple[1].state; })
.reduce(common_1.anyTrueR, false);
if (pathsDiffer)
return undefined;
// Find any parameter values that differ
var nodeSchemas = tc.to.map(function (node) { return node.paramSchema; });
var _a = [tc.to, tc.from].map(function (path) { return path.map(function (x) { return x.paramValues; }); }), toValues = _a[0], fromValues = _a[1];
var tuples = common_1.arrayTuples(nodeSchemas, toValues, fromValues);
return tuples.map(function (_a) {
var schema = _a[0], toVals = _a[1], fromVals = _a[2];
return param_1.Param.changed(schema, toVals, fromVals);
}).reduce(common_1.unnestR, []);
};
/**
* Returns true if the transition is dynamic.
*
* A transition is dynamic if no states are entered nor exited, but at least one dynamic parameter has changed.
*
* @returns true if the Transition is dynamic
*/
Transition.prototype.dynamic = function () {
var changes = this._changedParams();
return !changes ? false : changes.map(function (x) { return x.dynamic; }).reduce(common_1.anyTrueR, false);
};
/**
* Returns true if the transition is ignored.
*
* A transition is ignored if no states are entered nor exited, and no parameter values have changed.
*
* @returns true if the Transition is ignored.
*/
Transition.prototype.ignored = function () {
return !!this._ignoredReason();
};
/** @internal */
Transition.prototype._ignoredReason = function () {
var pending = this.router.globals.transition;
var reloadState = this._options.reloadState;
var same = function (pathA, pathB) {
if (pathA.length !== pathB.length)
return false;
var matching = pathUtils_1.PathUtils.matching(pathA, pathB);
return pathA.length === matching.filter(function (node) { return !reloadState || !node.state.includes[reloadState.name]; }).length;
};
var newTC = this.treeChanges();
var pendTC = pending && pending.treeChanges();
if (pendTC && same(pendTC.to, newTC.to) && same(pendTC.exiting, newTC.exiting))
return 'SameAsPending';
if (newTC.exiting.length === 0 && newTC.entering.length === 0 && same(newTC.from, newTC.to))
return 'SameAsCurrent';
};
/**
* Runs the transition
*
* This method is generally called from the [[StateService.transitionTo]]
*
* @internal
*
* @returns a promise for a successful transition.
*/
Transition.prototype.run = function () {
var _this = this;
var runAllHooks = transitionHook_1.TransitionHook.runAllHooks;
// Gets transition hooks array for the given phase
var getHooksFor = function (phase) { return _this._hookBuilder.buildHooksForPhase(phase); };
// When the chain is complete, then resolve or reject the deferred
var transitionSuccess = function () {
trace_1.trace.traceSuccess(_this.$to(), _this);
_this.success = true;
_this._deferred.resolve(_this.to());
runAllHooks(getHooksFor(interface_1.TransitionHookPhase.SUCCESS));
};
var transitionError = function (reason) {
trace_1.trace.traceError(reason, _this);
_this.success = false;
_this._deferred.reject(reason);
_this._error = reason;
runAllHooks(getHooksFor(interface_1.TransitionHookPhase.ERROR));
};
var runTransition = function () {
// Wait to build the RUN hook chain until the BEFORE hooks are done
// This allows a BEFORE hook to dynamically add additional RUN hooks via the Transition object.
var allRunHooks = getHooksFor(interface_1.TransitionHookPhase.RUN);
var done = function () { return coreservices_1.services.$q.when(undefined); };
return transitionHook_1.TransitionHook.invokeHooks(allRunHooks, done);
};
var startTransition = function () {
var globals = _this.router.globals;
globals.lastStartedTransitionId = _this.$id;
globals.transition = _this;
globals.transitionHistory.enqueue(_this);
trace_1.trace.traceTransitionStart(_this);
return coreservices_1.services.$q.when(undefined);
};
var allBeforeHooks = getHooksFor(interface_1.TransitionHookPhase.BEFORE);
transitionHook_1.TransitionHook.invokeHooks(allBeforeHooks, startTransition)
.then(runTransition)
.then(transitionSuccess, transitionError);
return this.promise;
};
/**
* Checks if the Transition is valid
*
* @returns true if the Transition is valid
*/
Transition.prototype.valid = function () {
return !this.error() || this.success !== undefined;
};
/**
* Aborts this transition
*
* Imperative API to abort a Transition.
* This only applies to Transitions that are not yet complete.
*/
Transition.prototype.abort = function () {
// Do not set flag if the transition is already complete
if (predicates_1.isUndefined(this.success)) {
this._aborted = true;
}
};
/**
* The Transition error reason.
*
* If the transition is invalid (and could not be run), returns the reason the transition is invalid.
* If the transition was valid and ran, but was not successful, returns the reason the transition failed.
*
* @returns a transition rejection explaining why the transition is invalid, or the reason the transition failed.
*/
Transition.prototype.error = function () {
var state = this.$to();
if (state.self.abstract) {
return rejectFactory_1.Rejection.invalid("Cannot transition to abstract state '" + state.name + "'");
}
var paramDefs = state.parameters();
var values = this.params();
var invalidParams = paramDefs.filter(function (param) { return !param.validates(values[param.id]); });
if (invalidParams.length) {
var invalidValues = invalidParams.map(function (param) { return "[" + param.id + ":" + strings_1.stringify(values[param.id]) + "]"; }).join(', ');
var detail = "The following parameter values are not valid for state '" + state.name + "': " + invalidValues;
return rejectFactory_1.Rejection.invalid(detail);
}
if (this.success === false)
return this._error;
};
/**
* A string representation of the Transition
*
* @returns A string representation of the Transition
*/
Transition.prototype.toString = function () {
var fromStateOrName = this.from();
var toStateOrName = this.to();
var avoidEmptyHash = function (params) {
return params['#'] !== null && params['#'] !== undefined ? params : common_1.omit(params, ['#']);
};
// (X) means the to state is invalid.
var id = this.$id, from = predicates_1.isObject(fromStateOrName) ? fromStateOrName.name : fromStateOrName, fromParams = strings_1.stringify(avoidEmptyHash(this._treeChanges.from.map(hof_1.prop('paramValues')).reduce(common_1.mergeR, {}))), toValid = this.valid() ? '' : '(X) ', to = predicates_1.isObject(toStateOrName) ? toStateOrName.name : toStateOrName, toParams = strings_1.stringify(avoidEmptyHash(this.params()));
return "Transition#" + id + "( '" + from + "'" + fromParams + " -> " + toValid + "'" + to + "'" + toParams + " )";
};
/** @internal */
Transition.diToken = Transition;
return Transition;
}());
exports.Transition = Transition;
//# sourceMappingURL=transition.js.map