text: /**
   * State-based routing for AngularJS 1.x
   * This bundle requires the ui-router-core.js bundle from the @uirouter/core package.
   * @version v1.0.18
   * @link https://ui-router.github.io
   * @license MIT License, http://www.opensource.org/licenses/MIT
   */
  (function (global, factory) {
      typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('angular'), require('@uirouter/core')) :
      typeof define === 'function' && define.amd ? define(['exports', 'angular', '@uirouter/core'], factory) :
      (factory((global['@uirouter/angularjs'] = {}),global.angular,global['@uirouter/core']));
  }(this, (function (exports,ng_from_import,core) { 'use strict';
  
      var ng_from_global = angular;
      var ng = ng_from_import && ng_from_import.module ? ng_from_import : ng_from_global;
  
      function getNg1ViewConfigFactory() {
          var templateFactory = null;
          return function (path, view) {
              templateFactory = templateFactory || core.services.$injector.get('$templateFactory');
              return [new Ng1ViewConfig(path, view, templateFactory)];
          };
      }
      var hasAnyKey = function (keys, obj) { return keys.reduce(function (acc, key) { return acc || core.isDefined(obj[key]); }, false); };
      /**
       * This is a [[StateBuilder.builder]] function for angular1 `views`.
       *
       * When the [[StateBuilder]] builds a [[StateObject]] object from a raw [[StateDeclaration]], this builder
       * handles the `views` property with logic specific to @uirouter/angularjs (ng1).
       *
       * If no `views: {}` property exists on the [[StateDeclaration]], then it creates the `views` object
       * and applies the state-level configuration to a view named `$default`.
       */
      function ng1ViewsBuilder(state) {
          // Do not process root state
          if (!state.parent)
              return {};
          var tplKeys = ['templateProvider', 'templateUrl', 'template', 'notify', 'async'], ctrlKeys = ['controller', 'controllerProvider', 'controllerAs', 'resolveAs'], compKeys = ['component', 'bindings', 'componentProvider'], nonCompKeys = tplKeys.concat(ctrlKeys), allViewKeys = compKeys.concat(nonCompKeys);
          // Do not allow a state to have both state-level props and also a `views: {}` property.
          // A state without a `views: {}` property can declare properties for the `$default` view as properties of the state.
          // However, the `$default` approach should not be mixed with a separate `views: ` block.
          if (core.isDefined(state.views) && hasAnyKey(allViewKeys, state)) {
              throw new Error("State '" + state.name + "' has a 'views' object. " +
                  "It cannot also have \"view properties\" at the state level.  " +
                  "Move the following properties into a view (in the 'views' object): " +
                  (" " + allViewKeys.filter(function (key) { return core.isDefined(state[key]); }).join(', ')));
          }
          var views = {}, viewsObject = state.views || { $default: core.pick(state, allViewKeys) };
          core.forEach(viewsObject, function (config, name) {
              // Account for views: { "": { template... } }
              name = name || '$default';
              // Account for views: { header: "headerComponent" }
              if (core.isString(config))
                  config = { component: config };
              // Make a shallow copy of the config object
              config = core.extend({}, config);
              // Do not allow a view to mix props for component-style view with props for template/controller-style view
              if (hasAnyKey(compKeys, config) && hasAnyKey(nonCompKeys, config)) {
                  throw new Error("Cannot combine: " + compKeys.join('|') + " with: " + nonCompKeys.join('|') + " in stateview: '" + name + "@" + state.name + "'");
              }
              config.resolveAs = config.resolveAs || '$resolve';
              config.$type = 'ng1';
              config.$context = state;
              config.$name = name;
              var normalized = core.ViewService.normalizeUIViewTarget(config.$context, config.$name);
              config.$uiViewName = normalized.uiViewName;
              config.$uiViewContextAnchor = normalized.uiViewContextAnchor;
              views[name] = config;
          });
          return views;
      }
      var id = 0;
      var Ng1ViewConfig = /** @class */ (function () {
          function Ng1ViewConfig(path, viewDecl, factory) {
              var _this = this;
              this.path = path;
              this.viewDecl = viewDecl;
              this.factory = factory;
              this.$id = id++;
              this.loaded = false;
              this.getTemplate = function (uiView, context) {
                  return _this.component
                      ? _this.factory.makeComponentTemplate(uiView, context, _this.component, _this.viewDecl.bindings)
                      : _this.template;
              };
          }
          Ng1ViewConfig.prototype.load = function () {
              var _this = this;
              var $q = core.services.$q;
              var context = new core.ResolveContext(this.path);
              var params = this.path.reduce(function (acc, node) { return core.extend(acc, node.paramValues); }, {});
              var promises = {
                  template: $q.when(this.factory.fromConfig(this.viewDecl, params, context)),
                  controller: $q.when(this.getController(context)),
              };
              return $q.all(promises).then(function (results) {
                  core.trace.traceViewServiceEvent('Loaded', _this);
                  _this.controller = results.controller;
                  core.extend(_this, results.template); // Either { template: "tpl" } or { component: "cmpName" }
                  return _this;
              });
          };
          /**
           * Gets the controller for a view configuration.
           *
           * @returns {Function|Promise.<Function>} Returns a controller, or a promise that resolves to a controller.
           */
          Ng1ViewConfig.prototype.getController = function (context) {
              var provider = this.viewDecl.controllerProvider;
              if (!core.isInjectable(provider))
                  return this.viewDecl.controller;
              var deps = core.services.$injector.annotate(provider);
              var providerFn = core.isArray(provider) ? core.tail(provider) : provider;
              var resolvable = new core.Resolvable('', providerFn, deps);
              return resolvable.get(context);
          };
          return Ng1ViewConfig;
      }());
  
      /** @module view */
      /**
       * Service which manages loading of templates from a ViewConfig.
       */
      var TemplateFactory = /** @class */ (function () {
          function TemplateFactory() {
              var _this = this;
              /** @hidden */ this._useHttp = ng.version.minor < 3;
              /** @hidden */ this.$get = [
                  '$http',
                  '$templateCache',
                  '$injector',
                  function ($http, $templateCache, $injector) {
                      _this.$templateRequest = $injector.has && $injector.has('$templateRequest') && $injector.get('$templateRequest');
                      _this.$http = $http;
                      _this.$templateCache = $templateCache;
                      return _this;
                  },
              ];
          }
          /** @hidden */
          TemplateFactory.prototype.useHttpService = function (value) {
              this._useHttp = value;
          };
          /**
           * Creates a template from a configuration object.
           *
           * @param config Configuration object for which to load a template.
           * The following properties are search in the specified order, and the first one
           * that is defined is used to create the template:
           *
           * @param params  Parameters to pass to the template function.
           * @param context The resolve context associated with the template's view
           *
           * @return {string|object}  The template html as a string, or a promise for
           * that string,or `null` if no template is configured.
           */
          TemplateFactory.prototype.fromConfig = function (config, params, context) {
              var defaultTemplate = '<ui-view></ui-view>';
              var asTemplate = function (result) { return core.services.$q.when(result).then(function (str) { return ({ template: str }); }); };
              var asComponent = function (result) { return core.services.$q.when(result).then(function (str) { return ({ component: str }); }); };
              return core.isDefined(config.template)
                  ? asTemplate(this.fromString(config.template, params))
                  : core.isDefined(config.templateUrl)
                      ? asTemplate(this.fromUrl(config.templateUrl, params))
                      : core.isDefined(config.templateProvider)
                          ? asTemplate(this.fromProvider(config.templateProvider, params, context))
                          : core.isDefined(config.component)
                              ? asComponent(config.component)
                              : core.isDefined(config.componentProvider)
                                  ? asComponent(this.fromComponentProvider(config.componentProvider, params, context))
                                  : asTemplate(defaultTemplate);
          };
          /**
           * Creates a template from a string or a function returning a string.
           *
           * @param template html template as a string or function that returns an html template as a string.
           * @param params Parameters to pass to the template function.
           *
           * @return {string|object} The template html as a string, or a promise for that
           * string.
           */
          TemplateFactory.prototype.fromString = function (template, params) {
              return core.isFunction(template) ? template(params) : template;
          };
          /**
           * Loads a template from the a URL via `$http` and `$templateCache`.
           *
           * @param {string|Function} url url of the template to load, or a function
           * that returns a url.
           * @param {Object} params Parameters to pass to the url function.
           * @return {string|Promise.<string>} The template html as a string, or a promise
           * for that string.
           */
          TemplateFactory.prototype.fromUrl = function (url, params) {
              if (core.isFunction(url))
                  url = url(params);
              if (url == null)
                  return null;
              if (this._useHttp) {
                  return this.$http
                      .get(url, { cache: this.$templateCache, headers: { Accept: 'text/html' } })
                      .then(function (response) {
                      return response.data;
                  });
              }
              return this.$templateRequest(url);
          };
          /**
           * Creates a template by invoking an injectable provider function.
           *
           * @param provider Function to invoke via `locals`
           * @param {Function} injectFn a function used to invoke the template provider
           * @return {string|Promise.<string>} The template html as a string, or a promise
           * for that string.
           */
          TemplateFactory.prototype.fromProvider = function (provider, params, context) {
              var deps = core.services.$injector.annotate(provider);
              var providerFn = core.isArray(provider) ? core.tail(provider) : provider;
              var resolvable = new core.Resolvable('', providerFn, deps);
              return resolvable.get(context);
          };
          /**
           * Creates a component's template by invoking an injectable provider function.
           *
           * @param provider Function to invoke via `locals`
           * @param {Function} injectFn a function used to invoke the template provider
           * @return {string} The template html as a string: "<component-name input1='::$resolve.foo'></component-name>".
           */
          TemplateFactory.prototype.fromComponentProvider = function (provider, params, context) {
              var deps = core.services.$injector.annotate(provider);
              var providerFn = core.isArray(provider) ? core.tail(provider) : provider;
              var resolvable = new core.Resolvable('', providerFn, deps);
              return resolvable.get(context);
          };
          /**
           * Creates a template from a component's name
           *
           * This implements route-to-component.
           * It works by retrieving the component (directive) metadata from the injector.
           * It analyses the component's bindings, then constructs a template that instantiates the component.
           * The template wires input and output bindings to resolves or from the parent component.
           *
           * @param uiView {object} The parent ui-view (for binding outputs to callbacks)
           * @param context The ResolveContext (for binding outputs to callbacks returned from resolves)
           * @param component {string} Component's name in camel case.
           * @param bindings An object defining the component's bindings: {foo: '<'}
           * @return {string} The template as a string: "<component-name input1='::$resolve.foo'></component-name>".
           */
          TemplateFactory.prototype.makeComponentTemplate = function (uiView, context, component, bindings) {
              bindings = bindings || {};
              // Bind once prefix
              var prefix = ng.version.minor >= 3 ? '::' : '';
              // Convert to kebob name. Add x- prefix if the string starts with `x-` or `data-`
              var kebob = function (camelCase) {
                  var kebobed = core.kebobString(camelCase);
                  return /^(x|data)-/.exec(kebobed) ? "x-" + kebobed : kebobed;
              };
              var attributeTpl = function (input) {
                  var name = input.name, type = input.type;
                  var attrName = kebob(name);
                  // If the ui-view has an attribute which matches a binding on the routed component
                  // then pass that attribute through to the routed component template.
                  // Prefer ui-view wired mappings to resolve data, unless the resolve was explicitly bound using `bindings:`
                  if (uiView.attr(attrName) && !bindings[name])
                      return attrName + "='" + uiView.attr(attrName) + "'";
                  var resolveName = bindings[name] || name;
                  // Pre-evaluate the expression for "@" bindings by enclosing in {{ }}
                  // some-attr="{{ ::$resolve.someResolveName }}"
                  if (type === '@')
                      return attrName + "='{{" + prefix + "$resolve." + resolveName + "}}'";
                  // Wire "&" callbacks to resolves that return a callback function
                  // Get the result of the resolve (should be a function) and annotate it to get its arguments.
                  // some-attr="$resolve.someResolveResultName(foo, bar)"
                  if (type === '&') {
                      var res = context.getResolvable(resolveName);
                      var fn = res && res.data;
                      var args = (fn && core.services.$injector.annotate(fn)) || [];
                      // account for array style injection, i.e., ['foo', function(foo) {}]
                      var arrayIdxStr = core.isArray(fn) ? "[" + (fn.length - 1) + "]" : '';
                      return attrName + "='$resolve." + resolveName + arrayIdxStr + "(" + args.join(',') + ")'";
                  }
                  // some-attr="::$resolve.someResolveName"
                  return attrName + "='" + prefix + "$resolve." + resolveName + "'";
              };
              var attrs = getComponentBindings(component)
                  .map(attributeTpl)
                  .join(' ');
              var kebobName = kebob(component);
              return "<" + kebobName + " " + attrs + "></" + kebobName + ">";
          };
          return TemplateFactory;
      }());
      // Gets all the directive(s)' inputs ('@', '=', and '<') and outputs ('&')
      function getComponentBindings(name) {
          var cmpDefs = core.services.$injector.get(name + 'Directive'); // could be multiple
          if (!cmpDefs || !cmpDefs.length)
              throw new Error("Unable to find component named '" + name + "'");
          return cmpDefs.map(getBindings).reduce(core.unnestR, []);
      }
      // Given a directive definition, find its object input attributes
      // Use different properties, depending on the type of directive (component, bindToController, normal)
      var getBindings = function (def) {
          if (core.isObject(def.bindToController))
              return scopeBindings(def.bindToController);
          return scopeBindings(def.scope);
      };
      // for ng 1.2 style, process the scope: { input: "=foo" }
      // for ng 1.3 through ng 1.5, process the component's bindToController: { input: "=foo" } object
      var scopeBindings = function (bindingsObj) {
          return Object.keys(bindingsObj || {})
              // [ 'input', [ '=foo', '=', 'foo' ] ]
              .map(function (key) { return [key, /^([=<@&])[?]?(.*)/.exec(bindingsObj[key])]; })
              // skip malformed values
              .filter(function (tuple) { return core.isDefined(tuple) && core.isArray(tuple[1]); })
              // { name: ('foo' || 'input'), type: '=' }
              .map(function (tuple) { return ({ name: tuple[1][2] || tuple[0], type: tuple[1][1] }); });
      };
  
      /** @module ng1 */ /** for typedoc */
      /**
       * The Angular 1 `StateProvider`
       *
       * The `$stateProvider` works similar to Angular's v1 router, but it focuses purely
       * on state.
       *
       * A state corresponds to a "place" in the application in terms of the overall UI and
       * navigation. A state describes (via the controller / template / view properties) what
       * the UI looks like and does at that place.
       *
       * States often have things in common, and the primary way of factoring out these
       * commonalities in this model is via the state hierarchy, i.e. parent/child states aka
       * nested states.
       *
       * The `$stateProvider` provides interfaces to declare these states for your app.
       */
      var StateProvider = /** @class */ (function () {
          function StateProvider(stateRegistry, stateService) {
              this.stateRegistry = stateRegistry;
              this.stateService = stateService;
              core.createProxyFunctions(core.val(StateProvider.prototype), this, core.val(this));
          }
          /**
           * Decorates states when they are registered
           *
           * Allows you to extend (carefully) or override (at your own peril) the
           * `stateBuilder` object used internally by [[StateRegistry]].
           * This can be used to add custom functionality to ui-router,
           * for example inferring templateUrl based on the state name.
           *
           * When passing only a name, it returns the current (original or decorated) builder
           * function that matches `name`.
           *
           * The builder functions that can be decorated are listed below. Though not all
           * necessarily have a good use case for decoration, that is up to you to decide.
           *
           * In addition, users can attach custom decorators, which will generate new
           * properties within the state's internal definition. There is currently no clear
           * use-case for this beyond accessing internal states (i.e. $state.$current),
           * however, expect this to become increasingly relevant as we introduce additional
           * meta-programming features.
           *
           * **Warning**: Decorators should not be interdependent because the order of
           * execution of the builder functions in non-deterministic. Builder functions
           * should only be dependent on the state definition object and super function.
           *
           *
           * Existing builder functions and current return values:
           *
           * - **parent** `{object}` - returns the parent state object.
           * - **data** `{object}` - returns state data, including any inherited data that is not
           *   overridden by own values (if any).
           * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
           *   or `null`.
           * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
           *   navigable).
           * - **params** `{object}` - returns an array of state params that are ensured to
           *   be a super-set of parent's params.
           * - **views** `{object}` - returns a views object where each key is an absolute view
           *   name (i.e. "viewName@stateName") and each value is the config object
           *   (template, controller) for the view. Even when you don't use the views object
           *   explicitly on a state config, one is still created for you internally.
           *   So by decorating this builder function you have access to decorating template
           *   and controller properties.
           * - **ownParams** `{object}` - returns an array of params that belong to the state,
           *   not including any params defined by ancestor states.
           * - **path** `{string}` - returns the full path from the root down to this state.
           *   Needed for state activation.
           * - **includes** `{object}` - returns an object that includes every state that
           *   would pass a `$state.includes()` test.
           *
           * #### Example:
           * Override the internal 'views' builder with a function that takes the state
           * definition, and a reference to the internal function being overridden:
           * ```js
           * $stateProvider.decorator('views', function (state, parent) {
           *   let result = {},
           *       views = parent(state);
           *
           *   angular.forEach(views, function (config, name) {
           *     let autoName = (state.name + '.' + name).replace('.', '/');
           *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
           *     result[name] = config;
           *   });
           *   return result;
           * });
           *
           * $stateProvider.state('home', {
           *   views: {
           *     'contact.list': { controller: 'ListController' },
           *     'contact.item': { controller: 'ItemController' }
           *   }
           * });
           * ```
           *
           *
           * ```js
           * // Auto-populates list and item views with /partials/home/contact/list.html,
           * // and /partials/home/contact/item.html, respectively.
           * $state.go('home');
           * ```
           *
           * @param {string} name The name of the builder function to decorate.
           * @param {object} func A function that is responsible for decorating the original
           * builder function. The function receives two parameters:
           *
           *   - `{object}` - state - The state config object.
           *   - `{object}` - super - The original builder function.
           *
           * @return {object} $stateProvider - $stateProvider instance
           */
          StateProvider.prototype.decorator = function (name, func) {
              return this.stateRegistry.decorator(name, func) || this;
          };
          StateProvider.prototype.state = function (name, definition) {
              if (core.isObject(name)) {
                  definition = name;
              }
              else {
                  definition.name = name;
              }
              this.stateRegistry.register(definition);
              return this;
          };
          /**
           * Registers an invalid state handler
           *
           * This is a passthrough to [[StateService.onInvalid]] for ng1.
           */
          StateProvider.prototype.onInvalid = function (callback) {
              return this.stateService.onInvalid(callback);
          };
          return StateProvider;
      }());
  
      /** @module ng1 */ /** */
      /**
       * This is a [[StateBuilder.builder]] function for angular1 `onEnter`, `onExit`,
       * `onRetain` callback hooks on a [[Ng1StateDeclaration]].
       *
       * When the [[StateBuilder]] builds a [[StateObject]] object from a raw [[StateDeclaration]], this builder
       * ensures that those hooks are injectable for @uirouter/angularjs (ng1).
       */
      var getStateHookBuilder = function (hookName) {
          return function stateHookBuilder(stateObject, parentFn) {
              var hook = stateObject[hookName];
              var pathname = hookName === 'onExit' ? 'from' : 'to';
              function decoratedNg1Hook(trans, state) {
                  var resolveContext = new core.ResolveContext(trans.treeChanges(pathname));
                  var subContext = resolveContext.subContext(state.$$state());
                  var locals = core.extend(getLocals(subContext), { $state$: state, $transition$: trans });
                  return core.services.$injector.invoke(hook, this, locals);
              }
              return hook ? decoratedNg1Hook : undefined;
          };
      };
  
      /**
       * @internalapi
       * @module ng1
       */ /** */
      /**
       * Implements UI-Router LocationServices and LocationConfig using Angular 1's $location service
       */
      var Ng1LocationServices = /** @class */ (function () {
          function Ng1LocationServices($locationProvider) {
              // .onChange() registry
              this._urlListeners = [];
              this.$locationProvider = $locationProvider;
              var _lp = core.val($locationProvider);
              core.createProxyFunctions(_lp, this, _lp, ['hashPrefix']);
          }
          /**
           * Applys ng1-specific path parameter encoding
           *
           * The Angular 1 `$location` service is a bit weird.
           * It doesn't allow slashes to be encoded/decoded bi-directionally.
           *
           * See the writeup at https://github.com/angular-ui/ui-router/issues/2598
           *
           * This code patches the `path` parameter type so it encoded/decodes slashes as ~2F
           *
           * @param router
           */
          Ng1LocationServices.monkeyPatchPathParameterType = function (router) {
              var pathType = router.urlMatcherFactory.type('path');
              pathType.encode = function (x) {
                  return x != null ? x.toString().replace(/(~|\/)/g, function (m) { return ({ '~': '~~', '/': '~2F' }[m]); }) : x;
              };
              pathType.decode = function (x) {
                  return x != null ? x.toString().replace(/(~~|~2F)/g, function (m) { return ({ '~~': '~', '~2F': '/' }[m]); }) : x;
              };
          };
          Ng1LocationServices.prototype.dispose = function () { };
          Ng1LocationServices.prototype.onChange = function (callback) {
              var _this = this;
              this._urlListeners.push(callback);
              return function () { return core.removeFrom(_this._urlListeners)(callback); };
          };
          Ng1LocationServices.prototype.html5Mode = function () {
              var html5Mode = this.$locationProvider.html5Mode();
              html5Mode = core.isObject(html5Mode) ? html5Mode.enabled : html5Mode;
              return html5Mode && this.$sniffer.history;
          };
          Ng1LocationServices.prototype.url = function (newUrl, replace, state) {
              if (replace === void 0) { replace = false; }
              if (core.isDefined(newUrl))
                  this.$location.url(newUrl);
              if (replace)
                  this.$location.replace();
              if (state)
                  this.$location.state(state);
              return this.$location.url();
          };
          Ng1LocationServices.prototype._runtimeServices = function ($rootScope, $location, $sniffer, $browser) {
              var _this = this;
              this.$location = $location;
              this.$sniffer = $sniffer;
              // Bind $locationChangeSuccess to the listeners registered in LocationService.onChange
              $rootScope.$on('$locationChangeSuccess', function (evt) { return _this._urlListeners.forEach(function (fn) { return fn(evt); }); });
              var _loc = core.val($location);
              var _browser = core.val($browser);
              // Bind these LocationService functions to $location
              core.createProxyFunctions(_loc, this, _loc, ['replace', 'path', 'search', 'hash']);
              // Bind these LocationConfig functions to $location
              core.createProxyFunctions(_loc, this, _loc, ['port', 'protocol', 'host']);
              // Bind these LocationConfig functions to $browser
              core.createProxyFunctions(_browser, this, _browser, ['baseHref']);
          };
          return Ng1LocationServices;
      }());
  
      /** @module url */ /** */
      /**
       * Manages rules for client-side URL
       *
       * ### Deprecation warning:
       * This class is now considered to be an internal API
       * Use the [[UrlService]] instead.
       * For configuring URL rules, use the [[UrlRulesApi]] which can be found as [[UrlService.rules]].
       *
       * This class manages the router rules for what to do when the URL changes.
       *
       * This provider remains for backwards compatibility.
       *
       * @deprecated
       */
      var UrlRouterProvider = /** @class */ (function () {
          /** @hidden */
          function UrlRouterProvider(router) {
              this._router = router;
              this._urlRouter = router.urlRouter;
          }
          UrlRouterProvider.injectableHandler = function (router, handler) {
              return function (match) { return core.services.$injector.invoke(handler, null, { $match: match, $stateParams: router.globals.params }); };
          };
          /** @hidden */
          UrlRouterProvider.prototype.$get = function () {
              var urlRouter = this._urlRouter;
              urlRouter.update(true);
              if (!urlRouter.interceptDeferred)
                  urlRouter.listen();
              return urlRouter;
          };
          /**
           * Registers a url handler function.
           *
           * Registers a low level url handler (a `rule`).
           * A rule detects specific URL patterns and returns a redirect, or performs some action.
           *
           * If a rule returns a string, the URL is replaced with the string, and all rules are fired again.
           *
           * #### Example:
           * ```js
           * var app = angular.module('app', ['ui.router.router']);
           *
           * app.config(function ($urlRouterProvider) {
           *   // Here's an example of how you might allow case insensitive urls
           *   $urlRouterProvider.rule(function ($injector, $location) {
           *     var path = $location.path(),
           *         normalized = path.toLowerCase();
           *
           *     if (path !== normalized) {
           *       return normalized;
           *     }
           *   });
           * });
           * ```
           *
           * @param ruleFn
           * Handler function that takes `$injector` and `$location` services as arguments.
           * You can use them to detect a url and return a different url as a string.
           *
           * @return [[UrlRouterProvider]] (`this`)
           */
          UrlRouterProvider.prototype.rule = function (ruleFn) {
              var _this = this;
              if (!core.isFunction(ruleFn))
                  throw new Error("'rule' must be a function");
              var match = function () { return ruleFn(core.services.$injector, _this._router.locationService); };
              var rule = new core.BaseUrlRule(match, core.identity);
              this._urlRouter.rule(rule);
              return this;
          };
          /**
           * Defines the path or behavior to use when no url can be matched.
           *
           * #### Example:
           * ```js
           * var app = angular.module('app', ['ui.router.router']);
           *
           * app.config(function ($urlRouterProvider) {
           *   // if the path doesn't match any of the urls you configured
           *   // otherwise will take care of routing the user to the
           *   // specified url
           *   $urlRouterProvider.otherwise('/index');
           *
           *   // Example of using function rule as param
           *   $urlRouterProvider.otherwise(function ($injector, $location) {
           *     return '/a/valid/url';
           *   });
           * });
           * ```
           *
           * @param rule
           * The url path you want to redirect to or a function rule that returns the url path or performs a `$state.go()`.
           * The function version is passed two params: `$injector` and `$location` services, and should return a url string.
           *
           * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
           */
          UrlRouterProvider.prototype.otherwise = function (rule) {
              var _this = this;
              var urlRouter = this._urlRouter;
              if (core.isString(rule)) {
                  urlRouter.otherwise(rule);
              }
              else if (core.isFunction(rule)) {
                  urlRouter.otherwise(function () { return rule(core.services.$injector, _this._router.locationService); });
              }
              else {
                  throw new Error("'rule' must be a string or function");
              }
              return this;
          };
          /**
           * Registers a handler for a given url matching.
           *
           * If the handler is a string, it is
           * treated as a redirect, and is interpolated according to the syntax of match
           * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).
           *
           * If the handler is a function, it is injectable.
           * It gets invoked if `$location` matches.
           * You have the option of inject the match object as `$match`.
           *
           * The handler can return
           *
           * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
           *   will continue trying to find another one that matches.
           * - **string** which is treated as a redirect and passed to `$location.url()`
           * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
           *
           * #### Example:
           * ```js
           * var app = angular.module('app', ['ui.router.router']);
           *
           * app.config(function ($urlRouterProvider) {
           *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
           *     if ($state.$current.navigable !== state ||
           *         !equalForKeys($match, $stateParams) {
           *      $state.transitionTo(state, $match, false);
           *     }
           *   });
           * });
           * ```
           *
           * @param what A pattern string to match, compiled as a [[UrlMatcher]].
           * @param handler The path (or function that returns a path) that you want to redirect your user to.
           * @param ruleCallback [optional] A callback that receives the `rule` registered with [[UrlMatcher.rule]]
           *
           * Note: the handler may also invoke arbitrary code, such as `$state.go()`
           */
          UrlRouterProvider.prototype.when = function (what, handler) {
              if (core.isArray(handler) || core.isFunction(handler)) {
                  handler = UrlRouterProvider.injectableHandler(this._router, handler);
              }
              this._urlRouter.when(what, handler);
              return this;
          };
          /**
           * Disables monitoring of the URL.
           *
           * Call this method before UI-Router has bootstrapped.
           * It will stop UI-Router from performing the initial url sync.
           *
           * This can be useful to perform some asynchronous initialization before the router starts.
           * Once the initialization is complete, call [[listen]] to tell UI-Router to start watching and synchronizing the URL.
           *
           * #### Example:
           * ```js
           * var app = angular.module('app', ['ui.router']);
           *
           * app.config(function ($urlRouterProvider) {
           *   // Prevent $urlRouter from automatically intercepting URL changes;
           *   $urlRouterProvider.deferIntercept();
           * })
           *
           * app.run(function (MyService, $urlRouter, $http) {
           *   $http.get("/stuff").then(function(resp) {
           *     MyService.doStuff(resp.data);
           *     $urlRouter.listen();
           *     $urlRouter.sync();
           *   });
           * });
           * ```
           *
           * @param defer Indicates whether to defer location change interception.
           *        Passing no parameter is equivalent to `true`.
           */
          UrlRouterProvider.prototype.deferIntercept = function (defer) {
              this._urlRouter.deferIntercept(defer);
          };
          return UrlRouterProvider;
      }());
  
      /**
       * # Angular 1 types
       *
       * UI-Router core provides various Typescript types which you can use for code completion and validating parameter values, etc.
       * The customizations to the core types for Angular UI-Router are documented here.
       *
       * The optional [[$resolve]] service is also documented here.
       *
       * @module ng1
       * @preferred
       */
      ng.module("ui.router.angular1", []);
      var mod_init = ng.module('ui.router.init', ['ng']);
      var mod_util = ng.module('ui.router.util', ['ui.router.init']);
      var mod_rtr = ng.module('ui.router.router', ['ui.router.util']);
      var mod_state = ng.module('ui.router.state', ['ui.router.router', 'ui.router.util', 'ui.router.angular1']);
      var mod_main = ng.module('ui.router', ['ui.router.init', 'ui.router.state', 'ui.router.angular1']);
      var mod_cmpt = ng.module('ui.router.compat', ['ui.router']); // tslint:disable-line
      var router = null;
      $uiRouterProvider.$inject = ['$locationProvider'];
      /** This angular 1 provider instantiates a Router and exposes its services via the angular injector */
      function $uiRouterProvider($locationProvider) {
          // Create a new instance of the Router when the $uiRouterProvider is initialized
          router = this.router = new core.UIRouter();
          router.stateProvider = new StateProvider(router.stateRegistry, router.stateService);
          // Apply ng1 specific StateBuilder code for `views`, `resolve`, and `onExit/Retain/Enter` properties
          router.stateRegistry.decorator('views', ng1ViewsBuilder);
          router.stateRegistry.decorator('onExit', getStateHookBuilder('onExit'));
          router.stateRegistry.decorator('onRetain', getStateHookBuilder('onRetain'));
          router.stateRegistry.decorator('onEnter', getStateHookBuilder('onEnter'));
          router.viewService._pluginapi._viewConfigFactory('ng1', getNg1ViewConfigFactory());
          var ng1LocationService = (router.locationService = router.locationConfig = new Ng1LocationServices($locationProvider));
          Ng1LocationServices.monkeyPatchPathParameterType(router);
          // backwards compat: also expose router instance as $uiRouterProvider.router
          router['router'] = router;
          router['$get'] = $get;
          $get.$inject = ['$location', '$browser', '$sniffer', '$rootScope', '$http', '$templateCache'];
          function $get($location, $browser, $sniffer, $rootScope, $http, $templateCache) {
              ng1LocationService._runtimeServices($rootScope, $location, $sniffer, $browser);
              delete router['router'];
              delete router['$get'];
              return router;
          }
          return router;
      }
      var getProviderFor = function (serviceName) { return [
          '$uiRouterProvider',
          function ($urp) {
              var service = $urp.router[serviceName];
              service['$get'] = function () { return service; };
              return service;
          },
      ]; };
      // This effectively calls $get() on `$uiRouterProvider` to trigger init (when ng enters runtime)
      runBlock.$inject = ['$injector', '$q', '$uiRouter'];
      function runBlock($injector, $q, $uiRouter) {
          core.services.$injector = $injector;
          core.services.$q = $q;
          // The $injector is now available.
          // Find any resolvables that had dependency annotation deferred
          $uiRouter.stateRegistry
              .get()
              .map(function (x) { return x.$$state().resolvables; })
              .reduce(core.unnestR, [])
              .filter(function (x) { return x.deps === 'deferred'; })
              .forEach(function (resolvable) { return (resolvable.deps = $injector.annotate(resolvable.resolveFn, $injector.strictDi)); });
      }
      // $urlRouter service and $urlRouterProvider
      var getUrlRouterProvider = function (uiRouter) { return (uiRouter.urlRouterProvider = new UrlRouterProvider(uiRouter)); };
      // $state service and $stateProvider
      // $urlRouter service and $urlRouterProvider
      var getStateProvider = function () { return core.extend(router.stateProvider, { $get: function () { return router.stateService; } }); };
      watchDigests.$inject = ['$rootScope'];
      function watchDigests($rootScope) {
          $rootScope.$watch(function () {
              core.trace.approximateDigests++;
          });
      }
      mod_init.provider('$uiRouter', $uiRouterProvider);
      mod_rtr.provider('$urlRouter', ['$uiRouterProvider', getUrlRouterProvider]);
      mod_util.provider('$urlService', getProviderFor('urlService'));
      mod_util.provider('$urlMatcherFactory', ['$uiRouterProvider', function () { return router.urlMatcherFactory; }]);
      mod_util.provider('$templateFactory', function () { return new TemplateFactory(); });
      mod_state.provider('$stateRegistry', getProviderFor('stateRegistry'));
      mod_state.provider('$uiRouterGlobals', getProviderFor('globals'));
      mod_state.provider('$transitions', getProviderFor('transitionService'));
      mod_state.provider('$state', ['$uiRouterProvider', getStateProvider]);
      mod_state.factory('$stateParams', ['$uiRouter', function ($uiRouter) { return $uiRouter.globals.params; }]);
      mod_main.factory('$view', function () { return router.viewService; });
      mod_main.service('$trace', function () { return core.trace; });
      mod_main.run(watchDigests);
      mod_util.run(['$urlMatcherFactory', function ($urlMatcherFactory) { }]);
      mod_state.run(['$state', function ($state) { }]);
      mod_rtr.run(['$urlRouter', function ($urlRouter) { }]);
      mod_init.run(runBlock);
      /** @hidden TODO: find a place to move this */
      var getLocals = function (ctx) {
          var tokens = ctx.getTokens().filter(core.isString);
          var tuples = tokens.map(function (key) {
              var resolvable = ctx.getResolvable(key);
              var waitPolicy = ctx.getPolicy(resolvable).async;
              return [key, waitPolicy === 'NOWAIT' ? resolvable.promise : resolvable.data];
          });
          return tuples.reduce(core.applyPairs, {});
      };
  
      /**
       * The current (or pending) State Parameters
       *
       * An injectable global **Service Object** which holds the state parameters for the latest **SUCCESSFUL** transition.
       *
       * The values are not updated until *after* a `Transition` successfully completes.
       *
       * **Also:** an injectable **Per-Transition Object** object which holds the pending state parameters for the pending `Transition` currently running.
       *
       * ### Deprecation warning:
       *
       * The value injected for `$stateParams` is different depending on where it is injected.
       *
       * - When injected into an angular service, the object injected is the global **Service Object** with the parameter values for the latest successful `Transition`.
       * - When injected into transition hooks, resolves, or view controllers, the object is the **Per-Transition Object** with the parameter values for the running `Transition`.
       *
       * Because of these confusing details, this service is deprecated.
       *
       * ### Instead of using the global `$stateParams` service object,
       * inject [[$uiRouterGlobals]] and use [[UIRouterGlobals.params]]
       *
       * ```js
       * MyService.$inject = ['$uiRouterGlobals'];
       * function MyService($uiRouterGlobals) {
       *   return {
       *     paramValues: function () {
       *       return $uiRouterGlobals.params;
       *     }
       *   }
       * }
       * ```
       *
       * ### Instead of using the per-transition `$stateParams` object,
       * inject the current `Transition` (as [[$transition$]]) and use [[Transition.params]]
       *
       * ```js
       * MyController.$inject = ['$transition$'];
       * function MyController($transition$) {
       *   var username = $transition$.params().username;
       *   // .. do something with username
       * }
       * ```
       *
       * ---
       *
       * This object can be injected into other services.
       *
       * #### Deprecated Example:
       * ```js
       * SomeService.$inject = ['$http', '$stateParams'];
       * function SomeService($http, $stateParams) {
       *   return {
       *     getUser: function() {
       *       return $http.get('/api/users/' + $stateParams.username);
       *     }
       *   }
       * };
       * angular.service('SomeService', SomeService);
       * ```
       * @deprecated
       */
  
      /**
       * # Angular 1 Directives
       *
       * These are the directives included in UI-Router for Angular 1.
       * These directives are used in templates to create viewports and link/navigate to states.
       *
       * @ng1api
       * @preferred
       * @module directives
       */ /** for typedoc */
      /** @hidden */
      function parseStateRef(ref) {
          var parsed;
          var paramsOnly = ref.match(/^\s*({[^}]*})\s*$/);
          if (paramsOnly)
              ref = '(' + paramsOnly[1] + ')';
          parsed = ref.replace(/\n/g, ' ').match(/^\s*([^(]*?)\s*(\((.*)\))?\s*$/);
          if (!parsed || parsed.length !== 4)
              throw new Error("Invalid state ref '" + ref + "'");
          return { state: parsed[1] || null, paramExpr: parsed[3] || null };
      }
      /** @hidden */
      function stateContext(el) {
          var $uiView = el.parent().inheritedData('$uiView');
          var path = core.parse('$cfg.path')($uiView);
          return path ? core.tail(path).state.name : undefined;
      }
      /** @hidden */
      function processedDef($state, $element, def) {
          var uiState = def.uiState || $state.current.name;
          var uiStateOpts = core.extend(defaultOpts($element, $state), def.uiStateOpts || {});
          var href = $state.href(uiState, def.uiStateParams, uiStateOpts);
          return { uiState: uiState, uiStateParams: def.uiStateParams, uiStateOpts: uiStateOpts, href: href };
      }
      /** @hidden */
      function getTypeInfo(el) {
          // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
          var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
          var isForm = el[0].nodeName === 'FORM';
          return {
              attr: isForm ? 'action' : isSvg ? 'xlink:href' : 'href',
              isAnchor: el.prop('tagName').toUpperCase() === 'A',
              clickable: !isForm,
          };
      }
      /** @hidden */
      function clickHook(el, $state, $timeout, type, getDef) {
          return function (e) {
              var button = e.which || e.button, target = getDef();
              if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) {
                  // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
                  var transition_1 = $timeout(function () {
                      if (!el.attr('disabled')) {
                          $state.go(target.uiState, target.uiStateParams, target.uiStateOpts);
                      }
                  });
                  e.preventDefault();
                  // if the state has no URL, ignore one preventDefault from the <a> directive.
                  var ignorePreventDefaultCount_1 = type.isAnchor && !target.href ? 1 : 0;
                  e.preventDefault = function () {
                      if (ignorePreventDefaultCount_1-- <= 0)
                          $timeout.cancel(transition_1);
                  };
              }
          };
      }
      /** @hidden */
      function defaultOpts(el, $state) {
          return {
              relative: stateContext(el) || $state.$current,
              inherit: true,
              source: 'sref',
          };
      }
      /** @hidden */
      function bindEvents(element, scope, hookFn, uiStateOpts) {
          var events;
          if (uiStateOpts) {
              events = uiStateOpts.events;
          }
          if (!core.isArray(events)) {
              events = ['click'];
          }
          var on = element.on ? 'on' : 'bind';
          for (var _i = 0, events_1 = events; _i < events_1.length; _i++) {
              var event_1 = events_1[_i];
              element[on](event_1, hookFn);
          }
          scope.$on('$destroy', function () {
              var off = element.off ? 'off' : 'unbind';
              for (var _i = 0, events_2 = events; _i < events_2.length; _i++) {
                  var event_2 = events_2[_i];
                  element[off](event_2, hookFn);
              }
          });
      }
      /**
       * `ui-sref`: A directive for linking to a state
       *
       * A directive which links to a state (and optionally, parameters).
       * When clicked, this directive activates the linked state with the supplied parameter values.
       *
       * ### Linked State
       * The attribute value of the `ui-sref` is the name of the state to link to.
       *
       * #### Example:
       * This will activate the `home` state when the link is clicked.
       * ```html
       * <a ui-sref="home">Home</a>
       * ```
       *
       * ### Relative Links
       * You can also use relative state paths within `ui-sref`, just like a relative path passed to `$state.go()` ([[StateService.go]]).
       * You just need to be aware that the path is relative to the state that *created* the link.
       * This allows a state to create a relative `ui-sref` which always targets the same destination.
       *
       * #### Example:
       * Both these links are relative to the parent state, even when a child state is currently active.
       * ```html
       * <a ui-sref=".child1">child 1 state</a>
       * <a ui-sref=".child2">child 2 state</a>
       * ```
       *
       * This link activates the parent state.
       * ```html
       * <a ui-sref="^">Return</a>
       * ```
       *
       * ### hrefs
       * If the linked state has a URL, the directive will automatically generate and
       * update the `href` attribute (using the [[StateService.href]]  method).
       *
       * #### Example:
       * Assuming the `users` state has a url of `/users/`
       * ```html
       * <a ui-sref="users" href="/users/">Users</a>
       * ```
       *
       * ### Parameter Values
       * In addition to the state name, a `ui-sref` can include parameter values which are applied when activating the state.
       * Param values can be provided in the `ui-sref` value after the state name, enclosed by parentheses.
       * The content inside the parentheses is an expression, evaluated to the parameter values.
       *
       * #### Example:
       * This example renders a list of links to users.
       * The state's `userId` parameter value comes from each user's `user.id` property.
       * ```html
       * <li ng-repeat="user in users">
       *   <a ui-sref="users.detail({ userId: user.id })">{{ user.displayName }}</a>
       * </li>
       * ```
       *
       * Note:
       * The parameter values expression is `$watch`ed for updates.
       *
       * ### Transition Options
       * You can specify [[TransitionOptions]] to pass to [[StateService.go]] by using the `ui-sref-opts` attribute.
       * Options are restricted to `location`, `inherit`, and `reload`.
       *
       * #### Example:
       * ```html
       * <a ui-sref="home" ui-sref-opts="{ reload: true }">Home</a>
       * ```
       *
       * ### Other DOM Events
       *
       * You can also customize which DOM events to respond to (instead of `click`) by
       * providing an `events` array in the `ui-sref-opts` attribute.
       *
       * #### Example:
       * ```html
       * <input type="text" ui-sref="contacts" ui-sref-opts="{ events: ['change', 'blur'] }">
       * ```
       *
       * ### Highlighting the active link
       * This directive can be used in conjunction with [[uiSrefActive]] to highlight the active link.
       *
       * ### Examples
       * If you have the following template:
       *
       * ```html
       * <a ui-sref="home">Home</a>
       * <a ui-sref="about">About</a>
       * <a ui-sref="{page: 2}">Next page</a>
       *
       * <ul>
       *     <li ng-repeat="contact in contacts">
       *         <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
       *     </li>
       * </ul>
       * ```
       *
       * Then (assuming the current state is `contacts`) the rendered html including hrefs would be:
       *
       * ```html
       * <a href="#/home" ui-sref="home">Home</a>
       * <a href="#/about" ui-sref="about">About</a>
       * <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
       *
       * <ul>
       *     <li ng-repeat="contact in contacts">
       *         <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
       *     </li>
       *     <li ng-repeat="contact in contacts">
       *         <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
       *     </li>
       *     <li ng-repeat="contact in contacts">
       *         <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
       *     </li>
       * </ul>
       *
       * <a href="#/home" ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
       * ```
       *
       * ### Notes
       *
       * - You can use `ui-sref` to change **only the parameter values** by omitting the state name and parentheses.
       * #### Example:
       * Sets the `lang` parameter to `en` and remains on the same state.
       *
       * ```html
       * <a ui-sref="{ lang: 'en' }">English</a>
       * ```
       *
       * - A middle-click, right-click, or ctrl-click is handled (natively) by the browser to open the href in a new window, for example.
       *
       * - Unlike the parameter values expression, the state name is not `$watch`ed (for performance reasons).
       * If you need to dynamically update the state being linked to, use the fully dynamic [[uiState]] directive.
       */
      var uiSrefDirective;
      uiSrefDirective = [
          '$uiRouter',
          '$timeout',
          function $StateRefDirective($uiRouter, $timeout) {
              var $state = $uiRouter.stateService;
              return {
                  restrict: 'A',
                  require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
                  link: function (scope, element, attrs, uiSrefActive) {
                      var type = getTypeInfo(element);
                      var active = uiSrefActive[1] || uiSrefActive[0];
                      var unlinkInfoFn = null;
                      var hookFn;
                      var rawDef = {};
                      var getDef = function () { return processedDef($state, element, rawDef); };
                      var ref = parseStateRef(attrs.uiSref);
                      rawDef.uiState = ref.state;
                      rawDef.uiStateOpts = attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {};
                      function update() {
                          var def = getDef();
                          if (unlinkInfoFn)
                              unlinkInfoFn();
                          if (active)
                              unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
                          if (def.href != null)
                              attrs.$set(type.attr, def.href);
                      }
                      if (ref.paramExpr) {
                          scope.$watch(ref.paramExpr, function (val) {
                              rawDef.uiStateParams = core.extend({}, val);
                              update();
                          }, true);
                          rawDef.uiStateParams = core.extend({}, scope.$eval(ref.paramExpr));
                      }
                      update();
                      scope.$on('$destroy', $uiRouter.stateRegistry.onStatesChanged(update));
                      scope.$on('$destroy', $uiRouter.transitionService.onSuccess({}, update));
                      if (!type.clickable)
                          return;
                      hookFn = clickHook(element, $state, $timeout, type, getDef);
                      bindEvents(element, scope, hookFn, rawDef.uiStateOpts);
                  },
              };
          },
      ];
      /**
       * `ui-state`: A fully dynamic directive for linking to a state
       *
       * A directive which links to a state (and optionally, parameters).
       * When clicked, this directive activates the linked state with the supplied parameter values.
       *
       * **This directive is very similar to [[uiSref]], but it `$observe`s and `$watch`es/evaluates all its inputs.**
       *
       * A directive which links to a state (and optionally, parameters).
       * When clicked, this directive activates the linked state with the supplied parameter values.
       *
       * ### Linked State
       * The attribute value of `ui-state` is an expression which is `$watch`ed and evaluated as the state to link to.
       * **This is in contrast with `ui-sref`, which takes a state name as a string literal.**
       *
       * #### Example:
       * Create a list of links.
       * ```html
       * <li ng-repeat="link in navlinks">
       *   <a ui-state="link.state">{{ link.displayName }}</a>
       * </li>
       * ```
       *
       * ### Relative Links
       * If the expression evaluates to a relative path, it is processed like [[uiSref]].
       * You just need to be aware that the path is relative to the state that *created* the link.
       * This allows a state to create relative `ui-state` which always targets the same destination.
       *
       * ### hrefs
       * If the linked state has a URL, the directive will automatically generate and
       * update the `href` attribute (using the [[StateService.href]]  method).
       *
       * ### Parameter Values
       * In addition to the state name expression, a `ui-state` can include parameter values which are applied when activating the state.
       * Param values should be provided using the `ui-state-params` attribute.
       * The `ui-state-params` attribute value is `$watch`ed and evaluated as an expression.
       *
       * #### Example:
       * This example renders a list of links with param values.
       * The state's `userId` parameter value comes from each user's `user.id` property.
       * ```html
       * <li ng-repeat="link in navlinks">
       *   <a ui-state="link.state" ui-state-params="link.params">{{ link.displayName }}</a>
       * </li>
       * ```
       *
       * ### Transition Options
       * You can specify [[TransitionOptions]] to pass to [[StateService.go]] by using the `ui-state-opts` attribute.
       * Options are restricted to `location`, `inherit`, and `reload`.
       * The value of the `ui-state-opts` is `$watch`ed and evaluated as an expression.
       *
       * #### Example:
       * ```html
       * <a ui-state="returnto.state" ui-state-opts="{ reload: true }">Home</a>
       * ```
       *
       * ### Other DOM Events
       *
       * You can also customize which DOM events to respond to (instead of `click`) by
       * providing an `events` array in the `ui-state-opts` attribute.
       *
       * #### Example:
       * ```html
       * <input type="text" ui-state="contacts" ui-state-opts="{ events: ['change', 'blur'] }">
       * ```
       *
       * ### Highlighting the active link
       * This directive can be used in conjunction with [[uiSrefActive]] to highlight the active link.
       *
       * ### Notes
       *
       * - You can use `ui-params` to change **only the parameter values** by omitting the state name and supplying only `ui-state-params`.
       *   However, it might be simpler to use [[uiSref]] parameter-only links.
       *
       * #### Example:
       * Sets the `lang` parameter to `en` and remains on the same state.
       *
       * ```html
       * <a ui-state="" ui-state-params="{ lang: 'en' }">English</a>
       * ```
       *
       * - A middle-click, right-click, or ctrl-click is handled (natively) by the browser to open the href in a new window, for example.
       * ```
       */
      var uiStateDirective;
      uiStateDirective = [
          '$uiRouter',
          '$timeout',
          function $StateRefDynamicDirective($uiRouter, $timeout) {
              var $state = $uiRouter.stateService;
              return {
                  restrict: 'A',
                  require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
                  link: function (scope, element, attrs, uiSrefActive) {
                      var type = getTypeInfo(element);
                      var active = uiSrefActive[1] || uiSrefActive[0];
                      var unlinkInfoFn = null;
                      var hookFn;
                      var rawDef = {};
                      var getDef = function () { return processedDef($state, element, rawDef); };
                      var inputAttrs = ['uiState', 'uiStateParams', 'uiStateOpts'];
                      var watchDeregFns = inputAttrs.reduce(function (acc, attr) { return ((acc[attr] = core.noop), acc); }, {});
                      function update() {
                          var def = getDef();
                          if (unlinkInfoFn)
                              unlinkInfoFn();
                          if (active)
                              unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
                          if (def.href != null)
                              attrs.$set(type.attr, def.href);
                      }
                      inputAttrs.forEach(function (field) {
                          rawDef[field] = attrs[field] ? scope.$eval(attrs[field]) : null;
                          attrs.$observe(field, function (expr) {
                              watchDeregFns[field]();
                              watchDeregFns[field] = scope.$watch(expr, function (newval) {
                                  rawDef[field] = newval;
                                  update();
                              }, true);
                          });
                      });
                      update();
                      scope.$on('$destroy', $uiRouter.stateRegistry.onStatesChanged(update));
                      scope.$on('$destroy', $uiRouter.transitionService.onSuccess({}, update));
                      if (!type.clickable)
                          return;
                      hookFn = clickHook(element, $state, $timeout, type, getDef);
                      bindEvents(element, scope, hookFn, rawDef.uiStateOpts);
                  },
              };
          },
      ];
      /**
       * `ui-sref-active` and `ui-sref-active-eq`: A directive that adds a CSS class when a `ui-sref` is active
       *
       * A directive working alongside [[uiSref]] and [[uiState]] to add classes to an element when the
       * related directive's state is active (and remove them when it is inactive).
       *
       * The primary use-case is to highlight the active link in navigation menus,
       * distinguishing it from the inactive menu items.
       *
       * ### Linking to a `ui-sref` or `ui-state`
       * `ui-sref-active` can live on the same element as `ui-sref`/`ui-state`, or it can be on a parent element.
       * If a `ui-sref-active` is a parent to more than one `ui-sref`/`ui-state`, it will apply the CSS class when **any of the links are active**.
       *
       * ### Matching
       *
       * The `ui-sref-active` directive applies the CSS class when the `ui-sref`/`ui-state`'s target state **or any child state is active**.
       * This is a "fuzzy match" which uses [[StateService.includes]].
       *
       * The `ui-sref-active-eq` directive applies the CSS class when the `ui-sref`/`ui-state`'s target state is directly active (not when child states are active).
       * This is an "exact match" which uses [[StateService.is]].
       *
       * ### Parameter values
       * If the `ui-sref`/`ui-state` includes parameter values, the current parameter values must match the link's values for the link to be highlighted.
       * This allows a list of links to the same state with different parameters to be rendered, and the correct one highlighted.
       *
       * #### Example:
       * ```html
       * <li ng-repeat="user in users" ui-sref-active="active">
       *   <a ui-sref="user.details({ userId: user.id })">{{ user.lastName }}</a>
       * </li>
       * ```
       *
       * ### Examples
       *
       * Given the following template:
       * #### Example:
       * ```html
       * <ul>
       *   <li ui-sref-active="active" class="item">
       *     <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
       *   </li>
       * </ul>
       * ```
       *
       * When the app state is `app.user` (or any child state),
       * and contains the state parameter "user" with value "bilbobaggins",
       * the resulting HTML will appear as (note the 'active' class):
       *
       * ```html
       * <ul>
       *   <li ui-sref-active="active" class="item active">
       *     <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
       *   </li>
       * </ul>
       * ```
       *
       * ### Glob mode
       *
       * It is possible to pass `ui-sref-active` an expression that evaluates to an object.
       * The objects keys represent active class names and values represent the respective state names/globs.
       * `ui-sref-active` will match if the current active state **includes** any of
       * the specified state names/globs, even the abstract ones.
       *
       * #### Example:
       * Given the following template, with "admin" being an abstract state:
       * ```html
       * <div ui-sref-active="{'active': 'admin.**'}">
       *   <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
       * </div>
       * ```
       *
       * Arrays are also supported as values in the `ngClass`-like interface.
       * This allows multiple states to add `active` class.
       *
       * #### Example:
       * Given the following template, with "admin.roles" being the current state, the class will be added too:
       * ```html
       * <div ui-sref-active="{'active': ['owner.**', 'admin.**']}">
       *   <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
       * </div>
       * ```
       *
       * When the current state is "admin.roles" the "active" class will be applied to both the `<div>` and `<a>` elements.
       * It is important to note that the state names/globs passed to `ui-sref-active` override any state provided by a linked `ui-sref`.
       *
       * ### Notes:
       *
       * - The class name is interpolated **once** during the directives link time (any further changes to the
       * interpolated value are ignored).
       *
       * - Multiple classes may be specified in a space-separated format: `ui-sref-active='class1 class2 class3'`
       */
      var uiSrefActiveDirective;
      uiSrefActiveDirective = [
          '$state',
          '$stateParams',
          '$interpolate',
          '$uiRouter',
          function $StateRefActiveDirective($state, $stateParams, $interpolate, $uiRouter) {
              return {
                  restrict: 'A',
                  controller: [
                      '$scope',
                      '$element',
                      '$attrs',
                      function ($scope, $element, $attrs) {
                          var states = [];
                          var activeEqClass;
                          var uiSrefActive;
                          // There probably isn't much point in $observing this
                          // uiSrefActive and uiSrefActiveEq share the same directive object with some
                          // slight difference in logic routing
                          activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
                          try {
                              uiSrefActive = $scope.$eval($attrs.uiSrefActive);
                          }
                          catch (e) {
                              // Do nothing. uiSrefActive is not a valid expression.
                              // Fall back to using $interpolate below
                          }
                          uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
                          setStatesFromDefinitionObject(uiSrefActive);
                          // Allow uiSref to communicate with uiSrefActive[Equals]
                          this.$$addStateInfo = function (newState, newParams) {
                              // we already got an explicit state provided by ui-sref-active, so we
                              // shadow the one that comes from ui-sref
                              if (core.isObject(uiSrefActive) && states.length > 0) {
                                  return;
                              }
                              var deregister = addState(newState, newParams, uiSrefActive);
                              update();
                              return deregister;
                          };
                          function updateAfterTransition(trans) {
                              trans.promise.then(update, core.noop);
                          }
                          $scope.$on('$destroy', setupEventListeners());
                          if ($uiRouter.globals.transition) {
                              updateAfterTransition($uiRouter.globals.transition);
                          }
                          function setupEventListeners() {
                              var deregisterStatesChangedListener = $uiRouter.stateRegistry.onStatesChanged(handleStatesChanged);
                              var deregisterOnStartListener = $uiRouter.transitionService.onStart({}, updateAfterTransition);
                              var deregisterStateChangeSuccessListener = $scope.$on('$stateChangeSuccess', update);
                              return function cleanUp() {
                                  deregisterStatesChangedListener();
                                  deregisterOnStartListener();
                                  deregisterStateChangeSuccessListener();
                              };
                          }
                          function handleStatesChanged() {
                              setStatesFromDefinitionObject(uiSrefActive);
                          }
                          function setStatesFromDefinitionObject(statesDefinition) {
                              if (core.isObject(statesDefinition)) {
                                  states = [];
                                  core.forEach(statesDefinition, function (stateOrName, activeClass) {
                                      // Helper function to abstract adding state.
                                      var addStateForClass = function (stateOrName, activeClass) {
                                          var ref = parseStateRef(stateOrName);
                                          addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
                                      };
                                      if (core.isString(stateOrName)) {
                                          // If state is string, just add it.
                                          addStateForClass(stateOrName, activeClass);
                                      }
                                      else if (core.isArray(stateOrName)) {
                                          // If state is an array, iterate over it and add each array item individually.
                                          core.forEach(stateOrName, function (stateOrName) {
                                              addStateForClass(stateOrName, activeClass);
                                          });
                                      }
                                  });
                              }
                          }
                          function addState(stateName, stateParams, activeClass) {
                              var state = $state.get(stateName, stateContext($element));
                              var stateInfo = {
                                  state: state || { name: stateName },
                                  params: stateParams,
                                  activeClass: activeClass,
                              };
                              states.push(stateInfo);
                              return function removeState() {
                                  core.removeFrom(states)(stateInfo);
                              };
                          }
                          // Update route state
                          function update() {
                              var splitClasses = function (str) { return str.split(/\s/).filter(core.identity); };
                              var getClasses = function (stateList) {
                                  return stateList
                                      .map(function (x) { return x.activeClass; })
                                      .map(splitClasses)
                                      .reduce(core.unnestR, []);
                              };
                              var allClasses = getClasses(states)
                                  .concat(splitClasses(activeEqClass))
                                  .reduce(core.uniqR, []);
                              var fuzzyClasses = getClasses(states.filter(function (x) { return $state.includes(x.state.name, x.params); }));
                              var exactlyMatchesAny = !!states.filter(function (x) { return $state.is(x.state.name, x.params); }).length;
                              var exactClasses = exactlyMatchesAny ? splitClasses(activeEqClass) : [];
                              var addClasses = fuzzyClasses.concat(exactClasses).reduce(core.uniqR, []);
                              var removeClasses = allClasses.filter(function (cls) { return !core.inArray(addClasses, cls); });
                              $scope.$evalAsync(function () {
                                  addClasses.forEach(function (className) { return $element.addClass(className); });
                                  removeClasses.forEach(function (className) { return $element.removeClass(className); });
                              });
                          }
                          update();
                      },
                  ],
              };
          },
      ];
      ng
          .module('ui.router.state')
          .directive('uiSref', uiSrefDirective)
          .directive('uiSrefActive', uiSrefActiveDirective)
          .directive('uiSrefActiveEq', uiSrefActiveDirective)
          .directive('uiState', uiStateDirective);
  
      /** @module ng1 */ /** for typedoc */
      /**
       * `isState` Filter: truthy if the current state is the parameter
       *
       * Translates to [[StateService.is]] `$state.is("stateName")`.
       *
       * #### Example:
       * ```html
       * <div ng-if="'stateName' | isState">show if state is 'stateName'</div>
       * ```
       */
      $IsStateFilter.$inject = ['$state'];
      function $IsStateFilter($state) {
          var isFilter = function (state, params, options) {
              return $state.is(state, params, options);
          };
          isFilter.$stateful = true;
          return isFilter;
      }
      /**
       * `includedByState` Filter: truthy if the current state includes the parameter
       *
       * Translates to [[StateService.includes]]` $state.is("fullOrPartialStateName")`.
       *
       * #### Example:
       * ```html
       * <div ng-if="'fullOrPartialStateName' | includedByState">show if state includes 'fullOrPartialStateName'</div>
       * ```
       */
      $IncludedByStateFilter.$inject = ['$state'];
      function $IncludedByStateFilter($state) {
          var includesFilter = function (state, params, options) {
              return $state.includes(state, params, options);
          };
          includesFilter.$stateful = true;
          return includesFilter;
      }
      ng
          .module('ui.router.state')
          .filter('isState', $IsStateFilter)
          .filter('includedByState', $IncludedByStateFilter);
  
      /**
       * @ng1api
       * @module directives
       */
      /**
       * `ui-view`: A viewport directive which is filled in by a view from the active state.
       *
       * ### Attributes
       *
       * - `name`: (Optional) A view name.
       *   The name should be unique amongst the other views in the same state.
       *   You can have views of the same name that live in different states.
       *   The ui-view can be targeted in a View using the name ([[Ng1StateDeclaration.views]]).
       *
       * - `autoscroll`: an expression. When it evaluates to true, the `ui-view` will be scrolled into view when it is activated.
       *   Uses [[$uiViewScroll]] to do the scrolling.
       *
       * - `onload`: Expression to evaluate whenever the view updates.
       *
       * #### Example:
       * A view can be unnamed or named.
       * ```html
       * <!-- Unnamed -->
       * <div ui-view></div>
       *
       * <!-- Named -->
       * <div ui-view="viewName"></div>
       *
       * <!-- Named (different style) -->
       * <ui-view name="viewName"></ui-view>
       * ```
       *
       * You can only have one unnamed view within any template (or root html). If you are only using a
       * single view and it is unnamed then you can populate it like so:
       *
       * ```html
       * <div ui-view></div>
       * $stateProvider.state("home", {
       *   template: "<h1>HELLO!</h1>"
       * })
       * ```
       *
       * The above is a convenient shortcut equivalent to specifying your view explicitly with the
       * [[Ng1StateDeclaration.views]] config property, by name, in this case an empty name:
       *
       * ```js
       * $stateProvider.state("home", {
       *   views: {
       *     "": {
       *       template: "<h1>HELLO!</h1>"
       *     }
       *   }
       * })
       * ```
       *
       * But typically you'll only use the views property if you name your view or have more than one view
       * in the same template. There's not really a compelling reason to name a view if its the only one,
       * but you could if you wanted, like so:
       *
       * ```html
       * <div ui-view="main"></div>
       * ```
       *
       * ```js
       * $stateProvider.state("home", {
       *   views: {
       *     "main": {
       *       template: "<h1>HELLO!</h1>"
       *     }
       *   }
       * })
       * ```
       *
       * Really though, you'll use views to set up multiple views:
       *
       * ```html
       * <div ui-view></div>
       * <div ui-view="chart"></div>
       * <div ui-view="data"></div>
       * ```
       *
       * ```js
       * $stateProvider.state("home", {
       *   views: {
       *     "": {
       *       template: "<h1>HELLO!</h1>"
       *     },
       *     "chart": {
       *       template: "<chart_thing/>"
       *     },
       *     "data": {
       *       template: "<data_thing/>"
       *     }
       *   }
       * })
       * ```
       *
       * #### Examples for `autoscroll`:
       * ```html
       * <!-- If autoscroll present with no expression,
       *      then scroll ui-view into view -->
       * <ui-view autoscroll/>
       *
       * <!-- If autoscroll present with valid expression,
       *      then scroll ui-view into view if expression evaluates to true -->
       * <ui-view autoscroll='true'/>
       * <ui-view autoscroll='false'/>
       * <ui-view autoscroll='scopeVariable'/>
       * ```
       *
       * Resolve data:
       *
       * The resolved data from the state's `resolve` block is placed on the scope as `$resolve` (this
       * can be customized using [[Ng1ViewDeclaration.resolveAs]]).  This can be then accessed from the template.
       *
       * Note that when `controllerAs` is being used, `$resolve` is set on the controller instance *after* the
       * controller is instantiated.  The `$onInit()` hook can be used to perform initialization code which
       * depends on `$resolve` data.
       *
       * #### Example:
       * ```js
       * $stateProvider.state('home', {
       *   template: '<my-component user="$resolve.user"></my-component>',
       *   resolve: {
       *     user: function(UserService) { return UserService.fetchUser(); }
       *   }
       * });
       * ```
       */
      var uiView;
      uiView = [
          '$view',
          '$animate',
          '$uiViewScroll',
          '$interpolate',
          '$q',
          function $ViewDirective($view, $animate, $uiViewScroll, $interpolate, $q) {
              function getRenderer(attrs, scope) {
                  return {
                      enter: function (element, target, cb) {
                          if (ng.version.minor > 2) {
                              $animate.enter(element, null, target).then(cb);
                          }
                          else {
                              $animate.enter(element, null, target, cb);
                          }
                      },
                      leave: function (element, cb) {
                          if (ng.version.minor > 2) {
                              $animate.leave(element).then(cb);
                          }
                          else {
                              $animate.leave(element, cb);
                          }
                      },
                  };
              }
              function configsEqual(config1, config2) {
                  return config1 === config2;
              }
              var rootData = {
                  $cfg: { viewDecl: { $context: $view._pluginapi._rootViewContext() } },
                  $uiView: {},
              };
              var directive = {
                  count: 0,
                  restrict: 'ECA',
                  terminal: true,
                  priority: 400,
                  transclude: 'element',
                  compile: function (tElement, tAttrs, $transclude) {
                      return function (scope, $element, attrs) {
                          var onloadExp = attrs['onload'] || '', autoScrollExp = attrs['autoscroll'], renderer = getRenderer(attrs, scope), inherited = $element.inheritedData('$uiView') || rootData, name = $interpolate(attrs['uiView'] || attrs['name'] || '')(scope) || '$default';
                          var previousEl, currentEl, currentScope, viewConfig, unregister;
                          var activeUIView = {
                              $type: 'ng1',
                              id: directive.count++,
                              name: name,
                              fqn: inherited.$uiView.fqn ? inherited.$uiView.fqn + '.' + name : name,
                              config: null,
                              configUpdated: configUpdatedCallback,
                              get creationContext() {
                                  // The context in which this ui-view "tag" was created
                                  var fromParentTagConfig = core.parse('$cfg.viewDecl.$context')(inherited);
                                  // Allow <ui-view name="foo"><ui-view name="bar"></ui-view></ui-view>
                                  // See https://github.com/angular-ui/ui-router/issues/3355
                                  var fromParentTag = core.parse('$uiView.creationContext')(inherited);
                                  return fromParentTagConfig || fromParentTag;
                              },
                          };
                          core.trace.traceUIViewEvent('Linking', activeUIView);
                          function configUpdatedCallback(config) {
                              if (config && !(config instanceof Ng1ViewConfig))
                                  return;
                              if (configsEqual(viewConfig, config))
                                  return;
                              core.trace.traceUIViewConfigUpdated(activeUIView, config && config.viewDecl && config.viewDecl.$context);
                              viewConfig = config;
                              updateView(config);
                          }
                          $element.data('$uiView', { $uiView: activeUIView });
                          updateView();
                          unregister = $view.registerUIView(activeUIView);
                          scope.$on('$destroy', function () {
                              core.trace.traceUIViewEvent('Destroying/Unregistering', activeUIView);
                              unregister();
                          });
                          function cleanupLastView() {
                              if (previousEl) {
                                  core.trace.traceUIViewEvent('Removing (previous) el', previousEl.data('$uiView'));
                                  previousEl.remove();
                                  previousEl = null;
                              }
                              if (currentScope) {
                                  core.trace.traceUIViewEvent('Destroying scope', activeUIView);
                                  currentScope.$destroy();
                                  currentScope = null;
                              }
                              if (currentEl) {
                                  var _viewData_1 = currentEl.data('$uiViewAnim');
                                  core.trace.traceUIViewEvent('Animate out', _viewData_1);
                                  renderer.leave(currentEl, function () {
                                      _viewData_1.$$animLeave.resolve();
                                      previousEl = null;
                                  });
                                  previousEl = currentEl;
                                  currentEl = null;
                              }
                          }
                          function updateView(config) {
                              var newScope = scope.$new();
                              var animEnter = $q.defer(), animLeave = $q.defer();
                              var $uiViewData = {
                                  $cfg: config,
                                  $uiView: activeUIView,
                              };
                              var $uiViewAnim = {
                                  $animEnter: animEnter.promise,
                                  $animLeave: animLeave.promise,
                                  $$animLeave: animLeave,
                              };
                              /**
                               * @ngdoc event
                               * @name ui.router.state.directive:ui-view#$viewContentLoading
                               * @eventOf ui.router.state.directive:ui-view
                               * @eventType emits on ui-view directive scope
                               * @description
                               *
                               * Fired once the view **begins loading**, *before* the DOM is rendered.
                               *
                               * @param {Object} event Event object.
                               * @param {string} viewName Name of the view.
                               */
                              newScope.$emit('$viewContentLoading', name);
                              var cloned = $transclude(newScope, function (clone) {
                                  clone.data('$uiViewAnim', $uiViewAnim);
                                  clone.data('$uiView', $uiViewData);
                                  renderer.enter(clone, $element, function onUIViewEnter() {
                                      animEnter.resolve();
                                      if (currentScope)
                                          currentScope.$emit('$viewContentAnimationEnded');
                                      if ((core.isDefined(autoScrollExp) && !autoScrollExp) || scope.$eval(autoScrollExp)) {
                                          $uiViewScroll(clone);
                                      }
                                  });
                                  cleanupLastView();
                              });
                              currentEl = cloned;
                              currentScope = newScope;
                              /**
                               * @ngdoc event
                               * @name ui.router.state.directive:ui-view#$viewContentLoaded
                               * @eventOf ui.router.state.directive:ui-view
                               * @eventType emits on ui-view directive scope
                               * @description           *
                               * Fired once the view is **loaded**, *after* the DOM is rendered.
                               *
                               * @param {Object} event Event object.
                               */
                              currentScope.$emit('$viewContentLoaded', config || viewConfig);
                              currentScope.$eval(onloadExp);
                          }
                      };
                  },
              };
              return directive;
          },
      ];
      $ViewDirectiveFill.$inject = ['$compile', '$controller', '$transitions', '$view', '$q', '$timeout'];
      /** @hidden */
      function $ViewDirectiveFill($compile, $controller, $transitions, $view, $q, $timeout) {
          var getControllerAs = core.parse('viewDecl.controllerAs');
          var getResolveAs = core.parse('viewDecl.resolveAs');
          return {
              restrict: 'ECA',
              priority: -400,
              compile: function (tElement) {
                  var initial = tElement.html();
                  tElement.empty();
                  return function (scope, $element) {
                      var data = $element.data('$uiView');
                      if (!data) {
                          $element.html(initial);
                          $compile($element.contents())(scope);
                          return;
                      }
                      var cfg = data.$cfg || { viewDecl: {}, getTemplate: core.noop };
                      var resolveCtx = cfg.path && new core.ResolveContext(cfg.path);
                      $element.html(cfg.getTemplate($element, resolveCtx) || initial);
                      core.trace.traceUIViewFill(data.$uiView, $element.html());
                      var link = $compile($element.contents());
                      var controller = cfg.controller;
                      var controllerAs = getControllerAs(cfg);
                      var resolveAs = getResolveAs(cfg);
                      var locals = resolveCtx && getLocals(resolveCtx);
                      scope[resolveAs] = locals;
                      if (controller) {
                          var controllerInstance = $controller(controller, core.extend({}, locals, { $scope: scope, $element: $element }));
                          if (controllerAs) {
                              scope[controllerAs] = controllerInstance;
                              scope[controllerAs][resolveAs] = locals;
                          }
                          // TODO: Use $view service as a central point for registering component-level hooks
                          // Then, when a component is created, tell the $view service, so it can invoke hooks
                          // $view.componentLoaded(controllerInstance, { $scope: scope, $element: $element });
                          // scope.$on('$destroy', () => $view.componentUnloaded(controllerInstance, { $scope: scope, $element: $element }));
                          $element.data('$ngControllerController', controllerInstance);
                          $element.children().data('$ngControllerController', controllerInstance);
                          registerControllerCallbacks($q, $transitions, controllerInstance, scope, cfg);
                      }
                      // Wait for the component to appear in the DOM
                      if (core.isString(cfg.viewDecl.component)) {
                          var cmp_1 = cfg.viewDecl.component;
                          var kebobName = core.kebobString(cmp_1);
                          var tagRegexp_1 = new RegExp("^(x-|data-)?" + kebobName + "$", 'i');
                          var getComponentController = function () {
                              var directiveEl = [].slice
                                  .call($element[0].children)
                                  .filter(function (el) { return el && el.tagName && tagRegexp_1.exec(el.tagName); });
                              return directiveEl && ng.element(directiveEl).data("$" + cmp_1 + "Controller");
                          };
                          var deregisterWatch_1 = scope.$watch(getComponentController, function (ctrlInstance) {
                              if (!ctrlInstance)
                                  return;
                              registerControllerCallbacks($q, $transitions, ctrlInstance, scope, cfg);
                              deregisterWatch_1();
                          });
                      }
                      link(scope);
                  };
              },
          };
      }
      /** @hidden */
      var hasComponentImpl = typeof ng.module('ui.router')['component'] === 'function';
      /** @hidden incrementing id */
      var _uiCanExitId = 0;
      /** @hidden TODO: move these callbacks to $view and/or `/hooks/components.ts` or something */
      function registerControllerCallbacks($q, $transitions, controllerInstance, $scope, cfg) {
          // Call $onInit() ASAP
          if (core.isFunction(controllerInstance.$onInit) && !(cfg.viewDecl.component && hasComponentImpl)) {
              controllerInstance.$onInit();
          }
          var viewState = core.tail(cfg.path).state.self;
          var hookOptions = { bind: controllerInstance };
          // Add component-level hook for onUiParamsChanged
          if (core.isFunction(controllerInstance.uiOnParamsChanged)) {
              var resolveContext = new core.ResolveContext(cfg.path);
              var viewCreationTrans_1 = resolveContext.getResolvable('$transition$').data;
              // Fire callback on any successful transition
              var paramsUpdated = function ($transition$) {
                  // Exit early if the $transition$ is the same as the view was created within.
                  // Exit early if the $transition$ will exit the state the view is for.
                  if ($transition$ === viewCreationTrans_1 || $transition$.exiting().indexOf(viewState) !== -1)
                      return;
                  var toParams = $transition$.params('to');
                  var fromParams = $transition$.params('from');
                  var getNodeSchema = function (node) { return node.paramSchema; };
                  var toSchema = $transition$
                      .treeChanges('to')
                      .map(getNodeSchema)
                      .reduce(core.unnestR, []);
                  var fromSchema = $transition$
                      .treeChanges('from')
                      .map(getNodeSchema)
                      .reduce(core.unnestR, []);
                  // Find the to params that have different values than the from params
                  var changedToParams = toSchema.filter(function (param) {
                      var idx = fromSchema.indexOf(param);
                      return idx === -1 || !fromSchema[idx].type.equals(toParams[param.id], fromParams[param.id]);
                  });
                  // Only trigger callback if a to param has changed or is new
                  if (changedToParams.length) {
                      var changedKeys_1 = changedToParams.map(function (x) { return x.id; });
                      // Filter the params to only changed/new to params.  `$transition$.params()` may be used to get all params.
                      var newValues = core.filter(toParams, function (val, key) { return changedKeys_1.indexOf(key) !== -1; });
                      controllerInstance.uiOnParamsChanged(newValues, $transition$);
                  }
              };
              $scope.$on('$destroy', $transitions.onSuccess({}, paramsUpdated, hookOptions));
          }
          // Add component-level hook for uiCanExit
          if (core.isFunction(controllerInstance.uiCanExit)) {
              var id_1 = _uiCanExitId++;
              var cacheProp_1 = '_uiCanExitIds';
              // Returns true if a redirect transition already answered truthy
              var prevTruthyAnswer_1 = function (trans) {
                  return !!trans && ((trans[cacheProp_1] && trans[cacheProp_1][id_1] === true) || prevTruthyAnswer_1(trans.redirectedFrom()));
              };
              // If a user answered yes, but the transition was later redirected, don't also ask for the new redirect transition
              var wrappedHook = function (trans) {
                  var promise;
                  var ids = (trans[cacheProp_1] = trans[cacheProp_1] || {});
                  if (!prevTruthyAnswer_1(trans)) {
                      promise = $q.when(controllerInstance.uiCanExit(trans));
                      promise.then(function (val) { return (ids[id_1] = val !== false); });
                  }
                  return promise;
              };
              var criteria = { exiting: viewState.name };
              $scope.$on('$destroy', $transitions.onBefore(criteria, wrappedHook, hookOptions));
          }
      }
      ng.module('ui.router.state').directive('uiView', uiView);
      ng.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
  
      /** @module ng1 */ /** */
      /** @hidden */
      function $ViewScrollProvider() {
          var useAnchorScroll = false;
          this.useAnchorScroll = function () {
              useAnchorScroll = true;
          };
          this.$get = [
              '$anchorScroll',
              '$timeout',
              function ($anchorScroll, $timeout) {
                  if (useAnchorScroll) {
                      return $anchorScroll;
                  }
                  return function ($element) {
                      return $timeout(function () {
                          $element[0].scrollIntoView();
                      }, 0, false);
                  };
              },
          ];
      }
      ng.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);
  
      /**
       * Main entry point for angular 1.x build
       * @module ng1
       */ /** */
      var index = 'ui.router';
  
      Object.keys(core).forEach(function (key) { exports[key] = core[key]; });
      exports.core = core;
      exports.default = index;
      exports.watchDigests = watchDigests;
      exports.getLocals = getLocals;
      exports.getNg1ViewConfigFactory = getNg1ViewConfigFactory;
      exports.ng1ViewsBuilder = ng1ViewsBuilder;
      exports.Ng1ViewConfig = Ng1ViewConfig;
      exports.StateProvider = StateProvider;
      exports.UrlRouterProvider = UrlRouterProvider;
  
      Object.defineProperty(exports, '__esModule', { value: true });
  
  })));
  //# sourceMappingURL=ui-router-angularjs.js.map
  