PageSourceSearch

https://www.webnames.ca/jsbundles/pricing?v=uhIUQGvIbAZYbvie0uCwBlspn9a_n-v7eC4_RfUf_4I1

js webnames.ca collected 2026-10-02 02:55:23 UTC 565,623 bytes, 12,560 lines download raw bytes

1/**
2 * @license AngularJS v1.8.2
vendor: 25,829 bytes, lines 2-692
2
3 * (c) 2010-2020 Google LLC. http://angularjs.org
4 * License: MIT
5 */
6(function(window, angular) {'use strict';
7
8/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9 *     Any commits to this file should be reviewed with security in mind.  *
10 *   Changes to this file can potentially create security vulnerabilities. *
11 *          An approval from 2 Core members with history of modifying      *
12 *                         this file is required.                          *
13 *                                                                         *
14 *  Does the change somehow allow for arbitrary javascript to be executed? *
15 *    Or allows for someone to change the prototype of built-in objects?   *
16 *     Or gives undesired access to variables likes document or window?    *
17 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
18
19var $sanitizeMinErr = angular.$$minErr('$sanitize');
20var bind;
21var extend;
22var forEach;
23var isArray;
24var isDefined;
25var lowercase;
26var noop;
27var nodeContains;
28var htmlParser;
29var htmlSanitizeWriter;
30
31/**
32 * @ngdoc module
33 * @name ngSanitize
34 * @description
35 *
36 * The `ngSanitize` module provides functionality to sanitize HTML.
37 *
38 * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
39 */
40
41/**
42 * @ngdoc service
43 * @name $sanitize
44 * @kind function
45 *
46 * @description
47 *   Sanitizes an html string by stripping all potentially dangerous tokens.
48 *
49 *   The input is sanitized by parsing the HTML into tokens. All safe tokens (from a trusted URI list) are
50 *   then serialized back to a properly escaped HTML string. This means that no unsafe input can make
51 *   it into the returned string.
52 *
53 *   The trusted URIs for URL sanitization of attribute values is configured using the functions
54 *   `aHrefSanitizationTrustedUrlList` and `imgSrcSanitizationTrustedUrlList` of {@link $compileProvider}.
55 *
56 *   The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
57 *
58 * @param {string} html HTML input.
59 * @returns {string} Sanitized HTML.
60 *
61 * @example
62   <example module="sanitizeExample" deps="angular-sanitize.js" name="sanitize-service">
63   <file name="index.html">
64     <script>
65         angular.module('sanitizeExample', ['ngSanitize'])
66           .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
67             $scope.snippet =
68               '<p style="color:blue">an html\n' +
69               '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
70               'snippet</p>';
71             $scope.deliberatelyTrustDangerousSnippet = function() {
72               return $sce.trustAsHtml($scope.snippet);
73             };
74           }]);
75     </script>
76     <div ng-controller="ExampleController">
77        Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
78       <table>
79         <tr>
80           <td>Directive</td>
81           <td>How</td>
82           <td>Source</td>
83           <td>Rendered</td>
84         </tr>
85         <tr id="bind-html-with-sanitize">
86           <td>ng-bind-html</td>
87           <td>Automatically uses $sanitize</td>
88           <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
89           <td><div ng-bind-html="snippet"></div></td>
90         </tr>
91         <tr id="bind-html-with-trust">
92           <td>ng-bind-html</td>
93           <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
94           <td>
95           <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
96&lt;/div&gt;</pre>
97           </td>
98           <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
99         </tr>
100         <tr id="bind-default">
101           <td>ng-bind</td>
102           <td>Automatically escapes</td>
103           <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
104           <td><div ng-bind="snippet"></div></td>
105         </tr>
106       </table>
107       </div>
108   </file>
109   <file name="protractor.js" type="protractor">
110     it('should sanitize the html snippet by default', function() {
111       expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
112         toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
113     });
114
115     it('should inline raw snippet if bound to a trusted value', function() {
116       expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).
117         toBe("<p style=\"color:blue\">an html\n" +
118              "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
119              "snippet</p>");
120     });
121
122     it('should escape snippet without any filter', function() {
123       expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).
124         toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
125              "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
126              "snippet&lt;/p&gt;");
127     });
128
129     it('should update', function() {
130       element(by.model('snippet')).clear();
131       element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
132       expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
133         toBe('new <b>text</b>');
134       expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).toBe(
135         'new <b onclick="alert(1)">text</b>');
136       expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).toBe(
137         "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
138     });
139   </file>
140   </example>
141 */
142
143
144/**
145 * @ngdoc provider
146 * @name $sanitizeProvider
147 * @this
148 *
149 * @description
150 * Creates and configures {@link $sanitize} instance.
151 */
152function $SanitizeProvider() {
153  var hasBeenInstantiated = false;
154  var svgEnabled = false;
155
156  this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
157    hasBeenInstantiated = true;
158    if (svgEnabled) {
159      extend(validElements, svgElements);
160    }
161    return function(html) {
162      var buf = [];
163      htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
164        return !/^unsafe:/.test($$sanitizeUri(uri, isImage));
165      }));
166      return buf.join('');
167    };
168  }];
169
170
171  /**
172   * @ngdoc method
173   * @name $sanitizeProvider#enableSvg
174   * @kind function
175   *
176   * @description
177   * Enables a subset of svg to be supported by the sanitizer.
178   *
179   * <div class="alert alert-warning">
180   *   <p>By enabling this setting without taking other precautions, you might expose your
181   *   application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned
182   *   outside of the containing element and be rendered over other elements on the page (e.g. a login
183   *   link). Such behavior can then result in phishing incidents.</p>
184   *
185   *   <p>To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg
186   *   tags within the sanitized content:</p>
187   *
188   *   <br>
189   *
190   *   <pre><code>
191   *   .rootOfTheIncludedContent svg {
192   *     overflow: hidden !important;
193   *   }
194   *   </code></pre>
195   * </div>
196   *
197   * @param {boolean=} flag Enable or disable SVG support in the sanitizer.
198   * @returns {boolean|$sanitizeProvider} Returns the currently configured value if called
199   *    without an argument or self for chaining otherwise.
200   */
201  this.enableSvg = function(enableSvg) {
202    if (isDefined(enableSvg)) {
203      svgEnabled = enableSvg;
204      return this;
205    } else {
206      return svgEnabled;
207    }
208  };
209
210
211  /**
212   * @ngdoc method
213   * @name $sanitizeProvider#addValidElements
214   * @kind function
215   *
216   * @description
217   * Extends the built-in lists of valid HTML/SVG elements, i.e. elements that are considered safe
218   * and are not stripped off during sanitization. You can extend the following lists of elements:
219   *
220   * - `htmlElements`: A list of elements (tag names) to extend the current list of safe HTML
221   *   elements. HTML elements considered safe will not be removed during sanitization. All other
222   *   elements will be stripped off.
223   *
224   * - `htmlVoidElements`: This is similar to `htmlElements`, but marks the elements as
225   *   "void elements" (similar to HTML
226   *   [void elements](https://rawgit.com/w3c/html/html5.1-2/single-page.html#void-elements)). These
227   *   elements have no end tag and cannot have content.
228   *
229   * - `svgElements`: This is similar to `htmlElements`, but for SVG elements. This list is only
230   *   taken into account if SVG is {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for
231   *   `$sanitize`.
232   *
233   * <div class="alert alert-info">
234   *   This method must be called during the {@link angular.Module#config config} phase. Once the
235   *   `$sanitize` service has been instantiated, this method has no effect.
236   * </div>
237   *
238   * <div class="alert alert-warning">
239   *   Keep in mind that extending the built-in lists of elements may expose your app to XSS or
240   *   other vulnerabilities. Be very mindful of the elements you add.
241   * </div>
242   *
243   * @param {Array<String>|Object} elements - A list of valid HTML elements or an object with one or
244   *   more of the following properties:
245   *   - **htmlElements** - `{Array<String>}` - A list of elements to extend the current list of
246   *     HTML elements.
247   *   - **htmlVoidElements** - `{Array<String>}` - A list of elements to extend the current list of
248   *     void HTML elements; i.e. elements that do not have an end tag.
249   *   - **svgElements** - `{Array<String>}` - A list of elements to extend the current list of SVG
250   *     elements. The list of SVG elements is only taken into account if SVG is
251   *     {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for `$sanitize`.
252   *
253   * Passing an array (`[...]`) is equivalent to passing `{htmlElements: [...]}`.
254   *
255   * @return {$sanitizeProvider} Returns self for chaining.
256   */
257  this.addValidElements = function(elements) {
258    if (!hasBeenInstantiated) {
259      if (isArray(elements)) {
260        elements = {htmlElements: elements};
261      }
262
263      addElementsTo(svgElements, elements.svgElements);
264      addElementsTo(voidElements, elements.htmlVoidElements);
265      addElementsTo(validElements, elements.htmlVoidElements);
266      addElementsTo(validElements, elements.htmlElements);
267    }
268
269    return this;
270  };
271
272
273  /**
274   * @ngdoc method
275   * @name $sanitizeProvider#addValidAttrs
276   * @kind function
277   *
278   * @description
279   * Extends the built-in list of valid attributes, i.e. attributes that are considered safe and are
280   * not stripped off during sanitization.
281   *
282   * **Note**:
283   * The new attributes will not be treated as URI attributes, which means their values will not be
284   * sanitized as URIs using `$compileProvider`'s
285   * {@link ng.$compileProvider#aHrefSanitizationTrustedUrlList aHrefSanitizationTrustedUrlList} and
286   * {@link ng.$compileProvider#imgSrcSanitizationTrustedUrlList imgSrcSanitizationTrustedUrlList}.
287   *
288   * <div class="alert alert-info">
289   *   This method must be called during the {@link angular.Module#config config} phase. Once the
290   *   `$sanitize` service has been instantiated, this method has no effect.
291   * </div>
292   *
293   * <div class="alert alert-warning">
294   *   Keep in mind that extending the built-in list of attributes may expose your app to XSS or
295   *   other vulnerabilities. Be very mindful of the attributes you add.
296   * </div>
297   *
298   * @param {Array<String>} attrs - A list of valid attributes.
299   *
300   * @returns {$sanitizeProvider} Returns self for chaining.
301   */
302  this.addValidAttrs = function(attrs) {
303    if (!hasBeenInstantiated) {
304      extend(validAttrs, arrayToMap(attrs, true));
305    }
306    return this;
307  };
308
309  //////////////////////////////////////////////////////////////////////////////////////////////////
310  // Private stuff
311  //////////////////////////////////////////////////////////////////////////////////////////////////
312
313  bind = angular.bind;
314  extend = angular.extend;
315  forEach = angular.forEach;
316  isArray = angular.isArray;
317  isDefined = angular.isDefined;
318  lowercase = angular.$$lowercase;
319  noop = angular.noop;
320
321  htmlParser = htmlParserImpl;
322  htmlSanitizeWriter = htmlSanitizeWriterImpl;
323
324  nodeContains = window.Node.prototype.contains || /** @this */ function(arg) {
325    // eslint-disable-next-line no-bitwise
326    return !!(this.compareDocumentPosition(arg) & 16);
327  };
328
329  // Regular Expressions for parsing tags and attributes
330  var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
331    // Match everything outside of normal chars and " (quote character)
332    NON_ALPHANUMERIC_REGEXP = /([^#-~ |!])/g;
333
334
335  // Good source of info about elements and attributes
336  // http://dev.w3.org/html5/spec/Overview.html#semantics
337  // http://simon.html5.org/html-elements
338
339  // Safe Void Elements - HTML5
340  // http://dev.w3.org/html5/spec/Overview.html#void-elements
341  var voidElements = stringToMap('area,br,col,hr,img,wbr');
342
343  // Elements that you can, intentionally, leave open (and which close themselves)
344  // http://dev.w3.org/html5/spec/Overview.html#optional-tags
345  var optionalEndTagBlockElements = stringToMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'),
346      optionalEndTagInlineElements = stringToMap('rp,rt'),
347      optionalEndTagElements = extend({},
348                                              optionalEndTagInlineElements,
349                                              optionalEndTagBlockElements);
350
351  // Safe Block Elements - HTML5
352  var blockElements = extend({}, optionalEndTagBlockElements, stringToMap('address,article,' +
353          'aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' +
354          'h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul'));
355
356  // Inline Elements - HTML5
357  var inlineElements = extend({}, optionalEndTagInlineElements, stringToMap('a,abbr,acronym,b,' +
358          'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,' +
359          'samp,small,span,strike,strong,sub,sup,time,tt,u,var'));
360
361  // SVG Elements
362  // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
363  // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
364  // They can potentially allow for arbitrary javascript to be executed. See #11290
365  var svgElements = stringToMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' +
366          'hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,' +
367          'radialGradient,rect,stop,svg,switch,text,title,tspan');
368
369  // Blocked Elements (will be stripped)
370  var blockedElements = stringToMap('script,style');
371
372  var validElements = extend({},
373                                     voidElements,
374                                     blockElements,
375                                     inlineElements,
376                                     optionalEndTagElements);
377
378  //Attributes that have href and hence need to be sanitized
379  var uriAttrs = stringToMap('background,cite,href,longdesc,src,xlink:href,xml:base');
380
381  var htmlAttrs = stringToMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
382      'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
383      'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
384      'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
385      'valign,value,vspace,width');
386
387  // SVG attributes (without "id" and "name" attributes)
388  // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
389  var svgAttrs = stringToMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
390      'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
391      'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
392      'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
393      'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
394      'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
395      'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
396      'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
397      'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
398      'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
399      'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
400      'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
401      'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
402      'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
403      'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
404
405  var validAttrs = extend({},
406                                  uriAttrs,
407                                  svgAttrs,
408                                  htmlAttrs);
409
410  function stringToMap(str, lowercaseKeys) {
411    return arrayToMap(str.split(','), lowercaseKeys);
412  }
413
414  function arrayToMap(items, lowercaseKeys) {
415    var obj = {}, i;
416    for (i = 0; i < items.length; i++) {
417      obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true;
418    }
419    return obj;
420  }
421
422  function addElementsTo(elementsMap, newElements) {
423    if (newElements && newElements.length) {
424      extend(elementsMap, arrayToMap(newElements));
425    }
426  }
427
428  /**
429   * Create an inert document that contains the dirty HTML that needs sanitizing.
430   * We use the DOMParser API by default and fall back to createHTMLDocument if DOMParser is not
431   * available.
432   */
433  var getInertBodyElement /* function(html: string): HTMLBodyElement */ = (function(window, document) {
434    if (isDOMParserAvailable()) {
435      return getInertBodyElement_DOMParser;
436    }
437
438    if (!document || !document.implementation) {
439      throw $sanitizeMinErr('noinert', 'Can\'t create an inert html document');
440    }
441    var inertDocument = document.implementation.createHTMLDocument('inert');
442    var inertBodyElement = (inertDocument.documentElement || inertDocument.getDocumentElement()).querySelector('body');
443    return getInertBodyElement_InertDocument;
444
445    function isDOMParserAvailable() {
446      try {
447        return !!getInertBodyElement_DOMParser('');
448      } catch (e) {
449        return false;
450      }
451    }
452
453    function getInertBodyElement_DOMParser(html) {
454      // We add this dummy element to ensure that the rest of the content is parsed as expected
455      // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the `<head>` tag.
456      html = '<remove></remove>' + html;
457      try {
458        var body = new window.DOMParser().parseFromString(html, 'text/html').body;
459        body.firstChild.remove();
460        return body;
461      } catch (e) {
462        return undefined;
463      }
464    }
465
466    function getInertBodyElement_InertDocument(html) {
467      inertBodyElement.innerHTML = html;
468
469      // Support: IE 9-11 only
470      // strip custom-namespaced attributes on IE<=11
471      if (document.documentMode) {
472        stripCustomNsAttrs(inertBodyElement);
473      }
474
475      return inertBodyElement;
476    }
477  })(window, window.document);
478
479  /**
480   * @example
481   * htmlParser(htmlString, {
482   *     start: function(tag, attrs) {},
483   *     end: function(tag) {},
484   *     chars: function(text) {},
485   *     comment: function(text) {}
486   * });
487   *
488   * @param {string} html string
489   * @param {object} handler
490   */
491  function htmlParserImpl(html, handler) {
492    if (html === null || html === undefined) {
493      html = '';
494    } else if (typeof html !== 'string') {
495      html = '' + html;
496    }
497
498    var inertBodyElement = getInertBodyElement(html);
499    if (!inertBodyElement) return '';
500
501    //mXSS protection
502    var mXSSAttempts = 5;
503    do {
504      if (mXSSAttempts === 0) {
505        throw $sanitizeMinErr('uinput', 'Failed to sanitize html because the input is unstable');
506      }
507      mXSSAttempts--;
508
509      // trigger mXSS if it is going to happen by reading and writing the innerHTML
510      html = inertBodyElement.innerHTML;
511      inertBodyElement = getInertBodyElement(html);
512    } while (html !== inertBodyElement.innerHTML);
513
514    var node = inertBodyElement.firstChild;
515    while (node) {
516      switch (node.nodeType) {
517        case 1: // ELEMENT_NODE
518          handler.start(node.nodeName.toLowerCase(), attrToMap(node.attributes));
519          break;
520        case 3: // TEXT NODE
521          handler.chars(node.textContent);
522          break;
523      }
524
525      var nextNode;
526      if (!(nextNode = node.firstChild)) {
527        if (node.nodeType === 1) {
528          handler.end(node.nodeName.toLowerCase());
529        }
530        nextNode = getNonDescendant('nextSibling', node);
531        if (!nextNode) {
532          while (nextNode == null) {
533            node = getNonDescendant('parentNode', node);
534            if (node === inertBodyElement) break;
535            nextNode = getNonDescendant('nextSibling', node);
536            if (node.nodeType === 1) {
537              handler.end(node.nodeName.toLowerCase());
538            }
539          }
540        }
541      }
542      node = nextNode;
543    }
544
545    while ((node = inertBodyElement.firstChild)) {
546      inertBodyElement.removeChild(node);
547    }
548  }
549
550  function attrToMap(attrs) {
551    var map = {};
552    for (var i = 0, ii = attrs.length; i < ii; i++) {
553      var attr = attrs[i];
554      map[attr.name] = attr.value;
555    }
556    return map;
557  }
558
559
560  /**
561   * Escapes all potentially dangerous characters, so that the
562   * resulting string can be safely inserted into attribute or
563   * element text.
564   * @param value
565   * @returns {string} escaped text
566   */
567  function encodeEntities(value) {
568    return value.
569      replace(/&/g, '&amp;').
570      replace(SURROGATE_PAIR_REGEXP, function(value) {
571        var hi = value.charCodeAt(0);
572        var low = value.charCodeAt(1);
573        return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
574      }).
575      replace(NON_ALPHANUMERIC_REGEXP, function(value) {
576        return '&#' + value.charCodeAt(0) + ';';
577      }).
578      replace(/</g, '&lt;').
579      replace(/>/g, '&gt;');
580  }
581
582  /**
583   * create an HTML/XML writer which writes to buffer
584   * @param {Array} buf use buf.join('') to get out sanitized html string
585   * @returns {object} in the form of {
586   *     start: function(tag, attrs) {},
587   *     end: function(tag) {},
588   *     chars: function(text) {},
589   *     comment: function(text) {}
590   * }
591   */
592  function htmlSanitizeWriterImpl(buf, uriValidator) {
593    var ignoreCurrentElement = false;
594    var out = bind(buf, buf.push);
595    return {
596      start: function(tag, attrs) {
597        tag = lowercase(tag);
598        if (!ignoreCurrentElement && blockedElements[tag]) {
599          ignoreCurrentElement = tag;
600        }
601        if (!ignoreCurrentElement && validElements[tag] === true) {
602          out('<');
603          out(tag);
604          forEach(attrs, function(value, key) {
605            var lkey = lowercase(key);
606            var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
607            if (validAttrs[lkey] === true &&
608              (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
609              out(' ');
610              out(key);
611              out('="');
612              out(encodeEntities(value));
613              out('"');
614            }
615          });
616          out('>');
617        }
618      },
619      end: function(tag) {
620        tag = lowercase(tag);
621        if (!ignoreCurrentElement && validElements[tag] === true && voidElements[tag] !== true) {
622          out('</');
623          out(tag);
624          out('>');
625        }
626        // eslint-disable-next-line eqeqeq
627        if (tag == ignoreCurrentElement) {
628          ignoreCurrentElement = false;
629        }
630      },
631      chars: function(chars) {
632        if (!ignoreCurrentElement) {
633          out(encodeEntities(chars));
634        }
635      }
636    };
637  }
638
639
640  /**
641   * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' attribute to declare
642   * ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo'). This is undesirable since we don't want
643   * to allow any of these custom attributes. This method strips them all.
644   *
645   * @param node Root element to process
646   */
647  function stripCustomNsAttrs(node) {
648    while (node) {
649      if (node.nodeType === window.Node.ELEMENT_NODE) {
650        var attrs = node.attributes;
651        for (var i = 0, l = attrs.length; i < l; i++) {
652          var attrNode = attrs[i];
653          var attrName = attrNode.name.toLowerCase();
654          if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {
655            node.removeAttributeNode(attrNode);
656            i--;
657            l--;
658          }
659        }
660      }
661
662      var nextNode = node.firstChild;
663      if (nextNode) {
664        stripCustomNsAttrs(nextNode);
665      }
666
667      node = getNonDescendant('nextSibling', node);
668    }
669  }
670
671  function getNonDescendant(propName, node) {
672    // An element is clobbered if its `propName` property points to one of its descendants
673    var nextNode = node[propName];
674    if (nextNode && nodeContains.call(node, nextNode)) {
675      throw $sanitizeMinErr('elclob', 'Failed to sanitize html because the element is clobbered: {0}', node.outerHTML || node.outerText);
676    }
677    return nextNode;
678  }
679}
680
681function sanitizeText(chars) {
682  var buf = [];
683  var writer = htmlSanitizeWriter(buf, noop);
684  writer.chars(chars);
685  return buf.join('');
686}
687
688
689// define ngSanitize module and register $sanitize service
690angular.module('ngSanitize', [])
691  .provider('$sanitize', $SanitizeProvider)
692  .info({ angularVersion: '1.8.
6922
vendor: 7,335 bytes, lines 692-891
692' });
693
694/**
695 * @ngdoc filter
696 * @name linky
697 * @kind function
698 *
699 * @description
700 * Finds links in text input and turns them into html links. Supports `http/https/ftp/sftp/mailto` and
701 * plain email address links.
702 *
703 * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
704 *
705 * @param {string} text Input text.
706 * @param {string} [target] Window (`_blank|_self|_parent|_top`) or named frame to open links in.
707 * @param {object|function(url)} [attributes] Add custom attributes to the link element.
708 *
709 *    Can be one of:
710 *
711 *    - `object`: A map of attributes
712 *    - `function`: Takes the url as a parameter and returns a map of attributes
713 *
714 *    If the map of attributes contains a value for `target`, it overrides the value of
715 *    the target parameter.
716 *
717 *
718 * @returns {string} Html-linkified and {@link $sanitize sanitized} text.
719 *
720 * @usage
721   <span ng-bind-html="linky_expression | linky"></span>
722 *
723 * @example
724   <example module="linkyExample" deps="angular-sanitize.js" name="linky-filter">
725     <file name="index.html">
726       <div ng-controller="ExampleController">
727       Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
728       <table>
729         <tr>
730           <th>Filter</th>
731           <th>Source</th>
732           <th>Rendered</th>
733         </tr>
734         <tr id="linky-filter">
735           <td>linky filter</td>
736           <td>
737             <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
738           </td>
739           <td>
740             <div ng-bind-html="snippet | linky"></div>
741           </td>
742         </tr>
743         <tr id="linky-target">
744          <td>linky target</td>
745          <td>
746            <pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
747          </td>
748          <td>
749            <div ng-bind-html="snippetWithSingleURL | linky:'_blank'"></div>
750          </td>
751         </tr>
752         <tr id="linky-custom-attributes">
753          <td>linky custom attributes</td>
754          <td>
755            <pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"&gt;<br>&lt;/div&gt;</pre>
756          </td>
757          <td>
758            <div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"></div>
759          </td>
760         </tr>
761         <tr id="escaped-html">
762           <td>no filter</td>
763           <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
764           <td><div ng-bind="snippet"></div></td>
765         </tr>
766       </table>
767     </file>
768     <file name="script.js">
769       angular.module('linkyExample', ['ngSanitize'])
770         .controller('ExampleController', ['$scope', function($scope) {
771           $scope.snippet =
772             'Pretty text with some links:\n' +
773             'http://angularjs.org/,\n' +
774             'mailto:[email protected],\n' +
775             '[email protected],\n' +
776             'and one more: ftp://127.0.0.1/.';
777           $scope.snippetWithSingleURL = 'http://angularjs.org/';
778         }]);
779     </file>
780     <file name="protractor.js" type="protractor">
781       it('should linkify the snippet with urls', function() {
782         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
783             toBe('Pretty text with some links: http://angularjs.org/, [email protected], ' +
784                  '[email protected], and one more: ftp://127.0.0.1/.');
785         expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
786       });
787
788       it('should not linkify snippet without the linky filter', function() {
789         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
790             toBe('Pretty text with some links: http://angularjs.org/, mailto:[email protected], ' +
791                  '[email protected], and one more: ftp://127.0.0.1/.');
792         expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
793       });
794
795       it('should update', function() {
796         element(by.model('snippet')).clear();
797         element(by.model('snippet')).sendKeys('new http://link.');
798         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
799             toBe('new http://link.');
800         expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
801         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
802             .toBe('new http://link.');
803       });
804
805       it('should work with the target property', function() {
806        expect(element(by.id('linky-target')).
807            element(by.binding("snippetWithSingleURL | linky:'_blank'")).getText()).
808            toBe('http://angularjs.org/');
809        expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
810       });
811
812       it('should optionally add custom attributes', function() {
813        expect(element(by.id('linky-custom-attributes')).
814            element(by.binding("snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}")).getText()).
815            toBe('http://angularjs.org/');
816        expect(element(by.css('#linky-custom-attributes a')).getAttribute('rel')).toEqual('nofollow');
817       });
818     </file>
819   </example>
820 */
821angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
822  var LINKY_URL_REGEXP =
823        /((s?ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
824      MAILTO_REGEXP = /^mailto:/i;
825
826  var linkyMinErr = angular.$$minErr('linky');
827  var isDefined = angular.isDefined;
828  var isFunction = angular.isFunction;
829  var isObject = angular.isObject;
830  var isString = angular.isString;
831
832  return function(text, target, attributes) {
833    if (text == null || text === '') return text;
834    if (!isString(text)) throw linkyMinErr('notstring', 'Expected string but received: {0}', text);
835
836    var attributesFn =
837      isFunction(attributes) ? attributes :
838      isObject(attributes) ? function getAttributesObject() {return attributes;} :
839      function getEmptyAttributesObject() {return {};};
840
841    var match;
842    var raw = text;
843    var html = [];
844    var url;
845    var i;
846    while ((match = raw.match(LINKY_URL_REGEXP))) {
847      // We can not end in these as they are sometimes found at the end of the sentence
848      url = match[0];
849      // if we did not match ftp/http/www/mailto then assume mailto
850      if (!match[2] && !match[4]) {
851        url = (match[3] ? 'http://' : 'mailto:') + url;
852      }
853      i = match.index;
854      addText(raw.substr(0, i));
855      addLink(url, match[0].replace(MAILTO_REGEXP, ''));
856      raw = raw.substring(i + match[0].length);
857    }
858    addText(raw);
859    return $sanitize(html.join(''));
860
861    function addText(text) {
862      if (!text) {
863        return;
864      }
865      html.push(sanitizeText(text));
866    }
867
868    function addLink(url, text) {
869      var key, linkAttributes = attributesFn(url);
870      html.push('<a ');
871
872      for (key in linkAttributes) {
873        html.push(key + '="' + linkAttributes[key] + '" ');
874      }
875
876      if (isDefined(target) && !('target' in linkAttributes)) {
877        html.push('target="',
878                  target,
879                  '" ');
880      }
881      html.push('href="',
882                url.replace(/"/g, '&quot;'),
883                '">');
884      addText(text);
885      html.push('</a>');
886    }
887  };
888}]);
889
890
891})(window, window.angular);
892
893/*
894    Webnames Error
895    -----------------------------
896    Module is meant to handle server and client side errors.
897
898Scenarios:
8991.) Unexpected error
900	StatusCode = 500
901
902	Symptoms:
903	- threw out of controller action method
904
905	What should happen:
906	- gets logged as special critical error to investigate
907	- if Angular error handler is present, let that handle the user error
908	- if it's a production environment, allow them to log an error report
909	- if it's local host, display stack trace etc
910
911	Examples:
912	- developer forgets to handle an exception that can be thrown, fixable error occurs (null reference)
913	- the user should be able to report that an error occurred and the error should be investigated
914	- these prohibit the user from continuing their intended action on the site
915
916	Solution:
917	- the user should log an error
918
919	- inline form or link to oops page
920
921
9222.) Expected error
923	StatusCode = 422
924
925	Symptoms:
926	- it was caught in the controller, the StatusCode was manually set to 422
927
928	What should happen:
929	- should be handled in Angular controller, displaying a special message to the user (should/could use the WnErrorHandler)
930	- handle required view state on the promise rejection
931
932	Examples:
933	- server side validation of a domain name fails, return an error object and error message to display to the user
934
935    Author: Akos Sebestyen
936*/
937(function () {
938    "use strict";
939
940    angular.module('WebnamesError', ['ngSanitize'])
941
942        .config(['$httpProvider', function ($httpProvider) {
943            $httpProvider.interceptors.push('WnHttpInterceptor');
944        }])
945
946        .factory('WnHttpInterceptor', ['$log', '$q', '$sce', 'WnErrorHandler', function ($log, $q, $sce, WnErrorHandler) {
947            return {
948                'request': function (config) {
949                    // Add a custom header so our BaseController.cs can recognize that the WebnamesError module is present.
950                    return config;
951                },
952
953                'responseError': function (response) {
954                    // Convert the array buffer data into an object
955                    if (response.data instanceof ArrayBuffer) {
956                        response.data = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(response.data)));
957                    }
958
959                    // Push the error into the error handler directive        
960                    if (response.status === 500 && !!response.data.wnAngularError) {
961                        WnErrorHandler.PushError(!!response.data.debugMode ? $sce.trustAsHtml(response.data.wnAngularError) : response.data.wnAngularError, true);
962                    }
963
964                    return $q.reject(response);
965                }
966            }
967        }]);
968
969})();
970
971/*
972 * Webnames Error
973 * ----------------
974 * Directives for displaying errors to the user from Angular. 
975 * 
976 * Author: Akos Sebestyen
977 */
978(function () {
979    "use strict";
980
981    angular.module('WebnamesError')
982
983        // you can specify the 'timeout-length' property to determine how long the notification should stay on screen
984        .directive('wnNotifications', wnNotifications)
985
986        // errors for the user to see
987        .directive('wnErrors', wnErrors)
988
989        .directive('helpdeskError', helpdeskError);
990
991    function wnNotifications() {
992        return {
993            restrict: 'EA',
994            replace: true,
995            template: '<div class="alert {{ notification.sCSSClass || \'alert-info\' }} alert-dismissible" data-ng-repeat="notification in wnn.notifications track by notification.id" role="alert">' +
996                '<button class="close" data-dismiss="alert" aria-label="Close"><i class="fas fa-times"></i></button>' +
997                '<p data-ng-bind-html="notification.message"></p>' +
998                '</div>',
999            controllerAs: 'wnn',
1000            link: function (scope, elem, attrs) {
1001                scope.$emit('wnNotifications loaded');
1002                if (!!attrs.timeoutLength) {
1003                    scope.timeoutLength = attrs.timeoutLength;
1004                }
1005            },
1006            controller: ['$scope', '$timeout', 'WnErrorHandler', function ($scope, $timeout, WnErrorHandler) {
1007                var vm = this;
1008
1009                vm.notifications = WnErrorHandler.Notifications;
1010
1011                $scope.$on('WnNotificationPushed', function (event, id) {
1012                    if (!!$scope.timeoutLength && $scope.timeoutLength > 0) {
1013                        $timeout(function () {
1014                            WnErrorHandler.RemoveById(id);
1015                        }, $scope.timeoutLength * 1000);
1016                    }
1017                });
1018
1019                vm.clear = function (id) {
1020                    WnErrorHandler.RemoveById(id);
1021                }
1022            }]
1023        }
1024    }
1025
1026    function wnErrors() {
1027        return {
1028            restrict: 'EA',
1029            replace: true,
1030            template: '<div id="webnames-error-directive" class="alert alert-danger alert-dismissible" data-ng-repeat="error in wne.errors track by error.id" role="alert">
1030' +
1031                '<button class="close" data-dismiss="alert" aria-label="Close" data-ng-if="!error.isCritical" data-ng-click="wne.clear(error.id)"><i class="fas fa-times"></i></button>' +
1032                '<p data-ng-bind-html="error.message"></p>' +
1033                '<p data-ng-if="error.isCritical">Timestamp: {{error.dtTimestamp | date: "yyyy-MM-dd H:mm:ss.sss"}}</p>' +
1034                '</div>',
1035            link: function (scope) {
1036                scope.$emit('wnErrors loaded');
1037            },
1038            controllerAs: 'wne',
1039            controller: ['$scope', '$timeout', 'WnErrorHandler', function ($scope, $timeout, WnErrorHandler) {
1040                var vm = this;
1041
1042                vm.errors = WnErrorHandler.Errors;
1043
1044                vm.clear = function (id) {
1045                    WnErrorHandler.RemoveById(id);
1046                }
1047            }]
1048        }
1049    }
1050
1051    function helpdeskError() {
1052        return {
1053            restrict: 'EA',
1054            template: '<div class="red-tip">' +
1055                '<h1>Cart Errors</h1>' +
1056                '<h3>Message</h3>' +
1057                '<p>{{message}}</p>' +
1058                '<h3>StackTrace</h3>' +
1059                '<p>{{stackTrace}}</p>' +
1060                '<h3>Suggested Solution</h3>' +
1061                '<p>{{suggestedSolution}}</p>' +
1062                '<h3>Timestamp</h3>' +
1063                '<p>{{dtCreated}}</p>' +
1064                '</div>',
1065            scope: {
1066                error: '='
1067            },
1068            controller: [
1069                '$scope', function ($scope) {
1070                    // When the error object changes, make sure it has all attributes and then display the error
1071                    $scope.$watch('error', function () {
1072                        if ($scope.error &&
1073                            $scope.error.message &&
1074                            $scope.error.stackTrace &&
1075                            $scope.error.suggestedSolution &&
1076                            $scope.error.dtCreated) {
1077                            $scope.message = $scope.error.message;
1078                            $scope.stackTrace = $scope.error.stackTrace;
1079                            $scope.suggestedSolution = $scope.error.suggestedSolution;
1080                            $scope.dtCreated = $scope.error.dtCreated;
1081                        }
1082                    });
1083                }
1084            ]
1085        }
1086    };
1087})();
1088
1089/*
1090    WebnamesError - WnErrorHandler
1091    ------------------
1092    Service used to push messages to the directive which will display them to the user.
1093
1094    Author: Akos Sebestyen
1095 */
1096(function () {
1097    "use strict";
1098
1099    angular.module('WebnamesError')
1100        .service('WnErrorHandler', ['$rootScope', '$timeout', '$window', '$location', '$anchorScroll', 'WnMessage', '$log', function ($rootScope, $timeout, $window, $location, $anchorScroll, WnMessage, $log) {
1101            var service = this;
1102            var messageCount = 0;
1103
1104            var wnNotificationsPresent = false;
1105            var wnErrorsPresent = false;
1106
1107            service.scrollToError = true;
1108            service.Notifications = [];
1109            service.Errors = [];
1110
1111            service.ClearAll = function () {
1112                // Must clear array using length so that references aren't lost
1113                service.Notifications.length = 0;
1114                service.Errors.length = 0;
1115            }
1116
1117            // Use this to push notifications to the user
1118            service.PushNotification = function (errorString, sCSSClass) {
1119                var id = messageCount;
1120                service.Notifications.push(new WnMessage(id, errorString, false, sCSSClass));
1121                $rootScope.$broadcast('WnNotificationPushed', id);
1122                messageCount++;
1123
1124                return service.Notifications[service.Notifications.length - 1];
1125            }
1126
1127            // Use this to push errors to the user
1128            service.PushError = function (errorString, isCritical) {
1129                var id = messageCount;
1130                service.Errors.push(new WnMessage(id, errorString, !!isCritical));
1131                $rootScope.$broadcast('WnErrorPushed', id);
1132                messageCount++;
1133
1134                if (service.scrollToError) {
1135                    $location.hash("webnames-error-directive");
1136                    $anchorScroll();
1137                }
1138
1139                return service.Errors[service.Errors.length - 1];
1140            }
1141
1142            service.GetById = function (id) {
1143                return _.findWhere(service.Notifications, { id: id });
1144            }
1145
1146            service.RemoveById = function (id) {
1147                var index = _.findIndex(service.Notifications, { id: id });
1148
1149                if (index < 0) {
1150                    index = _.findIndex(service.Errors, { id: id });
1151                    if (index > -1 && !service.Errors[index].isCritical) service.Errors.splice(index, 1);
1152                } else {
1153                    service.Notifications.splice(index, 1);
1154                }
1155            }
1156
1157            // TODO: implement parameters
1158            /**
1159             * Redirects client to the robot page.
1160             * @returns {} 
1161             */
1162            service.KillNonRecoverable = function () {
1163                $window.location.href = $window._SmartURL + "error/oops/default.aspx";
1164            }
1165
1166            // Save events from link function of directives for page validation
1167            $rootScope.$on('wnNotifications loaded', function () {
1168                wnNotificationsPresent = true;
1169            });
1170
1171            $rootScope.$on('wnErrors loaded', function () {
1172                wnErrorsPresent = true;
1173            });
1174
1175            // Used for validation of the Angular page
1176            $timeout(function () {
1177                if (!wnErrorsPresent) {
1178                    throw "No 'wnErrors' directive found! You should not use this module without placing this directive on your page first!";
1179                }
1180                if (!wnNotificationsPresent) {
1181                    throw "No 'wnNotifications' directive found! You should not use this module without placing this directive on your page first!";
1182                }
1183            });
1184        }])
1185
1186        .factory('WnMessage', [function () {
1187            function WnMessage(id, message, isCritical, sCSSClass) {
1188                var model = this;
1189
1190                model.id = id;
1191                model.dtTimestamp = new Date();
1192                model.isCritical = isCritical;
1193                model.sCSSClass = sCSSClass || "";
1194
1195                model.message = message;
1196            }
1197
1198            return WnMessage;
1199        }]);
1200})();
1201
1202/*
1203    Webnames Analytics
1204    --------------------------------
1205    Module to allow easy abstraction of analytics work in Angular.
1206
1207    Has services for Google Analytics.
1208
1209    It's best implemented using the server side Analytics helpers
1210    to construct the required JSON objects from BillPackages etc.
1211
1212    Modules
1213       GAService webnamesAnalytics.ga.service.cs
1214    
1215    Server Side Helpers
1216     GoogleAnalyticsHelpers.cs
1217
1218    Dependencies
1219    ~ Underscore : Using UnderscoreJS for any array/object work.   
1220
1221    Author: Akos Sebestyen 2015
1222*/
1223
1224(function () {
1225    angular.module("WebnamesAnalytics", [])
1226        .config(['$logProvider', function($logProvider) {
1227                $logProvider.debugEnabled(true);
1228            }
1229        ]);
1230})();
1231/*****
1232    WebnamesAnalytics::GoogleAnalytics Service
1233
1234    Handles Analytics requests from an Ajax call to push to Google Analytics
1235
1236    Sample Usage (in controller, etc)
1237      GAService.AddProduct($a.remove[i][0]);
1238
1239    Depends on:
1240    $window
1241    $log
1242****/
1243(function () {
1244    angular.module("WebnamesAnalytics")
1245        .service('GAService', ['$window', '$log', gaService]);
1246
1247    function gaService($window, $log) {
1248        if (!$window.ga) {
1249            // This could be inject tested. (like underscore)
1250            throw "You must have GA defined globally to use this service!";
1251        }
1252
1253        //***************** IMPORTANT ***************/
1254        // use GoogleAnalyticsHelper.cs to create 'objects' server side and then pass those in
1255
1256        var service = this;
1257
1258        // Example
1259        // ga('ec:addProduct', { 'id': 'PHOSTUNIX1FD_NEW' , 'name': 'Hosting Value Plan (Free Domain)' , 'brand': 'Webnames.ca' , 'variant': '6' , 'quantity': 1 , 'price': 37.5000 });         
1260        service.AddProduct = addProduct;
1261        service.AddProductAndSend = addProductAndSend;
1262
1263        service.RemoveProductAndSend = removeProductAndSend;
1264
1265        // Must be set by calling module module (set to undefined, but we don't test this later on)
1266        service.GAProperties = undefined;
1267
1268        // Example
1269        // ga('ec:setAction', 'add', { 'list': 'Cart Page' });
1270        service.TrackAction = trackAction;
1271
1272        // Example
1273        // ga('send', 'event', 'Cart Page', 'Add to Cart');
1274        service.Send = send;
1275
1276        function addProduct(obj) {
1277            $log.debug('ec:addProduct', obj);
1278            $window.ga('ec:addProduct', obj);
1279        }
1280
1281        function addProductAndSend(categoryName, actionName, arrProperties) {
1282            for (var i = 0; i < arrProperties.length; i++) {
1283                service.AddProduct(arrProperties[i]);
1284            }
1285
1286            service.TrackAction('add', { 'list': actionName });
1287
1288            service.Send(categoryName, actionName);
1289        }
1290
1291        function removeProductAndSend(categoryName, actionName, arrProperties) {
1292            for (var i = 0; i < arrProperties.length; i++) {
1293                service.AddProduct(arrProperties[i]);
1294            }
1295
1296            service.TrackAction('remove', { 'list': actionName });
1297
1298            service.Send(categoryName, actionName);
1299        }
1300
1301        function trackAction(action, obj) {
1302            $log.debug('ec:setAction', action, obj);
1303            $window.ga('ec:setAction', action, obj);
1304        }
1305
1306        function send(name, desc) {
1307            $log.debug('send', 'event', name, desc);
1308            $window.ga('send', 'event', name, desc);
1309        }
1310    }
1311})();
1312(function () {
1313    angular.module("WebnamesAnalytics")
1314        .service('GA4Service', ['$window', '$log', GA4Service]);
1315
1316    function GA4Service($window, $log) {
1317
1318        var service = this;
1319
1320        function sendEvent (sEventName, sEventData) {
1321            gtag('event', sEventName, sEventData);
1322        };
1323
1324        service.sendAddToCart = function (oData) {
1325            var sEventName = "add_to_cart";
1326            sendEvent(sEventName, oData);
1327
1328        }
1329        service.sendRemoveFromCart = function (oData) {
1330            var sEventName = "remove_from_cart";
1331            sendEvent(sEventName, oData);
1332
1333        }
1334    }
1335})();
1336(function () {
1337    "use strict";
1338    angular.module("WebnamesLocationHelper", ["WebnamesCommon"]);
1339})();
1340(function () {
1341    "use strict";
1342
1343    angular
1344        .module("WebnamesLocationHelper")
1345        .service("QueryStringFilterBinder", ["$location", "$rootScope", "$filter", QueryStringFilterBinder]);
1346
1347    function QueryStringFilterBinder($location, $rootScope, $filter) {
1348        var service = this;
1349
1350        var currentBindings = [];
1351
1352        /**
1353         * Unbinds all listeners set up
1354         * @returns {undefined} 
1355         */
1356        service.UnbindAllFilters = function () {
1357            var startingLength = currentBindings.length;
1358            for (var i = 0; i < startingLength; i++) {
1359                var binding = currentBindings.pop();
1360
1361                binding.deregisterLocationListener();
1362                binding.deregisterWatch();
1363            }
1364        }
1365
1366        /**
1367         * Binds a flat object of filters to url params
1368         * @param {Object} filterObj a flat object of filters which will be bound to the url params by type
1369         * @param {Boolean} bExcludeFilterKeys a boolean flag to indicate whether it shouldn't bind to URL params if all of the filter properties are true
1370         * @param {Object}
1370 excludeObj an object containing parameters with keys that are not counted when determining if location parameters are applied
1371         * @param {Object} includeObj an object containing parameters with keys that are counted when determining if location parameters are applied
1372         * Note: if (includeObj === undefined), all parameters (even random ones) will be counted
1373         * @returns {Function} a deregister function for this binding
1374         */
1375        service.BindFilters = function (filterObj, bExcludeFilterKeys, excludeObj, includeObj) {
1376
1377            if (bExcludeFilterKeys === undefined) bExcludeFilterKeys = false;
1378            if (excludeObj === undefined) excludeObj = {};
1379
1380            if (!_.isObject(filterObj)) throw new Error("parameter being bound must be an object");
1381            
1382            // only apply location parameters if there are any in the URL 
1383            //(that aren't "excluded", and, if includeObj is defined, also are "included")
1384            var bApplyLocationParams = false;
1385            for (var sParam in $location.search()) {
1386                if ($location.search().hasOwnProperty(sParam)) {
1387                    var bDontExclude = true;
1388                    for (var sExcludeParam in excludeObj) {
1389                        if (excludeObj.hasOwnProperty(sExcludeParam)) {
1390                            if (sParam == sExcludeParam) {
1391                                bDontExclude = false;
1392                                break;
1393                            }
1394                        }
1395                    }
1396                    if (!bDontExclude) continue;
1397                    
1398                    if (includeObj === undefined) {                        
1399                        bApplyLocationParams = true;
1400                        break;
1401                    }
1402                    var bInclude = false;
1403                    for (var sIncudeParam in includeObj) {
1404                        if (includeObj.hasOwnProperty(sIncudeParam)) {
1405                            if (sParam == sIncudeParam) {
1406                                bInclude = true;
1407                                break;
1408                            }
1409                        }
1410                    }
1411                    if (bInclude) {
1412                        bApplyLocationParams = true;
1413                        break;
1414                    }
1415                }
1416            }
1417            if (bApplyLocationParams) {
1418                applyLocationParams(filterObj, bExcludeFilterKeys, true);
1419            }
1420
1421            // Set up a watch on filter object to bind each one of its properties to changing the url
1422            var deregisterWatch = $rootScope.$watch(function () { return filterObj }, function (newVal) {
1423                _.each(_.keys(newVal), function (key) {
1424                    if (_.isBoolean(newVal[key])) {
1425                        // if we are doing exclusion, reverse our set operation
1426                        if (!bExcludeFilterKeys) {
1427                            $location.search(key, newVal[key] ? true : null);
1428                        } else {
1429                            $location.search(key, !newVal[key] ? true : null);
1430                        }
1431                    }
1432                    else if (_.isNumber(newVal[key]) || _.isString(newVal[key])) {
1433                        $location.search(key, newVal[key]);
1434                    }
1435                    else {
1436                        $location.search(key, newVal[key]);   
1437                    }
1438                });
1439            }, true);
1440
1441            var deregisterLocationListener = $rootScope.$on("$locationChangeSuccess", function () {
1442                applyLocationParams(filterObj, bExcludeFilterKeys);
1443            });
1444
1445            currentBindings.push({
1446                filterObj: filterObj,
1447                deregisterLocationListener: deregisterLocationListener,
1448                deregisterWatch: deregisterWatch
1449            });
1450
1451            return function () {
1452                var bindingIndex = _.findIndex(currentBindings, function(binding) {
1453                    return binding.filterObj === filterObj;
1454                });
1455                currentBindings[bindingIndex].deregisterWatch();
1456                currentBindings[bindingIndex].deregisterLocationListener();
1457                currentBindings.splice(bindingIndex, 1);
1458            }
1459        }
1460
1461        function applyLocationParams(filterObj, allTrueDontBind) {
1462            var params = $location.search();
1463            var paramKeys = _.keys(params);
1464            // Loop through each key of the filter object and update its value based on URL parameters
1465            _.each(_.keys(filterObj), function (key) {
1466
1467                switch (typeof filterObj[key]) {
1468                    case "boolean":
1469                        filterObj[key] = ((_.indexOf(paramKeys, key) < 0) ? !!allTrueDontBind : !allTrueDontBind);
1470                        break;
1471                    case "number":
1472                        if (params.hasOwnProperty(key) && !isNaN(params[key])) {
1473                            filterObj[key] = parseInt(params[key]);
1474                        }
1475                        break;
1476                    default:
1477                        filterObj[key]= params[key];
1478                        break;
1479                }
1480            });
1481        }
1482    }
1483})();
1484
1485(function () {
1486    "use strict";
1487
1488    angular.module("WebnamesLocationHelper")
1489    .service("LegacyParam", ['$window', function($window) {
1490        var service = this;
1491
1492        service.Params = {};
1493
1494        /**
1495         * Helper to get a list of domain name parameters from the URL
1496         * @returns {Array} An array of domain parameters (params that begin with 'dom')  
1497         */
1498        service.GetDomains = function() {
1499            return _.chain(service.Params)
1500                        .map(function (value, key) {
1501                            if (key.substr(0, 3) === "dom") return value;
1502                            else return undefined;
1503                        })
1504                        .compact()
1505                        .uniq()
1506                        .value();
1507        }
1508
1509        var paramArray = $window.location.search.substr(1).split("&");
1510
1511        _.each(paramArray, function (param) {
1512            var pair = param.split("=");
1513            service.Params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
1514        });
1515    }]);
1516})();
1517(function () {
1518    "use strict";
1519
1520    angular
1521      .module("WebnamesLocationHelper")
1522      .directive("wnHref", ["$window", wnHref]);
1523
1524    function wnHref($window) {
1525        var directive = {
1526            link: link,
1527            restrict: "A"
1528        };
1529
1530        function link(scope, element, attrs) {
1531            attrs.$set("href", $window._SmartURL + attrs.wnHref);
1532        }
1533
1534        return directive;
1535    }
1536})();
1537/*
1538    Webnames Common
1539    --------------------------------
1540    Module to hold common Angular functions
1541    
1542    Author: Akos Sebestyen 2015
1543*/
1544(function () {
1545    "use strict";
1546
1547    angular.module('WebnamesCommon', []);
1548
1549})();
1550
1551
1552/*
1553    Generic Injector
1554    --------------------------------
1555    Used to inject data into Angular on pageload.
1556
1557    The provider exposes a "InjectGenericProperty" method that can be used at config time to get JSON data into the service.
1558
1559    Then you can access the data from GenericInjector.PropBag.yourProperty
1560    
1561    Author: Akos Sebestyen 2015
1562*/
1563(function () {
1564    "use strict";
1565
1566    angular.module('WebnamesCommon')
1567    .provider('GenericInjector', function () {
1568        var _propBag = {};
1569
1570        // Assign the prop bag
1571        var GenericInjector = function () {
1572            this.PropBag = _propBag;            
1573        };
1574
1575        return {
1576            $get: ['$injector', function ($injector) { return $injector.instantiate(GenericInjector) }],
1577            InjectGenericProperty: function (propName, propValue) { _propBag[propName] = propValue}
1578        }
1579    });
1580
1581})();
1582
1583
1584(function () {
1585    "use strict";
1586
1587    angular.module("WebnamesCommon")
1588    .factory("WnFocus", ['$timeout', '$document', function ($timeout, $document) {
1589        return function(id) {
1590            $timeout(function () {
1591                var element = $document.getElementById(id);
1592                if (element)
1593                    element.focus();
1594            });
1595        }                
1596    }]);
1597})();
1598// Scrolls to the top of the given selector. Use offset to offset the value by pixels
1599
1600(function () {
1601    "use strict";
1602
1603    angular.module("WebnamesCommon")
1604    .factory("WnScroll", ['$timeout', function ($timeout) {
1605        return function (selector, offset, animateTime) {
1606            if (!offset) offset = 0;
1607            if (!animateTime) animateTime = 500;
1608            $timeout(function () {
1609                $('html, body').animate({ scrollTop: ($(selector).offset().top + offset) }, animateTime);
1610            });
1611        }
1612    }]);
1613})();
1614// https://gist.github.com/tommaitland/7579618
1615(function () {
1616    angular.module('WebnamesCommon').directive('ngDebounce', ['$timeout', function ($timeout) {
1617        return {
1618            restrict: 'A',
1619            require: 'ngModel',
1620            priority: 99,
1621            link: function (scope, elm, attr, ngModelCtrl) {
1622                if (attr.type === 'radio' || attr.type === 'checkbox') return;
1623
1624                elm.unbind('input');
1625
1626                var debounce;
1627                elm.bind('input', function () {
1628                    $timeout.cancel(debounce);
1629                    debounce = $timeout(function () {
1630                        scope.$apply(function () {
1631                            ngModelCtrl.$setViewValue(elm.val());
1632                        });
1633                    }, attr.ngDebounce || 1000);
1634                });
1635                elm.bind('blur', function () {
1636                    scope.$apply(function () {
1637                        ngModelCtrl.$setViewValue(elm.val());
1638                    });
1639                });
1640            }
1641
1642        }
1643    }]);
1644})();
1645
1646(function () {
1647    "use strict";
1648
1649    angular.module('WebnamesCommon')
1650        .filter('startFrom', function () {
1651
1652            return function (input, start) {
1653                if (input !== undefined && angular.isArray(input)) {
1654                    return input.slice(start);
1655                } else {
1656                    return [];
1657                }
1658            }
1659        })
1660    .filter("getActiveKeys", [function () {
1661        /**
1662         * Takes an object and returns an array of keys where the values are truthy
1663         * @param {Object} obj Flat object of key value pairs
1664         * @returns {Array} array of keys with truthy values
1665         */
1666        return function(obj) {
1667            return _.chain(obj)
1668            .pairs() // Turn object into array of arrays as key value pairs
1669            .filter(function (kvp) { return !!kvp[1] }) // Return all Key-Value pairs where value is truthy
1670            .map(function (kvp) { return kvp[0] }) // Map into an array of just strings of keys
1671            .value();
1672        }
1673    }])
1674    .filter('nullToEnd', function () {
1675        return function (array, key) {
1676            if (!angular.isArray(array)) return;
1677
1678            var present = array.filter(function (item) {
1679                return item[key];
1680            });
1681            var empty = array.filter(function (item) {
1682                return !item[key];
1683            });
1684
1685            return present.concat(empty);
1686        }
1687    })
1688    .run(["$http", function ($http) {
1689        $http.defaults.headers.common['X-XSRF-Token'] =
1690            angular.element(document.querySelector('input[name="__RequestVerificationToken"]')).attr('value');
1691    }]);
1692})();
1693
1694(function() {
1695    "use strict";
1696
1697    angular.module("WebnamesGridHelper", [])
1698    .directive("orderedHeader", [function () {
1699        return {
1700            restrict: 'EA',
1701            replace: true,
1702            transclude: true,
1703            template: '<th><span class="pointer h-underline" ng-click="toggleOrder()"><span ng-transclude></span ng-transclude>' +
1704                '<span class="ml5 fa-xs" ng-show="ordering.predicate === predicate && ordering.reverse"><i class="fa-solid fa-caret-down"></i></span>' +
1705                '<span class="ml5 fa-xs" ng-show="ordering.predicate === predicate && !ordering.reverse"><i class="fa-solid fa-caret-up"></i></span>' +
1706                '</span></span></th>',
1707            controller: ['$scope', function ($scope) {
1708                $scope.toggleOrder = function () {
1709                    if ($scope.ordering.predicate === $scope.predicate) {
1710                        $scope.ordering.reverse = !$scope.ordering.reverse;
1711                    } else {
1712                        $scope.ordering.predicate = $scope.predicate;
1713                        $scope.ordering.reverse = false;
1714                    }
1715                }
1716            }],
1717            scope: {
1718                predicate: "@",
1719                ordering: "="
1720            }
1721        }
1722    }]);
1723})();
1724/**
1725 * State-based routing for AngularJS 1.x
1726 * NOTICE: This monolithic bundle also bundles the @uirouter/core code.
1727 *         This causes it to be incompatible with plugins that depend on @uirouter/core.
1728 *         We recommend switching to the ui-router-core.js and ui-router-angularjs.js bundles instead.
1729 *         For more information, see https://ui-router.github.io/blog/uirouter-for-angularjs-umd-bundles
1730 * @version v1.0.30
1731 * @link https://ui-router.github.io
1732 * @license MIT License, http://www.opensource.org/licenses/MIT
1733 */
1734(function (global, factory) {
1735    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('angular')) :
1736    typeof define === 'function' && define.amd ? define(['exports', 'angular'], factory) :
1737    (global = global || self, factory(global['@uirouter/angularjs'] = {}, global.angular));
1738}(this, (function (exports, ng_from_import) { 'use strict';
1739
1740    /** @publicapi @module ng1 */ /** */
1741    /** @hidden */ var ng_from_global = angular;
1742    /** @hidden */ var ng = ng_from_import && ng_from_import.module ? ng_from_import : ng_from_global;
1743
1744    /**
1745     * Higher order functions
1746     *
1747     * These utility functions are exported, but are subject to change without notice.
1748     *
1749     * @packageDocumentation
1750     */
1751    var __spreadArrays = (undefined && undefined.__spreadArrays) || function () {
1752        for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
1753        for (var r = Array(s), k = 0, i = 0; i < il; i++)
1754            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
1755                r[k] = a[j];
1756        return r;
1757    };
1758    /**
1759     * Returns a new function for [Partial Application](https://en.wikipedia.org/wiki/Partial_application) of the original function.
1760     *
1761     * Given a function with N parameters, returns a new function that supports partial application.
1762     * The new function accepts anywhere from 1 to N parameters.  When that function is called with M parameters,
1763     * where M is less than N, it returns a new function that accepts the remaining parameters.  It continues to
1764     * accept more parameters until all N parameters have been supplied.
1765     *
1766     *
1767     * This contrived example uses a partially applied function as an predicate, which returns true
1768     * if an object is found in both arrays.
1769     * @example
1770     * ```
1771     * // returns true if an object is in both of the two arrays
1772     * function inBoth(array1, array2, object) {
1773     *   return array1.indexOf(object) !== -1 &&
1774     *          array2.indexOf(object) !== 1;
1775     * }
1776     * let obj1, obj2, obj3, obj4, obj5, obj6, obj7
1777     * let foos = [obj1, obj3]
1778     * let bars = [obj3, obj4, obj5]
1779     *
1780     * // A curried "copy" of inBoth
1781     * let curriedInBoth = curry(inBoth);
1782     * // Partially apply both the array1 and array2
1783     * let inFoosAndBars = curriedInBoth(foos, bars);
1784     *
1785     * // Supply the final argument; since all arguments are
1786     * // supplied, the original inBoth function is then called.
1787     * let obj1InBoth = inFoosAndBars(obj1); // false
1788     *
1789     * // Use the inFoosAndBars as a predicate.
1790     * // Filter, on each iteration, supplies the final argument
1791     * let allObjs = [ obj1, obj2, obj3, obj4, obj5, obj6, obj7 ];
1792     * let foundInBoth = allObjs.filter(inFoosAndBars); // [ obj3 ]
1793     *
1794     * ```
1795     *
1796     * @param fn
1797     * @returns {*|function(): (*|any)}
1798     */
1799    function curry(fn) {
1800        return function curried() {
1801            if (arguments.length >= fn.length) {
1802                return fn.apply(this, arguments);
1803            }
1804            var args = Array.prototype.slice.call(arguments);
1805            return curried.bind.apply(curried, __spreadArrays([this], args));
1806        };
1807    }
1808    /**
1809     * Given a varargs list of functions, returns a function that composes the argument functions, right-to-left
1810     * given: f(x), g(x), h(x)
1811     * let composed = compose(f,g,h)
1812     * then, composed is: f(g(h(x)))
1813     */
1814    function compose() {
1815        var args = arguments;
1816        var start = args.length - 1;
1817        return function () {
1818            var i = start, result = args[start].apply(this, arguments);
1819            while (i--)
1820                result = args[i].call(this, result);
1821            return result;
1822        };
1823    }
1824    /**
1825     * Given a varargs list of functions, returns a function that is composes the argument functions, left-to-right
1826     * given: f(x), g(x), h(x)
1827     * let piped = pipe(f,g,h);
1828     * then, piped is: h(g(f(x)))
1829     */
1830    function pipe() {
1831        var funcs = [];
1832        for (var _i = 0; _i < arguments.length; _i++) {
1833            funcs[_i] = arguments[_i];
1834        }
1835        return compose.apply(null, [].slice.call(arguments).reverse());
1836    }
1837    /**
1838     * Given a property name, returns a function that returns that property from an object
1839     * let obj = { foo: 1, name: "blarg" };
1840     * let getName = prop("name");
1841     * getName(obj) === "blarg"
1842     */
1843    var prop = function (name) { return function (obj) { return obj && obj[name]; }; };
1844    /**
1845     * Given a property name and a value, returns a function that returns a boolean based on whether
1846     * the passed object has a property that matches the value
1847     * let obj = { foo: 1, name: "blarg" };
1848     * let getName = propEq("name", "blarg");
1849     * getName(obj) === true
1850     */
1851    var propEq = curry(function (name, _val, obj) { return obj && obj[name] === _val; });
1852    /**
1853     * Given a dotted property name, returns a function that returns a nested property from an object, or undefined
1854     * let obj = { id: 1, nestedObj: { foo: 1, name: "blarg" }, };
1855     * let getName = prop("nestedObj.name");
1856     * getName(obj) === "blarg"
1857     * let propNotFound = prop("this.property.doesnt.exist");
1858     * propNotFound(obj) === undefined
1859     */
1860    var parse = function (name) { return pipe.apply(null, name.split('.').map(prop)); };
1861    /**
1862     * Given a function that returns a truthy or falsey value, returns a
1863     * function that returns the opposite (falsey or truthy) value given the same inputs
1864     */
1865    var not = function (fn) { return function () {
1866        var args = [];
1867        for (var _i = 0; _i < arguments.length; _i++) {
1868            args[_i] = arguments[_i];
1869        }
1870        return !fn.apply(null, args);
1871    }; };
1872    /**
1873     * Given two functions that return truthy or falsey values, returns a function that returns truthy
1874     * if both functions return truthy for the given arguments
1875     */
1876    function and(fn1, fn2) {
1877        return function () {
1878            var args = [];
1879            for (var _i = 0; _i < arguments.length; _i++) {
1880                args[_i] = arguments[_i];
1881            }
1882            return fn1.apply(null, args) && fn2.apply(null, args);
1883        };
1884    }
1885    /**
1886     * Given two functions that return truthy or falsey values, returns a function that returns truthy
1887     * if at least one of the functions returns truthy for the given arguments
1888     */
1889    function or(fn1, fn2) {
1890        return function () {
1891            var args = [];
1892            for (var _i = 0; _i < arguments.length; _i++) {
1893                args[_i] = arguments[_i];
1894            }
1895            return fn1.apply(null, args) || fn2.apply(null, args);
1896        };
1897    }
1898    /**
1899     * Check if all the elements of an array match a predicate function
1900     *
1901     * @param fn1 a predicate function `fn1`
1902     * @returns a function which takes an array and returns true if `fn1` is true for all elements of the array
1903     */
1904    var all = function (fn1) { return function (arr) { return arr.reduce(function (b, x) { return b && !!fn1(x); }, true); }; };
1905    // tslint:disable-next-line:variable-name
1906    var any = function (fn1) { return function (arr) { return arr.reduce(function (b, x) { return b || !!fn1(x); }, false); }; };
1907    /** Given a class, returns a Predicate function that returns true if the object is of that class */
1908    var is = function (ctor) { return function (obj) {
1909        return (obj != null && obj.constructor === ctor) || obj instanceof ctor;
1910    }; };
1911    /** Given a value, returns a Predicate function that returns true if another value is === equal to the original value */
1912    var eq = function (value) { return function (other) { return value === other; }; };
1913    /** Given a value, returns a function which returns the value */
1914    var val = function (v) { return function () { return v; }; };
1915    function invoke(fnName, args) {
1916        return function (obj) { return obj[fnName].apply(obj, args); };
1917    }
1918    /**
1919     * Sorta like Pattern Matching (a functional programming conditional construct)
1920     *
1921     * See http://c2.com/cgi/wiki?PatternMatching
1922     *
1923     * This is a conditional construct which allows a series of predicates and output functions
1924     * to be checked and then applied.  Each predicate receives the input.  If the predicate
1925     * returns truthy, then its matching output function (mapping function) is provided with
1926     * the input and, then the result is returned.
1927     *
1928     * Each combination (2-tuple) of predicate + output function should be placed in an array
1929     * of size 2: [ predicate, mapFn ]
1930     *
1931     * These 2-tuples should be put in an outer array.
1932     *
1933     * @example
1934     * ```
1935     *
1936     * // Here's a 2-tuple where the first element is the isString predicate
1937     * // and the second element is a function that returns a description of the input
1938     * let firstTuple = [ angular.isString, (input) => `Heres your string ${input}` ];
1939     *
1940     * // Second tuple: predicate "isNumber", mapfn returns a description
1941     * let secondTuple = [ angular.isNumber, (input) => `(${input}) That's a number!` ];
1942     *
1943     * let third = [ (input) => input === null,  (input) => `Oh, null...` ];
1944     *
1945     * let fourth = [ (input) => input === undefined,  (input) => `notdefined` ];
1946     *
1947     * let descriptionOf = pattern([ firstTuple, secondTuple, third, fourth ]);
1948     *
1949     * console.log(descriptionOf(undefined)); // 'notdefined'
1950     * console.log(descriptionOf(55)); // '(55) That's a number!'
1951     * console.log(descriptionOf("foo")); // 'Here's your string foo'
1952     * ```
1953     *
1954     * @param struct A 2D array.  Each element of the array should be an array, a 2-tuple,
1955     * with a Predicate and a mapping/output function
1956     * @returns {function(any): *}
1957     */
1958    function pattern(struct) {
1959        return function (x) {
1960            for (var i = 0; i < struct.length; i++) {
1961                if (struct[i][0](x))
1962                    return struct[i][1](x);
1963            }
1964        };
1965    }
1966
1967    /**
1968     * Predicates
1969     *
1970     * These predicates return true/false based on the input.
1971     * Although these functions are exported, they are subject to change without notice.
1972     *
1973     * @packageDocumentation
1974     */
1975    var toStr = Object.prototype.toString;
1976    var tis = function (t) { return function (x) { return typeof x === t; }; };
1977    var isUndefined = tis('undefined');
1978    var isDefined = not(isUndefined);
1979    var isNull = function (o) { return o === null; };
1980    var isNullOrUndefined = or(isNull, isUndefined);
1981    var isFunction = tis('function');
1982    var isNumber = tis('number');
1983    var isString = tis('string');
1984    var isObject = function (x) { return x !== null && typeof x === 'object'; };
1985    var isArray = Array.isArray;
1986    var isDate = (function (x) { return toStr.call(x) === '[object Date]'; });
1987    var isRegExp = (function (x) { return toStr.call(x) === '[object RegExp]'; });
1988    /**
1989     * Predicate which checks if a value is injectable
1990     *
1991     * A value is "injectable" if it is a function, or if it is an ng1 array-notation-style array
1992     * where all the elements in the array are Strings, except the last one, which is a Function
1993     */
1994    function isInjectable(val) {
1995        if (isArray(val) && val.length) {
1996            var head = val.slice(0, -1), tail = val.slice(-1);
1997            return !(head.filter(not(isString)).length || tail.filter(not(isFunction)).length);
1998        }
1999        return isFunction(val);
2000    }
2001    /**
2002     * Predicate which checks if a value looks like a Promise
2003     *
2004     * It is probably a Promise if it's an object, and it has a `then` property which is a Function
2005     */
2006    var isPromise = and(isObject, pipe(prop('then'), isFunction));
2007
2008    var noImpl = function (fnname) { return function () {
2009        throw new Error("No implementation for " + fnname + ". The framework specific code did not implement this method.");
2010    }; };
2011    var makeStub = function (service, methods) {
2012        return methods.reduce(function (acc, key) { return ((acc[key] = noImpl(service + "." + key + "()")), acc); }, {});
2013    };
2014    var services = {
2015        $q: undefined,
2016        $injector: undefined,
2017    };
2018
2019    var __spreadArrays$1 = (undefined && undefined.__spreadArrays) || function () {
2020        for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
2021        for (var r = Array(s), k = 0, i = 0; i < il; i++)
2022            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
2023                r[k] = a[j];
2024        return r;
2025    };
2026    var root = (typeof self === 'object' && self.self === self && self) ||
2027        (typeof global === 'object' && global.global === global && global) ||
2028        undefined;
2029    var angular$1 = root.angular || {};
2030    var fromJson = angular$1.fromJson || JSON.parse.bind(JSON);
2031    var toJson = angular$1.toJson || JSON.stringify.bind(JSON);
2032    var forEach = angular$1.forEach || _forEach;
2033    var extend = Object.assign || _extend;
2034    var equals = angular$1.equals || _equals;
2035    function identity(x) {
2036        return x;
2037    }
2038    function noop() { }
2039    /**
2040     * Builds proxy functions on the `to` object which pass through to the `from` object.
2041     *
2042     * For each key in `fnNames`, creates a proxy function on the `to` object.
2043     * The proxy function calls the real function on the `from` object.
2044     *
2045     *
2046     * #### Example:
2047     * This example creates an new class instance whose functions are prebound to the new'd object.
2048     * ```js
2049     * class Foo {
2050     *   constructor(data) {
2051     *     // Binds all functions from Foo.prototype to 'this',
2052     *     // then copies them to 'this'
2053     *     bindFunctions(Foo.prototype, this, this);
2054     *     this.data = data;
2055     *   }
2056     *
2057     *   log() {
2058     *     console.log(this.data);
2059     *   }
2060     * }
2061     *
2062     * let myFoo = new Foo([1,2,3]);
2063     * var logit = myFoo.log;
2064     * logit(); // logs [1, 2, 3] from the myFoo 'this' instance
2065     * ```
2066     *
2067     * #### Example:
2068     * This example creates a bound version of a service function, and copies it to another object
2069     * ```
2070     *
2071     * var SomeService = {
2072     *   this.data = [3, 4, 5];
2073     *   this.log = function() {
2074     *     console.log(this.data);
2075     *   }
2076     * }
2077     *
2078     * // Constructor fn
2079     * function OtherThing() {
2080     *   // Binds all functions from SomeService to SomeService,
2081     *   // then copies them to 'this'
2082     *   bindFunctions(SomeService, this, SomeService);
2083     * }
2084     *
2085     * let myOtherThing = new OtherThing();
2086     * myOtherThing.log(); // logs [3, 4, 5] from SomeService's 'this'
2087     * ```
2088     *
2089     * @param source A function that returns the source object which contains the original functions to be bound
2090     * @param target A function that returns the target object which will receive the bound functions
2091     * @param bind A function that returns the object which the functions will be bound to
2092     * @param fnNames The function names which will be bound (Defaults to all the functions foun
2092d on the 'from' object)
2093     * @param latebind If true, the binding of the function is delayed until the first time it's invoked
2094     */
2095    function createProxyFunctions(source, target, bind, fnNames, latebind) {
2096        if (latebind === void 0) { latebind = false; }
2097        var bindFunction = function (fnName) { return source()[fnName].bind(bind()); };
2098        var makeLateRebindFn = function (fnName) {
2099            return function lateRebindFunction() {
2100                target[fnName] = bindFunction(fnName);
2101                return target[fnName].apply(null, arguments);
2102            };
2103        };
2104        fnNames = fnNames || Object.keys(source());
2105        return fnNames.reduce(function (acc, name) {
2106            acc[name] = latebind ? makeLateRebindFn(name) : bindFunction(name);
2107            return acc;
2108        }, target);
2109    }
2110    /**
2111     * prototypal inheritance helper.
2112     * Creates a new object which has `parent` object as its prototype, and then copies the properties from `extra` onto it
2113     */
2114    var inherit = function (parent, extra) { return extend(Object.create(parent), extra); };
2115    /** Given an array, returns true if the object is found in the array, (using indexOf) */
2116    var inArray = curry(_inArray);
2117    function _inArray(array, obj) {
2118        return array.indexOf(obj) !== -1;
2119    }
2120    /**
2121     * Given an array, and an item, if the item is found in the array, it removes it (in-place).
2122     * The same array is returned
2123     */
2124    var removeFrom = curry(_removeFrom);
2125    function _removeFrom(array, obj) {
2126        var idx = array.indexOf(obj);
2127        if (idx >= 0)
2128            array.splice(idx, 1);
2129        return array;
2130    }
2131    /** pushes a values to an array and returns the value */
2132    var pushTo = curry(_pushTo);
2133    function _pushTo(arr, val) {
2134        return arr.push(val), val;
2135    }
2136    /** Given an array of (deregistration) functions, calls all functions and removes each one from the source array */
2137    var deregAll = function (functions) {
2138        return functions.slice().forEach(function (fn) {
2139            typeof fn === 'function' && fn();
2140            removeFrom(functions, fn);
2141        });
2142    };
2143    /**
2144     * Applies a set of defaults to an options object.  The options object is filtered
2145     * to only those properties of the objects in the defaultsList.
2146     * Earlier objects in the defaultsList take precedence when applying defaults.
2147     */
2148    function defaults(opts) {
2149        var defaultsList = [];
2150        for (var _i = 1; _i < arguments.length; _i++) {
2151            defaultsList[_i - 1] = arguments[_i];
2152        }
2153        var defaultVals = extend.apply(void 0, __spreadArrays$1([{}], defaultsList.reverse()));
2154        return extend(defaultVals, pick(opts || {}, Object.keys(defaultVals)));
2155    }
2156    /** Reduce function that merges each element of the list into a single object, using extend */
2157    var mergeR = function (memo, item) { return extend(memo, item); };
2158    /**
2159     * Finds the common ancestor path between two states.
2160     *
2161     * @param {Object} first The first state.
2162     * @param {Object} second The second state.
2163     * @return {Array} Returns an array of state names in descending order, not including the root.
2164     */
2165    function ancestors(first, second) {
2166        var path = [];
2167        // tslint:disable-next-line:forin
2168        for (var n in first.path) {
2169            if (first.path[n] !== second.path[n])
2170                break;
2171            path.push(first.path[n]);
2172        }
2173        return path;
2174    }
2175    /**
2176     * Return a copy of the object only containing the whitelisted properties.
2177     *
2178     * #### Example:
2179     * ```
2180     * var foo = { a: 1, b: 2, c: 3 };
2181     * var ab = pick(foo, ['a', 'b']); // { a: 1, b: 2 }
2182     * ```
2183     * @param obj the source object
2184     * @param propNames an Array of strings, which are the whitelisted property names
2185     */
2186    function pick(obj, propNames) {
2187        var objCopy = {};
2188        for (var _prop in obj) {
2189            if (propNames.indexOf(_prop) !== -1) {
2190                objCopy[_prop] = obj[_prop];
2191            }
2192        }
2193        return objCopy;
2194    }
2195    /**
2196     * Return a copy of the object omitting the blacklisted properties.
2197     *
2198     * @example
2199     * ```
2200     *
2201     * var foo = { a: 1, b: 2, c: 3 };
2202     * var ab = omit(foo, ['a', 'b']); // { c: 3 }
2203     * ```
2204     * @param obj the source object
2205     * @param propNames an Array of strings, which are the blacklisted property names
2206     */
2207    function omit(obj, propNames) {
2208        return Object.keys(obj)
2209            .filter(not(inArray(propNames)))
2210            .reduce(function (acc, key) { return ((acc[key] = obj[key]), acc); }, {});
2211    }
2212    /**
2213     * Maps an array, or object to a property (by name)
2214     */
2215    function pluck(collection, propName) {
2216        return map(collection, prop(propName));
2217    }
2218    /** Filters an Array or an Object's properties based on a predicate */
2219    function filter(collection, callback) {
2220        var arr = isArray(collection), result = arr ? [] : {};
2221        var accept = arr ? function (x) { return result.push(x); } : function (x, key) { return (result[key] = x); };
2222        forEach(collection, function (item, i) {
2223            if (callback(item, i))
2224                accept(item, i);
2225        });
2226        return result;
2227    }
2228    /** Finds an object from an array, or a property of an object, that matches a predicate */
2229    function find(collection, callback) {
2230        var result;
2231        forEach(collection, function (item, i) {
2232            if (result)
2233                return;
2234            if (callback(item, i))
2235                result = item;
2236        });
2237        return result;
2238    }
2239    /** Given an object, returns a new object, where each property is transformed by the callback function */
2240    var mapObj = map;
2241    /** Maps an array or object properties using a callback function */
2242    function map(collection, callback, target) {
2243        target = target || (isArray(collection) ? [] : {});
2244        forEach(collection, function (item, i) { return (target[i] = callback(item, i)); });
2245        return target;
2246    }
2247    /**
2248     * Given an object, return its enumerable property values
2249     *
2250     * @example
2251     * ```
2252     *
2253     * let foo = { a: 1, b: 2, c: 3 }
2254     * let vals = values(foo); // [ 1, 2, 3 ]
2255     * ```
2256     */
2257    var values = function (obj) { return Object.keys(obj).map(function (key) { return obj[key]; }); };
2258    /**
2259     * Reduce function that returns true if all of the values are truthy.
2260     *
2261     * @example
2262     * ```
2263     *
2264     * let vals = [ 1, true, {}, "hello world"];
2265     * vals.reduce(allTrueR, true); // true
2266     *
2267     * vals.push(0);
2268     * vals.reduce(allTrueR, true); // false
2269     * ```
2270     */
2271    var allTrueR = function (memo, elem) { return memo && elem; };
2272    /**
2273     * Reduce function that returns true if any of the values are truthy.
2274     *
2275     *  * @example
2276     * ```
2277     *
2278     * let vals = [ 0, null, undefined ];
2279     * vals.reduce(anyTrueR, true); // false
2280     *
2281     * vals.push("hello world");
2282     * vals.reduce(anyTrueR, true); // true
2283     * ```
2284     */
2285    var anyTrueR = function (memo, elem) { return memo || elem; };
2286    /**
2287     * Reduce function which un-nests a single level of arrays
2288     * @example
2289     * ```
2290     *
2291     * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ];
2292     * input.reduce(unnestR, []) // [ "a", "b", "c", "d", [ "double, "nested" ] ]
2293     * ```
2294     */
2295    var unnestR = function (memo, elem) { return memo.concat(elem); };
2296    /**
2297     * Reduce function which recursively un-nests all arrays
2298     *
2299     * @example
2300     * ```
2301     *
2302     * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ];
2303     * input.reduce(unnestR, []) // [ "a", "b", "c", "d", "double, "nested" ]
2304     * ```
2305     */
2306    var flattenR = function (memo, elem) {
2307        return isArray(elem) ? memo.concat(elem.reduce(flattenR, [])) : pushR(memo, elem);
2308    };
2309    /**
2310     * Reduce function that pushes an object to an array, then returns the array.
2311     * Mostly just for [[flattenR]] and [[uniqR]]
2312     */
2313    function pushR(arr, obj) {
2314        arr.push(obj);
2315        return arr;
2316    }
2317    /** Reduce function that filters out duplicates */
2318    var uniqR = function (acc, token) { return (inArray(acc, token) ? acc : pushR(acc, token)); };
2319    /**
2320     * Return a new array with a single level of arrays unnested.
2321     *
2322     * @example
2323     * ```
2324     *
2325     * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ];
2326     * unnest(input) // [ "a", "b", "c", "d", [ "double, "nested" ] ]
2327     * ```
2328     */
2329    var unnest = function (arr) { return arr.reduce(unnestR, []); };
2330    /**
2331     * Return a completely flattened version of an array.
2332     *
2333     * @example
2334     * ```
2335     *
2336     * let input = [ [ "a", "b" ], [ "c", "d" ], [ [ "double", "nested" ] ] ];
2337     * flatten(input) // [ "a", "b", "c", "d", "double, "nested" ]
2338     * ```
2339     */
2340    var flatten = function (arr) { return arr.reduce(flattenR, []); };
2341    /**
2342     * Given a .filter Predicate, builds a .filter Predicate which throws an error if any elements do not pass.
2343     * @example
2344     * ```
2345     *
2346     * let isNumber = (obj) => typeof(obj) === 'number';
2347     * let allNumbers = [ 1, 2, 3, 4, 5 ];
2348     * allNumbers.filter(assertPredicate(isNumber)); //OK
2349     *
2350     * let oneString = [ 1, 2, 3, 4, "5" ];
2351     * oneString.filter(assertPredicate(isNumber, "Not all numbers")); // throws Error(""Not all numbers"");
2352     * ```
2353     */
2354    var assertPredicate = assertFn;
2355    /**
2356     * Given a .map function, builds a .map function which throws an error if any mapped elements do not pass a truthyness test.
2357     * @example
2358     * ```
2359     *
2360     * var data = { foo: 1, bar: 2 };
2361     *
2362     * let keys = [ 'foo', 'bar' ]
2363     * let values = keys.map(assertMap(key => data[key], "Key not found"));
2364     * // values is [1, 2]
2365     *
2366     * let keys = [ 'foo', 'bar', 'baz' ]
2367     * let values = keys.map(assertMap(key => data[key], "Key not found"));
2368     * // throws Error("Key not found")
2369     * ```
2370     */
2371    var assertMap = assertFn;
2372    function assertFn(predicateOrMap, errMsg) {
2373        if (errMsg === void 0) { errMsg = 'assert failure'; }
2374        return function (obj) {
2375            var result = predicateOrMap(obj);
2376            if (!result) {
2377                throw new Error(isFunction(errMsg) ? errMsg(obj) : errMsg);
2378            }
2379            return result;
2380        };
2381    }
2382    /**
2383     * Like _.pairs: Given an object, returns an array of key/value pairs
2384     *
2385     * @example
2386     * ```
2387     *
2388     * pairs({ foo: "FOO", bar: "BAR }) // [ [ "foo", "FOO" ], [ "bar": "BAR" ] ]
2389     * ```
2390     */
2391    var pairs = function (obj) { return Object.keys(obj).map(function (key) { return [key, obj[key]]; }); };
2392    /**
2393     * Given two or more parallel arrays, returns an array of tuples where
2394     * each tuple is composed of [ a[i], b[i], ... z[i] ]
2395     *
2396     * @example
2397     * ```
2398     *
2399     * let foo = [ 0, 2, 4, 6 ];
2400     * let bar = [ 1, 3, 5, 7 ];
2401     * let baz = [ 10, 30, 50, 70 ];
2402     * arrayTuples(foo, bar);       // [ [0, 1], [2, 3], [4, 5], [6, 7] ]
2403     * arrayTuples(foo, bar, baz);  // [ [0, 1, 10], [2, 3, 30], [4, 5, 50], [6, 7, 70] ]
2404     * ```
2405     */
2406    function arrayTuples() {
2407        var args = [];
2408        for (var _i = 0; _i < arguments.length; _i++) {
2409            args[_i] = arguments[_i];
2410        }
2411        if (args.length === 0)
2412            return [];
2413        var maxArrayLen = args.reduce(function (min, arr) { return Math.min(arr.length, min); }, 9007199254740991); // aka 2^53 − 1 aka Number.MAX_SAFE_INTEGER
2414        var result = [];
2415        var _loop_1 = function (i) {
2416            // This is a hot function
2417            // Unroll when there are 1-4 arguments
2418            switch (args.length) {
2419                case 1:
2420                    result.push([args[0][i]]);
2421                    break;
2422                case 2:
2423                    result.push([args[0][i], args[1][i]]);
2424                    break;
2425                case 3:
2426                    result.push([args[0][i], args[1][i], args[2][i]]);
2427                    break;
2428                case 4:
2429                    result.push([args[0][i], args[1][i], args[2][i], args[3][i]]);
2430                    break;
2431                default:
2432                    result.push(args.map(function (array) { return array[i]; }));
2433                    break;
2434            }
2435        };
2436        for (var i = 0; i < maxArrayLen; i++) {
2437            _loop_1(i);
2438        }
2439        return result;
2440    }
2441    /**
2442     * Reduce function which builds an object from an array of [key, value] pairs.
2443     *
2444     * Each iteration sets the key/val pair on the memo object, then returns the memo for the next iteration.
2445     *
2446     * Each keyValueTuple should be an array with values [ key: string, value: any ]
2447     *
2448     * @example
2449     * ```
2450     *
2451     * var pairs = [ ["fookey", "fooval"], ["barkey", "barval"] ]
2452     *
2453     * var pairsToObj = pairs.reduce((memo, pair) => applyPairs(memo, pair), {})
2454     * // pairsToObj == { fookey: "fooval", barkey: "barval" }
2455     *
2456     * // Or, more simply:
2457     * var pairsToObj = pairs.reduce(applyPairs, {})
2458     * // pairsToObj == { fookey: "fooval", barkey: "barval" }
2459     * ```
2460     */
2461    function applyPairs(memo, keyValTuple) {
2462        var key, value;
2463        if (isArray(keyValTuple))
2464            key = keyValTuple[0], value = keyValTuple[1];
2465        if (!isString(key))
2466            throw new Error('invalid parameters to applyPairs');
2467        memo[key] = value;
2468        return memo;
2469    }
2470    /** Get the last element of an array */
2471    function tail(arr) {
2472        return (arr.length && arr[arr.length - 1]) || undefined;
2473    }
2474    /**
2475     * shallow copy from src to dest
2476     */
2477    function copy(src, dest) {
2478        if (dest)
2479            Object.keys(dest).forEach(function (key) { return delete dest[key]; });
2480        if (!dest)
2481            dest = {};
2482        return extend(dest, src);
2483    }
2484    /** Naive forEach implementation works with Objects or Arrays */
2485    function _forEach(obj, cb, _this) {
2486        if (isArray(obj))
2487            return obj.forEach(cb, _this);
2488        Object.keys(obj).forEach(function (key) { return cb(obj[key], key); });
2489    }
2490    function _extend(toObj) {
2491        for (var i = 1; i < arguments.length; i++) {
2492            var obj = arguments[i];
2493            if (!obj)
2494                continue;
2495            var keys = Object.keys(obj);
2496            for (var j = 0; j < keys.length; j++) {
2497                toObj[keys[j]] = obj[keys[j]];
2498            }
2499        }
2500        return toObj;
2501    }
2502    function _equals(o1, o2) {
2503        if (o1 === o2)
2504            return true;
2505        if (o1 === null || o2 === null)
2506            return false;
2507        if (o1 !== o1 && o2 !== o2)
2508            return true; // NaN === NaN
2509        var t1 = typeof o1, t2 = typeof o2;
2510        if (t1 !== t2 || t1 !== 'object')
2511            return false;
2512        var tup = [o1, o2];
2513        if (all(isArray)(tup))
2514            return _arraysEq(o1, o2);
2515        if (all(isDate)(tup))
2516            return o1.getTime() === o2.getTime();
2517        if (all(isRegExp)(tup))
2518            return o1.toString() === o2.toString();
2519        if (all(isFunction)(tup))
2520            return true; // meh
2521        var predicates = [isFunction, isArray, isDate, isRegExp];
2522        if (predicates.map(any).reduce(function (b, fn) { return b || !!fn(tup); }, false))
2523            return false;
2524        var keys = {};
2525        // tslint:disable-next-line:forin
2526        for (var key in o1) {
2527            if (!_equals(o1[key], o2[key]))
2528                return false;
2529            keys[key] = true;
2530        }
2531        for (var key in o2) {
2532            if (!keys[key])
2533                return false;
2534        }
2535        return true;
2536    }
2537    function _arraysEq(a1, a2) {
2538        if (a1.length !== a2.length)
2539            return false;
2540        return arrayTuples(a1, a2).reduce(function (b, t) { return b && _equals(t[0], t[1]); }, true);
2541    }
2542    // issue #2676
2543    var silenceUncaughtInPromise = function (promise) { return promise.catch(function (e) { return 0; }) && promise; };
2544    var silentRejection = function (error) { return silenceUncaughtInPromise(services.$q.reject(error)); };
2545
2546    /**
2547     * Matches state names using glob-like pattern strings.
2548     *
2549     * Globs can be used in specific APIs including:
2550     *
2551     * - [[StateService.is]]
2552     * - [[StateService.includes]]
2553     * - The first argument to Hook Registration functions like [[TransitionService.onStart]]
2554     *    - [[HookMatchCriteria]] and [[HookMatchCriterion]]
2555     *
2556     * A `Glob` string is a pattern which matches state names.
2557     * Nested state names are split into segments (separated by a dot) when processing.
2558     * The state named `foo.bar.baz` is split into three segments ['foo', 'bar', 'baz']
2559     *
2560     * Globs work according to the following rules:
2561     *
2562     * ### Exact match:
2563     *
2564     * The glob `'A.B'` matches the state named exactly `'A.B'`.
2565     *
2566     * | Glob        |Matches states named|Does not match state named|
2567     * |:------------|:--------------------|:---------------------|
2568     * | `'A'`       | `'A'`               | `'B'` , `'A.C'`      |
2569     * | `'A.B'`     | `'A.B'`             | `'A'` , `'A.B.C'`    |
2570     * | `'foo'`     | `'foo'`             | `'FOO'` , `'foo.bar'`|
2571     *
2572     * ### Single star (`*`)
2573     *
2574     * A single star (`*`) is a wildcard that matches exactly one segment.
2575     *
2576     * | Glob        |Matches states named  |Does not match state named |
2577     * |:------------|:---------------------|:--------------------------|
2578     * | `'*'`       | `'A'` , `'Z'`        | `'A.B'` , `'Z.Y.X'`       |
2579     * | `'A.*'`     | `'A.B'` , `'A.C'`    | `'A'` , `'A.B.C'`         |
2580     * | `'A.*.*'`   | `'A.B.C'` , `'A.X.Y'`| `'A'`, `'A.B'` , `'Z.Y.X'`|
2581     *
2582     * ### Double star (`**`)
2583     *
2584     * A double star (`'**'`) is a wildcard that matches *zero or more segments*
2585     *
2586     * | Glob        |Matches states named                           |Does not match state named         |
2587     * |:------------|:----------------------------------------------|:----------------------------------|
2588     * | `'**'`      | `'A'` , `'A.B'`, `'Z.Y.X'`                    | (matches all states)              |
2589     * | `'A.**'`    | `'A'` , `'A.B'` , `'A.C.X'`                   | `'Z.Y.X'`                         |
2590     * | `'**.X'`    | `'X'` , `'A.X'` , `'Z.Y.X'`                   | `'A'` , `'A.login.Z'`             |
2591     * | `'A.**.X'`  | `'A.X'` , `'A.B.X'` , `'A.B.C.X'`             | `'A'` , `'A.B.C'`                 |
2592     *
2593     * @packageDocumentation
2594     */
2595    var Glob = /** @class */ (function () {
2596        function Glob(text) {
2597            this.text = text;
2598            this.glob = text.split('.');
2599            var regexpString = this.text
2600                .split('.')
2601                .map(function (seg) {
2602                if (seg === '**')
2603                    return '(?:|(?:\\.[^.]*)*)';
2604                if (seg === '*')
2605                    return '\\.[^.]*';
2606                return '\\.' + seg;
2607            })
2608                .join('');
2609            this.regexp = new RegExp('^' + regexpString + '$');
2610        }
2611        /** Returns true if the string has glob-like characters in it */
2612        Glob.is = function (text) {
2613            return !!/[!,*]+/.exec(text);
2614        };
2615        /** Returns a glob from the string, or null if the string isn't Glob-like */
2616        Glob.fromString = function (text) {
2617            return Glob.is(text) ? new Glob(text) : null;
2618        };
2619        Glob.prototype.matches = function (name) {
2620            return this.regexp.test('.' + name);
2621        };
2622        return Glob;
2623    }());
2624
2625    var Queue = /** @class */ (function () {
2626        function Queue(_items, _limit) {
2627            if (_items === void 0) { _items = []; }
2628            if (_limit === void 0) { _limit = null; }
2629            this._items = _items;
2630            this._limit = _limit;
2631            this._evictListeners = [];
2632            this.onEvict = pushTo(this._evictListeners);
2633        }
2634        Queue.prototype.enqueue = function (item) {
2635            var items = this._items;
2636            items.push(item);
2637            if (this._limit && items.length > this._limit)
2638                this.evict();
2639            return item;
2640        };
2641        Queue.prototype.evict = function () {
2642            var item = this._items.shift();
2643            this._evictListeners.forEach(function (fn) { return fn(item); });
2644            return item;
2645        };
2646        Queue.prototype.dequeue = function () {
2647            if (this.size())
2648                return this._items.splice(0, 1)[0];
2649        };
2650        Queue.prototype.clear = function () {
2651            var current = this._items;
2652            this._items = [];
2653            return current;
2654        };
2655        Queue.prototype.size = function () {
2656            return this._items.length;
2657        };
2658        Queue.prototype.remove = function (item) {
2659            var idx = this._items.indexOf(item);
2660            return idx > -1 && this._items.splice(idx, 1)[0];
2661        };
2662        Queue.prototype.peekTail = function () {
2663            return this._items[this._items.length - 1];
2664        };
2665        Queue.prototype.peekHead = function () {
2666            if (this.size())
2667                return this._items[0];
2668        };
2669        return Queue;
2670    }());
2671
2672    /** An enum for Transition Rejection reasons */
2673
2674    (function (RejectType) {
2675        /**
2676         * A new transition superseded this one.
2677         *
2678         * While this transition was running, a new transition started.
2679         * This transition is cancelled because it was superseded by new transition.
2680         */
2681        RejectType[RejectType["SUPERSEDED"] = 2] = "SUPERSEDED";
2682        /**
2683         * The transition was aborted
2684         *
2685         * The transition was aborted by a hook which returned `false`
2686         */
2687        RejectType[RejectType["ABORTED"] = 3] = "ABORTED";
2688        /**
2689         * The transition was invalid
2690         *
2691         * The transition was never started because it was invali
2691d
2692         */
2693        RejectType[RejectType["INVALID"] = 4] = "INVALID";
2694        /**
2695         * The transition was ignored
2696         *
2697         * The transition was ignored because it would have no effect.
2698         *
2699         * Either:
2700         *
2701         * - The transition is targeting the current state and parameter values
2702         * - The transition is targeting the same state and parameter values as the currently running transition.
2703         */
2704        RejectType[RejectType["IGNORED"] = 5] = "IGNORED";
2705        /**
2706         * The transition errored.
2707         *
2708         * This generally means a hook threw an error or returned a rejected promise
2709         */
2710        RejectType[RejectType["ERROR"] = 6] = "ERROR";
2711    })(exports.RejectType || (exports.RejectType = {}));
2712    /** @internal */
2713    var id = 0;
2714    var Rejection = /** @class */ (function () {
2715        function Rejection(type, message, detail) {
2716            /** @internal */
2717            this.$id = id++;
2718            this.type = type;
2719            this.message = message;
2720            this.detail = detail;
2721        }
2722        /** Returns true if the obj is a rejected promise created from the `asPromise` factory */
2723        Rejection.isRejectionPromise = function (obj) {
2724            return obj && typeof obj.then === 'function' && is(Rejection)(obj._transitionRejection);
2725        };
2726        /** Returns a Rejection due to transition superseded */
2727        Rejection.superseded = function (detail, options) {
2728            var message = 'The transition has been superseded by a different transition';
2729            var rejection = new Rejection(exports.RejectType.SUPERSEDED, message, detail);
2730            if (options && options.redirected) {
2731                rejection.redirected = true;
2732            }
2733            return rejection;
2734        };
2735        /** Returns a Rejection due to redirected transition */
2736        Rejection.redirected = function (detail) {
2737            return Rejection.superseded(detail, { redirected: true });
2738        };
2739        /** Returns a Rejection due to invalid transition */
2740        Rejection.invalid = function (detail) {
2741            var message = 'This transition is invalid';
2742            return new Rejection(exports.RejectType.INVALID, message, detail);
2743        };
2744        /** Returns a Rejection due to ignored transition */
2745        Rejection.ignored = function (detail) {
2746            var message = 'The transition was ignored';
2747            return new Rejection(exports.RejectType.IGNORED, message, detail);
2748        };
2749        /** Returns a Rejection due to aborted transition */
2750        Rejection.aborted = function (detail) {
2751            var message = 'The transition has been aborted';
2752            return new Rejection(exports.RejectType.ABORTED, message, detail);
2753        };
2754        /** Returns a Rejection due to aborted transition */
2755        Rejection.errored = function (detail) {
2756            var message = 'The transition errored';
2757            return new Rejection(exports.RejectType.ERROR, message, detail);
2758        };
2759        /**
2760         * Returns a Rejection
2761         *
2762         * Normalizes a value as a Rejection.
2763         * If the value is already a Rejection, returns it.
2764         * Otherwise, wraps and returns the value as a Rejection (Rejection type: ERROR).
2765         *
2766         * @returns `detail` if it is already a `Rejection`, else returns an ERROR Rejection.
2767         */
2768        Rejection.normalize = function (detail) {
2769            return is(Rejection)(detail) ? detail : Rejection.errored(detail);
2770        };
2771        Rejection.prototype.toString = function () {
2772            var detailString = function (d) { return (d && d.toString !== Object.prototype.toString ? d.toString() : stringify(d)); };
2773            var detail = detailString(this.detail);
2774            var _a = this, $id = _a.$id, type = _a.type, message = _a.message;
2775            return "Transition Rejection($id: " + $id + " type: " + type + ", message: " + message + ", detail: " + detail + ")";
2776        };
2777        Rejection.prototype.toPromise = function () {
2778            return extend(silentRejection(this), { _transitionRejection: this });
2779        };
2780        return Rejection;
2781    }());
2782
2783    /**
2784     * Functions that manipulate strings
2785     *
2786     * Although these functions are exported, they are subject to change without notice.
2787     *
2788     * @packageDocumentation
2789     */
2790    /**
2791     * Returns a string shortened to a maximum length
2792     *
2793     * If the string is already less than the `max` length, return the string.
2794     * Else return the string, shortened to `max - 3` and append three dots ("...").
2795     *
2796     * @param max the maximum length of the string to return
2797     * @param str the input string
2798     */
2799    function maxLength(max, str) {
2800        if (str.length <= max)
2801            return str;
2802        return str.substr(0, max - 3) + '...';
2803    }
2804    /**
2805     * Returns a string, with spaces added to the end, up to a desired str length
2806     *
2807     * If the string is already longer than the desired length, return the string.
2808     * Else returns the string, with extra spaces on the end, such that it reaches `length` characters.
2809     *
2810     * @param length the desired length of the string to return
2811     * @param str the input string
2812     */
2813    function padString(length, str) {
2814        while (str.length < length)
2815            str += ' ';
2816        return str;
2817    }
2818    function kebobString(camelCase) {
2819        return camelCase
2820            .replace(/^([A-Z])/, function ($1) { return $1.toLowerCase(); }) // replace first char
2821            .replace(/([A-Z])/g, function ($1) { return '-' + $1.toLowerCase(); }); // replace rest
2822    }
2823    function functionToString(fn) {
2824        var fnStr = fnToString(fn);
2825        var namedFunctionMatch = fnStr.match(/^(function [^ ]+\([^)]*\))/);
2826        var toStr = namedFunctionMatch ? namedFunctionMatch[1] : fnStr;
2827        var fnName = fn['name'] || '';
2828        if (fnName && toStr.match(/function \(/)) {
2829            return 'function ' + fnName + toStr.substr(9);
2830        }
2831        return toStr;
2832    }
2833    function fnToString(fn) {
2834        var _fn = isArray(fn) ? fn.slice(-1)[0] : fn;
2835        return (_fn && _fn.toString()) || 'undefined';
2836    }
2837    function stringify(o) {
2838        var seen = [];
2839        var isRejection = Rejection.isRejectionPromise;
2840        var hasToString = function (obj) {
2841            return isObject(obj) && !isArray(obj) && obj.constructor !== Object && isFunction(obj.toString);
2842        };
2843        var stringifyPattern = pattern([
2844            [isUndefined, val('undefined')],
2845            [isNull, val('null')],
2846            [isPromise, val('[Promise]')],
2847            [isRejection, function (x) { return x._transitionRejection.toString(); }],
2848            [hasToString, function (x) { return x.toString(); }],
2849            [isInjectable, functionToString],
2850            [val(true), identity],
2851        ]);
2852        function format(value) {
2853            if (isObject(value)) {
2854                if (seen.indexOf(value) !== -1)
2855                    return '[circular ref]';
2856                seen.push(value);
2857            }
2858            return stringifyPattern(value);
2859        }
2860        if (isUndefined(o)) {
2861            // Workaround for IE & Edge Spec incompatibility where replacer function would not be called when JSON.stringify
2862            // is given `undefined` as value. To work around that, we simply detect `undefined` and bail out early by
2863            // manually stringifying it.
2864            return format(o);
2865        }
2866        return JSON.stringify(o, function (key, value) { return format(value); }).replace(/\\"/g, '"');
2867    }
2868    /** Returns a function that splits a string on a character or substring */
2869    var beforeAfterSubstr = function (char) {
2870        return function (str) {
2871            if (!str)
2872                return ['', ''];
2873            var idx = str.indexOf(char);
2874            if (idx === -1)
2875                return [str, ''];
2876            return [str.substr(0, idx), str.substr(idx + 1)];
2877        };
2878    };
2879    var hostRegex = new RegExp('^(?:[a-z]+:)?//[^/]+/');
2880    var stripLastPathElement = function (str) { return str.replace(/\/[^/]*$/, ''); };
2881    var splitHash = beforeAfterSubstr('#');
2882    var splitQuery = beforeAfterSubstr('?');
2883    var splitEqual = beforeAfterSubstr('=');
2884    var trimHashVal = function (str) { return (str ? str.replace(/^#/, '') : ''); };
2885    /**
2886     * Splits on a delimiter, but returns the delimiters in the array
2887     *
2888     * #### Example:
2889     * ```js
2890     * var splitOnSlashes = splitOnDelim('/');
2891     * splitOnSlashes("/foo"); // ["/", "foo"]
2892     * splitOnSlashes("/foo/"); // ["/", "foo", "/"]
2893     * ```
2894     */
2895    function splitOnDelim(delim) {
2896        var re = new RegExp('(' + delim + ')', 'g');
2897        return function (str) { return str.split(re).filter(identity); };
2898    }
2899    /**
2900     * Reduce fn that joins neighboring strings
2901     *
2902     * Given an array of strings, returns a new array
2903     * where all neighboring strings have been joined.
2904     *
2905     * #### Example:
2906     * ```js
2907     * let arr = ["foo", "bar", 1, "baz", "", "qux" ];
2908     * arr.reduce(joinNeighborsR, []) // ["foobar", 1, "bazqux" ]
2909     * ```
2910     */
2911    function joinNeighborsR(acc, x) {
2912        if (isString(tail(acc)) && isString(x))
2913            return acc.slice(0, -1).concat(tail(acc) + x);
2914        return pushR(acc, x);
2915    }
2916
2917    /**
2918     * workaround for missing console object in IE9 when dev tools haven't been opened o_O
2919     * @packageDocumentation
2920     */
2921    var noopConsoleStub = { log: noop, error: noop, table: noop };
2922    function ie9Console(console) {
2923        var bound = function (fn) { return Function.prototype.bind.call(fn, console); };
2924        return {
2925            log: bound(console.log),
2926            error: bound(console.log),
2927            table: bound(console.log),
2928        };
2929    }
2930    function fallbackConsole(console) {
2931        var log = console.log.bind(console);
2932        var error = console.error ? console.error.bind(console) : log;
2933        var table = console.table ? console.table.bind(console) : log;
2934        return { log: log, error: error, table: table };
2935    }
2936    function getSafeConsole() {
2937        // @ts-ignore
2938        var isIE9 = typeof document !== 'undefined' && document.documentMode && document.documentMode === 9;
2939        if (isIE9) {
2940            return window && window.console ? ie9Console(window.console) : noopConsoleStub;
2941        }
2942        else if (!console.table || !console.error) {
2943            return fallbackConsole(console);
2944        }
2945        else {
2946            return console;
2947        }
2948    }
2949    var safeConsole = getSafeConsole();
2950
2951    /**
2952     * # Transition tracing (debug)
2953     *
2954     * Enable transition tracing to print transition information to the console,
2955     * in order to help debug your application.
2956     * Tracing logs detailed information about each Transition to your console.
2957     *
2958     * To enable tracing, import the [[Trace]] singleton and enable one or more categories.
2959     *
2960     * ### ES6
2961     * ```js
2962     * import {trace} from "@uirouter/core";
2963     * trace.enable(1, 5); // TRANSITION and VIEWCONFIG
2964     * ```
2965     *
2966     * ### CJS
2967     * ```js
2968     * let trace = require("@uirouter/core").trace;
2969     * trace.enable("TRANSITION", "VIEWCONFIG");
2970     * ```
2971     *
2972     * ### Globals
2973     * ```js
2974     * let trace = window["@uirouter/core"].trace;
2975     * trace.enable(); // Trace everything (very verbose)
2976     * ```
2977     *
2978     * ### Angular 1:
2979     * ```js
2980     * app.run($trace => $trace.enable());
2981     * ```
2982     *
2983     * @packageDocumentation
2984     */
2985    function uiViewString(uiview) {
2986        if (!uiview)
2987            return 'ui-view (defunct)';
2988        var state = uiview.creationContext ? uiview.creationContext.name || '(root)' : '(none)';
2989        return "[ui-view#" + uiview.id + " " + uiview.$type + ":" + uiview.fqn + " (" + uiview.name + "@" + state + ")]";
2990    }
2991    var viewConfigString = function (viewConfig) {
2992        var view = viewConfig.viewDecl;
2993        var state = view.$context.name || '(root)';
2994        return "[View#" + viewConfig.$id + " from '" + state + "' state]: target ui-view: '" + view.$uiViewName + "@" + view.$uiViewContextAnchor + "'";
2995    };
2996    function normalizedCat(input) {
2997        return isNumber(input) ? exports.Category[input] : exports.Category[exports.Category[input]];
2998    }
2999    /**
3000     * Trace categories Enum
3001     *
3002     * Enable or disable a category using [[Trace.enable]] or [[Trace.disable]]
3003     *
3004     * `trace.enable(Category.TRANSITION)`
3005     *
3006     * These can also be provided using a matching string, or position ordinal
3007     *
3008     * `trace.enable("TRANSITION")`
3009     *
3010     * `trace.enable(1)`
3011     */
3012
3013    (function (Category) {
3014        Category[Category["RESOLVE"] = 0] = "RESOLVE";
3015        Category[Category["TRANSITION"] = 1] = "TRANSITION";
3016        Category[Category["HOOK"] = 2] = "HOOK";
3017        Category[Category["UIVIEW"] = 3] = "UIVIEW";
3018        Category[Category["VIEWCONFIG"] = 4] = "VIEWCONFIG";
3019    })(exports.Category || (exports.Category = {}));
3020    var _tid = parse('$id');
3021    var _rid = parse('router.$id');
3022    var transLbl = function (trans) { return "Transition #" + _tid(trans) + "-" + _rid(trans); };
3023    /**
3024     * Prints UI-Router Transition trace information to the console.
3025     */
3026    var Trace = /** @class */ (function () {
3027        /** @internal */
3028        function Trace() {
3029            /** @internal */
3030            this._enabled = {};
3031            this.approximateDigests = 0;
3032        }
3033        /** @internal */
3034        Trace.prototype._set = function (enabled, categories) {
3035            var _this = this;
3036            if (!categories.length) {
3037                categories = Object.keys(exports.Category)
3038                    .map(function (k) { return parseInt(k, 10); })
3039                    .filter(function (k) { return !isNaN(k); })
3040                    .map(function (key) { return exports.Category[key]; });
3041            }
3042            categories.map(normalizedCat).forEach(function (category) { return (_this._enabled[category] = enabled); });
3043        };
3044        Trace.prototype.enable = function () {
3045            var categories = [];
3046            for (var _i = 0; _i < arguments.length; _i++) {
3047                categories[_i] = arguments[_i];
3048            }
3049            this._set(true, categories);
3050        };
3051        Trace.prototype.disable = function () {
3052            var categories = [];
3053            for (var _i = 0; _i < arguments.length; _i++) {
3054                categories[_i] = arguments[_i];
3055            }
3056            this._set(false, categories);
3057        };
3058        /**
3059         * Retrieves the enabled stateus of a [[Category]]
3060         *
3061         * ```js
3062         * trace.enabled("VIEWCONFIG"); // true or false
3063         * ```
3064         *
3065         * @returns boolean true if the category is enabled
3066         */
3067        Trace.prototype.enabled = function (category) {
3068            return !!this._enabled[normalizedCat(category)];
3069        };
3070        /** @internal called by ui-router code */
3071        Trace.prototype.traceTransitionStart = function (trans) {
3072            if (!this.enabled(exports.Category.TRANSITION))
3073                return;
3074            safeConsole.log(transLbl(trans) + ": Started  -> " + stringify(trans));
3075        };
3076        /** @internal called by ui-router code */
3077        Trace.prototype.traceTransitionIgnored = function (trans) {
3078            if (!this.enabled(exports.Category.TRANSITION))
3079                return;
3080            safeConsole.log(transLbl(trans) + ": Ignored  <> " + stringify(trans));
3081        };
3082        /** @internal called by ui-router code */
3083        Trace.prototype.traceHookInvocation = function (step, trans, options) {
3084            if (!this.enabled(exports.Category.HOOK))
3085                return;
3086            var event = parse('traceData.hookType')(options) || 'internal', context = parse('traceData.context.state.name')(options) || parse('traceData.context')(options) || 'unknown', name = functionToString(step.registeredHook.callback);
3087            safeConsole.log(transLbl(trans) + ":   Hook -> " + event + " context: " + context + ", " + maxLength(200, name));
3088        };
3089        /** @internal called by ui-router code */
3090        Trace.prototype.traceHookResult = function (hookResult, trans, transitionOptions) {
3091            if (!this.enabled(exports.Category.HOOK))
3092                return;
3093            safeConsole.log(transLbl(trans) + ":   <- Hook returned: " + maxLength(200, stringify(hookResult)));
3094        };
3095        /** @internal called by ui-router code */
3096        Trace.prototype.traceResolvePath = function (path, when, trans) {
3097            if (!this.enabled(exports.Category.RESOLVE))
3098                return;
3099            safeConsole.log(transLbl(trans) + ":         Resolving " + path + " (" + when + ")");
3100        };
3101        /** @internal called by ui-router code */
3102        Trace.prototype.traceResolvableResolved = function (resolvable, trans) {
3103            if (!this.enabled(exports.Category.RESOLVE))
3104                return;
3105            safeConsole.log(transLbl(trans) + ":               <- Resolved  " + resolvable + " to: " + maxLength(200, stringify(resolvable.data)));
3106        };
3107        /** @internal called by ui-router code */
3108        Trace.prototype.traceError = function (reason, trans) {
3109            if (!this.enabled(exports.Category.TRANSITION))
3110                return;
3111            safeConsole.log(transLbl(trans) + ": <- Rejected " + stringify(trans) + ", reason: " + reason);
3112        };
3113        /** @internal called by ui-router code */
3114        Trace.prototype.traceSuccess = function (finalState, trans) {
3115            if (!this.enabled(exports.Category.TRANSITION))
3116                return;
3117            safeConsole.log(transLbl(trans) + ": <- Success  " + stringify(trans) + ", final state: " + finalState.name);
3118        };
3119        /** @internal called by ui-router code */
3120        Trace.prototype.traceUIViewEvent = function (event, viewData, extra) {
3121            if (extra === void 0) { extra = ''; }
3122            if (!this.enabled(exports.Category.UIVIEW))
3123                return;
3124            safeConsole.log("ui-view: " + padString(30, event) + " " + uiViewString(viewData) + extra);
3125        };
3126        /** @internal called by ui-router code */
3127        Trace.prototype.traceUIViewConfigUpdated = function (viewData, context) {
3128            if (!this.enabled(exports.Category.UIVIEW))
3129                return;
3130            this.traceUIViewEvent('Updating', viewData, " with ViewConfig from context='" + context + "'");
3131        };
3132        /** @internal called by ui-router code */
3133        Trace.prototype.traceUIViewFill = function (viewData, html) {
3134            if (!this.enabled(exports.Category.UIVIEW))
3135                return;
3136            this.traceUIViewEvent('Fill', viewData, " with: " + maxLength(200, html));
3137        };
3138        /** @internal called by ui-router code */
3139        Trace.prototype.traceViewSync = function (pairs) {
3140            if (!this.enabled(exports.Category.VIEWCONFIG))
3141                return;
3142            var uivheader = 'uiview component fqn';
3143            var cfgheader = 'view config state (view name)';
3144            var mapping = pairs
3145                .map(function (_a) {
3146                var _b;
3147                var uiView = _a.uiView, viewConfig = _a.viewConfig;
3148                var uiv = uiView && uiView.fqn;
3149                var cfg = viewConfig && viewConfig.viewDecl.$context.name + ": (" + viewConfig.viewDecl.$name + ")";
3150                return _b = {}, _b[uivheader] = uiv, _b[cfgheader] = cfg, _b;
3151            })
3152                .sort(function (a, b) { return (a[uivheader] || '').localeCompare(b[uivheader] || ''); });
3153            safeConsole.table(mapping);
3154        };
3155        /** @internal called by ui-router code */
3156        Trace.prototype.traceViewServiceEvent = function (event, viewConfig) {
3157            if (!this.enabled(exports.Category.VIEWCONFIG))
3158                return;
3159            safeConsole.log("VIEWCONFIG: " + event + " " + viewConfigString(viewConfig));
3160        };
3161        /** @internal called by ui-router code */
3162        Trace.prototype.traceViewServiceUIViewEvent = function (event, viewData) {
3163            if (!this.enabled(exports.Category.VIEWCONFIG))
3164                return;
3165            safeConsole.log("VIEWCONFIG: " + event + " " + uiViewString(viewData));
3166        };
3167        return Trace;
3168    }());
3169    /**
3170     * The [[Trace]] singleton
3171     *
3172     * #### Example:
3173     * ```js
3174     * import {trace} from "@uirouter/core";
3175     * trace.enable(1, 5);
3176     * ```
3177     */
3178    var trace = new Trace();
3179
3180    /**
3181     * An internal class which implements [[ParamTypeDefinition]].
3182     *
3183     * A [[ParamTypeDefinition]] is a plain javascript object used to register custom parameter types.
3184     * When a param type definition is registered, an instance of this class is created internally.
3185     *
3186     * This class has naive implementations for all the [[ParamTypeDefinition]] methods.
3187     *
3188     * Used by [[UrlMatcher]] when matching or formatting URLs, or comparing and validating parameter values.
3189     *
3190     * #### Example:
3191     * ```js
3192     * var paramTypeDef = {
3193     *   decode: function(val) { return parseInt(val, 10); },
3194     *   encode: function(val) { return val && val.toString(); },
3195     *   equals: function(a, b) { return this.is(a) && a === b; },
3196     *   is: function(val) { return angular.isNumber(val) && isFinite(val) && val % 1 === 0; },
3197     *   pattern: /\d+/
3198     * }
3199     *
3200     * var paramType = new ParamType(paramTypeDef);
3201     * ```
3202     */
3203    var ParamType = /** @class */ (function () {
3204        /**
3205         * @param def  A configuration object which contains the custom type definition.  The object's
3206         *        properties will override the default methods and/or pattern in `ParamType`'s public interface.
3207         * @returns a new ParamType object
3208         */
3209        function ParamType(def) {
3210            /** @inheritdoc */
3211            this.pattern = /.*/;
3212            /** @inheritdoc */
3213            this.inherit = true;
3214            extend(this, def);
3215        }
3216        // consider these four methods to be "abstract methods" that should be overridden
3217        /** @inheritdoc */
3218        ParamType.prototype.is = function (val, key) {
3219            return true;
3220        };
3221        /** @inheritdoc */
3222        ParamType.prototype.encode = function (val, key) {
3223            return val;
3224        };
3225        /** @inheritdoc */
3226        ParamType.prototype.decode = function (val, key) {
3227            return val;
3228        };
3229        /** @inheritdoc */
3230        ParamType.prototype.equals = function (a, b) {
3231            // tslint:disable-next-line:triple-equals
3232            return a == b;
3233        };
3234        ParamType.prototype.$subPattern = function () {
3235            var sub = this.pattern.toString();
3236            return sub.substr(1, sub.length - 2);
3237        };
3238        ParamType.prototype.toString = function () {
3239            return "{ParamType:" + this.name + "}";
3240        };
3241        /** Given an encoded string, or a decoded object, returns a decoded object */
3242        ParamType.prototype.$normalize = function (val) {
3243            return this.is(val) ? val : this.decode(val);
3244        };
3245        /**
3246         * Wraps an existing custom ParamType as an array of ParamType, depending on 'mode'.
3247         * e.g.:
3248         * - urlmatcher pattern "/path?{queryParam[]:int}"
3249         * - url: "/path?queryParam=1&queryParam=2
3250         * - $stateParams.queryParam will be [1, 2]
3251         * if `mode` is "auto", then
3252         * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1
3253         * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]
3254         */
3255        ParamType.prototype.$asArray = function (mode, isSearch) {
3256            if (!mode)
3257                return this;
3258            if (mode === 'auto' && !isSearch)
3259                throw new Error("'auto' array mode is for query parameters only");
3260            return new ArrayType(this, mode);
3261        };
3262        return ParamType;
3263    }());
3264    /** Wraps up a `ParamType` object to handle array values. */
3265    function ArrayType(type, mode) {
3266        var _this = this;
3267        // Wrap non-array value as array
3268        function arrayWrap(val) {
3269            return isArray(val) ? val : isDefined(val) ? [val] : [];
3270        }
3271        // Unwrap array value for "auto" mode. Return undefined for empty array.
3272        function arrayUnwrap(val) {
3273            switch (val.length) {
3274                case 0:
3275                    return undefined;
3276                case 1:
3277                    return mode === 'auto' ? val[0] : val;
3278                default:
3279                    return val;
3280            }
3281        }
3282        // Wraps type (.is/.encode/.decode) functions to operate on each value of an array
3283        function arrayHandler(callback, allTruthyMode) {
3284            return function handleArray(val) {
3285                if (isArray(val) && val.length === 0)
3286                    return val;
3287                var arr = arrayWrap(val);
3288                var result = map(arr, callback);
3289                return allTruthyMode === true ? filter(result, function (x) { return !x; }).length === 0 : arrayUnwrap(result);
3290            };
3291        }
3292        // Wraps type (.equals) functions to operate on each value of an array
3293        function arrayEqualsHandler(callback) {
3294            return function handleArray(val1, val2) {
3295                var left = arrayWrap(val1), right = arrayWrap(val2);
3296                if (left.length !== right.length)
3297                    return false;
3298                for (var i = 0; i < left.length; i++) {
3299                    if (!callback(left[i], right[i]))
3300                        return false;
3301                }
3302                return true;
3303            };
3304        }
3305        ['encode', 'decode', 'equals', '$normalize'].forEach(function (name) {
3306            var paramTypeFn = type[name].bind(type);
3307            var wrapperFn = name === 'equals' ? arrayEqualsHandler : arrayHandler;
3308            _this[name] = wrapperFn(paramTypeFn);
3309        });
3310        extend(this, {
3311            dynamic: type.dynamic,
3312            name: type.name,
3313            pattern: type.pattern,
3314            inherit: type.inherit,
3315            raw: type.raw,
3316            is: arrayHandler(type.is.bind(type), true),
3317            $arrayMode: mode,
3318        });
3319    }
3320
3321    var hasOwn = Object.prototype.hasOwnProperty;
3322    var isShorthand = function (cfg) {
3323        return ['value', 'type', 'squash', 'array', 'dynamic'].filter(hasOwn.bind(cfg || {})).length === 0;
3324    };
3325
3326    (function (DefType) {
3327        DefType[DefType["PATH"] = 0] = "PATH";
3328        DefType[DefType["SEARCH"] = 1] = "SEARCH";
3329        DefType[DefType["CONFIG"] = 2] = "CONFIG";
3330    })(exports.DefType || (exports.DefType = {}));
3331    function getParamDeclaration(paramName, location, state) {
3332        var noReloadOnSearch = (state.reloadOnSearch === false && location === exports.DefType.SEARCH) || undefined;
3333        var dynamic = find([state.dynamic, noReloadOnSearch], isDefined);
3334        var defaultConfig = isDefined(dynamic) ? { dynamic: dynamic } : {};
3335        var paramConfig = unwrapShorthand(state && state.params && state.params[paramName]);
3336        return extend(defaultConfig, paramConfig);
3337    }
3338    function unwrapShorthand(cfg) {
3339        cfg = isShorthand(cfg) ? { value: cfg } : cfg;
3340        getStaticDefaultValue['__cacheable'] = true;
3341        function getStaticDefaultValue() {
3342            return cfg.value;
3343        }
3344        var $$fn = isInjectable(cfg.value) ? cfg.value : getStaticDefaultValue;
3345        return extend(cfg, { $$fn: $$fn });
3346    }
3347    function getType(cfg, urlType, location, id, paramTypes) {
3348        if (cfg.type && urlType && urlType.name !== 'string')
3349            throw new Error("Param '" + id + "' has two type configurations.");
3350        if (cfg.type && urlType && urlType.name === 'string' && paramTypes.type(cfg.type))
3351            return paramTypes.type(cfg.type);
3352        if (urlType)
3353            return urlType;
3354        if (!cfg.type) {
3355            var type = location === exports.DefType.CONFIG
3356                ? 'any'
3357                : location === exports.DefType.PATH
3358                    ? 'path'
3359                    : location === exports.DefType.SEARCH
3360                        ? 'query'
3361                        : 'string';
3362            return paramTypes.type(type);
3363        }
3364        return cfg.type instanceof ParamType ? cfg.type : paramTypes.type(cfg.type);
3365    }
3366    /** returns false, true, or the squash value to indicate the "default parameter url squash policy". */
3367    function getSquashPolicy(config, isOptional, defaultPolicy) {
3368        var squash = config.squash;
3369        if (!isOptional || squash === false)
3370            return false;
3371        if (!isDefined(squash) || squash == null)
3372            return defaultPolicy;
3373        if (squash === true || isString(squash))
3374            return squash;
3375        throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string");
3376    }
3377    function getReplace(config, arrayMode, isOptional, squash) {
3378        var defaultPolicy = [
3379            { from: '', to: isOptional || arrayMode ? undefined : '' },
3380            { from: null, to: isOptional || arrayMode ? undefined : '' },
3381        ];
3382        var replace = isArray(config.replace) ? config.replace : [];
3383        if (isString(squash))
3384            replace.push({ from: squash, to: undefined });
3385        var configuredKeys = map(replace, prop('from'));
3386        return filter(defaultPolicy, function (item) { return configuredKeys.indexOf(item.from) === -1; }).concat(replace);
3387    }
3388    var Param = /** @class */ (function () {
3389        function Param(id, type, location, urlConfig, state) {
3390            var config = getParamDeclaration(id, location, state);
3391            type = getType(config, type, location, id, urlConfig.paramTypes);
3392            var arrayMode = getArrayMode();
3393            type = arrayMode ? type.$asArray(arrayMode, location === exports.DefType.SEARCH) : type;
3394            var isOptional = config.value !== undefined || location === exports.DefType.SEARCH;
3395            var dynamic = isDefined(config.dynamic) ? !!config.dynamic : !!type.dynamic;
3396            var raw = isDefined(config.raw) ? !!config.raw : !!type.raw;
3397            var squash = getSquashPolicy(config, isOptional, urlConfig.defaultSquashPolicy());
3398            var replace = getReplace(config, arrayMode, isOptional, squash);
3399            var inherit = isDefined(config.inherit) ? !!config.inherit : !!type.inherit;
3400            // array config: param name (param[]) overrides default settings.  explicit config overrides param name.
3401            function getArrayMode() {
3402                var arrayDefaults = { array: location === exports.DefType.SEARCH ? 'auto' : false };
3403                var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {};
3404                return extend(arrayDefaults, arrayParamNomenclature, config).array;
3405            }
3406            extend(this, { id: id, type: type, location: location, isOptional: isOptional, dynamic: dynamic, raw: raw, squash: squash, replace: replace, inherit: inherit, array: arrayMode, config: config });
3407        }
3408        Param.values = function (params, values) {
3409            if (values === void 0) { values = {}; }
3410            var paramValues = {};
3411            for (var _i = 0, params_1 = params; _i < params_1.length; _i++) {
3412                var param = params_1[_i];
3413                paramValues[param.id] = param.value(values[param.id]);
3414            }
3415            return paramValues;
3416        };
3417        /**
3418         * Finds [[Param]] objects which have different param values
3419         *
3420         * Filters a list of [[Param]] objects to only those whose parameter values differ in two param value objects
3421         *
3422         * @param params: The list of Param objects to filter
3423         * @param values1: The first set of parameter values
3424         * @param values2: the second set of parameter values
3425         *
3426         * @returns any Param objects whose values were different between values1 and values2
3427         */
3428        Param.changed = function (params, values1, values2) {
3429            if (values1 === void 0) { values1 = {}; }
3430            if (values2 === void 0) { values2 = {}; }
3431            return params.filter(function (param) { return !param.type.equals(values1[param.id], values2[param.id]); });
3432        };
3433        /**
3434         * Checks if two param value objects are equal (for a set of [[Param]] objects)
3435         *
3436         * @param params The list of [[Param]] objects to check
3437         * @param values1 The first set of param values
3438         * @param values2 The second set of param values
3439         *
3440         * @returns true if the param values in values1 and values2 are equal
3441         */
3442        Param.equals = function (params, values1, values2) {
3443            if (values1 === void 0) { values1 = {}; }
3444            if (values2 === void 0) { values2 = {}; }
3445            return Param.changed(params, values1, values2).length === 0;
3446        };
3447        /** Returns true if a the parameter values are valid, according to the Param definitions */
3448        Param.validates = function (params, values) {
3449            if (values === void 0) { values = {}; }
3450            return params.map(function (param) { return param.validates(values[param.id]); }).reduce(allTrueR, true);
3451        };
3452        Param.prototype.isDefaultValue = function (value) {
3453            return this.isOptional && this.type.equals(this.value(), value);
3454        };
3455        /**
3456         * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
3457         * default value, which may be the result of an injectable function.
3458         */
3459        Param.prototype.value = function (value) {
3460            var _this = this;
3461            /**
3462             * [Internal] Get the default value of a parameter, which may be an injectable function.
3463             */
3464            var getDefaultValue = function () {
3465                if (_this._defaultValueCache)
3466                    return _this._defaultValueCache.defaultValue;
3467                if (!services.$injector)
3468                    throw new Error('Injectable functions cannot be called at configuration time');
3469                var defaultValue = services.$injector.invoke(_this.config.$$fn);
3470                if (defaultValue !== null && defaultValue !== undefined && !_this.type.is(defaultValue))
3471                    throw new Error("Default value (" + defaultValue + ") for parameter '" + _this.id + "' is not an instance of ParamType (" + _this.type.name + ")");
3472                if (_this.config.$$fn['__cacheable']) {
3473                    _this._defaultValueCache = { defaultValue: defaultValue };
3474                }
3475                return defaultValue;
3476            };
3477            var replaceSpecialValues = function (val) {
3478                for (var _i = 0, _a = _this.replace; _i < _a.length; _i++) {
3479                    var tuple = _a[_i];
3480                    if (tuple.from === val)
3481                        return tuple.to;
3482                }
3483                return val;
3484            };
3485            value = replaceSpecialValues(value);
3486            return isUndefined(value) ? getDefaultValue() : this.type.$normalize(value);
3487        };
3488        Param.prototype.isSearch = function () {
3489            return this.location === exports.DefType.SEARCH;
3490        };
3491        Param.prototype.validates = function (value) {
3492            // There was no parameter value, but the param is optional
3493            if ((isUndefined(value) || value === null) && this.isOptional)
3494                return true;
3495            // The value was not of the correct ParamType, and could not be decoded to the correct ParamType
3496            var normalized = this.type.$normalize(value);
3497            if (!this.type.is(normalized))
3498                return false;
3499            // The value was of the correct type, but when encoded, did not match the ParamType's regexp
3500            var encoded = this.type.encode(normalized);
3501            return !(isString(encoded) && !this.type.pattern.exec(encoded));
3502        };
3503        Param.prototype.toString = function () {
3504            return "{Param:" + this.id + " " + this.type + " squash: '" + this.squash + "' optional: " + this.isOptional + "}";
3505        };
3506        return Param;
3507    }());
3508
3509    /**
3510     * A registry for parameter types.
3511     *
3512     * This registry manages the built-in (and custom) parameter types.
3513     *
3514     * The built-in parameter types are:
3515     *
3516     * - [[string]]
3517     * - [[path]]
3518     * - [[query]]
3519     * - [[hash]]
3520     * - [[int]]
3521     * - [[bool]]
3522     * - [[date]]
3523     * - [[json]]
3524     * - [[any]]
3525     *
3526     * To register custom parameter types, use [[UrlConfig.type]], i.e.,
3527     *
3528     * ```js
3529     * router.urlService.config.type(customType)
3530     * ```
3531     */
3532    var ParamTypes = /** @class */ (function () {
3533        function ParamTypes() {
3534            this.enqueue = true;
3535            this.typeQueue = [];
3536            this.defaultTypes = pick(ParamTypes.prototype, [
3537                'hash',
3538                'string',
3539                'query',
3540                'path',
3541                'int',
3542                'bool',
3543                'date',
3544                'json',
3545                'any',
3546            ]);
3547            // Register default types. Store them in the prototype of this.types.
3548            var makeType = function (definition, name) { return new ParamType(extend({ name: name }, definition)); };
3549            this.types = inherit(map(this.defaultTypes, makeType), {});
3550        }
3551        ParamTypes.prototype.dispose = function () {
3552            this.types = {};
3553        };
3554        /**
3555         * Registers a parameter type
3556         *
3557         * End users should call [[UrlMatcherFactory.type]], which delegates to this method.
3558         */
3559        ParamTypes.prototype.type = function (name, definition, definitionFn) {
3560            if (!isDefined(definition))
3561                return this.types[name];
3562            if (this.types.hasOwnProperty(name))
3563                throw new Error("A type named '" + name + "' has already been defined.");
3564            this.types[name] = new ParamType(extend({ name: name }, definition));
3565            if (definitionFn) {
3566                this.typeQueue.push({ name: name, def: definitionFn });
3567                if (!this.enqueue)
3568                    this._flushTypeQueue();
3569            }
3570            return this;
3571        };
3572        ParamTypes.prototype._flushTypeQueue = function () {
3573            while (this.typeQueue.length) {
3574                var type = this.typeQueue.shift();
3575                if (type.pattern)
3576                    throw new Error("You cannot override a type's .pattern at runtime.");
3577                extend(this.types[type.name], services.$injector.invoke(type.def));
3578            }
3579        };
3580        return ParamTypes;
3581    }());
3582    function initDefaultTypes() {
3583        var makeDefaultType = function (def) {
3584            var valToString = function (val) { return (val != null ? val.toString() : val); };
3585            var defaultTypeBase = {
3586                encode: valToString,
3587                decode: valToString,
3588                is: is(String),
3589                pattern: /.*/,
3590                // tslint:disable-next-line:triple-equals
3591                equals: function (a, b) { return a == b; },
3592            };
3593            return extend({}, defaultTypeBase, def);
3594        };
3595        // Default Parameter Type Definitions
3596        extend(ParamTypes.prototype, {
3597            string: makeDefaultType({}),
3598            path: makeDefaultType({
3599                pattern: /[^/]*/,
3600            }),
3601            query: makeDefaultType({}),
3602            hash: makeDefaultType({
3603                inherit: false,
3604            }),
3605            int: makeDefaultType({
3606                decode: function (val) { return parseInt(val, 10); },
3607                is: function (val) {
3608                    return !isNullOrUndefined(val) && this.decode(val.toString()) === val;
3609                },
3610                pattern: /-?\d+/,
3611            }),
3612            bool: makeDefaultType({
3613                encode: function (val) { return (val && 1) || 0; },
3614                decode: function (val) { return parseInt(val, 10) !== 0; },
3615                is: is(Boolean),
3616                pattern: /0|1/,
3617            }),
3618            date: makeDefaultType({
3619                encode: function (val) {
3620                    return !this.is(val)
3621                        ? undefined
3622                        : [val.getFullYear(), ('0' + (val.getMonth() + 1)).slice(-2), ('0' + val.getDate()).slice(-2)].join('-');
3623                },
3624                decode: function (val) {
3625                    if (this.is(val))
3626                        return val;
3627                    var match = this.capture.exec(val);
3628                    return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;
3629                },
3630                is: function (val) { return val instanceof Date && !isNaN(val.valueOf()); },
3631                equals: function (l, r) {
3632                    return ['getFullYear', 'getMonth', 'getDate'].reduce(function (acc, fn) { return acc && l[fn]() === r[fn](); }, true);
3633                },
3634                pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,
3635                capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/,
3636            }),
3637            json: makeDefaultType({
3638                encode: toJson,
3639                decode: fromJson,
3640                is: is(Object),
3641                equals: equals,
3642                pattern: /[^/]*/,
3643            }),
3644            // does not encode/decode
3645            any: makeDefaultType({
3646                encode: identity,
3647                decode: identity,
3648                is: function () { return true; },
3649                equals: equals,
3650            }),
3651        });
3652    }
3653    initDefaultTypes();
3654
3655    var StateParams = /** @class */ (function () {
3656        function StateParams(params) {
3657            if (params === void 0) { params = {}; }
3658            extend(this, params);
3659        }
3660        /**
3661         * Merges a set of parameters with all parameters inherited between the common parents of the
3662         * current state and a given destination state.
3663         *
3664         * @param {Object}
3664 newParams The set of parameters which will be composited with inherited params.
3665         * @param {Object} $current Internal definition of object representing the current state.
3666         * @param {Object} $to Internal definition of object representing state to transition to.
3667         */
3668        StateParams.prototype.$inherit = function (newParams, $current, $to) {
3669            var parentParams;
3670            var parents = ancestors($current, $to), inherited = {}, inheritList = [];
3671            for (var i in parents) {
3672                if (!parents[i] || !parents[i].params)
3673                    continue;
3674                parentParams = Object.keys(parents[i].params);
3675                if (!parentParams.length)
3676                    continue;
3677                for (var j in parentParams) {
3678                    if (inheritList.indexOf(parentParams[j]) >= 0)
3679                        continue;
3680                    inheritList.push(parentParams[j]);
3681                    inherited[parentParams[j]] = this[parentParams[j]];
3682                }
3683            }
3684            return extend({}, inherited, newParams);
3685        };
3686        return StateParams;
3687    }());
3688
3689    /**
3690     * A node in a [[TreeChanges]] path
3691     *
3692     * For a [[TreeChanges]] path, this class holds the stateful information for a single node in the path.
3693     * Each PathNode corresponds to a state being entered, exited, or retained.
3694     * The stateful information includes parameter values and resolve data.
3695     */
3696    var PathNode = /** @class */ (function () {
3697        function PathNode(stateOrNode) {
3698            if (stateOrNode instanceof PathNode) {
3699                var node = stateOrNode;
3700                this.state = node.state;
3701                this.paramSchema = node.paramSchema.slice();
3702                this.paramValues = extend({}, node.paramValues);
3703                this.resolvables = node.resolvables.slice();
3704                this.views = node.views && node.views.slice();
3705            }
3706            else {
3707                var state = stateOrNode;
3708                this.state = state;
3709                this.paramSchema = state.parameters({ inherit: false });
3710                this.paramValues = {};
3711                this.resolvables = state.resolvables.map(function (res) { return res.clone(); });
3712            }
3713        }
3714        PathNode.prototype.clone = function () {
3715            return new PathNode(this);
3716        };
3717        /** Sets [[paramValues]] for the node, from the values of an object hash */
3718        PathNode.prototype.applyRawParams = function (params) {
3719            var getParamVal = function (paramDef) { return [paramDef.id, paramDef.value(params[paramDef.id])]; };
3720            this.paramValues = this.paramSchema.reduce(function (memo, pDef) { return applyPairs(memo, getParamVal(pDef)); }, {});
3721            return this;
3722        };
3723        /** Gets a specific [[Param]] metadata that belongs to the node */
3724        PathNode.prototype.parameter = function (name) {
3725            return find(this.paramSchema, propEq('id', name));
3726        };
3727        /**
3728         * @returns true if the state and parameter values for another PathNode are
3729         * equal to the state and param values for this PathNode
3730         */
3731        PathNode.prototype.equals = function (node, paramsFn) {
3732            var diff = this.diff(node, paramsFn);
3733            return diff && diff.length === 0;
3734        };
3735        /**
3736         * Finds Params with different parameter values on another PathNode.
3737         *
3738         * Given another node (of the same state), finds the parameter values which differ.
3739         * Returns the [[Param]] (schema objects) whose parameter values differ.
3740         *
3741         * Given another node for a different state, returns `false`
3742         *
3743         * @param node The node to compare to
3744         * @param paramsFn A function that returns which parameters should be compared.
3745         * @returns The [[Param]]s which differ, or null if the two nodes are for different states
3746         */
3747        PathNode.prototype.diff = function (node, paramsFn) {
3748            if (this.state !== node.state)
3749                return false;
3750            var params = paramsFn ? paramsFn(this) : this.paramSchema;
3751            return Param.changed(params, this.paramValues, node.paramValues);
3752        };
3753        /**
3754         * Returns a clone of the PathNode
3755         * @deprecated use instance method `node.clone()`
3756         */
3757        PathNode.clone = function (node) { return node.clone(); };
3758        return PathNode;
3759    }());
3760
3761    /**
3762     * Encapsulate the target (destination) state/params/options of a [[Transition]].
3763     *
3764     * This class is frequently used to redirect a transition to a new destination.
3765     *
3766     * See:
3767     *
3768     * - [[HookResult]]
3769     * - [[TransitionHookFn]]
3770     * - [[TransitionService.onStart]]
3771     *
3772     * To create a `TargetState`, use [[StateService.target]].
3773     *
3774     * ---
3775     *
3776     * This class wraps:
3777     *
3778     * 1) an identifier for a state
3779     * 2) a set of parameters
3780     * 3) and transition options
3781     * 4) the registered state object (the [[StateDeclaration]])
3782     *
3783     * Many UI-Router APIs such as [[StateService.go]] take a [[StateOrName]] argument which can
3784     * either be a *state object* (a [[StateDeclaration]] or [[StateObject]]) or a *state name* (a string).
3785     * The `TargetState` class normalizes those options.
3786     *
3787     * A `TargetState` may be valid (the state being targeted exists in the registry)
3788     * or invalid (the state being targeted is not registered).
3789     */
3790    var TargetState = /** @class */ (function () {
3791        /**
3792         * The TargetState constructor
3793         *
3794         * Note: Do not construct a `TargetState` manually.
3795         * To create a `TargetState`, use the [[StateService.target]] factory method.
3796         *
3797         * @param _stateRegistry The StateRegistry to use to look up the _definition
3798         * @param _identifier An identifier for a state.
3799         *    Either a fully-qualified state name, or the object used to define the state.
3800         * @param _params Parameters for the target state
3801         * @param _options Transition options.
3802         *
3803         * @internal
3804         */
3805        function TargetState(_stateRegistry, _identifier, _params, _options) {
3806            this._stateRegistry = _stateRegistry;
3807            this._identifier = _identifier;
3808            this._identifier = _identifier;
3809            this._params = extend({}, _params || {});
3810            this._options = extend({}, _options || {});
3811            this._definition = _stateRegistry.matcher.find(_identifier, this._options.relative);
3812        }
3813        /** The name of the state this object targets */
3814        TargetState.prototype.name = function () {
3815            return (this._definition && this._definition.name) || this._identifier;
3816        };
3817        /** The identifier used when creating this TargetState */
3818        TargetState.prototype.identifier = function () {
3819            return this._identifier;
3820        };
3821        /** The target parameter values */
3822        TargetState.prototype.params = function () {
3823            return this._params;
3824        };
3825        /** The internal state object (if it was found) */
3826        TargetState.prototype.$state = function () {
3827            return this._definition;
3828        };
3829        /** The internal state declaration (if it was found) */
3830        TargetState.prototype.state = function () {
3831            return this._definition && this._definition.self;
3832        };
3833        /** The target options */
3834        TargetState.prototype.options = function () {
3835            return this._options;
3836        };
3837        /** True if the target state was found */
3838        TargetState.prototype.exists = function () {
3839            return !!(this._definition && this._definition.self);
3840        };
3841        /** True if the object is valid */
3842        TargetState.prototype.valid = function () {
3843            return !this.error();
3844        };
3845        /** If the object is invalid, returns the reason why */
3846        TargetState.prototype.error = function () {
3847            var base = this.options().relative;
3848            if (!this._definition && !!base) {
3849                var stateName = base.name ? base.name : base;
3850                return "Could not resolve '" + this.name() + "' from state '" + stateName + "'";
3851            }
3852            if (!this._definition)
3853                return "No such state '" + this.name() + "'";
3854            if (!this._definition.self)
3855                return "State '" + this.name() + "' has an invali
3855d definition";
3856        };
3857        TargetState.prototype.toString = function () {
3858            return "'" + this.name() + "'" + stringify(this.params());
3859        };
3860        /**
3861         * Returns a copy of this TargetState which targets a different state.
3862         * The new TargetState has the same parameter values and transition options.
3863         *
3864         * @param state The new state that should be targeted
3865         */
3866        TargetState.prototype.withState = function (state) {
3867            return new TargetState(this._stateRegistry, state, this._params, this._options);
3868        };
3869        /**
3870         * Returns a copy of this TargetState, using the specified parameter values.
3871         *
3872         * @param params the new parameter values to use
3873         * @param replace When false (default) the new parameter values will be merged with the current values.
3874         *                When true the parameter values will be used instead of the current values.
3875         */
3876        TargetState.prototype.withParams = function (params, replace) {
3877            if (replace === void 0) { replace = false; }
3878            var newParams = replace ? params : extend({}, this._params, params);
3879            return new TargetState(this._stateRegistry, this._identifier, newParams, this._options);
3880        };
3881        /**
3882         * Returns a copy of this TargetState, using the specified Transition Options.
3883         *
3884         * @param options the new options to use
3885         * @param replace When false (default) the new options will be merged with the current options.
3886         *                When true the options will be used instead of the current options.
3887         */
3888        TargetState.prototype.withOptions = function (options, replace) {
3889            if (replace === void 0) { replace = false; }
3890            var newOpts = replace ? options : extend({}, this._options, options);
3891            return new TargetState(this._stateRegistry, this._identifier, this._params, newOpts);
3892        };
3893        /** Returns true if the object has a state property that might be a state or state name */
3894        TargetState.isDef = function (obj) {
3895            return obj && obj.state && (isString(obj.state) || (isObject(obj.state) && isString(obj.state.name)));
3896        };
3897        return TargetState;
3898    }());
3899
3900    /**
3901     * This class contains functions which convert TargetStates, Nodes and paths from one type to another.
3902     */
3903    var PathUtils = /** @class */ (function () {
3904        function PathUtils() {
3905        }
3906        /** Given a PathNode[], create an TargetState */
3907        PathUtils.makeTargetState = function (registry, path) {
3908            var state = tail(path).state;
3909            return new TargetState(registry, state, path.map(prop('paramValues')).reduce(mergeR, {}), {});
3910        };
3911        PathUtils.buildPath = function (targetState) {
3912            var toParams = targetState.params();
3913            return targetState.$state().path.map(function (state) { return new PathNode(state).applyRawParams(toParams); });
3914        };
3915        /** Given a fromPath: PathNode[] and a TargetState, builds a toPath: PathNode[] */
3916        PathUtils.buildToPath = function (fromPath, targetState) {
3917            var toPath = PathUtils.buildPath(targetState);
3918            if (targetState.options().inherit) {
3919                return PathUtils.inheritParams(fromPath, toPath, Object.keys(targetState.params()));
3920            }
3921            return toPath;
3922        };
3923        /**
3924         * Creates ViewConfig objects and adds to nodes.
3925         *
3926         * On each [[PathNode]], creates ViewConfig objects from the views: property of the node's state
3927         */
3928        PathUtils.applyViewConfigs = function ($view, path, states) {
3929            // Only apply the viewConfigs to the nodes for the given states
3930            path
3931                .filter(function (node) { return inArray(states, node.state); })
3932                .forEach(function (node) {
3933                var viewDecls = values(node.state.views || {});
3934                var subPath = PathUtils.subPath(path, function (n) { return n === node; });
3935                var viewConfigs = viewDecls.map(function (view) { return $view.createViewConfig(subPath, view); });
3936                node.views = viewConfigs.reduce(unnestR, []);
3937            });
3938        };
3939        /**
3940         * Given a fromPath and a toPath, returns a new to path which inherits parameters from the fromPath
3941         *
3942         * For a parameter in a node to be inherited from the from path:
3943         * - The toPath's node must have a matching node in the fromPath (by state).
3944         * - The parameter name must not be found in the toKeys parameter array.
3945         *
3946         * Note: the keys provided in toKeys are intended to be those param keys explicitly specified by some
3947         * caller, for instance, $state.transitionTo(..., toParams).  If a key was found in toParams,
3948         * it is not inherited from the fromPath.
3949         */
3950        PathUtils.inheritParams = function (fromPath, toPath, toKeys) {
3951            if (toKeys === void 0) { toKeys = []; }
3952            function nodeParamVals(path, state) {
3953                var node = find(path, propEq('state', state));
3954                return extend({}, node && node.paramValues);
3955            }
3956            var noInherit = fromPath
3957                .map(function (node) { return node.paramSchema; })
3958                .reduce(unnestR, [])
3959                .filter(function (param) { return !param.inherit; })
3960                .map(prop('id'));
3961            /**
3962             * Given an [[PathNode]] "toNode", return a new [[PathNode]] with param values inherited from the
3963             * matching node in fromPath.  Only inherit keys that aren't found in "toKeys" from the node in "fromPath""
3964             */
3965            function makeInheritedParamsNode(toNode) {
3966                // All param values for the node (may include default key/vals, when key was not found in toParams)
3967                var toParamVals = extend({}, toNode && toNode.paramValues);
3968                // limited to only those keys found in toParams
3969                var incomingParamVals = pick(toParamVals, toKeys);
3970                toParamVals = omit(toParamVals, toKeys);
3971                var fromParamVals = omit(nodeParamVals(fromPath, toNode.state) || {}, noInherit);
3972                // extend toParamVals with any fromParamVals, then override any of those those with incomingParamVals
3973                var ownParamVals = extend(toParamVals, fromParamVals, incomingParamVals);
3974                return new PathNode(toNode.state).applyRawParams(ownParamVals);
3975            }
3976            // The param keys specified by the incoming toParams
3977            return toPath.map(makeInheritedParamsNode);
3978        };
3979        /**
3980         * Computes the tree changes (entering, exiting) between a fromPath and toPath.
3981         */
3982        PathUtils.treeChanges = function (fromPath, toPath, reloadState) {
3983            var max = Math.min(fromPath.length, toPath.length);
3984            var keep = 0;
3985            var nodesMatch = function (node1, node2) { return node1.equals(node2, PathUtils.nonDynamicParams); };
3986            while (keep < max && fromPath[keep].state !== reloadState && nodesMatch(fromPath[keep], toPath[keep])) {
3987                keep++;
3988            }
3989            /** Given a retained node, return a new node which uses the to node's param values */
3990            function applyToParams(retainedNode, idx) {
3991                var cloned = retainedNode.clone();
3992                cloned.paramValues = toPath[idx].paramValues;
3993                return cloned;
3994            }
3995            var from, retained, exiting, entering, to;
3996            from = fromPath;
3997            retained = from.slice(0, keep);
3998            exiting = from.slice(keep);
3999            // Create a new retained path (with shallow copies of nodes) which have the params of the toPath mapped
4000            var retainedWithToParams = retained.map(applyToParams);
4001            entering = toPath.slice(keep);
4002            to = retainedWithToParams.concat(entering);
4003            return { from: from, to: to, retained: retained, retainedWithToParams: retainedWithToParams, exiting: exiting, entering: entering };
4004        };
4005        /**
4006         * Returns a new path which is: the subpath of the first path which matches the second path.
4007         *
4008         * The new path starts from root and contains any nodes that match the nodes in the second path.
4009         * It stops before the first non-matching node.
4010         *
4011         * Nodes are compared using their state property and their parameter values.
4012         * If a `paramsFn` is provided, only the [[Param]] returned by the function will be considered when comparing nodes.
4013         *
4014         * @param pathA the first path
4015         * @param pathB the second path
4016         * @param paramsFn a function which returns the parameters to consider when comparing
4017         *
4018         * @returns an array of PathNodes from the first path which match the nodes in the second path
4019         */
4020        PathUtils.matching = function (pathA, pathB, paramsFn) {
4021            var done = false;
4022            var tuples = arrayTuples(pathA, pathB);
4023            return tuples.reduce(function (matching, _a) {
4024                var nodeA = _a[0], nodeB = _a[1];
4025                done = done || !nodeA.equals(nodeB, paramsFn);
4026                return done ? matching : matching.concat(nodeA);
4027            }, []);
4028        };
4029        /**
4030         * Returns true if two paths are identical.
4031         *
4032         * @param pathA
4033         * @param pathB
4034         * @param paramsFn a function which returns the parameters to consider when comparing
4035         * @returns true if the the states and parameter values for both paths are identical
4036         */
4037        PathUtils.equals = function (pathA, pathB, paramsFn) {
4038            return pathA.length === pathB.length && PathUtils.matching(pathA, pathB, paramsFn).length === pathA.length;
4039        };
4040        /**
4041         * Return a subpath of a path, which stops at the first matching node
4042         *
4043         * Given an array of nodes, returns a subset of the array starting from the first node,
4044         * stopping when the first node matches the predicate.
4045         *
4046         * @param path a path of [[PathNode]]s
4047         * @param predicate a [[Predicate]] fn that matches [[PathNode]]s
4048         * @returns a subpath up to the matching node, or undefined if no match is found
4049         */
4050        PathUtils.subPath = function (path, predicate) {
4051            var node = find(path, predicate);
4052            var elementIdx = path.indexOf(node);
4053            return elementIdx === -1 ? undefined : path.slice(0, elementIdx + 1);
4054        };
4055        PathUtils.nonDynamicParams = function (node) {
4056            return node.state.parameters({ inherit: false }).filter(function (param) { return !param.dynamic; });
4057        };
4058        /** Gets the raw parameter values from a path */
4059        PathUtils.paramValues = function (path) { return path.reduce(function (acc, node) { return extend(acc, node.paramValues); }, {}); };
4060        return PathUtils;
4061    }());
4062
4063    var resolvePolicies = {
4064        when: {
4065            LAZY: 'LAZY',
4066            EAGER: 'EAGER',
4067        },
4068        async: {
4069            WAIT: 'WAIT',
4070            NOWAIT: 'NOWAIT',
4071        },
4072    };
4073
4074    // TODO: explicitly make this user configurable
4075    var defaultResolvePolicy = {
4076        when: 'LAZY',
4077        async: 'WAIT',
4078    };
4079    /**
4080     * The basic building block for the resolve system.
4081     *
4082     * Resolvables encapsulate a state's resolve's resolveFn, the resolveFn's declared dependencies, the wrapped (.promise),
4083     * and the unwrapped-when-complete (.data) result of the resolveFn.
4084     *
4085     * Resolvable.get() either retrieves the Resolvable's existing promise, or else invokes resolve() (which invokes the
4086     * resolveFn) and returns the resulting promise.
4087     *
4088     * Resolvable.get() and Resolvable.resolve() both execute within a context path, which is passed as the first
4089     * parameter to those fns.
4090     */
4091    var Resolvable = /** @class */ (function () {
4092        function Resolvable(arg1, resolveFn, deps, policy, data) {
4093            this.resolved = false;
4094            this.promise = undefined;
4095            if (arg1 instanceof Resolvable) {
4096                extend(this, arg1);
4097            }
4098            else if (isFunction(resolveFn)) {
4099                if (isNullOrUndefined(arg1))
4100                    throw new Error('new Resolvable(): token argument is required');
4101                if (!isFunction(resolveFn))
4102                    throw new Error('new Resolvable(): resolveFn argument must be a function');
4103                this.token = arg1;
4104                this.policy = policy;
4105                this.resolveFn = resolveFn;
4106                this.deps = deps || [];
4107                this.data = data;
4108                this.resolved = data !== undefined;
4109                this.promise = this.resolved ? services.$q.when(this.data) : undefined;
4110            }
4111            else if (isObject(arg1) && arg1.token && (arg1.hasOwnProperty('resolveFn') || arg1.hasOwnProperty('data'))) {
4112                var literal = arg1;
4113                return new Resolvable(literal.token, literal.resolveFn, literal.deps, literal.policy, literal.data);
4114            }
4115        }
4116        Resolvable.prototype.getPolicy = function (state) {
4117            var thisPolicy = this.policy || {};
4118            var statePolicy = (state && state.resolvePolicy) || {};
4119            return {
4120                when: thisPolicy.when || statePolicy.when || defaultResolvePolicy.when,
4121                async: thisPolicy.async || statePolicy.async || defaultResolvePolicy.async,
4122            };
4123        };
4124        /**
4125         * Asynchronously resolve this Resolvable's data
4126         *
4127         * Given a ResolveContext that this Resolvable is found in:
4128         * Wait for this Resolvable's dependencies, then invoke this Resolvable's function
4129         * and update the Resolvable's state
4130         */
4131        Resolvable.prototype.resolve = function (resolveContext, trans) {
4132            var _this = this;
4133            var $q = services.$q;
4134            // Gets all dependencies from ResolveContext and wait for them to be resolved
4135            var getResolvableDependencies = function () {
4136                return $q.all(resolveContext.getDependencies(_this).map(function (resolvable) { return resolvable.get(resolveContext, trans); }));
4137            };
4138            // Invokes the resolve function passing the resolved dependencies as arguments
4139            var invokeResolveFn = function (resolvedDeps) { return _this.resolveFn.apply(null, resolvedDeps); };
4140            var node = resolveContext.findNode(this);
4141            var state = node && node.state;
4142            var asyncPolicy = this.getPolicy(state).async;
4143            var customAsyncPolicy = isFunction(asyncPolicy) ? asyncPolicy : identity;
4144            // After the final value has been resolved, update the state of the Resolvable
4145            var applyResolvedValue = function (resolvedValue) {
4146                _this.data = resolvedValue;
4147                _this.resolved = true;
4148                _this.resolveFn = null;
4149                trace.traceResolvableResolved(_this, trans);
4150                return _this.data;
4151            };
4152            // Sets the promise property first, then getsResolvableDependencies in the context of the promise chain. Always waits one tick.
4153            return (this.promise = $q
4154                .when()
4155                .then(getResolvableDependencies)
4156                .then(invokeResolveFn)
4157                .then(customAsyncPolicy)
4158                .then(applyResolvedValue));
4159        };
4160        /**
4161         * Gets a promise for this Resolvable's data.
4162         *
4163         * Fetches the data and returns a promise.
4164         * Returns the existing promise if it has already been fetched once.
4165         */
4166        Resolvable.prototype.get = function (resolveContext, trans) {
4167            return this.promise || this.resolve(resolveContext, trans);
4168        };
4169        Resolvable.prototype.toString = function () {
4170            return "Resolvable(token: " + stringify(this.token) + ", requires: [" + this.deps.map(stringify) + "])";
4171        };
4172        Resolvable.prototype.clone = function () {
4173            return new Resolvable(this);
4174        };
4175        Resolvable.fromData = function (token, data) { return new Resolvable(token, function () { return data; }, null, null, data); };
4176        return Resolvable;
4177    }());
4178
4179    var whens = resolvePolicies.when;
4180    var ALL_WHENS = [whens.EAGER, whens.LAZY];
4181    var EAGER_WHENS = [whens.EAGER];
4182    // tslint:disable-next-line:no-inferrable-types
4183    var NATIVE_INJECTOR_TOKEN = 'Native Injector';
4184    /**
4185     * Encapsulates Dependency Injection for a path of nodes
4186     *
4187     * UI-Router states are organized as a tree.
4188     * A nested state has a path of ancestors to the root of the tree.
4189     * When a state is being activated, each element in the path is wrapped as a [[PathNode]].
4190     * A `PathNode` is a stateful object that holds things like parameters and resolvables for the state being activated.
4191     *
4192     * The ResolveContext closes over the [[PathNode]]s, and provides DI for the last node in the path.
4193     */
4194    var ResolveContext = /** @class */ (function () {
4195        function ResolveContext(_path) {
4196            this._path = _path;
4197        }
4198        /** Gets all the tokens found in the resolve context, de-duplicated */
4199        ResolveContext.prototype.getTokens = function () {
4200            return this._path.reduce(function (acc, node) { return acc.concat(node.resolvables.map(function (r) { return r.token; })); }, []).reduce(uniqR, []);
4201        };
4202        /**
4203         * Gets the Resolvable that matches the token
4204         *
4205         * Gets the last Resolvable that matches the token in this context, or undefined.
4206         * Throws an error if it doesn't exist in the ResolveContext
4207         */
4208        ResolveContext.prototype.getResolvable = function (token) {
4209            var matching = this._path
4210                .map(function (node) { return node.resolvables; })
4211                .reduce(unnestR, [])
4212                .filter(function (r) { return r.token === token; });
4213            return tail(matching);
4214        };
4215        /** Returns the [[ResolvePolicy]] for the given [[Resolvable]] */
4216        ResolveContext.prototype.getPolicy = function (resolvable) {
4217            var node = this.findNode(resolvable);
4218            return resolvable.getPolicy(node.state);
4219        };
4220        /**
4221         * Returns a ResolveContext that includes a portion of this one
4222         *
4223         * Given a state, this method creates a new ResolveContext from this one.
4224         * The new context starts at the first node (root) and stops at the node for the `state` parameter.
4225         *
4226         * #### Why
4227         *
4228         * When a transition is created, the nodes in the "To Path" are injected from a ResolveContext.
4229         * A ResolveContext closes over a path of [[PathNode]]s and processes the resolvables.
4230         * The "To State" can inject values from its own resolvables, as well as those from all its ancestor state's (node'
4230s).
4231         * This method is used to create a narrower context when injecting ancestor nodes.
4232         *
4233         * @example
4234         * `let ABCD = new ResolveContext([A, B, C, D]);`
4235         *
4236         * Given a path `[A, B, C, D]`, where `A`, `B`, `C` and `D` are nodes for states `a`, `b`, `c`, `d`:
4237         * When injecting `D`, `D` should have access to all resolvables from `A`, `B`, `C`, `D`.
4238         * However, `B` should only be able to access resolvables from `A`, `B`.
4239         *
4240         * When resolving for the `B` node, first take the full "To Path" Context `[A,B,C,D]` and limit to the subpath `[A,B]`.
4241         * `let AB = ABCD.subcontext(a)`
4242         */
4243        ResolveContext.prototype.subContext = function (state) {
4244            return new ResolveContext(PathUtils.subPath(this._path, function (node) { return node.state === state; }));
4245        };
4246        /**
4247         * Adds Resolvables to the node that matches the state
4248         *
4249         * This adds a [[Resolvable]] (generally one created on the fly; not declared on a [[StateDeclaration.resolve]] block).
4250         * The resolvable is added to the node matching the `state` parameter.
4251         *
4252         * These new resolvables are not automatically fetched.
4253         * The calling code should either fetch them, fetch something that depends on them,
4254         * or rely on [[resolvePath]] being called when some state is being entered.
4255         *
4256         * Note: each resolvable's [[ResolvePolicy]] is merged with the state's policy, and the global default.
4257         *
4258         * @param newResolvables the new Resolvables
4259         * @param state Used to find the node to put the resolvable on
4260         */
4261        ResolveContext.prototype.addResolvables = function (newResolvables, state) {
4262            var node = find(this._path, propEq('state', state));
4263            var keys = newResolvables.map(function (r) { return r.token; });
4264            node.resolvables = node.resolvables.filter(function (r) { return keys.indexOf(r.token) === -1; }).concat(newResolvables);
4265        };
4266        /**
4267         * Returns a promise for an array of resolved path Element promises
4268         *
4269         * @param when
4270         * @param trans
4271         * @returns {Promise<any>|any}
4272         */
4273        ResolveContext.prototype.resolvePath = function (when, trans) {
4274            var _this = this;
4275            if (when === void 0) { when = 'LAZY'; }
4276            // This option determines which 'when' policy Resolvables we are about to fetch.
4277            var whenOption = inArray(ALL_WHENS, when) ? when : 'LAZY';
4278            // If the caller specified EAGER, only the EAGER Resolvables are fetched.
4279            // if the caller specified LAZY, both EAGER and LAZY Resolvables are fetched.`
4280            var matchedWhens = whenOption === resolvePolicies.when.EAGER ? EAGER_WHENS : ALL_WHENS;
4281            // get the subpath to the state argument, if provided
4282            trace.traceResolvePath(this._path, when, trans);
4283            var matchesPolicy = function (acceptedVals, whenOrAsync) { return function (resolvable) {
4284                return inArray(acceptedVals, _this.getPolicy(resolvable)[whenOrAsync]);
4285            }; };
4286            // Trigger all the (matching) Resolvables in the path
4287            // Reduce all the "WAIT" Resolvables into an array
4288            var promises = this._path.reduce(function (acc, node) {
4289                var nodeResolvables = node.resolvables.filter(matchesPolicy(matchedWhens, 'when'));
4290                var nowait = nodeResolvables.filter(matchesPolicy(['NOWAIT'], 'async'));
4291                var wait = nodeResolvables.filter(not(matchesPolicy(['NOWAIT'], 'async')));
4292                // For the matching Resolvables, start their async fetch process.
4293                var subContext = _this.subContext(node.state);
4294                var getResult = function (r) {
4295                    return r
4296                        .get(subContext, trans)
4297                        // Return a tuple that includes the Resolvable's token
4298                        .then(function (value) { return ({ token: r.token, value: value }); });
4299                };
4300                nowait.forEach(getResult);
4301                return acc.concat(wait.map(getResult));
4302            }, []);
4303            // Wait for all the "WAIT" resolvables
4304            return services.$q.all(promises);
4305        };
4306        ResolveContext.prototype.injector = function () {
4307            return this._injector || (this._injector = new UIInjectorImpl(this));
4308        };
4309        ResolveContext.prototype.findNode = function (resolvable) {
4310            return find(this._path, function (node) { return inArray(node.resolvables, resolvable); });
4311        };
4312        /**
4313         * Gets the async dependencies of a Resolvable
4314         *
4315         * Given a Resolvable, returns its dependencies as a Resolvable[]
4316         */
4317        ResolveContext.prototype.getDependencies = function (resolvable) {
4318            var _this = this;
4319            var node = this.findNode(resolvable);
4320            // Find which other resolvables are "visible" to the `resolvable` argument
4321            // subpath stopping at resolvable's node, or the whole path (if the resolvable isn't in the path)
4322            var subPath = PathUtils.subPath(this._path, function (x) { return x === node; }) || this._path;
4323            var availableResolvables = subPath
4324                .reduce(function (acc, _node) { return acc.concat(_node.resolvables); }, []) // all of subpath's resolvables
4325                .filter(function (res) { return res !== resolvable; }); // filter out the `resolvable` argument
4326            var getDependency = function (token) {
4327                var matching = availableResolvables.filter(function (r) { return r.token === token; });
4328                if (matching.length)
4329                    return tail(matching);
4330                var fromInjector = _this.injector().getNative(token);
4331                if (isUndefined(fromInjector)) {
4332                    throw new Error('Could not find Dependency Injection token: ' + stringify(token));
4333                }
4334                return new Resolvable(token, function () { return fromInjector; }, [], fromInjector);
4335            };
4336            return resolvable.deps.map(getDependency);
4337        };
4338        return ResolveContext;
4339    }());
4340    /** @internal */
4341    var UIInjectorImpl = /** @class */ (function () {
4342        function UIInjectorImpl(context) {
4343            this.context = context;
4344            this.native = this.get(NATIVE_INJECTOR_TOKEN) || services.$injector;
4345        }
4346        UIInjectorImpl.prototype.get = function (token) {
4347            var resolvable = this.context.getResolvable(token);
4348            if (resolvable) {
4349                if (this.context.getPolicy(resolvable).async === 'NOWAIT') {
4350                    return resolvable.get(this.context);
4351                }
4352                if (!resolvable.resolved) {
4353                    throw new Error('Resolvable async .get() not complete:' + stringify(resolvable.token));
4354                }
4355                return resolvable.data;
4356            }
4357            return this.getNative(token);
4358        };
4359        UIInjectorImpl.prototype.getAsync = function (token) {
4360            var resolvable = this.context.getResolvable(token);
4361            if (resolvable)
4362                return resolvable.get(this.context);
4363            return services.$q.when(this.native.get(token));
4364        };
4365        UIInjectorImpl.prototype.getNative = function (token) {
4366            return this.native && this.native.get(token);
4367        };
4368        return UIInjectorImpl;
4369    }());
4370
4371    var parseUrl = function (url) {
4372        if (!isString(url))
4373            return false;
4374        var root = url.charAt(0) === '^';
4375        return { val: root ? url.substring(1) : url, root: root };
4376    };
4377    function nameBuilder(state) {
4378        return state.name;
4379    }
4380    function selfBuilder(state) {
4381        state.self.$$state = function () { return state; };
4382        return state.self;
4383    }
4384    function dataBuilder(state) {
4385        if (state.parent && state.parent.data) {
4386            state.data = state.self.data = inherit(state.parent.data, state.data);
4387        }
4388        return state.data;
4389    }
4390    var getUrlBuilder = function ($urlMatcherFactoryProvider, root) {
4391        return function urlBuilder(stateObject) {
4392            var stateDec = stateObject.self;
4393            // For future states, i.e., states whose name ends with `.**`,
4394            // match anything that starts with the url prefix
4395            if (stateDec && stateDec.url && stateDec.name && stateDec.name.match(/\.\*\*$/)) {
4396                var newStateDec = {};
4397                copy(stateDec, newStateDec);
4398                newStateDec.url += '{remainder:any}'; // match any path (.*)
4399                stateDec = newStateDec;
4400            }
4401            var parent = stateObject.parent;
4402            var parsed = parseUrl(stateDec.url);
4403            var url = !parsed ? stateDec.url : $urlMatcherFactoryProvider.compile(parsed.val, { state: stateDec });
4404            if (!url)
4405                return null;
4406            if (!$urlMatcherFactoryProvider.isMatcher(url))
4407                throw new Error("Invalid url '" + url + "' in state '" + stateObject + "'");
4408            return parsed && parsed.root ? url : ((parent && parent.navigable) || root()).url.append(url);
4409        };
4410    };
4411    var getNavigableBuilder = function (isRoot) {
4412        return function navigableBuilder(state) {
4413            return !isRoot(state) && state.url ? state : state.parent ? state.parent.navigable : null;
4414        };
4415    };
4416    var getParamsBuilder = function (paramFactory) {
4417        return function paramsBuilder(state) {
4418            var makeConfigParam = function (config, id) { return paramFactory.fromConfig(id, null, state.self); };
4419            var urlParams = (state.url && state.url.parameters({ inherit: false })) || [];
4420            var nonUrlParams = values(mapObj(omit(state.params || {}, urlParams.map(prop('id'))), makeConfigParam));
4421            return urlParams
4422                .concat(nonUrlParams)
4423                .map(function (p) { return [p.id, p]; })
4424                .reduce(applyPairs, {});
4425        };
4426    };
4427    function pathBuilder(state) {
4428        return state.parent ? state.parent.path.concat(state) : /*root*/ [state];
4429    }
4430    function includesBuilder(state) {
4431        var includes = state.parent ? extend({}, state.parent.includes) : {};
4432        includes[state.name] = true;
4433        return includes;
4434    }
4435    /**
4436     * This is a [[StateBuilder.builder]] function for the `resolve:` block on a [[StateDeclaration]].
4437     *
4438     * When the [[StateBuilder]] builds a [[StateObject]] object from a raw [[StateDeclaration]], this builder
4439     * validates the `resolve` property and converts it to a [[Resolvable]] array.
4440     *
4441     * resolve: input value can be:
4442     *
4443     * {
4444     *   // analyzed but not injected
4445     *   myFooResolve: function() { return "myFooData"; },
4446     *
4447     *   // function.toString() parsed, "DependencyName" dep as string (not min-safe)
4448     *   myBarResolve: function(DependencyName) { return DependencyName.fetchSomethingAsPromise() },
4449     *
4450     *   // Array split; "DependencyName" dep as string
4451     *   myBazResolve: [ "DependencyName", function(dep) { return dep.fetchSomethingAsPromise() },
4452     *
4453     *   // Array split; DependencyType dep as token (compared using ===)
4454     *   myQuxResolve: [ DependencyType, function(dep) { return dep.fetchSometingAsPromise() },
4455     *
4456     *   // val.$inject used as deps
4457     *   // where:
4458     *   //     corgeResolve.$inject = ["DependencyName"];
4459     *   //     function corgeResolve(dep) { dep.fetchSometingAsPromise() }
4460     *   // then "DependencyName" dep as string
4461     *   myCorgeResolve: corgeResolve,
4462     *
4463     *  // inject service by name
4464     *  // When a string is found, desugar creating a resolve that injects the named service
4465     *   myGraultResolve: "SomeService"
4466     * }
4467     *
4468     * or:
4469     *
4470     * [
4471     *   new Resolvable("myFooResolve", function() { return "myFooData" }),
4472     *   new Resolvable("myBarResolve", function(dep) { return dep.fetchSomethingAsPromise() }, [ "DependencyName" ]),
4473     *   { provide: "myBazResolve", useFactory: function(dep) { dep.fetchSomethingAsPromise() }, deps: [ "DependencyName" ] }
4474     * ]
4475     */
4476    function resolvablesBuilder(state) {
4477        /** convert resolve: {} and resolvePolicy: {} objects to an array of tuples */
4478        var objects2Tuples = function (resolveObj, resolvePolicies) {
4479            return Object.keys(resolveObj || {}).map(function (token) { return ({
4480                token: token,
4481                val: resolveObj[token],
4482                deps: undefined,
4483                policy: resolvePolicies[token],
4484            }); });
4485        };
4486        /** fetch DI annotations from a function or ng1-style array */
4487        var annotate = function (fn) {
4488            var $injector = services.$injector;
4489            // ng1 doesn't have an $injector until runtime.
4490            // If the $injector doesn't exist, use "deferred" literal as a
4491            // marker indicating they should be annotated when runtime starts
4492            return fn['$inject'] || ($injector && $injector.annotate(fn, $injector.strictDi)) || 'deferred';
4493        };
4494        /** true if the object has both `token` and `resolveFn`, and is probably a [[ResolveLiteral]] */
4495        var isResolveLiteral = function (obj) { return !!(obj.token && obj.resolveFn); };
4496        /** true if the object looks like a provide literal, or a ng2 Provider */
4497        var isLikeNg2Provider = function (obj) {
4498            return !!((obj.provide || obj.token) && (obj.useValue || obj.useFactory || obj.useExisting || obj.useClass));
4499        };
4500        /** true if the object looks like a tuple from obj2Tuples */
4501        var isTupleFromObj = function (obj) {
4502            return !!(obj && obj.val && (isString(obj.val) || isArray(obj.val) || isFunction(obj.val)));
4503        };
4504        /** extracts the token from a Provider or provide literal */
4505        var getToken = function (p) { return p.provide || p.token; };
4506        // prettier-ignore: Given a literal resolve or provider object, returns a Resolvable
4507        var literal2Resolvable = pattern([
4508            [prop('resolveFn'), function (p) { return new Resolvable(getToken(p), p.resolveFn, p.deps, p.policy); }],
4509            [prop('useFactory'), function (p) { return new Resolvable(getToken(p), p.useFactory, p.deps || p.dependencies, p.policy); }],
4510            [prop('useClass'), function (p) { return new Resolvable(getToken(p), function () { return new p.useClass(); }, [], p.policy); }],
4511            [prop('useValue'), function (p) { return new Resolvable(getToken(p), function () { return p.useValue; }, [], p.policy, p.useValue); }],
4512            [prop('useExisting'), function (p) { return new Resolvable(getToken(p), identity, [p.useExisting], p.policy); }],
4513        ]);
4514        // prettier-ignore
4515        var tuple2Resolvable = pattern([
4516            [pipe(prop('val'), isString), function (tuple) { return new Resolvable(tuple.token, identity, [tuple.val], tuple.policy); }],
4517            [pipe(prop('val'), isArray), function (tuple) { return new Resolvable(tuple.token, tail(tuple.val), tuple.val.slice(0, -1), tuple.policy); }],
4518            [pipe(prop('val'), isFunction), function (tuple) { return new Resolvable(tuple.token, tuple.val, annotate(tuple.val), tuple.policy); }],
4519        ]);
4520        // prettier-ignore
4521        var item2Resolvable = pattern([
4522            [is(Resolvable), function (r) { return r; }],
4523            [isResolveLiteral, literal2Resolvable],
4524            [isLikeNg2Provider, literal2Resolvable],
4525            [isTupleFromObj, tuple2Resolvable],
4526            [val(true), function (obj) { throw new Error('Invalid resolve value: ' + stringify(obj)); },],
4527        ]);
4528        // If resolveBlock is already an array, use it as-is.
4529        // Otherwise, assume it's an object and convert to an Array of tuples
4530        var decl = state.resolve;
4531        var items = isArray(decl) ? decl : objects2Tuples(decl, state.resolvePolicy || {});
4532        return items.map(item2Resolvable);
4533    }
4534    /**
4535     * A internal global service
4536     *
4537     * StateBuilder is a factory for the internal [[StateObject]] objects.
4538     *
4539     * When you register a state with the [[StateRegistry]], you register a plain old javascript object which
4540     * conforms to the [[StateDeclaration]] interface.  This factory takes that object and builds the corresponding
4541     * [[StateObject]] object, which has an API and is used internally.
4542     *
4543     * Custom properties or API may be added to the internal [[StateObject]] object by registering a decorator function
4544     * using the [[builder]] method.
4545     */
4546    var StateBuilder = /** @class */ (function () {
4547        function StateBuilder(matcher, urlMatcherFactory) {
4548            this.matcher = matcher;
4549            var self = this;
4550            var root = function () { return matcher.find(''); };
4551            var isRoot = function (state) { return state.name === ''; };
4552            function parentBuilder(state) {
4553                if (isRoot(state))
4554                    return null;
4555                return matcher.find(self.parentName(state)) || root();
4556            }
4557            this.builders = {
4558                name: [nameBuilder],
4559                self: [selfBuilder],
4560                parent: [parentBuilder],
4561                data: [dataBuilder],
4562                // Build a URLMatcher if necessary, either via a relative or absolute URL
4563                url: [getUrlBuilder(urlMatcherFactory, root)],
4564                // Keep track of the closest ancestor state that has a URL (i.e. is navigable)
4565                navigable: [getNavigableBuilder(isRoot)],
4566                params: [getParamsBuilder(urlMatcherFactory.paramFactory)],
4567                // Each framework-specific ui-router implementation should define its own `views` builder
4568                // e.g., src/ng1/statebuilders/views.ts
4569                views: [],
4570                // Keep a full path from the root down to this state as this is needed for state activation.
4571                path: [pathBuilder],
4572                // Speed up $state.includes() as it's used a lot
4573                includes: [includesBuilder],
4574                resolvables: [resolvablesBuilder],
4575            };
4576        }
4577        StateBuilder.prototype.builder = function (name, fn) {
4578            var builders = this.builders;
4579            var array = builders[name] || [];
4580            // Backwards compat: if only one builder exists, return it, else return whole arary.
4581            if (isString(name) && !isDefined(fn))
4582                return array.length > 1 ? array : array[0];
4583            if (!isString(name) || !isFunction(fn))
4584                return;
4585            builders[name] = array;
4586            builders[name].push(fn);
4587            return function () { return builders[name].splice(builders[name].indexOf(fn, 1)) && null; };
4588        };
4589        /**
4590         * Builds all of the properties on an essentially blank State object, returning a State object which has all its
4591         * properties and API built.
4592         *
4593         * @param state an uninitialized State object
4594         * @returns the built State object
4595         */
4596        StateBuilder.prototype.build = function (state) {
4597            var _a = this, matcher = _a.matcher, builders = _a.builders;
4598            var parent = this.parentName(state);
4599            if (parent && !matcher.find(parent, undefined, false)) {
4600                return null;
4601            }
4602            for (var key in builders) {
4603                if (!builders.hasOwnProperty(key))
4604                    continue;
4605                var chain = builders[key].reduce(function (parentFn, step) { return function (_state) { return step(_state, parentFn); }; }, noop);
4606                state[key] = chain(state);
4607            }
4608            return state;
4609        };
4610        StateBuilder.prototype.parentName = function (state) {
4611            // name = 'foo.bar.baz.**'
4612            var name = state.name || '';
4613            // segments = ['foo', 'bar', 'baz', '.**']
4614            var segments = name.split('.');
4615            // segments = ['foo', 'bar', 'baz']
4616            var lastSegment = segments.pop();
4617            // segments = ['foo', 'bar'] (ignore .** segment for future states)
4618            if (lastSegment === '**')
4619                segments.pop();
4620            if (segments.length) {
4621                if (state.parent) {
4622                    throw new Error("States that specify the 'parent:' property should not have a '.' in their name (" + name + ")");
4623                }
4624                // 'foo.bar'
4625                return segments.join('.');
4626            }
4627            if (!state.parent)
4628                return '';
4629            return isString(state.parent) ? state.parent : state.parent.name;
4630        };
4631        StateBuilder.prototype.name = function (state) {
4632            var name = state.name;
4633            if (name.indexOf('.') !== -1 || !state.parent)
4634                return name;
4635            var parentName = isString(state.parent) ? state.parent : state.parent.name;
4636            return parentName ? parentName + '.' + name : name;
4637        };
4638        return StateBuilder;
4639    }());
4640
4641    /**
4642     * Internal representation of a UI-Router state.
4643     *
4644     * Instances of this class are created when a [[StateDeclaration]] is registered with the [[StateRegistry]].
4645     *
4646     * A registered [[StateDeclaration]] is augmented with a getter ([[StateDeclaration.$$state]]) which returns the corresponding [[StateObject]] object.
4647     *
4648     * This class prototypally inherits from the corresponding [[StateDeclaration]].
4649     * Each of its own properties (i.e., `hasOwnProperty`) are built using builders from the [[StateBuilder]].
4650     */
4651    var StateObject = /** @class */ (function () {
4652        /** @deprecated use State.create() */
4653        function StateObject(config) {
4654            return StateObject.create(config || {});
4655        }
4656        /**
4657         * Create a state object to put the private/internal implementation details onto.
4658         * The object's prototype chain looks like:
4659         * (Internal State Object) -> (Copy of State.prototype) -> (State Declaration object) -> (State Declaration's prototype...)
4660         *
4661         * @param stateDecl the user-supplied State Declaration
4662         * @returns {StateObject} an internal State object
4663         */
4664        StateObject.create = function (stateDecl) {
4665            stateDecl = StateObject.isStateClass(stateDecl) ? new stateDecl() : stateDecl;
4666            var state = inherit(inherit(stateDecl, StateObject.prototype));
4667            stateDecl.$$state = function () { return state; };
4668            state.self = stateDecl;
4669            state.__stateObjectCache = {
4670                nameGlob: Glob.fromString(state.name),
4671            };
4672            return state;
4673        };
4674        /**
4675         * Returns true if the provided parameter is the same state.
4676         *
4677         * Compares the identity of the state against the passed value, which is either an object
4678         * reference to the actual `State` instance, the original definition object passed to
4679         * `$stateProvider.state()`, or the fully-qualified name.
4680         *
4681         * @param ref Can be one of (a) a `State` instance, (b) an object that was passed
4682         *        into `$stateProvider.state()`, (c) the fully-qualified name of a state as a string.
4683         * @returns Returns `true` if `ref` matches the current `State` instance.
4684         */
4685        StateObject.prototype.is = function (ref) {
4686            return this === ref || this.self === ref || this.fqn() === ref;
4687        };
4688        /**
4689         * @deprecated this does not properly handle dot notation
4690         * @returns Returns a dot-separated name of the state.
4691         */
4692        StateObject.prototype.fqn = function () {
4693            if (!this.parent || !(this.parent instanceof this.constructor))
4694                return this.name;
4695            var name = this.parent.fqn();
4696            return name ? name + '.' + this.name : this.name;
4697        };
4698        /**
4699         * Returns the root node of this state's tree.
4700         *
4701         * @returns The root of this state's tree.
4702         */
4703        StateObject.prototype.root = function () {
4704            return (this.parent && this.parent.root()) || this;
4705        };
4706        /**
4707         * Gets the state's `Param` objects
4708         *
4709         * Gets the list of [[Param]] objects owned by the state.
4710         * If `opts.inherit` is true, it also includes the ancestor states' [[Param]] objects.
4711         * If `opts.matchingKeys` exists, returns only `Param`s whose `id` is a key on the `matchingKeys` object
4712         *
4713         * @param opts options
4714         */
4715        StateObject.prototype.parameters = function (opts) {
4716            opts = defaults(opts, { inherit: true, matchingKeys: null });
4717            var inherited = (opts.inherit && this.parent && this.parent.parameters()) || [];
4718            return inherited
4719                .concat(values(this.params))
4720                .filter(function (param) { return !opts.matchingKeys || opts.matchingKeys.hasOwnProperty(param.id); });
4721        };
4722        /**
4723         * Returns a single [[Param]] that is owned by the state
4724         *
4725         * If `opts.inherit` is true, it also searches the ancestor states` [[Param]]s.
4726         * @param id the name of the [[Param]] to return
4727         * @param opts options
4728         */
4729        StateObject.prototype.parameter = function (id, opts) {
4730            if (opts === void 0) { opts = {}; }
4731            return ((this.url && this.url.parameter(id, opts)) ||
4732                find(values(this.params), propEq('id', id)) ||
4733                (opts.inherit && this.parent && this.parent.parameter(id)));
4734        };
4735        StateObject.prototype.toString = function () {
4736            return this.fqn();
4737        };
4738        /** Predicate which returns true if the object is an class with @State() decorator */
4739        StateObject.isStateClass = function (stateDecl) {
4740            return isFunction(stateDecl) && stateDecl['__uiRouterState'] === true;
4741        };
4742        /** Predicate which returns true if the object is a [[StateDeclaration]] object */
4743        StateObject.isStateDeclaration = function (obj) { return isFunction(obj['$$state']); };
4744        /** Predicate which returns true if the object is an internal [[StateObject]] object */
4745        StateObject.isState = function (obj) { return isObject(obj['__stateObjectCache']); };
4746        return StateObject;
4747    }());
4748
4749    var StateMatcher = /** @class */ (function () {
4750        function StateMatcher(_states) {
4751            this._states = _states;
4752        }
4753        StateMatcher.prototype.isRelative = function (stateName) {
4754            stateName = stateName || '';
4755            return stateName.indexOf('.') === 0 || stateName.indexOf('^') === 0;
4756        };
4757        StateMatcher.prototype.find = function (stateOrName, base, matchGlob) {
4758            if (matchGlob === void 0) { matchGlob = true; }
4759            if (!stateOrName && stateOrName !== '')
4760                return undefined;
4761            var isStr = isString(stateOrName);
4762            var name = isStr ? stateOrName : stateOrName.name;
4763            if (this.isRelative(name))
4764                name = this.resolvePath(name, base);
4765            var state = this._states[name];
4766            if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) {
4767                return state;
4768            }
4769            else if (isStr && matchGlob) {
4770                var _states = values(this._states);
4771                var matches = _states.filter(function (_state) { return _state.__stateObjectCache.nameGlob && _state.__stateObjectCache.nameGlob.matches(name); });
4772                if (matches.length > 1) {
4773                    safeConsole.error("stateMatcher.find: Found multiple matches for " + name + " using glob: ", matches.map(function (match) { return match.name; }));
4774                }
4775                return matches[0];
4776            }
4777            return undefined;
4778        };
4779        StateMatcher.prototype.resolvePath = function (name, base) {
4780            if (!base)
4781                throw new Error("No reference point given for path '" + name + "'");
4782            var baseState = this.find(base);
4783            var splitName = name.split('.');
4784            var pathLength = splitName.length;
4785            var i = 0, current = baseState;
4786            for (; i < pathLength; i++) {
4787                if (splitName[i] === '' && i === 0) {
4788                    current = baseState;
4789                    continue;
4790                }
4791                if (splitName[i] === '^') {
4792                    if (!current.parent)
4793                        throw new Error("Path '" + name + "' not valid for state '" + baseState.name + "'");
4794                    current = current.parent;
4795                    continue;
4796                }
4797                break;
4798            }
4799            var relName = splitName.slice(i).join('.');
4800            return current.name + (current.name && relName ? '.' : '') + relName;
4801        };
4802        return StateMatcher;
4803    }());
4804
4805    var StateQueueManager = /** @class */ (function () {
4806        function StateQueueManager(router, states, builder, listeners) {
4807            this.router = router;
4808            this.states = states;
4809            this.builder = builder;
4810            this.listeners = listeners;
4811            this.queue = [];
4812        }
4813        StateQueueManager.prototype.dispose = function () {
4814            this.queue = [];
4815        };
4816        StateQueueManager.prototype.register = function (stateDecl) {
4817            var queue = this.queue;
4818            var state = StateObject.create(stateDecl);
4819            var name = state.name;
4820            if (!isString(name))
4821                throw new Error('State must have a valid name');
4822            if (this.states.hasOwnProperty(name) || inArray(queue.map(prop('name')), name))
4823                throw new Error("State '" + name + "' is already defined");
4824            queue.push(state);
4825            this.flush();
4826            return state;
4827        };
4828        StateQueueManager.prototype.flush = function () {
4829            var _this = this;
4830            var _a = this, queue = _a.queue, states = _a.states, builder = _a.builder;
4831            var registered = [], // states that got registered
4832            orphans = [], // states that don't yet have a parent registered
4833            previousQueueLength = {}; // keep track of how long the queue when an orphan was first encountered
4834            var getState = function (name) { return _this.states.hasOwnProperty(name) && _this.states[name]; };
4835            var notifyListeners = function () {
4836                if (registered.length) {
4837                    _this.listeners.forEach(function (listener) {
4838                        return listener('registered', registered.map(function (s) { return s.self; }));
4839                    });
4840                }
4841            };
4842            while (queue.length > 0) {
4843                var state = queue.shift();
4844                var name_1 = state.name;
4845                var result = builder.build(state);
4846                var orphanIdx = orphans.indexOf(state);
4847                if (result) {
4848                    var existingState = getState(name_1);
4849                    if (existingState && existingState.name === name_1) {
4850                        throw new Error("State '" + name_1 + "' is already defined");
4851                    }
4852                    var existingFutureState = getState(name_1 + '.**');
4853                    if (existingFutureState) {
4854                        // Remove future state of the same name
4855                        this.router.stateRegistry.deregister(existingFutureState);
4856                    }
4857                    states[name_1] = state;
4858                    this.attachRoute(state);
4859                    if (orphanIdx >= 0)
4860                        orphans.splice(orphanIdx, 1);
4861                    registered.push(state);
4862                    continue;
4863                }
4864                var prev = previousQueueLength[name_1];
4865                previousQueueLength[name_1] = queue.length;
4866                if (orphanIdx >= 0 && prev === queue.length) {
4867                    // Wait until two consecutive iterations where no additional states were dequeued successfully.
4868                    // throw new Error(`Cannot register orphaned state '${name}'`);
4869                    queue.push(state);
4870                    notifyListeners();
4871                    return states;
4872                }
4873                else if (orphanIdx < 0) {
4874                    orphans.push(state);
4875                }
4876                queue.push(state);
4877            }
4878            notifyListeners();
4879            return states;
4880        };
4881        StateQueueManager.prototype.attachRoute = function (state) {
4882            if (state.abstract || !state.url)
4883                return;
4884            var rulesApi = this.router.urlService.rules;
4885            rulesApi.rule(rulesApi.urlRuleFactory.create(state));
4886        };
4887        return StateQueueManager;
4888    }());
4889
4890    /**
4891     * A registry for all of the application's [[StateDeclaration]]s
4892     *
4893     * This API is found at `router.stateRegistry` ([[UIRouter.stateRegistry]])
4894     */
4895    var StateRegistry = /** @class */ (function () {
4896        /** @internal */
4897        function StateRegistry(router) {
4898            this.router = router;
4899            this.states = {};
4900            /** @internal */
4901            this.listeners = [];
4902            this.matcher = new StateMatcher(this.states);
4903            this.builder = new StateBuilder(this.matcher, router.urlMatcherFactory);
4904            this.stateQueue = new StateQueueManager(router, this.states, this.builder, this.listeners);
4905            this._registerRoot();
4906        }
4907        /** @internal */
4908        StateRegistry.prototype._registerRoot = function () {
4909            var rootStateDef = {
4910                name: '',
4911                url: '^',
4912                views: null,
4913                params: {
4914                    '#': { value: null, type: 'hash', dynamic: true },
4915                },
4916                abstract: true,
4917            };
4918            var _root = (this._root = this.stateQueue.register(rootStateDef));
4919            _root.navigable = null;
4920        };
4921        /** @internal */
4922        StateRegistry.prototype.dispose = function () {
4923            var _this = this;
4924            this.stateQueue.dispose();
4925            this.listeners = [];
4926            this.get().forEach(function (state) { return _this.get(state) && _this.deregister(state); });
4927        };
4928        /**
4929         * Listen for a State Registry events
4930         *
4931         * Adds a callback that is invoked when states are registered or deregistered with the StateRegistry.
4932         *
4933         * #### Example:
4934         * ```js
4935         * let allStates = registry.get();
4936         *
4937         * // Later, invoke deregisterFn() to remove the listener
4938         * let deregisterFn = registry.onStatesChanged((event, states) => {
4939         *   switch(event) {
4940         *     case: 'registered':
4941         *       states.forEach(state => allStates.push(state));
4942         *       break;
4943         *     case: 'deregistered':
4944         *       states.forEach(state => {
4945         *         let idx = allStates.indexOf(state);
4946         *         if (idx !== -1) allStates.splice(idx, 1);
4947         *       });
4948         *       break;
4949         *   }
4950         * });
4951         * ```
4952         *
4953         * @param listener a callback function invoked when the registered states changes.
4954         *        The function receives two parameters, `event` and `state`.
4955         *        See [[StateRegistryListener]]
4956         * @return a function that deregisters the listener
4957         */
4958        StateRegistry.prototype.onStatesChanged = function (listener) {
4959            this.listeners.push(listener);
4960            return function deregisterListener() {
4961                removeFrom(this.listeners)(listener);
4962            }.bind(this);
4963        };
4964        /**
4965         * Gets the implicit root state
4966         *
4967         * Gets the root of the state tree.
4968         * The root state is implicitly created by UI-Router.
4969         * Note: this returns the internal [[StateObject]] representation, not a [[StateDeclaration]]
4970         *
4971         * @return the root [[StateObject]]
4972         */
4973        StateRegistry.prototype.root = function () {
4974            return this._root;
4975        };
4976        /**
4977         * Adds a state to the registry
4978         *
4979         * Registers a [[StateDeclaration]] or queues it for registration.
4980         *
4981         * Note: a state will be queued if the state's parent isn't yet registered.
4982         *
4983         * @param stateDefinition the definition of the state to register.
4984         * @returns the internal [[StateObject]] object.
4985         *          If the state was successfully registered, then the object is fully built (See: [[StateBuilder]]).
4986         *          If the state was only queued, then the object is not fully built.
4987         */
4988        StateRegistry.prototype.register = function (stateDefinition) {
4989            return this.stateQueue.register(stateDefinition);
4990        };
4991        /** @internal */
4992        StateRegistry.prototype._deregisterTree = function (state) {
4993            var _this = this;
4994            var all = this.get().map(function (s) { return s.$$state(); });
4995            var getChildren = function (states) {
4996                var _children = all.filter(function (s) { return states.indexOf(s.parent) !== -1; });
4997                return _children.length === 0 ? _children : _children.concat(getChildren(_children));
4998            };
4999            var children = getChildren([state]);
5000            var deregistered = [state].concat(children).reverse();
5001            deregistered.forEach(function (_state) {
5002                var rulesApi = _this.router.urlService.rules;
5003                // Remove URL rule
5004                rulesApi
5005                    .rules()
5006                    .filter(propEq('state', _state))
5007                    .forEach(function (rule) { return rulesApi.removeRule(rule); });
5008                // Remove state from registry
5009                delete _this.states[_state.name];
5010            });
5011            return deregistered;
5012        };
5013        /**
5014         * Removes a state from the registry
5015         *
5016         * This removes a state from the registry.
5017         * If the state has children, they are are also removed from the registry.
5018         *
5019         * @param stateOrName the state's name or object representation
5020         * @returns {StateObject[]} a list of removed states
5021         */
5022        StateRegistry.prototype.deregister = function (stateOrName) {
5023            var _state = this.get(stateOrName);
5024            if (!_state)
5025                throw new Error("Can't deregister state; not found: " + stateOrName);
5026            var deregisteredStates = this._deregisterTree(_state.$$state());
5027            this.listeners.forEach(function (listener) {
5028                return listener('deregistered', deregisteredStates.map(function (s) { return s.self; }));
5029            });
5030            return deregisteredStates;
5031        };
5032        StateRegistry.prototype.get = function (stateOrName, base) {
5033            var _this = this;
5034            if (arguments.length === 0)
5035                return Object.keys(this.states).map(function (name) { return _this.states[name].self; });
5036            var found = this.matcher.find(stateOrName, base);
5037            return (found && found.self) || null;
5038        };
5039        /**
5040         * Registers a [[BuilderFunction]] for a specific [[StateObject]] property (e.g., `parent`, `url`, or `path`).
5041         * More than one BuilderFunction can be registered for a given property.
5042         *
5043         * The BuilderFunction(s) will be used to define the property on any subsequently built [[StateObject]] objects.
5044         *
5045         * @param property The name of the State property being registered for.
5046         * @param builderFunction The BuilderFunction which will be used to build the State property
5047         * @returns a function which deregisters the BuilderFunction
5048         */
5049        StateRegistry.prototype.decorator = function (property, builderFunction) {
5050            return this.builder.builder(property, builderFunction);
5051        };
5052        return StateRegistry;
5053    }());
5054
5055    (function (TransitionHookPhase) {
5056        TransitionHookPhase[TransitionHookPhase["CREATE"] = 0] = "CREATE";
5057        TransitionHookPhase[TransitionHookPhase["BEFORE"] = 1] = "BEFORE";
5058        TransitionHookPhase[TransitionHookPhase["RUN"] = 2] = "RUN";
5059        TransitionHookPhase[TransitionHookPhase["SUCCESS"] = 3] = "SUCCESS";
5060        TransitionHookPhase[TransitionHookPhase["ERROR"] = 4] = "ERROR";
5061    })(exports.TransitionHookPhase || (exports.TransitionHookPhase = {}));
5062
5063    (function (TransitionHookScope) {
5064        TransitionHookScope[TransitionHookScope["TRANSITION"] = 0] = "TRANSITION";
5065        TransitionHookScope[TransitionHookScope["STATE"] = 1] = "STATE";
5066    })(exports.TransitionHookScope || (exports.TransitionHookScope = {}));
5067
5068    var defaultOptions = {
5069        current: noop,
5070        transition: null,
5071        traceData: {},
5072        bind: null,
5073    };
5074    var TransitionHook = /** @class */ (function () {
5075        function TransitionHook(transition, stateContext, registeredHook, options) {
5076            var _this = this;
5077            this.transition = transition;
5078            this.stateContext = stateContext;
5079            this.registeredHook = registeredHook;
5080            this.options = options;
5081            this.isSuperseded = function () { return _this.type.hookPhase === exports.TransitionHookPhase.RUN && !_this.options.transition.isActive(); };
5082            this.options = defaults(options, defaultOptions);
5083            this.type = registeredHook.eventType;
5084        }
5085        /**
5086         * Chains together an array of TransitionHooks.
5087         *
5088         * Given a list of [[TransitionHook]] objects, chains them together.
5089         * Each hook is invoked after the previous one completes.
5090         *
5091         * #### Example:
5092         * ```js
5093         * var hooks: TransitionHook[] = getHooks();
5094         * let promise: Promise<any> = TransitionHook.chain(hooks);
5095         *
5096         * promise.then(handleSuccess, handleError);
5097         * ```
5098         *
5099         * @param hooks the list of hooks to chain together
5100         * @param waitFor if provided, the chain is `.then()`'ed off this promise
5101         * @returns a `Promise` for sequentially invoking the hooks (in order)
5102         */
5103        TransitionHook.chain = function (hooks, waitFor) {
5104            // Chain the next hook off the previous
5105            var createHookChainR = function (prev, nextHook) { return prev.then(function () { return nextHook.invokeHook(); }); };
5106            return hooks.reduce(createHookChainR, waitFor || services.$q.when());
5107        };
5108        /**
5109         * Invokes all the provided TransitionHooks, in order.
5110         * Each hook's return value is checked.
5111         * If any hook returns a promise, then the rest of the hooks are chained off that promise, and the promise is returned.
5112         * If no hook returns a promise, then all hooks are processed synchronously.
5113         *
5114         * @param hooks the list of TransitionHooks to invoke
5115         * @param doneCallback a callback that is invoked after all the hooks have successfully completed
5116         *
5117         * @returns a promise for the async result, or the result of the callback
5118         */
5119        TransitionHook.invokeHooks = function (hooks, doneCallback) {
5120            for (var idx = 0; idx < hooks.length; idx++) {
5121                var hookResult = hooks[idx].invokeHook();
5122                if (isPromise(hookResult)) {
5123                    var remainingHooks = hooks.slice(idx + 1);
5124                    return TransitionHook.chain(remainingHooks, hookResult).then(doneCallback);
5125                }
5126            }
5127            return doneCallback();
5128        };
5129        /**
5130         * Run all TransitionHooks, ignoring their return value.
5131         */
5132        TransitionHook.runAllHooks = function (hooks) {
5133            hooks.forEach(function (hook) { return hook.invokeHook(); });
5134        };
5135        TransitionHook.prototype.logError = function (err) {
5136            this.transition.router.stateService.defaultErrorHandler()(err);
5137        };
5138        TransitionHook.prototype.invokeHook = function () {
5139            var _this = this;
5140            var hook = this.registeredHook;
5141            if (hook._deregistered)
5142                return;
5143            var notCurrent = this.getNotCurrentRejection();
5144            if (notCurrent)
5145                return notCurrent;
5146            var options = this.options;
5147            trace.traceHookInvocation(this, this.transition, options);
5148            var invokeCallback = function () { return hook.callback.call(options.bind, _this.transition, _this.stateContext); };
5149            var normalizeErr = function (err) { return Rejection.normalize(err).toPromise(); };
5150            var handleError = function (err) { return hook.eventType.getErrorHandler(_this)(err); };
5151            var handleResult = function (result) { return hook.eventType.getResultHandler(_this)(result); };
5152            try {
5153                var result = invokeCallback();
5154                if (!this.type.synchronous && isPromise(result)) {
5155                    return result.catch(normalizeErr).then(handleResult, handleError);
5156                }
5157                else {
5158                    return handleResult(result);
5159                }
5160            }
5161            catch (err) {
5162                // If callback throws (synchronously)
5163                return handleError(Rejection.normalize(err));
5164            }
5165            finally {
5166                if (hook.invokeLimit && ++hook.invokeCount >= hook.invokeLimit) {
5167                    hook.deregister();
5168                }
5169            }
5170        };
5171        /**
5172         * This method handles the return value of a Transition Hook.
5173         *
5174         * A hook can return false (cancel), a TargetState (redirect),
5175         * or a promise (which may later resolve to false or a redirect)
5176         *
5177         * This also handles "transition superseded" -- when a new transition
5178         * was started while the hook was still running
5179         */
5180        TransitionHook.prototype.handleHookResult = function (result) {
5181            var _this = this;
5182            var notCurrent = this.getNotCurrentRejection();
5183            if (notCurrent)
5184                return notCurrent;
5185            // Hook returned a promise
5186            if (isPromise(result)) {
5187                // Wait for the promise, then reprocess with the resulting value
5188                return result.then(function (val) { return _this.handleHookResult(val); });
5189            }
5190            trace.traceHookResult(result, this.transition, this.options);
5191            // Hook returned false
5192            if (result === false) {
5193                // Abort this Transition
5194                return Rejection.aborted('Hook aborted transition').toPromise();
5195            }
5196            var isTargetState = is(TargetState);
5197            // hook returned a TargetState
5198            if (isTargetState(result)) {
5199                // Halt the current Transition and redirect (a new Transition) to the TargetState.
5200                return Rejection.redirected(result).toPromise();
5201            }
5202        };
5203        /**
5204         * Return a Rejection promise if the transition is no longer current due
5205         * to a stopped router (disposed), or a new transition has started and superseded this one.
5206         */
5207        TransitionHook.prototype.getNotCurrentRejection = function () {
5208            var router = this.transition.router;
5209            // The router is stopped
5210            if (router._disposed) {
5211                return Rejection.aborted("UIRouter instance #" + router.$i
5211d + " has been stopped (disposed)").toPromise();
5212            }
5213            if (this.transition._aborted) {
5214                return Rejection.aborted().toPromise();
5215            }
5216            // This transition is no longer current.
5217            // Another transition started while this hook was still running.
5218            if (this.isSuperseded()) {
5219                // Abort this transition
5220                return Rejection.superseded(this.options.current()).toPromise();
5221            }
5222        };
5223        TransitionHook.prototype.toString = function () {
5224            var _a = this, options = _a.options, registeredHook = _a.registeredHook;
5225            var event = parse('traceData.hookType')(options) || 'internal', context = parse('traceData.context.state.name')(options) || parse('traceData.context')(options) || 'unknown', name = fnToString(registeredHook.callback);
5226            return event + " context: " + context + ", " + maxLength(200, name);
5227        };
5228        /**
5229         * These GetResultHandler(s) are used by [[invokeHook]] below
5230         * Each HookType chooses a GetResultHandler (See: [[TransitionService._defineCoreEvents]])
5231         */
5232        TransitionHook.HANDLE_RESULT = function (hook) { return function (result) {
5233            return hook.handleHookResult(result);
5234        }; };
5235        /**
5236         * If the result is a promise rejection, log it.
5237         * Otherwise, ignore the result.
5238         */
5239        TransitionHook.LOG_REJECTED_RESULT = function (hook) { return function (result) {
5240            isPromise(result) && result.catch(function (err) { return hook.logError(Rejection.normalize(err)); });
5241            return undefined;
5242        }; };
5243        /**
5244         * These GetErrorHandler(s) are used by [[invokeHook]] below
5245         * Each HookType chooses a GetErrorHandler (See: [[TransitionService._defineCoreEvents]])
5246         */
5247        TransitionHook.LOG_ERROR = function (hook) { return function (error) { return hook.logError(error); }; };
5248        TransitionHook.REJECT_ERROR = function (hook) { return function (error) { return silentRejection(error); }; };
5249        TransitionHook.THROW_ERROR = function (hook) { return function (error) {
5250            throw error;
5251        }; };
5252        return TransitionHook;
5253    }());
5254
5255    /**
5256     * Determines if the given state matches the matchCriteria
5257     *
5258     * @internal
5259     *
5260     * @param state a State Object to test against
5261     * @param criterion
5262     * - If a string, matchState uses the string as a glob-matcher against the state name
5263     * - If an array (of strings), matchState uses each string in the array as a glob-matchers against the state name
5264     *   and returns a positive match if any of the globs match.
5265     * - If a function, matchState calls the function with the state and returns true if the function's result is truthy.
5266     * @returns {boolean}
5267     */
5268    function matchState(state, criterion, transition) {
5269        var toMatch = isString(criterion) ? [criterion] : criterion;
5270        function matchGlobs(_state) {
5271            var globStrings = toMatch;
5272            for (var i = 0; i < globStrings.length; i++) {
5273                var glob = new Glob(globStrings[i]);
5274                if ((glob && glob.matches(_state.name)) || (!glob && globStrings[i] === _state.name)) {
5275                    return true;
5276                }
5277            }
5278            return false;
5279        }
5280        var matchFn = (isFunction(toMatch) ? toMatch : matchGlobs);
5281        return !!matchFn(state, transition);
5282    }
5283    /**
5284     * The registration data for a registered transition hook
5285     */
5286    var RegisteredHook = /** @class */ (function () {
5287        function RegisteredHook(tranSvc, eventType, callback, matchCriteria, removeHookFromRegistry, options) {
5288            if (options === void 0) { options = {}; }
5289            this.tranSvc = tranSvc;
5290            this.eventType = eventType;
5291            this.callback = callback;
5292            this.matchCriteria = matchCriteria;
5293            this.removeHookFromRegistry = removeHookFromRegistry;
5294            this.invokeCount = 0;
5295            this._deregistered = false;
5296            this.priority = options.priority || 0;
5297            this.bind = options.bind || null;
5298            this.invokeLimit = options.invokeLimit;
5299        }
5300        /**
5301         * Gets the matching [[PathNode]]s
5302         *
5303         * Given an array of [[PathNode]]s, and a [[HookMatchCriterion]], returns an array containing
5304         * the [[PathNode]]s that the criteria matches, or `null` if there were no matching nodes.
5305         *
5306         * Returning `null` is significant to distinguish between the default
5307         * "match-all criterion value" of `true` compared to a `() => true` function,
5308         * when the nodes is an empty array.
5309         *
5310         * This is useful to allow a transition match criteria of `entering: true`
5311         * to still match a transition, even when `entering === []`.  Contrast that
5312         * with `entering: (state) => true` which only matches when a state is actually
5313         * being entered.
5314         */
5315        RegisteredHook.prototype._matchingNodes = function (nodes, criterion, transition) {
5316            if (criterion === true)
5317                return nodes;
5318            var matching = nodes.filter(function (node) { return matchState(node.state, criterion, transition); });
5319            return matching.length ? matching : null;
5320        };
5321        /**
5322         * Gets the default match criteria (all `true`)
5323         *
5324         * Returns an object which has all the criteria match paths as keys and `true` as values, i.e.:
5325         *
5326         * ```js
5327         * {
5328         *   to: true,
5329         *   from: true,
5330         *   entering: true,
5331         *   exiting: true,
5332         *   retained: true,
5333         * }
5334         */
5335        RegisteredHook.prototype._getDefaultMatchCriteria = function () {
5336            return mapObj(this.tranSvc._pluginapi._getPathTypes(), function () { return true; });
5337        };
5338        /**
5339         * Gets matching nodes as [[IMatchingNodes]]
5340         *
5341         * Create a IMatchingNodes object from the TransitionHookTypes that is roughly equivalent to:
5342         *
5343         * ```js
5344         * let matches: IMatchingNodes = {
5345         *   to:       _matchingNodes([tail(treeChanges.to)],   mc.to),
5346         *   from:     _matchingNodes([tail(treeChanges.from)], mc.from),
5347         *   exiting:  _matchingNodes(treeChanges.exiting,      mc.exiting),
5348         *   retained: _matchingNodes(treeChanges.retained,     mc.retained),
5349         *   entering: _matchingNodes(treeChanges.entering,     mc.entering),
5350         * };
5351         * ```
5352         */
5353        RegisteredHook.prototype._getMatchingNodes = function (treeChanges, transition) {
5354            var _this = this;
5355            var criteria = extend(this._getDefaultMatchCriteria(), this.matchCriteria);
5356            var paths = values(this.tranSvc._pluginapi._getPathTypes());
5357            return paths.reduce(function (mn, pathtype) {
5358                // STATE scope criteria matches against every node in the path.
5359                // TRANSITION scope criteria matches against only the last node in the path
5360                var isStateHook = pathtype.scope === exports.TransitionHookScope.STATE;
5361                var path = treeChanges[pathtype.name] || [];
5362                var nodes = isStateHook ? path : [tail(path)];
5363                mn[pathtype.name] = _this._matchingNodes(nodes, criteria[pathtype.name], transition);
5364                return mn;
5365            }, {});
5366        };
5367        /**
5368         * Determines if this hook's [[matchCriteria]] match the given [[TreeChanges]]
5369         *
5370         * @returns an IMatchingNodes object, or null. If an IMatchingNodes object is returned, its values
5371         * are the matching [[PathNode]]s for each [[HookMatchCriterion]] (to, from, exiting, retained, entering)
5372         */
5373        RegisteredHook.prototype.matches = function (treeChanges, transition) {
5374            var matches = this._getMatchingNodes(treeChanges, transition);
5375            // Check if all the criteria matched the TreeChanges object
5376            var allMatched = values(matches).every(identity);
5377            return allMatched ? matches : null;
5378        };
5379        RegisteredHook.prototype.deregister = function () {
5380            this.removeHookFromRegistry(this);
5381            this._deregistered = true;
5382        };
5383        return RegisteredHook;
5384    }());
5385    /** Return a registration function of the requested type. */
5386    function makeEvent(registry, transitionService, eventType) {
5387        // Create the object which holds the registered transition hooks.
5388        var _registeredHooks = (registry._registeredHooks = registry._registeredHooks || {});
5389        var hooks = (_registeredHooks[eventType.name] = []);
5390        var removeHookFn = removeFrom(hooks);
5391        // Create hook registration function on the IHookRegistry for the event
5392        registry[eventType.name] = hookRegistrationFn;
5393        function hookRegistrationFn(matchObject, callback, options) {
5394            if (options === void 0) { options = {}; }
5395            var registeredHook = new RegisteredHook(transitionService, eventType, callback, matchObject, removeHookFn, options);
5396            hooks.push(registeredHook);
5397            return registeredHook.deregister.bind(registeredHook);
5398        }
5399        return hookRegistrationFn;
5400    }
5401
5402    /**
5403     * This class returns applicable TransitionHooks for a specific Transition instance.
5404     *
5405     * Hooks ([[RegisteredHook]]) may be registered globally, e.g., $transitions.onEnter(...), or locally, e.g.
5406     * myTransition.onEnter(...).  The HookBuilder finds matching RegisteredHooks (where the match criteria is
5407     * determined by the type of hook)
5408     *
5409     * The HookBuilder also converts RegisteredHooks objects to TransitionHook objects, which are used to run a Transition.
5410     *
5411     * The HookBuilder constructor is given the $transitions service and a Transition instance.  Thus, a HookBuilder
5412     * instance may only be used for one specific Transition object. (side note: the _treeChanges accessor is private
5413     * in the Transition class, so we must also provide the Transition's _treeChanges)
5414     */
5415    var HookBuilder = /** @class */ (function () {
5416        function HookBuilder(transition) {
5417            this.transition = transition;
5418        }
5419        HookBuilder.prototype.buildHooksForPhase = function (phase) {
5420            var _this = this;
5421            var $transitions = this.transition.router.transitionService;
5422            return $transitions._pluginapi
5423                ._getEvents(phase)
5424                .map(function (type) { return _this.buildHooks(type); })
5425                .reduce(unnestR, [])
5426                .filter(identity);
5427        };
5428        /**
5429         * Returns an array of newly built TransitionHook objects.
5430         *
5431         * - Finds all RegisteredHooks registered for the given `hookType` which matched the transition's [[TreeChanges]].
5432         * - Finds [[PathNode]] (or `PathNode[]`) to use as the TransitionHook context(s)
5433         * - For each of the [[PathNode]]s, creates a TransitionHook
5434         *
5435         * @param hookType the type of the hook registration function, e.g., 'onEnter', 'onFinish'.
5436         */
5437        HookBuilder.prototype.buildHooks = function (hookType) {
5438            var transition = this.transition;
5439            var treeChanges = transition.treeChanges();
5440            // Find all the matching registered hooks for a given hook type
5441            var matchingHooks = this.getMatchingHooks(hookType, treeChanges, transition);
5442            if (!matchingHooks)
5443                return [];
5444            var baseHookOptions = {
5445                transition: transition,
5446                current: transition.options().current,
5447            };
5448            var makeTransitionHooks = function (hook) {
5449                // Fetch the Nodes that caused this hook to match.
5450                var matches = hook.matches(treeChanges, transition);
5451                // Select the PathNode[] that will be used as TransitionHook context objects
5452                var matchingNodes = matches[hookType.criteriaMatchPath.name];
5453                // Return an array of HookTuples
5454                return matchingNodes.map(function (node) {
5455                    var _options = extend({
5456                        bind: hook.bind,
5457                        traceData: { hookType: hookType.name, context: node },
5458                    }, baseHookOptions);
5459                    var state = hookType.criteriaMatchPath.scope === exports.TransitionHookScope.STATE ? node.state.self : null;
5460                    var transitionHook = new TransitionHook(transition, state, hook, _options);
5461                    return { hook: hook, node: node, transitionHook: transitionHook };
5462                });
5463            };
5464            return matchingHooks
5465                .map(makeTransitionHooks)
5466                .reduce(unnestR, [])
5467                .sort(tupleSort(hookType.reverseSort))
5468                .map(function (tuple) { return tuple.transitionHook; });
5469        };
5470        /**
5471         * Finds all RegisteredHooks from:
5472         * - The Transition object instance hook registry
5473         * - The TransitionService ($transitions) global hook registry
5474         *
5475         * which matched:
5476         * - the eventType
5477         * - the matchCriteria (to, from, exiting, retained, entering)
5478         *
5479         * @returns an array of matched [[RegisteredHook]]s
5480         */
5481        HookBuilder.prototype.getMatchingHooks = function (hookType, treeChanges, transition) {
5482            var isCreate = hookType.hookPhase === exports.TransitionHookPhase.CREATE;
5483            // Instance and Global hook registries
5484            var $transitions = this.transition.router.transitionService;
5485            var registries = isCreate ? [$transitions] : [this.transition, $transitions];
5486            return registries
5487                .map(function (reg) { return reg.getHooks(hookType.name); }) // Get named hooks from registries
5488                .filter(assertPredicate(isArray, "broken event named: " + hookType.name)) // Sanity check
5489                .reduce(unnestR, []) // Un-nest RegisteredHook[][] to RegisteredHook[] array
5490                .filter(function (hook) { return hook.matches(treeChanges, transition); }); // Only those satisfying matchCriteria
5491        };
5492        return HookBuilder;
5493    }());
5494    /**
5495     * A factory for a sort function for HookTuples.
5496     *
5497     * The sort function first compares the PathNode depth (how deep in the state tree a node is), then compares
5498     * the EventHook priority.
5499     *
5500     * @param reverseDepthSort a boolean, when true, reverses the sort order for the node depth
5501     * @returns a tuple sort function
5502     */
5503    function tupleSort(reverseDepthSort) {
5504        if (reverseDepthSort === void 0) { reverseDepthSort = false; }
5505        return function nodeDepthThenPriority(l, r) {
5506            var factor = reverseDepthSort ? -1 : 1;
5507            var depthDelta = (l.node.state.path.length - r.node.state.path.length) * factor;
5508            return depthDelta !== 0 ? depthDelta : r.hook.priority - l.hook.priority;
5509        };
5510    }
5511
5512    /** @internal */
5513    var stateSelf = prop('self');
5514    /**
5515     * Represents a transition between two states.
5516     *
5517     * When navigating to a state, we are transitioning **from** the current state **to** the new state.
5518     *
5519     * This object contains all contextual information about the to/from states, parameters, resolves.
5520     * It has information about all states being entered and exited as a result of the transition.
5521     */
5522    var Transition = /** @class */ (function () {
5523        /**
5524         * Creates a new Transition object.
5525         *
5526         * If the target state is not valid, an error is thrown.
5527         *
5528         * @internal
5529         *
5530         * @param fromPath The path of [[PathNode]]s from which the transition is leaving.  The last node in the `fromPath`
5531         *        encapsulates the "from state".
5532         * @param targetState The target state and parameters being transitioned to (also, the transition options)
5533         * @param router The [[UIRouter]] instance
5534         * @internal
5535         */
5536        function Transition(fromPath, targetState, router) {
5537            var _this = this;
5538            /** @internal */
5539            this._deferred = services.$q.defer();
5540            /**
5541             * This promise is resolved or rejected based on the outcome of the Transition.
5542             *
5543             * When the transition is successful, the promise is resolved
5544             * When the transition is unsuccessful, the promise is rejected with the [[Rejection]] or javascript error
5545             */
5546            this.promise = this._deferred.promise;
5547            /** @internal Holds the hook registration functions such as those passed to Transition.onStart() */
5548            this._registeredHooks = {};
5549            /** @internal */
5550            this._hookBuilder = new HookBuilder(this);
5551            /** Checks if this transition is currently active/running. */
5552            this.isActive = function () { return _this.router.globals.transition === _this; };
5553            this.router = router;
5554            this._targetState = targetState;
5555            if (!targetState.valid()) {
5556                throw new Error(targetState.error());
5557            }
5558            // current() is assumed to come from targetState.options, but provide a naive implementation otherwise.
5559            this._options = extend({ current: val(this) }, targetState.options());
5560            this.$id = router.transitionService._transitionCount++;
5561            var toPath = PathUtils.buildToPath(fromPath, targetState);
5562            this._treeChanges = PathUtils.treeChanges(fromPath, toPath, this._options.reloadState);
5563            this.createTransitionHookRegFns();
5564            var onCreateHooks = this._hookBuilder.buildHooksForPhase(exports.TransitionHookPhase.CREATE);
5565            TransitionHook.invokeHooks(onCreateHooks, function () { return null; });
5566            this.applyViewConfigs(router);
5567        }
5568        /** @internal */
5569        Transition.prototype.onBefore = function (criteria, callback, options) {
5570            return;
5571        };
5572        /** @inheritdoc */
5573        Transition.prototype.onStart = function (criteria, callback, options) {
5574            return;
5575        };
5576        /** @inheritdoc */
5577        Transition.prototype.onExit = function (criteria, callback, options) {
5578            return;
5579        };
5580        /** @inheritdoc */
5581        Transition.prototype.onRetain = function (criteria, callback, options) {
5582            return;
5583        };
5584        /** @inheritdoc */
5585        Transition.prototype.onEnter = function (criteria, callback, options) {
5586            return;
5587        };
5588        /** @inheritdoc */
5589        Transition.prototype.onFinish = function (criteria, callback, options) {
5590            return;
5591        };
5592        /** @inheritdoc */
5593        Transition.prototype.onSuccess = function (criteria, callback, options) {
5594            return;
5595        };
5596        /** @inheritdoc */
5597        Transition.prototype.onError = function (criteria, callback, options) {
5598            return;
5599        };
5600        /** @internal
5601         * Creates the transition-level hook registration functions
5602         * (which can then be used to register hooks)
5603         */
5604        Transition.prototype.createTransitionHookRegFns = function () {
5605            var _this = this;
5606            this.router.transitionService._pluginapi
5607                ._getEvents()
5608                .filter(function (type) { return type.hookPhase !== exports.TransitionHookPhase.CREATE; })
5609                .forEach(function (type) { return makeEvent(_this, _this.router.transitionService, type); });
5610        };
5611        /** @internal */
5612        Transition.prototype.getHooks = function (hookName) {
5613            return this._registeredHooks[hookName];
5614        };
5615        Transition.prototype.applyViewConfigs = function (router) {
5616            var enteringStates = this._treeChanges.entering.map(function (node) { return node.state; });
5617            PathUtils.applyViewConfigs(router.transitionService.$view, this._treeChanges.to, enteringStates);
5618        };
5619        /**
5620         * @internal
5621         * @returns the internal from [State] object
5622         */
5623        Transition.prototype.$from = function () {
5624            return tail(this._treeChanges.from).state;
5625        };
5626        /**
5627         * @internal
5628         * @returns the internal to [State] object
5629         */
5630        Transition.prototype.$to = function () {
5631            return tail(this._treeChanges.to).state;
5632        };
5633        /**
5634         * Returns the "from state"
5635         *
5636         * Returns the state that the transition is coming *from*.
5637         *
5638         * @returns The state declaration object for the Transition's ("from state").
5639         */
5640        Transition.prototype.from = function () {
5641            return this.$from().self;
5642        };
5643        /**
5644         * Returns the "to state"
5645         *
5646         * Returns the state that the transition is going *to*.
5647         *
5648         * @returns The state declaration object for the Transition's target state ("to state").
5649         */
5650        Transition.prototype.to = function () {
5651            return this.$to().self;
5652        };
5653        /**
5654         * Gets the Target State
5655         *
5656         * A transition's [[TargetState]] encapsulates the [[to]] state, the [[params]], and the [[options]] as a single object.
5657         *
5658         * @returns the [[TargetState]] of this Transition
5659         */
5660        Transition.prototype.targetState = function () {
5661            return this._targetState;
5662        };
5663        /**
5664         * Determines whether two transitions are equivalent.
5665         * @deprecated
5666         */
5667        Transition.prototype.is = function (compare) {
5668            if (compare instanceof Transition) {
5669                // TODO: Also compare parameters
5670                return this.is({ to: compare.$to().name, from: compare.$from().name });
5671            }
5672            return !((compare.to && !matchState(this.$to(), compare.to, this)) ||
5673                (compare.from && !matchState(this.$from(), compare.from, this)));
5674        };
5675        Transition.prototype.params = function (pathname) {
5676            if (pathname === void 0) { pathname = 'to'; }
5677            return Object.freeze(this._treeChanges[pathname].map(prop('paramValues')).reduce(mergeR, {}));
5678        };
5679        Transition.prototype.paramsChanged = function () {
5680            var fromParams = this.params('from');
5681            var toParams = this.params('to');
5682            // All the parameters declared on both the "to" and "from" paths
5683            var allParamDescriptors = []
5684                .concat(this._treeChanges.to)
5685                .concat(this._treeChanges.from)
5686                .map(function (pathNode) { return pathNode.paramSchema; })
5687                .reduce(flattenR, [])
5688                .reduce(uniqR, []);
5689            var changedParamDescriptors = Param.changed(allParamDescriptors, fromParams, toParams);
5690            return changedParamDescriptors.reduce(function (changedValues, descriptor) {
5691                changedValues[descriptor.id] = toParams[descriptor.id];
5692                return changedValues;
5693            }, {});
5694        };
5695        /**
5696         * Creates a [[UIInjector]] Dependency Injector
5697         *
5698         * Returns a Dependency Injector for the Transition's target state (to state).
5699         * The injector provides resolve values which the target state has access to.
5700         *
5701         * The `UIInjector` can also provide values from the native root/global injector (ng1/ng2).
5702         *
5703         * #### Example:
5704         * ```js
5705         * .onEnter({ entering: 'myState' }, trans => {
5706         *   var myResolveValue = trans.injector().get('myResolve');
5707         *   // Inject a global service from the global/native injector (if it exists)
5708         *   var MyService = trans.injector().get('MyService');
5709         * })
5710         * ```
5711         *
5712         * In some cases (such as `onBefore`), you may need access to some resolve data but it has not yet been fetched.
5713         * You can use [[UIInjector.getAsync]] to get a promise for the data.
5714         * #### Example:
5715         * ```js
5716         * .onBefore({}, trans => {
5717         *   return trans.injector().getAsync('myResolve').then(myResolveValue =>
5718         *     return myResolveValue !== 'ABORT';
5719         *   });
5720         * });
5721         * ```
5722         *
5723         * If a `state` is provided, the injector that is returned will be limited to resolve values that the provided state has access to.
5724         * This can be useful if both a parent state `foo` and a child state `foo.bar` have both defined a resolve such as `data`.
5725         * #### Example:
5726         * ```js
5727         * .onEnter({ to: 'foo.bar' }, trans => {
5728         *   // returns result of `foo` state's `myResolve` resolve
5729         *   // even though `foo.bar` also has a `myResolve` resolve
5730         *   var fooData = trans.injector('foo').get('myResolve');
5731         * });
5732         * ```
5733         *
5734         * If you need resolve data from the exiting states, pass `'from'` as `pathName`.
5735         * The resolve data from the `from` path will be returned.
5736         * #### Example:
5737         * ```js
5738         * .onExit({ exiting: 'foo.bar' }, trans => {
5739         *   // Gets the resolve value of `myResolve` from the state being exited
5740         *   var fooData = trans.injector(null, 'from').get('myResolve');
5741         * });
5742         * ```
5743         *
5744         *
5745         * @param state Limits the resolves provided to only the resolves the provided state has access to.
5746         * @param pathName Default: `'to'`: Chooses the path for which to create the injector. Use this to access resolves for `exiting` states.
5747         *
5748         * @returns a [[UIInjector]]
5749         */
5750        Transition.prototype.injector = function (state, pathName) {
5751            if (pathName === void 0) { pathName = 'to'; }
5752            var path = this._treeChanges[pathName];
5753            if (state)
5754                path = PathUtils.subPath(path, function (node) { return node.state === state || node.state.name === state; });
5755            return new ResolveContext(path).injector();
5756        };
5757        /**
5758         * Gets all available resolve tokens (keys)
5759         *
5760         * This method can be used in conjunction with [[injector]] to inspect the resolve values
5761         * available to the Transition.
5762         *
5763         * This returns all the tokens defined on [[StateDeclaration.resolve]] blocks, for the states
5764         * in the Transition's [[TreeChanges.to]] path.
5765         *
5766         * #### Example:
5767         * This example logs all resolve values
5768         * ```js
5769         * let tokens = trans.getResolveTokens();
5770         * tokens.forEach(token => console.log(token + " = " + trans.injector().get(token)));
5771         * ```
5772         *
5773         * #### Example:
5774         * This example creates promises for each resolve value.
5775         * This triggers fetches of resolves (if any have not yet been fetched).
5776         * When all promises have all settled, it logs the resolve values.
5777         * ```js
5778         * let tokens = trans.getResolveTokens();
5779         * let promise = tokens.map(token => trans.injector().getAsync(token));
5780         * Promise.all(promises).then(values => console.log("Resolved values: " + values));
5781         * ```
5782         *
5783         * Note: Angular 1 users whould use `$q.all()`
5784         *
5785         * @param pathname resolve context's path name (e.g., `to` or `from`)
5786         *
5787         * @returns an array of resolve tokens (keys)
5788         */
5789        Transition.prototype.getResolveTokens = function (pathname) {
5790            if (pathname === void 0) { pathname = 'to'; }
5791            return new ResolveContext(this._treeChanges[pathname]).getTokens();
5792        };
5793        /**
5794         * Dynamically adds a new [[Resolvable]] (i.e., [[StateDeclaration.resolve]]) to this transition.
5795         *
5796         * Allows a transition hook to dynamically add a Resolvable to this Transition.
5797         *
5798         * Use the [[Transition.injector]] to retrieve the resolved data in subsequent hooks ([[UIInjector.get]]
5798).
5799         *
5800         * If a `state` argument is provided, the Resolvable is processed when that state is being entered.
5801         * If no `state` is provided then the root state is used.
5802         * If the given `state` has already been entered, the Resolvable is processed when any child state is entered.
5803         * If no child states will be entered, the Resolvable is processed during the `onFinish` phase of the Transition.
5804         *
5805         * The `state` argument also scopes the resolved data.
5806         * The resolved data is available from the injector for that `state` and any children states.
5807         *
5808         * #### Example:
5809         * ```js
5810         * transitionService.onBefore({}, transition => {
5811         *   transition.addResolvable({
5812         *     token: 'myResolve',
5813         *     deps: ['MyService'],
5814         *     resolveFn: myService => myService.getData()
5815         *   });
5816         * });
5817         * ```
5818         *
5819         * @param resolvable a [[ResolvableLiteral]] object (or a [[Resolvable]])
5820         * @param state the state in the "to path" which should receive the new resolve (otherwise, the root state)
5821         */
5822        Transition.prototype.addResolvable = function (resolvable, state) {
5823            if (state === void 0) { state = ''; }
5824            resolvable = is(Resolvable)(resolvable) ? resolvable : new Resolvable(resolvable);
5825            var stateName = typeof state === 'string' ? state : state.name;
5826            var topath = this._treeChanges.to;
5827            var targetNode = find(topath, function (node) { return node.state.name === stateName; });
5828            var resolveContext = new ResolveContext(topath);
5829            resolveContext.addResolvables([resolvable], targetNode.state);
5830        };
5831        /**
5832         * Gets the transition from which this transition was redirected.
5833         *
5834         * If the current transition is a redirect, this method returns the transition that was redirected.
5835         *
5836         * #### Example:
5837         * ```js
5838         * let transitionA = $state.go('A').transition
5839         * transitionA.onStart({}, () => $state.target('B'));
5840         * $transitions.onSuccess({ to: 'B' }, (trans) => {
5841         *   trans.to().name === 'B'; // true
5842         *   trans.redirectedFrom() === transitionA; // true
5843         * });
5844         * ```
5845         *
5846         * @returns The previous Transition, or null if this Transition is not the result of a redirection
5847         */
5848        Transition.prototype.redirectedFrom = function () {
5849            return this._options.redirectedFrom || null;
5850        };
5851        /**
5852         * Gets the original transition in a redirect chain
5853         *
5854         * A transition might belong to a long chain of multiple redirects.
5855         * This method walks the [[redirectedFrom]] chain back to the original (first) transition in the chain.
5856         *
5857         * #### Example:
5858         * ```js
5859         * // states
5860         * registry.register({ name: 'A', redirectTo: 'B' });
5861         * registry.register({ name: 'B', redirectTo: 'C' });
5862         * registry.register({ name: 'C', redirectTo: 'D' });
5863         * registry.register({ name: 'D' });
5864         *
5865         * let transitionA = $state.go('A').transition
5866         *
5867         * $transitions.onSuccess({ to: 'D' }, (trans) => {
5868         *   trans.to().name === 'D'; // true
5869         *   trans.redirectedFrom().to().name === 'C'; // true
5870         *   trans.originalTransition() === transitionA; // true
5871         *   trans.originalTransition().to().name === 'A'; // true
5872         * });
5873         * ```
5874         *
5875         * @returns The original Transition that started a redirect chain
5876         */
5877        Transition.prototype.originalTransition = function () {
5878            var rf = this.redirectedFrom();
5879            return (rf && rf.originalTransition()) || this;
5880        };
5881        /**
5882         * Get the transition options
5883         *
5884         * @returns the options for this Transition.
5885         */
5886        Transition.prototype.options = function () {
5887            return this._options;
5888        };
5889        /**
5890         * Gets the states being entered.
5891         *
5892         * @returns an array of states that will be entered during this transition.
5893         */
5894        Transition.prototype.entering = function () {
5895            return map(this._treeChanges.entering, prop('state')).map(stateSelf);
5896        };
5897        /**
5898         * Gets the states being exited.
5899         *
5900         * @returns an array of states that will be exited during this transition.
5901         */
5902        Transition.prototype.exiting = function () {
5903            return map(this._treeChanges.exiting, prop('state')).map(stateSelf).reverse();
5904        };
5905        /**
5906         * Gets the states being retained.
5907         *
5908         * @returns an array of states that are already entered from a previous Transition, that will not be
5909         *    exited during this Transition
5910         */
5911        Transition.prototype.retained = function () {
5912            return map(this._treeChanges.retained, prop('state')).map(stateSelf);
5913        };
5914        /**
5915         * Get the [[ViewConfig]]s associated with this Transition
5916         *
5917         * Each state can define one or more views (template/controller), which are encapsulated as `ViewConfig` objects.
5918         * This method fetches the `ViewConfigs` for a given path in the Transition (e.g., "to" or "entering").
5919         *
5920         * @param pathname the name of the path to fetch views for:
5921         *   (`'to'`, `'from'`, `'entering'`, `'exiting'`, `'retained'`)
5922         * @param state If provided, only returns the `ViewConfig`s for a single state in the path
5923         *
5924         * @returns a list of ViewConfig objects for the given path.
5925         */
5926        Transition.prototype.views = function (pathname, state) {
5927            if (pathname === void 0) { pathname = 'entering'; }
5928            var path = this._treeChanges[pathname];
5929            path = !state ? path : path.filter(propEq('state', state));
5930            return path.map(prop('views')).filter(identity).reduce(unnestR, []);
5931        };
5932        Transition.prototype.treeChanges = function (pathname) {
5933            return pathname ? this._treeChanges[pathname] : this._treeChanges;
5934        };
5935        /**
5936         * Creates a new transition that is a redirection of the current one.
5937         *
5938         * This transition can be returned from a [[TransitionService]] hook to
5939         * redirect a transition to a new state and/or set of parameters.
5940         *
5941         * @internal
5942         *
5943         * @returns Returns a new [[Transition]] instance.
5944         */
5945        Transition.prototype.redirect = function (targetState) {
5946            var redirects = 1, trans = this;
5947            // tslint:disable-next-line:no-conditional-assignment
5948            while ((trans = trans.redirectedFrom()) != null) {
5949                if (++redirects > 20)
5950                    throw new Error("Too many consecutive Transition redirects (20+)");
5951            }
5952            var redirectOpts = { redirectedFrom: this, source: 'redirect' };
5953            // If the original transition was caused by URL sync, then use { location: 'replace' }
5954            // on the new transition (unless the target state explicitly specifies location: false).
5955            // This causes the original url to be replaced with the url for the redirect target
5956            // so the original url disappears from the browser history.
5957            if (this.options().source === 'url' && targetState.options().location !== false) {
5958                redirectOpts.location = 'replace';
5959            }
5960            var newOptions = extend({}, this.options(), targetState.options(), redirectOpts);
5961            targetState = targetState.withOptions(newOptions, true);
5962            var newTransition = this.router.transitionService.create(this._treeChanges.from, targetState);
5963            var originalEnteringNodes = this._treeChanges.entering;
5964            var redirectEnteringNodes = newTransition._treeChanges.entering;
5965            // --- Re-use resolve data from original transition ---
5966            // When redirecting from a parent state to a child state where the parent parameter values haven't changed
5967            // (because of the redirect), the resolves fetched by the original transition are still valid in the
5968            // redirected transition.
5969            //
5970            // This allows you to define a redirect on a parent state which depends on an async resolve value.
5971            // You can wait for the resolve, then redirect to a child state based on the result.
5972            // The redirected transition does not have to re-fetch the resolve.
5973            // ---------------------------------------------------------
5974            var nodeIsReloading = function (reloadState) { return function (node) {
5975                return reloadState && node.state.includes[reloadState.name];
5976            }; };
5977            // Find any "entering" nodes in the redirect path that match the original path and aren't being reloaded
5978            var matchingEnteringNodes = PathUtils.matching(redirectEnteringNodes, originalEnteringNodes, PathUtils.nonDynamicParams).filter(not(nodeIsReloading(targetState.options().reloadState)));
5979            // Use the existing (possibly pre-resolved) resolvables for the matching entering nodes.
5980            matchingEnteringNodes.forEach(function (node, idx) {
5981                node.resolvables = originalEnteringNodes[idx].resolvables;
5982            });
5983            return newTransition;
5984        };
5985        /** @internal If a transition doesn't exit/enter any states, returns any [[Param]] whose value changed */
5986        Transition.prototype._changedParams = function () {
5987            var tc = this._treeChanges;
5988            /** Return undefined if it's not a "dynamic" transition, for the following reasons */
5989            // If user explicitly wants a reload
5990            if (this._options.reload)
5991                return undefined;
5992            // If any states are exiting or entering
5993            if (tc.exiting.length || tc.entering.length)
5994                return undefined;
5995            // If to/from path lengths differ
5996            if (tc.to.length !== tc.from.length)
5997                return undefined;
5998            // If the to/from paths are different
5999            var pathsDiffer = arrayTuples(tc.to, tc.from)
6000                .map(function (tuple) { return tuple[0].state !== tuple[1].state; })
6001                .reduce(anyTrueR, false);
6002            if (pathsDiffer)
6003                return undefined;
6004            // Find any parameter values that differ
6005            var nodeSchemas = tc.to.map(function (node) { return node.paramSchema; });
6006            var _a = [tc.to, tc.from].map(function (path) { return path.map(function (x) { return x.paramValues; }); }), toValues = _a[0], fromValues = _a[1];
6007            var tuples = arrayTuples(nodeSchemas, toValues, fromValues);
6008            return tuples.map(function (_a) {
6009                var schema = _a[0], toVals = _a[1], fromVals = _a[2];
6010                return Param.changed(schema, toVals, fromVals);
6011            }).reduce(unnestR, []);
6012        };
6013        /**
6014         * Returns true if the transition is dynamic.
6015         *
6016         * A transition is dynamic if no states are entered nor exited, but at least one dynamic parameter has changed.
6017         *
6018         * @returns true if the Transition is dynamic
6019         */
6020        Transition.prototype.dynamic = function () {
6021            var changes = this._changedParams();
6022            return !changes ? false : changes.map(function (x) { return x.dynamic; }).reduce(anyTrueR, false);
6023        };
6024        /**
6025         * Returns true if the transition is ignored.
6026         *
6027         * A transition is ignored if no states are entered nor exited, and no parameter values have changed.
6028         *
6029         * @returns true if the Transition is ignored.
6030         */
6031        Transition.prototype.ignored = function () {
6032            return !!this._ignoredReason();
6033        };
6034        /** @internal */
6035        Transition.prototype._ignoredReason = function () {
6036            var pending = this.router.globals.transition;
6037            var reloadState = this._options.reloadState;
6038            var same = function (pathA, pathB) {
6039                if (pathA.length !== pathB.length)
6040                    return false;
6041                var matching = PathUtils.matching(pathA, pathB);
6042                return pathA.length === matching.filter(function (node) { return !reloadState || !node.state.includes[reloadState.name]; }).length;
6043            };
6044            var newTC = this.treeChanges();
6045            var pendTC = pending && pending.treeChanges();
6046            if (pendTC && same(pendTC.to, newTC.to) && same(pendTC.exiting, newTC.exiting))
6047                return 'SameAsPending';
6048            if (newTC.exiting.length === 0 && newTC.entering.length === 0 && same(newTC.from, newTC.to))
6049                return 'SameAsCurrent';
6050        };
6051        /**
6052         * Runs the transition
6053         *
6054         * This method is generally called from the [[StateService.transitionTo]]
6055         *
6056         * @internal
6057         *
6058         * @returns a promise for a successful transition.
6059         */
6060        Transition.prototype.run = function () {
6061            var _this = this;
6062            var runAllHooks = TransitionHook.runAllHooks;
6063            // Gets transition hooks array for the given phase
6064            var getHooksFor = function (phase) { return _this._hookBuilder.buildHooksForPhase(phase); };
6065            // When the chain is complete, then resolve or reject the deferred
6066            var transitionSuccess = function () {
6067                trace.traceSuccess(_this.$to(), _this);
6068                _this.success = true;
6069                _this._deferred.resolve(_this.to());
6070                runAllHooks(getHooksFor(exports.TransitionHookPhase.SUCCESS));
6071            };
6072            var transitionError = function (reason) {
6073                trace.traceError(reason, _this);
6074                _this.success = false;
6075                _this._deferred.reject(reason);
6076                _this._error = reason;
6077                runAllHooks(getHooksFor(exports.TransitionHookPhase.ERROR));
6078            };
6079            var runTransition = function () {
6080                // Wait to build the RUN hook chain until the BEFORE hooks are done
6081                // This allows a BEFORE hook to dynamically add additional RUN hooks via the Transition object.
6082                var allRunHooks = getHooksFor(exports.TransitionHookPhase.RUN);
6083                var done = function () { return services.$q.when(undefined); };
6084                return TransitionHook.invokeHooks(allRunHooks, done);
6085            };
6086            var startTransition = function () {
6087                var globals = _this.router.globals;
6088                globals.lastStartedTransitionId = _this.$id;
6089                globals.transition = _this;
6090                globals.transitionHistory.enqueue(_this);
6091                trace.traceTransitionStart(_this);
6092                return services.$q.when(undefined);
6093            };
6094            var allBeforeHooks = getHooksFor(exports.TransitionHookPhase.BEFORE);
6095            TransitionHook.invokeHooks(allBeforeHooks, startTransition)
6096                .then(runTransition)
6097                .then(transitionSuccess, transitionError);
6098            return this.promise;
6099        };
6100        /**
6101         * Checks if the Transition is valid
6102         *
6103         * @returns true if the Transition is valid
6104         */
6105        Transition.prototype.valid = function () {
6106            return !this.error() || this.success !== undefined;
6107        };
6108        /**
6109         * Aborts this transition
6110         *
6111         * Imperative API to abort a Transition.
6112         * This only applies to Transitions that are not yet complete.
6113         */
6114        Transition.prototype.abort = function () {
6115            // Do not set flag if the transition is already complete
6116            if (isUndefined(this.success)) {
6117                this._aborted = true;
6118            }
6119        };
6120        /**
6121         * The Transition error reason.
6122         *
6123         * If the transition is invalid (and could not be run), returns the reason the transition is invalid.
6124         * If the transition was valid and ran, but was not successful, returns the reason the transition failed.
6125         *
6126         * @returns a transition rejection explaining why the transition is invalid, or the reason the transition failed.
6127         */
6128        Transition.prototype.error = function () {
6129            var state = this.$to();
6130            if (state.self.abstract) {
6131                return Rejection.invalid("Cannot transition to abstract state '" + state.name + "'");
6132            }
6133            var paramDefs = state.parameters();
6134            var values = this.params();
6135            var invalidParams = paramDefs.filter(function (param) { return !param.validates(values[param.id]); });
6136            if (invalidParams.length) {
6137                var invalidValues = invalidParams.map(function (param) { return "[" + param.id + ":" + stringify(values[param.id]) + "]"; }).join(', ');
6138                var detail = "The following parameter values are not valid for state '" + state.name + "': " + invalidValues;
6139                return Rejection.invalid(detail);
6140            }
6141            if (this.success === false)
6142                return this._error;
6143        };
6144        /**
6145         * A string representation of the Transition
6146         *
6147         * @returns A string representation of the Transition
6148         */
6149        Transition.prototype.toString = function () {
6150            var fromStateOrName = this.from();
6151            var toStateOrName = this.to();
6152            var avoidEmptyHash = function (params) {
6153                return params['#'] !== null && params['#'] !== undefined ? params : omit(params, ['#']);
6154            };
6155            // (X) means the to state is invalid.
6156            var id = this.$id, from = isObject(fromStateOrName) ? fromStateOrName.name : fromStateOrName, fromParams = stringify(avoidEmptyHash(this._treeChanges.from.map(prop('paramValues')).reduce(mergeR, {}))), toValid = this.valid() ? '' : '(X) ', to = isObject(toStateOrName) ? toStateOrName.name : toStateOrName, toParams = stringify(avoidEmptyHash(this.params()));
6157            return "Transition#" + id + "( '" + from + "'" + fromParams + " -> " + toValid + "'" + to + "'" + toParams + " )";
6158        };
6159        /** @internal */
6160        Transition.diToken = Transition;
6161        return Transition;
6162    }());
6163
6164    function quoteRegExp(str, param) {
6165        var surroundPattern = ['', ''], result = str.replace(/[\\\[\]\^$*+?.()|{}]/g, '\\$&');
6166        if (!param)
6167            return result;
6168        switch (param.squash) {
6169            case false:
6170                surroundPattern = ['(', ')' + (param.isOptional ? '?' : '')];
6171                break;
6172            case true:
6173                result = result.replace(/\/$/, '');
6174                surroundPattern = ['(?:/(', ')|/)?'];
6175                break;
6176            default:
6177                surroundPattern = ["(" + param.squash + "|", ')?'];
6178                break;
6179        }
6180        return result + surroundPattern[0] + param.type.pattern.source + surroundPattern[1];
6181    }
6182    var memoizeTo = function (obj, _prop, fn) { return (obj[_prop] = obj[_prop] || fn()); };
6183    var splitOnSlash = splitOnDelim('/');
6184    var defaultConfig = {
6185        state: { params: {} },
6186        strict: true,
6187        caseInsensitive: true,
6188        decodeParams: true,
6189    };
6190    /**
6191     * Matches URLs against patterns.
6192     *
6193     * Matches URLs against patterns and extracts named parameters from the path or the search
6194     * part of the URL.
6195     *
6196     * A URL pattern consists of a path pattern, optionally followed by '?' and a list of search (query)
6197     * parameters. Multiple search parameter names are separated by '&'. Search parameters
6198     * do not influence whether or not a URL is matched, but their values are passed through into
6199     * the matched parameters returned by [[UrlMatcher.exec]].
6200     *
6201     * - *Path parameters* are defined using curly brace placeholders (`/somepath/{param}`)
6202     * or colon placeholders (`/somePath/:param`).
6203     *
6204     * - *A parameter RegExp* may be defined for a param after a colon
6205     * (`/somePath/{param:[a-zA-Z0-9]+}`) in a curly brace placeholder.
6206     * The regexp must match for the url to be matched.
6207     * Should the regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.
6208     *
6209     * Note: a RegExp parameter will encode its value using either [[ParamTypes.path]] or [[ParamTypes.query]].
6210     *
6211     * - *Custom parameter types* may also be specified after a colon (`/somePath/{param:int}`) in curly brace parameters.
6212     *   See [[UrlMatcherFactory.type]] for more information.
6213     *
6214     * - *Catch-all parameters* are defined using an asterisk placeholder (`/somepath/*catchallparam`).
6215     *   A catch-all * parameter value will contain the remainder of the URL.
6216     *
6217     * ---
6218     *
6219     * Parameter names may contain only word characters (latin letters, digits, and underscore) and
6220     * must be unique within the pattern (across both path and search parameters).
6221     * A path parameter matches any number of characters other than '/'. For catch-all
6222     * placeholders the path parameter matches any number of characters.
6223     *
6224     * Examples:
6225     *
6226     * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for
6227     *   trailing slashes, and patterns have to match the entire path, not just a prefix.
6228     * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
6229     *   '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
6230     * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.
6231     * * `'/user/{id:[^/]*}'` - Same as the previous example.
6232     * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id
6233     *   parameter consists of 1 to 8 hex digits.
6234     * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the
6235     *   path into the parameter 'path'.
6236     * * `'/files/*path'` - ditto.
6237     * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined
6238     *   in the built-in  `date` ParamType matches `2014-11-12`) and provides a Date object in $stateParams.start
6239     *
6240     */
6241    var UrlMatcher = /** @class */ (function () {
6242        /**
6243         * @param pattern The pattern to compile into a matcher.
6244         * @param paramTypes The [[ParamTypes]] registry
6245         * @param paramFactory A [[ParamFactory]] object
6246         * @param config  A [[UrlMatcherCompileConfig]] configuration object
6247         */
6248        function UrlMatcher(pattern, paramTypes, paramFactory, config) {
6249            var _this = this;
6250            /** @internal */
6251            this._cache = { path: [this] };
6252            /** @internal */
6253            this._children = [];
6254            /** @internal */
6255            this._params = [];
6256            /** @internal */
6257            this._segments = [];
6258            /** @internal */
6259            this._compiled = [];
6260            this.config = config = defaults(config, defaultConfig);
6261            this.pattern = pattern;
6262            // Find all placeholders and create a compiled pattern, using either classic or curly syntax:
6263            //   '*' name
6264            //   ':' name
6265            //   '{' name '}'
6266            //   '{' name ':' regexp '}'
6267            // The regular expression is somewhat complicated due to the need to allow curly braces
6268            // inside the regular expression. The placeholder regexp breaks down as follows:
6269            //    ([:*])([\w\[\]]+)              - classic placeholder ($1 / $2) (search version has - for snake-case)
6270            //    \{([\w\[\]]+)(?:\:\s*( ... ))?\}  - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case
6271            //    (?: ... | ... | ... )+         - the regexp consists of any number of atoms, an atom being either
6272            //    [^{}\\]+                       - anything other than curly braces or backslash
6273            //    \\.                            - a backslash escape
6274            //    \{(?:[^{}\\]+|\\.)*\}          - a matched set of curly braces containing other atoms
6275            var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g;
6276            var searchPlaceholder = /([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g;
6277            var patterns = [];
6278            var last = 0;
6279            var matchArray;
6280            var checkParamErrors = function (id) {
6281                if (!UrlMatcher.nameValidator.test(id))
6282                    throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
6283                if (find(_this._params, propEq('id', id)))
6284                    throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
6285            };
6286            // Split into static segments separated by path parameter placeholders.
6287            // The number of segments is always 1 more than the number of parameters.
6288            var matchDetails = function (m, isSearch) {
6289                // IE[78] returns '' for unmatched groups instead of null
6290                var id = m[2] || m[3];
6291                var regexp = isSearch ? m[4] : m[4] || (m[1] === '*' ? '[\\s\\S]*' : null);
6292                var makeRegexpType = function (str) {
6293                    return inherit(paramTypes.type(isSearch ? 'query' : 'path'), {
6294                        pattern: new RegExp(str, _this.config.caseInsensitive ? 'i' : undefined),
6295                    });
6296                };
6297                return {
6298                    id: id,
6299                    regexp: regexp,
6300                    segment: pattern.substring(last, m.index),
6301                    type: !regexp ? null : paramTypes.type(regexp) || makeRegexpType(regexp),
6302                };
6303            };
6304            var details;
6305            var segment;
6306            // tslint:disable-next-line:no-conditional-assignment
6307            while ((matchArray = placeholder.exec(pattern))) {
6308                details = matchDetails(matchArray, false);
6309                if (details.segment.indexOf('?') >= 0)
6310                    break; // we're into the search part
6311                checkParamErrors(details.id);
6312                this._params.push(paramFactory.fromPath(details.id, details.type, config.state));
6313                this._segments.push(details.segment);
6314                patterns.push([details.segment, tail(this._params)]);
6315                last = placeholder.lastIndex;
6316            }
6317            segment = pattern.substring(last);
6318            // Find any search parameter names and remove them from the last segment
6319            var i = segment.indexOf('?');
6320            if (i >= 0) {
6321                var search = segment.substring(i);
6322                segment = segment.substring(0, i);
6323                if (search.length > 0) {
6324                    last = 0;
6325                    // tslint:disable-next-line:no-conditional-assignment
6326                    while ((matchArray = searchPlaceholder.exec(search))) {
6327                        details = matchDetails(matchArray, true);
6328                        checkParamErrors(details.id);
6329                        this._params.push(paramFactory.fromSearch(details.id, details.type, config.state));
6330                        last = placeholder.lastIndex;
6331                        // check if ?&
6332                    }
6333                }
6334            }
6335            this._segments.push(segment);
6336            this._compiled = patterns.map(function (_pattern) { return quoteRegExp.apply(null, _pattern); }).concat(quoteRegExp(segment));
6337        }
6338        /** @internal */
6339        UrlMatcher.encodeDashes = function (str) {
6340            // Replace dashes with encoded "\-"
6341            return encodeURIComponent(str).replace(/-/g, function (c) { return "%5C%" + c.charCodeAt(0).toString(16).toUpperCase(); });
6342        };
6343        /** @internal Given a matcher, return an array with the matcher's path segments and path params, in order */
6344        UrlMatcher.pathSegmentsAndParams = function (matcher) {
6345            var staticSegments = matcher._segments;
6346            var pathParams = matcher._params.filter(function (p) { return p.location === exports.DefType.PATH; });
6347            return arrayTuples(staticSegments, pathParams.concat(undefined))
6348                .reduce(unnestR, [])
6349                .filter(function (x) { return x !== '' && isDefined(x); });
6350        };
6351        /** @internal Given a matcher, return an array with the matcher's query params */
6352        UrlMatcher.queryParams = function (matcher) {
6353            return matcher._params.filter(function (p) { return p.location === exports.DefType.SEARCH; });
6354        };
6355        /**
6356         * Compare two UrlMatchers
6357         *
6358         * This comparison function converts a UrlMatcher into static and dynamic path segments.
6359         * Each static path segment is a static string between a path separator (slash character).
6360         * Each dynamic segment is a path parameter.
6361         *
6362         * The comparison function sorts static segments before dynamic ones.
6363         */
6364        UrlMatcher.compare = function (a, b) {
6365            /**
6366             * Turn a UrlMatcher and all its parent matchers into an array
6367             * of slash literals '/', string literals, and Param objects
6368             *
6369             * This example matcher matches strings like "/foo/:param/tail":
6370             * var matcher = $umf.compile("/foo").append($umf.compile("/:param")).append($umf.compile("/")).append($umf.compile("tail"));
6371             * var result = segments(matcher); // [ '/', 'foo', '/', Param, '/', 'tail' ]
6372             *
6373             * Caches the result as `matcher._cache.segments`
6374             */
6375            var segments = function (matcher) {
6376                return (matcher._cache.segments =
6377                    matcher._cache.segments ||
6378                        matcher._cache.path
6379                            .map(UrlMatcher.pathSegmentsAndParams)
6380                            .reduce(unnestR, [])
6381                            .reduce(joinNeighborsR, [])
6382                            .map(function (x) { return (isString(x) ? splitOnSlash(x) : x); })
6383                            .reduce(unnestR, []));
6384            };
6385            /**
6386             * Gets the sort weight for each segment of a UrlMatcher
6387             *
6388             * Caches the result as `matcher._cache.weights`
6389             */
6390            var weights = function (matcher) {
6391                return (matcher._cache.weights =
6392                    matcher._cache.weights ||
6393                        segments(matcher).map(function (segment) {
6394                            // Sort slashes first, then static strings, the Param
6394s
6395                            if (segment === '/')
6396                                return 1;
6397                            if (isString(segment))
6398                                return 2;
6399                            if (segment instanceof Param)
6400                                return 3;
6401                        }));
6402            };
6403            /**
6404             * Pads shorter array in-place (mutates)
6405             */
6406            var padArrays = function (l, r, padVal) {
6407                var len = Math.max(l.length, r.length);
6408                while (l.length < len)
6409                    l.push(padVal);
6410                while (r.length < len)
6411                    r.push(padVal);
6412            };
6413            var weightsA = weights(a), weightsB = weights(b);
6414            padArrays(weightsA, weightsB, 0);
6415            var _pairs = arrayTuples(weightsA, weightsB);
6416            var cmp, i;
6417            for (i = 0; i < _pairs.length; i++) {
6418                cmp = _pairs[i][0] - _pairs[i][1];
6419                if (cmp !== 0)
6420                    return cmp;
6421            }
6422            return 0;
6423        };
6424        /**
6425         * Creates a new concatenated UrlMatcher
6426         *
6427         * Builds a new UrlMatcher by appending another UrlMatcher to this one.
6428         *
6429         * @param url A `UrlMatcher` instance to append as a child of the current `UrlMatcher`.
6430         */
6431        UrlMatcher.prototype.append = function (url) {
6432            this._children.push(url);
6433            url._cache = {
6434                path: this._cache.path.concat(url),
6435                parent: this,
6436                pattern: null,
6437            };
6438            return url;
6439        };
6440        /** @internal */
6441        UrlMatcher.prototype.isRoot = function () {
6442            return this._cache.path[0] === this;
6443        };
6444        /** Returns the input pattern string */
6445        UrlMatcher.prototype.toString = function () {
6446            return this.pattern;
6447        };
6448        UrlMatcher.prototype._getDecodedParamValue = function (value, param) {
6449            if (isDefined(value)) {
6450                if (this.config.decodeParams && !param.type.raw) {
6451                    if (isArray(value)) {
6452                        value = value.map(function (paramValue) { return decodeURIComponent(paramValue); });
6453                    }
6454                    else {
6455                        value = decodeURIComponent(value);
6456                    }
6457                }
6458                value = param.type.decode(value);
6459            }
6460            return param.value(value);
6461        };
6462        /**
6463         * Tests the specified url/path against this matcher.
6464         *
6465         * Tests if the given url matches this matcher's pattern, and returns an object c
6465ontaining the captured
6466         * parameter values.  Returns null if the path does not match.
6467         *
6468         * The returned object contains the values
6469         * of any search parameters that are mentioned in the pattern, but their value may be null if
6470         * they are not present in `search`. This means that search parameters are always treated
6471         * as optional.
6472         *
6473         * #### Example:
6474         * ```js
6475         * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
6476         *   x: '1', q: 'hello'
6477         * });
6478         * // returns { id: 'bob', q: 'hello', r: null }
6479         * ```
6480         *
6481         * @param path    The URL path to match, e.g. `$location.path()`.
6482         * @param search  URL search parameters, e.g. `$location.search()`.
6483         * @param hash    URL hash e.g. `$location.hash()`.
6484         * @param options
6485         *
6486         * @returns The captured parameter values.
6487         */
6488        UrlMatcher.prototype.exec = function (path, search, hash, options) {
6489            var _this = this;
6490            if (search === void 0) { search = {}; }
6491            var match = memoizeTo(this._cache, 'pattern', function () {
6492                return new RegExp([
6493                    '^',
6494                    unnest(_this._cache.path.map(prop('_compiled'))).join(''),
6495                    _this.config.strict === false ? '/?' : '',
6496                    '$',
6497                ].join(''), _this.config.caseInsensitive ? 'i' : undefined);
6498            }).exec(path);
6499            if (!match)
6500                return null;
6501            // options = defaults(options, { isolate: false });
6502            var allParams = this.parameters(), pathParams = allParams.filter(function (param) { return !param.isSearch(); }), searchParams = allParams.filter(function (param) { return param.isSearch(); }), nPathSegments = this._cache.path.map(function (urlm) { return urlm._segments.length - 1; }).reduce(function (a, x) { return a + x; }), values = {};
6503            if (nPathSegments !== match.length - 1)
6504                throw new Error("Unbalanced capture group in route '" + this.pattern + "'");
6505            function decodePathArray(paramVal) {
6506                var reverseString = function (str) { return str.split('').reverse().join(''); };
6507                var unquoteDashes = function (str) { return str.replace(/\\-/g, '-'); };
6508                var split = reverseString(paramVal).split(/-(?!\\)/);
6509                var allReversed = map(split, reverseString);
6510                return map(allReversed, unquoteDashes).reverse();
6511            }
6512            for (var i = 0; i < nPathSegments; i++) {
6513                var param = pathParams[i];
6514                var value = match[i + 1];
6515                // if the param value matches a pre-replace pair, replace the value before decoding.
6516                for (var j = 0; j < param.replace.length; j++) {
6517                    if (param.replace[j].from === value)
6518                        value = param.replace[j].to;
6519                }
6520                if (value && param.array === true)
6521                    value = decodePathArray(value);
6522                values[param.id] = this._getDecodedParamValue(value, param);
6523            }
6524            searchParams.forEach(function (param) {
6525                var value = search[param.id];
6526                for (var j = 0; j < param.replace.length; j++) {
6527                    if (param.replace[j].from === value)
6528                        value = param.replace[j].to;
6529                }
6530                values[param.id] = _this._getDecodedParamValue(value, param);
6531            });
6532            if (hash)
6533                values['#'] = hash;
6534            return values;
6535        };
6536        /**
6537         * @internal
6538         * Returns all the [[Param]] objects of all path and search parameters of this pattern in order of appearance.
6539         *
6540         * @returns {Array.<Param>}  An array of [[Param]] objects. Must be treated as read-only. If the
6541         *    pattern has no parameters, an empty array is returned.
6542         */
6543        UrlMatcher.prototype.parameters = function (opts) {
6544            if (opts === void 0) { opts = {}; }
6545            if (opts.inherit === false)
6546                return this._params;
6547            return unnest(this._cache.path.map(function (matcher) { return matcher._params; }));
6548        };
6549        /**
6550         * @internal
6551         * Returns a single parameter from this UrlMatcher by id
6552         *
6553         * @param id
6554         * @param opts
6555         * @returns {T|Param|any|boolean|UrlMatcher|null}
6556         */
6557        UrlMatcher.prototype.parameter = function (id, opts) {
6558            var _this = this;
6559            if (opts === void 0) { opts = {}; }
6560            var findParam = function () {
6561                for (var _i = 0, _a = _this._params; _i < _a.length; _i++) {
6562                    var param = _a[_i];
6563                    if (param.id === id)
6564                        return param;
6565                }
6566            };
6567            var parent = this._cache.parent;
6568            return findParam() || (opts.inherit !== false && parent && parent.parameter(id, opts)) || null;
6569        };
6570        /**
6571         * Validates the input parameter values against this UrlMatcher
6572         *
6573         * Checks an object hash of parameters to validate their correctness according to the parameter
6574         * types of this `UrlMatcher`.
6575         *
6576         * @param params The object hash of parameters to validate.
6577         * @returns Returns `true` if `params` validates, otherwise `false`.
6578         */
6579        UrlMatcher.prototype.validates = function (params) {
6580            var validParamVal = function (param, val) { return !param || param.validates(val); };
6581            params = params || {};
6582            // I'm not sure why this checks only the param keys passed in, and not all the params known to the matcher
6583            var paramSchema = this.parameters().filter(function (paramDef) { return params.hasOwnProperty(paramDef.id); });
6584            return paramSchema.map(function (paramDef) { return validParamVal(paramDef, params[paramDef.id]); }).reduce(allTrueR, true);
6585        };
6586        /**
6587         * Given a set of parameter values, creates a URL from this UrlMatcher.
6588         *
6589         * Creates a URL that matches this pattern by substituting the specified values
6590         * for the path and search parameters.
6591         *
6592         * #### Example:
6593         * ```js
6594         * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
6595         * // returns '/user/bob?q=yes'
6596         * ```
6597         *
6598         * @param values  the values to substitute for the parameters in this pattern.
6599         * @returns the formatted URL (path and optionally search part).
6600         */
6601        UrlMatcher.prototype.format = function (values) {
6602            if (values === void 0) { values = {}; }
6603            // Build the full path of UrlMatchers (including all parent UrlMatchers)
6604            var urlMatchers = this._cache.path;
6605            // Extract all the static segments and Params (processed as ParamDetails)
6606            // into an ordered array
6607            var pathSegmentsAndParams = urlMatchers
6608                .map(UrlMatcher.pathSegmentsAndParams)
6609                .reduce(unnestR, [])
6610                .map(function (x) { return (isString(x) ? x : getDetails(x)); });
6611            // Extract the query params into a separate array
6612            var queryParams = urlMatchers
6613                .map(UrlMatcher.queryParams)
6614                .reduce(unnestR, [])
6615                .map(getDetails);
6616            var isInvalid = function (param) { return param.isValid === false; };
6617            if (pathSegmentsAndParams.concat(queryParams).filter(isInvalid).length) {
6618                return null;
6619            }
6620            /**
6621             * Given a Param, applies the parameter value, then returns detailed information about it
6622             */
6623            function getDetails(param) {
6624                // Normalize to typed value
6625                var value = param.value(values[param.id]);
6626                var isValid = param.validates(value);
6627                var isDefaultValue = param.isDefaultValue(value);
6628                // Check if we're in squash mode for the parameter
6629                var squash = isDefaultValue ? param.squash : false;
6630                // Allow the Parameter's Type to encode the value
6631                var encoded = param.type.encode(value);
6632                return { param: param, value: value, isValid: isValid, isDefaultValue: isDefaultValue, squash: squash, encoded: encoded };
6633            }
6634            // Build up the path-portion from the list of static segments and parameters
6635            var pathString = pathSegmentsAndParams.reduce(function (acc, x) {
6636                // The element is a static segment (a raw string); just append it
6637                if (isString(x))
6638                    return acc + x;
6639                // Otherwise, it's a ParamDetails.
6640                var squash = x.squash, encoded = x.encoded, param = x.param;
6641                // If squash is === true, try to remove a slash from the path
6642                if (squash === true)
6643                    return acc.match(/\/$/) ? acc.slice(0, -1) : acc;
6644                // If squash is a string, use the string for the param value
6645                if (isString(squash))
6646                    return acc + squash;
6647                if (squash !== false)
6648                    return acc; // ?
6649                if (encoded == null)
6650                    return acc;
6651                // If this parameter value is an array, encode the value using encodeDashes
6652                if (isArray(encoded))
6653                    return acc + map(encoded, UrlMatcher.encodeDashes).join('-');
6654                // If the parameter type is "raw", then do not encodeURIComponent
6655                if (param.raw)
6656                    return acc + encoded;
6657                // Encode the value
6658                return acc + encodeURIComponent(encoded);
6659            }, '');
6660            // Build the query string by applying parameter values (array or regular)
6661            // then mapping to key=value, then flattening and joining using "&"
6662            var queryString = queryParams
6663                .map(function (paramDetails) {
6664                var param = paramDetails.param, squash = paramDetails.squash, encoded = paramDetails.encoded, isDefaultValue = paramDetails.isDefaultValue;
6665                if (encoded == null || (isDefaultValue && squash !== false))
6666                    return;
6667                if (!isArray(encoded))
6668                    encoded = [encoded];
6669                if (encoded.length === 0)
6670                    return;
6671                if (!param.raw)
6672                    encoded = map(encoded, encodeURIComponent);
6673                return encoded.map(function (val) { return param.id + "=" + val; });
6674            })
6675                .filter(identity)
6676                .reduce(unnestR, [])
6677                .join('&');
6678            // Concat the pathstring with the queryString (if exists) and the hashString (if exists)
6679            return pathString + (queryString ? "?" + queryString : '') + (values['#'] ? '#' + values['#'] : '');
6680        };
6681        /** @internal */
6682        UrlMatcher.nameValidator = /^\w+([-.]+\w+)*(?:\[\])?$/;
6683        return UrlMatcher;
6684    }());
6685
6686    var __assign = (undefined && undefined.__assign) || function () {
6687        __assign = Object.assign || function(t) {
6688            for (var s, i = 1, n = arguments.length; i < n; i++) {
6689                s = arguments[i];
6690                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6691                    t[p] = s[p];
6692            }
6693            return t;
6694        };
6695        return __assign.apply(this, arguments);
6696    };
6697    var ParamFactory = /** @class */ (function () {
6698        function ParamFactory(router) {
6699            this.router = router;
6700        }
6701        ParamFactory.prototype.fromConfig = function (id, type, state) {
6702            return new Param(id, type, exports.DefType.CONFIG, this.router.urlService.config, state);
6703        };
6704        ParamFactory.prototype.fromPath = function (id, type, state) {
6705            return new Param(id, type, exports.DefType.PATH, this.router.urlService.config, state);
6706        };
6707        ParamFactory.prototype.fromSearch = function (id, type, state) {
6708            return new Param(id, type, exports.DefType.SEARCH, this.router.urlService.config, state);
6709        };
6710        return ParamFactory;
6711    }());
6712    /**
6713     * Factory for [[UrlMatcher]] instances.
6714     *
6715     * The factory is available to ng1 services as
6716     * `$urlMatcherFactory` or ng1 providers as `$urlMatcherFactoryProvi
6716der`.
6717     */
6718    var UrlMatcherFactory = /** @class */ (function () {
6719        // TODO: move implementations to UrlConfig (urlService.config)
6720        function UrlMatcherFactory(/** @internal */ router) {
6721            var _this = this;
6722            this.router = router;
6723            /** Creates a new [[Param]] for a given location (DefType) */
6724            this.paramFactory = new ParamFactory(this.router);
6725            // TODO: Check if removal of this will break anything, then remove these
6726            this.UrlMatcher = UrlMatcher;
6727            this.Param = Param;
6728            /** @deprecated use [[UrlConfig.caseInsensitive]] */
6729            this.caseInsensitive = function (value) { return _this.router.urlService.config.caseInsensitive(value); };
6730            /** @deprecated use [[UrlConfig.defaultSquashPolicy]] */
6731            this.defaultSquashPolicy = function (value) { return _this.router.urlService.config.defaultSquashPolicy(value); };
6732            /** @deprecated use [[UrlConfig.strictMode]] */
6733            this.strictMode = function (value) { return _this.router.urlService.config.strictMode(value); };
6734            /** @deprecated use [[UrlConfig.type]] */
6735            this.type = function (name, definition, definitionFn) {
6736                return _this.router.urlService.config.type(name, definition, definitionFn) || _this;
6737            };
6738        }
6739        /**
6740         * Creates a [[UrlMatcher]] for the specified pattern.
6741         *
6742         * @param pattern  The URL pattern.
6743         * @param config  The config object hash.
6744         * @returns The UrlMatcher.
6745         */
6746        UrlMatcherFactory.prototype.compile = function (pattern, config) {
6747            var urlConfig = this.router.urlService.config;
6748            // backward-compatible support for config.params -> config.state.params
6749            var params = config && !config.state && config.params;
6750            config = params ? __assign({ state: { params: params } }, config) : config;
6751            var globalConfig = {
6752                strict: urlConfig._isStrictMode,
6753                caseInsensitive: urlConfig._isCaseInsensitive,
6754                decodeParams: urlConfig._decodeParams,
6755            };
6756            return new UrlMatcher(pattern, urlConfig.paramTypes, this.paramFactory, extend(globalConfig, config));
6757        };
6758        /**
6759         * Returns true if the specified object is a [[UrlMatcher]], or false otherwise.
6760         *
6761         * @param object  The object to perform the type check against.
6762         * @returns `true` if the object matches the `UrlMatcher` interface, by
6763         *          implementing all the same methods.
6764         */
6765        UrlMatcherFactory.prototype.isMatcher = function (object) {
6766            // TODO: typeof?
6767            if (!isObject(object))
6768                return false;
6769            var result = true;
6770            forEach(UrlMatcher.prototype, function (val, name) {
6771                if (isFunction(val))
6772                    result = result && isDefined(object[name]) && isFunction(object[name]);
6773            });
6774            return result;
6775        };
6776        /** @internal */
6777        UrlMatcherFactory.prototype.$get = function () {
6778            var urlConfig = this.router.urlService.config;
6779            urlConfig.paramTypes.enqueue = false;
6780            urlConfig.paramTypes._flushTypeQueue();
6781            return this;
6782        };
6783        return UrlMatcherFactory;
6784    }());
6785
6786    /**
6787     * Creates a [[UrlRule]]
6788     *
6789     * Creates a [[UrlRule]] from a:
6790     *
6791     * - `string`
6792     * - [[UrlMatcher]]
6793     * - `RegExp`
6794     * - [[StateObject]]
6795     */
6796    var UrlRuleFactory = /** @class */ (function () {
6797        function UrlRuleFactory(router) {
6798            this.router = router;
6799        }
6800        UrlRuleFactory.prototype.compile = function (str) {
6801            return this.router.urlMatcherFactory.compile(str);
6802        };
6803        UrlRuleFactory.prototype.create = function (what, handler) {
6804            var _this = this;
6805            var isState = StateObject.isState, isStateDeclaration = StateObject.isStateDeclaration;
6806            var makeRule = pattern([
6807                [isString, function (_what) { return makeRule(_this.compile(_what)); }],
6808                [is(UrlMatcher), function (_what) { return _this.fromUrlMatcher(_what, handler); }],
6809                [or(isState, isStateDeclaration), function (_what) { return _this.fromState(_what, _this.router); }],
6810                [is(RegExp), function (_what) { return _this.fromRegExp(_what, handler); }],
6811                [isFunction, function (_what) { return new BaseUrlRule(_what, handler); }],
6812            ]);
6813            var rule = makeRule(what);
6814            if (!rule)
6815                throw new Error("invalid 'what' in when()");
6816            return rule;
6817        };
6818        /**
6819         * A UrlRule which matches based on a UrlMatcher
6820         *
6821         * The `handler` may be either a `string`, a [[UrlRuleHandlerFn]] or another [[UrlMatcher]]
6822         *
6823         * ## Handler as a function
6824         *
6825         * If `handler` is a function, the function is invoked with:
6826         *
6827         * - matched parameter values ([[RawParams]] from [[UrlMatcher.exec]])
6828         * - url: the current Url ([[UrlParts]])
6829         * - router: the router object ([[UIRouter]])
6830         *
6831         * #### Example:
6832         * ```js
6833         * var urlMatcher = $umf.compile("/foo/:fooId/:barId");
6834         * var rule = factory.fromUrlMatcher(urlMatcher, match => "/home/" + match.fooId + "/" + match.barId);
6835         * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' }
6836         * var result = rule.handler(match); // '/home/123/456'
6837         * ```
6838         *
6839         * ## Handler as UrlMatcher
6840         *
6841         * If `handler` is a UrlMatcher, the handler matcher is used to create the new url.
6842         * The `handler` UrlMatcher is formatted using the matched param from the first matcher.
6843         * The url is replaced with the result.
6844         *
6845         * #### Example:
6846         * ```js
6847         * var urlMatcher = $umf.compile("/foo/:fooId/:barId");
6848         * var handler = $umf.compile("/home/:fooId/:barId");
6849         * var rule = factory.fromUrlMatcher(urlMatcher, handler);
6850         * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' }
6851         * var result = rule.handler(match); // '/home/123/456'
6852         * ```
6853         */
6854        UrlRuleFactory.prototype.fromUrlMatcher = function (urlMatcher, handler) {
6855            var _handler = handler;
6856            if (isString(handler))
6857                handler = this.router.urlMatcherFactory.compile(handler);
6858            if (is(UrlMatcher)(handler))
6859                _handler = function (match) { return handler.format(match); };
6860            function matchUrlParamters(url) {
6861                var params = urlMatcher.exec(url.path, url.search, url.hash);
6862                return urlMatcher.validates(params) && params;
6863            }
6864            // Prioritize URLs, lowest to highest:
6865            // - Some optional URL parameters, but none matched
6866            // - No optional parameters in URL
6867            // - Some optional parameters, some matched
6868            // - Some optional parameters, all matched
6869            function matchPriority(params) {
6870                var optional = urlMatcher.parameters().filter(function (param) { return param.isOptional; });
6871                if (!optional.length)
6872                    return 0.000001;
6873                var matched = optional.filter(function (param) { return params[param.id]; });
6874                return matched.length / optional.length;
6875            }
6876            var details = { urlMatcher: urlMatcher, matchPriority: matchPriority, type: 'URLMATCHER' };
6877            return extend(new BaseUrlRule(matchUrlParamters, _handler), details);
6878        };
6879        /**
6880         * A UrlRule which matches a state by its url
6881         *
6882         * #### Example:
6883         * ```js
6884         * var rule = factory.fromState($state.get('foo'), router);
6885         * var match = rule.match('/foo/123/456'); // results in { fooId: '123', barId: '456' }
6886         * var result = rule.handler(match);
6887         * // Starts a transition to 'foo' with params: { fooId: '123', barId: '456' }
6888         * ```
6889         */
6890        UrlRuleFactory.prototype.fromState = function (stateOrDecl, router) {
6891            var state = StateObject.isStateDeclaration(stateOrDecl) ? stateOrDecl.$$state() : stateOrDecl;
6892            /**
6893             * Handles match by transitioning to matched state
6894             *
6895             * First checks if the router should start a new transition.
6896             * A new transition is not required if the current state's URL
6897             * and the new URL are already identical
6898             */
6899            var handler = function (match) {
6900                var $state = router.stateService;
6901                var globals = router.globals;
6902                if ($state.href(state, match) !== $state.href(globals.current, globals.params)) {
6903                    $state.transitionTo(state, match, { inherit: true, source: 'url' });
6904                }
6905            };
6906            var details = { state: state, type: 'STATE' };
6907            return extend(this.fromUrlMatcher(state.url, handler), details);
6908        };
6909        /**
6910         * A UrlRule which matches based on a regular expression
6911         *
6912         * The `handler` may be either a [[UrlRuleHandlerFn]] or a string.
6913         *
6914         * ## Handler as a function
6915         *
6916         * If `handler` is a function, the function is invoked with:
6917         *
6918         * - regexp match array (from `regexp`)
6919         * - url: the current Url ([[UrlParts]])
6920         * - router: the router object ([[UIRouter]])
6921         *
6922         * #### Example:
6923         * ```js
6924         * var rule = factory.fromRegExp(/^\/foo\/(bar|baz)$/, match => "/home/" + match[1])
6925         * var match = rule.match('/foo/bar'); // results in [ '/foo/bar', 'bar' ]
6926         * var result = rule.handler(match); // '/home/bar'
6927         * ```
6928         *
6929         * ## Handler as string
6930         *
6931         * If `handler` is a string, the url is *replaced by the string* when the Rule is invoked.
6932         * The string is first interpolated using `string.replace()` style pattern.
6933         *
6934         * #### Example:
6935         * ```js
6936         * var rule = factory.fromRegExp(/^\/foo\/(bar|baz)$/, "/home/$1")
6937         * var match = rule.match('/foo/bar'); // results in [ '/foo/bar', 'bar' ]
6938         * var result = rule.handler(match); // '/home/bar'
6939         * ```
6940         */
6941        UrlRuleFactory.prototype.fromRegExp = function (regexp, handler) {
6942            if (regexp.global || regexp.sticky)
6943                throw new Error('Rule RegExp must not be global or sticky');
6944            /**
6945             * If handler is a string, the url will be replaced by the string.
6946             * If the string has any String.replace() style variables in it (like `$2`),
6947             * they will be replaced by the captures from [[match]]
6948             */
6949            var redirectUrlTo = function (match) {
6950                // Interpolates matched values into $1 $2, etc using a String.replace()-style pattern
6951                return handler.replace(/\$(\$|\d{1,2})/, function (m, what) { return match[what === '$' ? 0 : Number(what)]; });
6952            };
6953            var _handler = isString(handler) ? redirectUrlTo : handler;
6954            var matchParamsFromRegexp = function (url) { return regexp.exec(url.path); };
6955            var details = { regexp: regexp, type: 'REGEXP' };
6956            return extend(new BaseUrlRule(matchParamsFromRegexp, _handler), details);
6957        };
6958        UrlRuleFactory.isUrlRule = function (obj) { return obj && ['type', 'match', 'handler'].every(function (key) { return isDefined(obj[key]); }); };
6959        return UrlRuleFactory;
6960    }());
6961    /**
6962     * A base rule which calls `match`
6963     *
6964     * The value from the `match` function is passed through to the `handler`.
6965     * @internal
6966     */
6967    var BaseUrlRule = /** @class */ (function () {
6968        function BaseUrlRule(match, handler) {
6969            var _this = this;
6970            this.match = match;
6971            this.type = 'RAW';
6972            this.matchPriority = function (match) { return 0 - _this.$id; };
6973            this.handler = handler || identity;
6974        }
6975        return BaseUrlRule;
6976    }());
6977
6978    function appendBasePath(url, isHtml5, absolute, baseHref) {
6979        if (baseHref === '/')
6980            return url;
6981        if (isHtml5)
6982            return stripLastPathElement(baseHref) + url;
6983        if (absolute)
6984            return baseHref.slice(1) + url;
6985        return url;
6986    }
6987    /**
6988     * Updates URL and responds to URL changes
6989     *
6990     * ### Deprecation warning:
6991     * This class is now considered to be an internal API
6992     * Use the [[UrlService]] instead.
6993     * For configuring URL rules, use the [[UrlRules]] which can be found as [[UrlService.rules]].
6994     */
6995    var UrlRouter = /** @class */ (function () {
6996        /** @internal */
6997        function UrlRouter(/** @internal */ router) {
6998            var _this = this;
6999            this.router = router;
7000            // Delegate these calls to [[UrlService]]
7001            /** @deprecated use [[UrlService.sync]]*/
7002            this.sync = function (evt) { return _this.router.urlService.sync(evt); };
7003            /** @deprecated use [[UrlService.listen]]*/
7004            this.listen = function (enabled) { return _this.router.urlService.listen(enabled); };
7005            /** @deprecated use [[UrlService.deferIntercept]]*/
7006            this.deferIntercept = function (defer) { return _this.router.urlService.deferIntercept(defer); };
7007            /** @deprecated use [[UrlService.match]]*/
7008            this.match = function (urlParts) { return _this.router.urlService.match(urlParts); };
7009            // Delegate these calls to [[UrlRules]]
7010            /** @deprecated use [[UrlRules.initial]]*/
7011            this.initial = function (handler) {
7012                return _this.router.urlService.rules.initial(handler);
7013            };
7014            /** @deprecated use [[UrlRules.otherwise]]*/
7015            this.otherwise = function (handler) {
7016                return _this.router.urlService.rules.otherwise(handler);
7017            };
7018            /** @deprecated use [[UrlRules.removeRule]]*/
7019            this.removeRule = function (rule) { return _this.router.urlService.rules.removeRule(rule); };
7020            /** @deprecated use [[UrlRules.rule]]*/
7021            this.rule = function (rule) { return _this.router.urlService.rules.rule(rule); };
7022            /** @deprecated use [[UrlRules.rules]]*/
7023            this.rules = function () { return _this.router.urlService.rules.rules(); };
7024            /** @deprecated use [[UrlRules.sort]]*/
7025            this.sort = function (compareFn) { return _this.router.urlService.rules.sort(compareFn); };
7026            /** @deprecated use [[UrlRules.when]]*/
7027            this.when = function (matcher, handler, options) { return _this.router.urlService.rules.when(matcher, handler, options); };
7028            this.urlRuleFactory = new UrlRuleFactory(router);
7029        }
7030        /** Internal API. */
7031        UrlRouter.prototype.update = function (read) {
7032            var $url = this.router.locationService;
7033            if (read) {
7034                this.location = $url.url();
7035                return;
7036            }
7037            if ($url.url() === this.location)
7038                return;
7039            $url.url(this.location, true);
7040        };
7041        /**
7042         * Internal API.
7043         *
7044         * Pushes a new location to the browser history.
7045         *
7046         * @internal
7047         * @param urlMatcher
7048         * @param params
7049         * @param options
7050         */
7051        UrlRouter.prototype.push = function (urlMatcher, params, options) {
7052            var replace = options && !!options.replace;
7053            this.router.urlService.url(urlMatcher.format(params || {}), replace);
7054        };
7055        /**
7056         * Builds and returns a URL with interpolated parameters
7057         *
7058         * #### Example:
7059         * ```js
7060         * matcher = $umf.compile("/about/:person");
7061         * params = { person: "bob" };
7062         * $bob = $urlRouter.href(matcher, params);
7063         * // $bob == "/about/bob";
7064         * ```
7065         *
7066         * @param urlMatcher The [[UrlMatcher]] object which is used as the template of the URL to generate.
7067         * @param pa
7067rams An object of parameter values to fill the matcher's required parameters.
7068         * @param options Options object. The options are:
7069         *
7070         * - **`absolute`** - {boolean=false},  If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
7071         *
7072         * @returns Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher`
7073         */
7074        UrlRouter.prototype.href = function (urlMatcher, params, options) {
7075            var url = urlMatcher.format(params);
7076            if (url == null)
7077                return null;
7078            options = options || { absolute: false };
7079            var cfg = this.router.urlService.config;
7080            var isHtml5 = cfg.html5Mode();
7081            if (!isHtml5 && url !== null) {
7082                url = '#' + cfg.hashPrefix() + url;
7083            }
7084            url = appendBasePath(url, isHtml5, options.absolute, cfg.baseHref());
7085            if (!options.absolute || !url) {
7086                return url;
7087            }
7088            var slash = !isHtml5 && url ? '/' : '';
7089            var cfgPort = cfg.port();
7090            var port = (cfgPort === 80 || cfgPort === 443 ? '' : ':' + cfgPort);
7091            return [cfg.protocol(), '://', cfg.host(), port, slash, url].join('');
7092        };
7093        Object.defineProperty(UrlRouter.prototype, "interceptDeferred", {
7094            /** @deprecated use [[UrlService.interceptDeferred]]*/
7095            get: function () {
7096                return this.router.urlService.interceptDeferred;
7097            },
7098            enumerable: false,
7099            configurable: true
7100        });
7101        return UrlRouter;
7102    }());
7103
7104    /**
7105     * The View service
7106     *
7107     * This service pairs existing `ui-view` components (which live in the DOM)
7108     * with view configs (from the state declaration objects: [[StateDeclaration.views]]).
7109     *
7110     * - After a successful Transition, the views from the newly entered states are activated via [[activateViewConfig]].
7111     *   The views from exited states are deactivated via [[deactivateViewConfig]].
7112     *   (See: the [[registerActivateViews]] Transition Hook)
7113     *
7114     * - As `ui-view` components pop in and out of existence, they register themselves using [[registerUIView]].
7115     *
7116     * - When the [[sync]] function is called, the registered `ui-view`(s) ([[ActiveU
7116IView]])
7117     * are configured with the matching [[ViewConfig]](s)
7118     *
7119     */
7120    var ViewService = /** @class */ (function () {
7121        /** @internal */
7122        function ViewService(/** @internal */ router) {
7123            var _this = this;
7124            this.router = router;
7125            /** @internal */ this._uiViews = [];
7126            /** @internal */ this._viewConfigs = [];
7127            /** @internal */ this._viewConfigFactories = {};
7128            /** @internal */ this._listeners = [];
7129            /** @internal */
7130            this._pluginapi = {
7131                _rootViewContext: this._rootViewContext.bind(this),
7132                _viewConfigFactory: this._viewConfigFactory.bind(this),
7133                _registeredUIView: function (id) { return find(_this._uiViews, function (view) { return _this.router.$id + "." + view.id === id; }); },
7134                _registeredUIViews: function () { return _this._uiViews; },
7135                _activeViewConfigs: function () { return _this._viewConfigs; },
7136                _onSync: function (listener) {
7137                    _this._listeners.push(listener);
7138                    return function () { return removeFrom(_this._listeners, listener); };
7139                },
7140            };
7141        }
7142        /**
7143         * Normalizes a view's name from a state.views configuration block.
7144         *
7145         * This should be used by a framework implementation to calculate the values for
7146         * [[_ViewDeclaration.$uiViewName]] and [[_ViewDeclaration.$uiViewContextAnchor]].
7147         *
7148         * @param context the context object (state declaration) that the view belongs to
7149         * @param rawViewName the name of the view, as declared in the [[StateDeclaration.views]]
7150         *
7151         * @returns the normalized uiViewName and uiViewContextAnchor that the view targets
7152         */
7153        ViewService.normalizeUIViewTarget = function (context, rawViewName) {
7154            if (rawViewName === void 0) { rawViewName = ''; }
7155            // TODO: Validate incoming view name with a regexp to allow:
7156            // ex: "[email protected]" , "^.^.view.name" , "view.name@^.^" , "" ,
7157            // "@" , "$default@^" , "!$default.$default" , "!foo.bar"
7158            var viewAtContext = rawViewName.split('@');
7159            var uiViewName = viewAtContext[0] || '$default'; // default to unnamed view
7160            var uiViewContextAnchor = isString(viewAtContext[1]) ? viewAtContext[1] : '^'; // default to parent context
7161            // Handle relative view-name sugar syntax.
7162            // Matches rawViewName "^.^.^.foo.bar" into array: ["^.^.^.foo.bar", "^.^.^", "foo.bar"],
7163            var relativeViewNameSugar = /^(\^(?:\.\^)*)\.(.*$)/.exec(uiViewName);
7164            if (relativeViewNameSugar) {
7165                // Clobbers existing contextAnchor (rawViewName validation will fix this)
7166                uiViewContextAnchor = relativeViewNameSugar[1]; // set anchor to "^.^.^"
7167                uiViewName = relativeViewNameSugar[2]; // set view-name to "foo.bar"
7168            }
7169            if (uiViewName.charAt(0) === '!') {
7170                uiViewName = uiViewName.substr(1);
7171                uiViewContextAnchor = ''; // target absolutely from root
7172            }
7173            // handle parent relative targeting "^.^.^"
7174            var relativeMatch = /^(\^(?:\.\^)*)$/;
7175            if (relativeMatch.exec(uiViewContextAnchor)) {
7176                var anchorState = uiViewContextAnchor.split('.').reduce(function (anchor, x) { return anchor.parent; }, context);
7177                uiViewContextAnchor = anchorState.name;
7178            }
7179            else if (uiViewContextAnchor === '.') {
7180                uiViewContextAnchor = context.name;
7181            }
7182            return { uiViewName: uiViewName, uiViewContextAnchor: uiViewContextAnchor };
7183        };
7184        /** @internal */
7185        ViewService.prototype._rootViewContext = function (context) {
7186            return (this._rootContext = context || this._rootContext);
7187        };
7188        /** @internal */
7189        ViewService.prototype._viewConfigFactory = function (viewType, factory) {
7190            this._viewConfigFactories[viewType] = factory;
7191        };
7192        ViewService.prototype.createViewConfig = function (path, decl) {
7193            var cfgFactory = this._viewConfigFactories[decl.$type];
7194            if (!cfgFactory)
7195                throw new Error('ViewService: No view config factory registered for type ' + decl.$type);
7196            var cfgs = cfgFactory(path, decl);
7197            return isArray(cfgs) ? cfgs : [cfgs];
7198        };
7199        /**
7200         * Deactivates a ViewConfig.
7201         *
7202         * This function deactivates a `ViewConfig`.
7203         * After calling [[sync]], it will un-pair from any `ui-view` with which it is currently paired.
7204         *
7205         * @param viewConfig The ViewConfig view to deregister.
7206         */
7207        ViewService.prototype.deactivateViewConfig = function (viewConfig) {
7208            trace.traceViewServiceEvent('<- Removing', viewConfig);
7209            removeFrom(this._viewConfigs, viewConfig);
7210        };
7211        ViewService.prototype.activateViewConfig = function (viewConfig) {
7212            trace.traceViewServiceEvent('-> Registering', viewConfig);
7213            this._viewConfigs.push(viewConfig);
7214        };
7215        ViewService.prototype.sync = function () {
7216            var _this = this;
7217            var uiViewsByFqn = this._uiViews.map(function (uiv) { return [uiv.fqn, uiv]; }).reduce(applyPairs, {});
7218            // Return a weighted depth value for a uiView.
7219            // The depth is the nesting depth of ui-views (based on FQN; times 10,000)
7220            // plus the depth of the state that is populating the uiView
7221            function uiViewDepth(uiView) {
7222                var stateDepth = function (context) { return (context && context.parent ? stateDepth(context.parent) + 1 : 1); };
7223                return uiView.fqn.split('.').length * 10000 + stateDepth(uiView.creationContext);
7224            }
7225            // Return the ViewConfig's context's depth in the context tree.
7226            function viewConfigDepth(config) {
7227                var context = config.viewDecl.$context, count = 0;
7228                while (++count && context.parent)
7229                    context = context.parent;
7230                return count;
7231            }
7232            // Given a depth function, returns a compare function which can return either ascending or descending order
7233            var depthCompare = curry(function (depthFn, posNeg, left, right) { return posNeg * (depthFn(left) - depthFn(right)); });
7234            var matchingConfigPair = function (uiView) {
7235                var matchingConfigs = _this._viewConfigs.filter(ViewService.matches(uiViewsByFqn, uiView));
7236                if (matchingConfigs.length > 1) {
7237                    // This is OK.  Child states can target a ui-view that the parent state also targets (the child wins)
7238                    // Sort by depth and return the match from the deepest child
7239                    // console.log(`Multiple matching view configs for ${uiView.fqn}`, matchingConfigs);
7240                    matchingConfigs.sort(depthCompare(viewConfigDepth, -1)); // descending
7241                }
7242                return { uiView: uiView, viewConfig: matchingConfigs[0] };
7243            };
7244            var configureUIView = function (tuple) {
7245                // If a parent ui-view is reconfigured, it could destroy child ui-views.
7246                // Before configuring a child ui-view, make sure it's still in the active uiViews array.
7247                if (_this._uiViews.indexOf(tuple.uiView) !== -1)
7248                    tuple.uiView.configUpdated(tuple.viewConfig);
7249            };
7250            // Sort views by FQN and state depth. Process uiviews nearest the root first.
7251            var uiViewTuples = this._uiViews.sort(depthCompare(uiViewDepth, 1)).map(matchingConfigPair);
7252            var matchedViewConfigs = uiViewTuples.map(function (tuple) { return tuple.viewConfig; });
7253            var unmatchedConfigTuples = this._viewConfigs
7254                .filter(function (config) { return !inArray(matchedViewConfigs, config); })
7255                .map(function (viewConfig) { return ({ uiView: undefined, viewConfig: viewConfig }); });
7256            uiViewTuples.forEach(configureUIView);
7257            var allTuples = uiViewTuples.concat(unmatchedConfigTuples);
7258            this._listeners.forEach(function (cb) { return cb(allTuples); });
7259            trace.traceViewSync(allTuples);
7260        };
7261        /**
7262         * Registers a `ui-view` component
7263         *
7264         * When a `ui-view` component is created, it uses this method to register itself.
7265         * After registration the [[sync]] method is used to ensure all `ui-view` are configured with the proper [[ViewConfig]].
7266         *
7267         * Note: the `ui-view` component uses the `ViewConfig` to determine what view should be loaded inside the `ui-view`,
7268         * and what the view's state context is.
7269         *
7270         * Note: There is no corresponding `deregisterUIView`.
7271         *       A `ui-view` should hang on to the return value of `registerUIView` and invoke it to deregister itself.
7272         *
7273         * @param uiView The metadata for a UIView
7274         * @return a de-registration function used when the view is destroyed.
7275         */
7276        ViewService.prototype.registerUIView = function (uiView) {
7277            trace.traceViewServiceUIViewEvent('-> Registering', uiView);
7278            var uiViews = this._uiViews;
7279            var fqnAndTypeMatches = function (uiv) { return uiv.fqn === uiView.fqn && uiv.$type === uiView.$type; };
7280            if (uiViews.filter(fqnAndTypeMatches).length)
7281                trace.traceViewServiceUIViewEvent('!!!! duplicate uiView named:', uiView);
7282            uiViews.push(uiView);
7283            this.sync();
7284            return function () {
7285                var idx = uiViews.indexOf(uiView);
7286                if (idx === -1) {
7287                    trace.traceViewServiceUIViewEvent('Tried removing non-registered uiView', uiView);
7288                    return;
7289                }
7290                trace.traceViewServiceUIViewEvent('<- Deregistering', uiView);
7291                removeFrom(uiViews)(uiView);
7292            };
7293        };
7294        /**
7295         * Returns the list of views currently available on the page, by fully-qualified name.
7296         *
7297         * @return {Array} Returns an array of fully-qualified view names.
7298         */
7299        ViewService.prototype.available = function () {
7300            return this._uiViews.map(prop('fqn'));
7301        };
7302        /**
7303         * Returns the list of views on the page containing loaded content.
7304         *
7305         * @return {Array} Returns an array of fully-qualified view names.
7306         */
7307        ViewService.prototype.active = function () {
7308            return this._uiViews.filter(prop('$config')).map(prop('name'));
7309        };
7310        /**
7311         * Given a ui-view and a ViewConfig, determines if they "match".
7312         *
7313         * A ui-view has a fully qualified name (fqn) and a context object.  The fqn is built from its overall location in
7314         * the DOM, describing its nesting relationship to any parent ui-view tags it is nested inside of.
7315         *
7316         * A ViewConfig has a target ui-view name and a context anchor.  The ui-view name can be a simple name, or
7317         * can be a segmented ui-view path, describing a portion of a ui-view fqn.
7318         *
7319         * In order for a ui-view to match ViewConfig, ui-view's $type must match the ViewConfig's $type
7320         *
7321         * If the ViewConfig's target ui-view name is a simple name (no dots), then a ui-view matches if:
7322         * - the ui-view's name matches the ViewConfig's target name
7323         * - the ui-view's context matches the ViewConfig's anchor
7324         *
7325         * If the ViewConfig's target ui-view name is a segmented name (with dots), then a ui-view matches if:
7326         * - There exists a parent ui-view where:
7327         *    - the parent ui-view's name matches the first segment (index 0) of the ViewConfig's target name
7328         *    - the parent ui-view's context matches the ViewConfig's anchor
7329         * - And the remaining segments (index 1..n) of the ViewConfig's target name match the tail of the ui-view's fqn
7330         *
7331         * Example:
7332         *
7333         * DOM:
7334         * <ui-view>                        <!-- created in the root context (name: "") -->
7335         *   <ui-view name="foo">                <!-- created in the context named: "A"      -->
7336         *     <ui-view>                    <!-- created in the context named: "A.B"    -->
7337         *       <ui-view name="bar">            <!-- created in the context named: "A.B.C"  -->
7338         *       </ui-view>
7339         *     </ui-view>
7340         *   </ui-view>
7341         * </ui-view>
7342         *
7343         * uiViews: [
7344         *  { fqn: "$default",                  creationContext: { name: "" } },
7345         *  { fqn: "$default.foo",              creationContext: { name: "A" } },
7346         *  { fqn: "$default.foo.$default",     creationContext: { name: "A.B" } }
7347         *  { fqn: "$default.foo.$default.bar", creationContext: { name: "A.B.C" } }
7348         * ]
7349         *
7350         * These four view configs all match the ui-view with the fqn: "$default.foo.$default.bar":
7351         *
7352         * - ViewConfig1: { uiViewName: "bar",                       uiViewContextAnchor: "A.B.C" }
7353         * - ViewConfig2: { uiViewName: "$default.bar",              uiViewContextAnchor: "A.B" }
7354         * - ViewConfig3: { uiViewName: "foo.$default.bar",          uiViewContextAnchor: "A" }
7355         * - ViewConfig4: { uiViewName: "$default.foo.$default.bar", uiViewContextAnchor: "" }
7356         *
7357         * Using ViewConfig3 as an example, it matches the ui-view with fqn "$default.foo.$default.bar" because:
7358         * - The ViewConfig's segmented target name is: [ "foo", "$default", "bar" ]
7359         * - There exists a parent ui-view (which has fqn: "$default.foo") where:
7360         *    - the parent ui-view's name "foo" matches the first segment "foo" of the ViewConfig's target name
7361         *    - the parent ui-view's context "A" matches the ViewConfig's anchor context "A"
7362         * - And the remaining segments [ "$default", "bar" ].join("."_ of the ViewConfig's target name match
7363         *   the tail of the ui-view's fqn "default.bar"
7364         *
7365         * @internal
7366         */
7367        ViewService.matches = function (uiViewsByFqn, uiView) { return function (viewConfig) {
7368            // Don't supply an ng1 ui-view with an ng2 ViewConfig, etc
7369            if (uiView.$type !== viewConfig.viewDecl.$type)
7370                return false;
7371            // Split names apart from both viewConfig and uiView into segments
7372            var vc = viewConfig.viewDecl;
7373            var vcSegments = vc.$uiViewName.split('.');
7374            var uivSegments = uiView.fqn.split('.');
7375            // Check if the tails of the segment arrays match. ex, these arrays' tails match:
7376            // vc: ["foo", "bar"], uiv fqn: ["$default", "foo", "bar"]
7377            if (!equals(vcSegments, uivSegments.slice(0 - vcSegments.length)))
7378                return false;
7379            // Now check if the fqn ending at the first segment of the viewConfig matches the context:
7380            // ["$default", "foo"].join(".") == "$default.foo", does the ui-view $default.foo context match?
7381            var negOffset = 1 - vcSegments.length || undefined;
7382            var fqnToFirstSegment = uivSegments.slice(0, negOffset).join('.');
7383            var uiViewContext = uiViewsByFqn[fqnToFirstSegment].creationContext;
7384            return vc.$uiViewContextAnchor === (uiViewContext && uiViewContext.name);
7385        }; };
7386        return ViewService;
7387    }());
7388
7389    /**
7390     * Global router state
7391     *
7392     * This is where we hold the global mutable state such as current state, current
7393     * params, current transition, etc.
7394     */
7395    var UIRouterGlobals = /** @class */ (function () {
7396        function UIRouterGlobals() {
7397            /**
7398             * Current parameter values
7399             *
7400             * The parameter values from the latest successful transition
7401             */
7402            this.params = new StateParams();
7403            /** @internal */
7404            this.lastStartedTransitionId = -1;
7405            /** @internal */
7406            this.transitionHistory = new Queue([], 1);
7407            /** @internal */
7408            this.successfulTransitions = new Queue([], 1);
7409        }
7410        UIRouterGlobals.prototype.dispose = function () {
7411            this.transitionHistory.clear();
7412            this.successfulTransitions.clear();
7413            this.transition = null;
7414        };
7415        return UIRouterGlobals;
7416    }());
7417
7418    var prioritySort = function (a, b) { return (b.priority || 0) - (a.priority || 0); };
7419    var typeSort = function (a, b) {
7420        var weights = { STATE: 4, URLMATCHER: 4, REGEXP: 3, RAW: 2, OTHER: 1 };
7421        return (weights[a.type] || 0) - (weights[b.type] || 0);
7422    };
7423    var urlMatcherSort = function (a, b) {
7424        return !a.urlMatcher || !b.urlMatcher ? 0 : UrlMatcher.compare(a.urlMatcher, b.urlMatcher);
7425    };
7426    var idSort = function (a, b) {
7427        // Identically sorted STATE and URLMATCHER best rule will be chosen by `matchPriority` after each rule matches the URL
7428        var useMatchPriority = { STATE: true, URLMATCHER: true };
7429        var equal = useMatchPriority[a.type] && useMatchPriority[b.type];
7430        return equal ? 0 : (a.$id || 0) - (b.$id || 0);
7431    };
7432    /**
7433     * Default rule priority sorting function.
7434     *
7435     * Sorts rules by:
7436     *
7437     * - Explicit priority (set rule priority using [[UrlRules.when]])
7438     * - Rule type (STATE: 4, URLMATCHER: 4, REGEXP: 3, RAW: 2, OTHER: 1)
7439     * - `UrlMatcher` specificity ([[UrlMatcher.compare]]): works for STATE and URLMATCHER types to pick the most specific rule.
7440     * - Rule registration order (for rule types other than STATE and URLMATCHER)
7441     *   - Equally sorted State and UrlMatcher rules will each match the URL.
7442     *     Then, the *best* match is chosen based on how many parameter values were matched.
7443     */
7444    var defaultRuleSortFn;
7445    defaultRuleSortFn = function (a, b) {
7446        var cmp = prioritySort(a, b);
7447        if (cmp !== 0)
7448            return cmp;
7449        cmp = typeSort(a, b);
7450        if (cmp !== 0)
7451            return cmp;
7452        cmp = urlMatcherSort(a, b);
7453        if (cmp !== 0)
7454            return cmp;
7455        return idSort(a, b);
7456    };
7457    function getHandlerFn(handler) {
7458        if (!isFunction(handler) && !isString(handler) && !is(TargetState)(handler) && !TargetState.isDef(handler)) {
7459            throw new Error("'handler' must be a string, function, TargetState, or have a state: 'newtarget' property");
7460        }
7461        return isFunction(handler) ? handler : val(handler);
7462    }
7463    /**
7464     * API for managing URL rules
7465     *
7466     * This API is used to create and manage URL rules.
7467     * URL rules are a mechanism to respond to specific URL patterns.
7468     *
7469     * The most commonly used methods are [[otherwise]] and [[when]].
7470     *
7471     * This API is found at `router.urlService.rules` (see: [[UIRouter.urlService]], [[URLService.rules]])
7472     */
7473    var UrlRules = /** @class */ (function () {
7474        /** @internal */
7475        function UrlRules(/** @internal */ router) {
7476            this.router = router;
7477            /** @internal */ this._sortFn = defaultRuleSortFn;
7478            /** @internal */ this._rules = [];
7479            /** @internal */ this._id = 0;
7480            this.urlRuleFactory = new UrlRuleFactory(router);
7481        }
7482        /** @internal */
7483        UrlRules.prototype.dispose = function (router) {
7484            this._rules = [];
7485            delete this._otherwiseFn;
7486        };
7487        /**
7488         * Defines the initial state, path, or behavior to use when the app starts.
7489         *
7490         * This rule defines the initial/starting state for the application.
7491         *
7492         * This rule is triggered the first time the URL is checked (when the app initially loads).
7493         * The rule is triggered only when the url matches either `""` or `"/"`.
7494         *
7495         * Note: The rule is intended to be used when the root of the application is directly linked to.
7496         * When the URL is *not* `""` or `"/"` and doesn't match other rules, the [[otherwise]] rule is triggered.
7497         * This allows 404-like behavior when an unknown URL is deep-linked.
7498         *
7499         * #### Example:
7500         * Start app at `home` state.
7501         * ```js
7502         * .initial({ state: 'home' });
7503         * ```
7504         *
7505         * #### Example:
7506         * Start app at `/home` (by url)
7507         * ```js
7508         * .initial('/home');
7509         * ```
7510         *
7511         * #### Example:
7512         * When no other url rule matches, go to `home` state
7513         * ```js
7514         * .initial((matchValue, url, router) => {
7515         *   console.log('initial state');
7516         *   return { state: 'home' };
7517         * })
7518         * ```
7519         *
7520         * @param handler The initial state or url path, or a function which returns the state or url path (or performs custom logic).
7521         */
7522        UrlRules.prototype.initial = function (handler) {
7523            var handlerFn = getHandlerFn(handler);
7524            var matchFn = function (urlParts, router) {
7525                return router.globals.transitionHistory.size() === 0 && !!/^\/?$/.exec(urlParts.path);
7526            };
7527            this.rule(this.urlRuleFactory.create(matchFn, handlerFn));
7528        };
7529        /**
7530         * Defines the state, url, or behavior to use when no other rule matches the URL.
7531         *
7532         * This rule is matched when *no other rule* matches.
7533         * It is generally used to handle unknown URLs (similar to "404" behavior, but on the client side).
7534         *
7535         * - If `handler` a string, it is treated as a url redirect
7536         *
7537         * #### Example:
7538         * When no other url rule matches, redirect to `/index`
7539         * ```js
7540         * .otherwise('/index');
7541         * ```
7542         *
7543         * - If `handler` is an object with a `state` property, the state is activated.
7544         *
7545         * #### Example:
7546         * When no other url rule matches, redirect to `home` and provide a `dashboard` parameter value.
7547         * ```js
7548         * .otherwise({ state: 'home', params: { dashboard: 'default' } });
7549         * ```
7550         *
7551         * - If `handler` is a function, the function receives the current url ([[UrlParts]]) and the [[UIRouter]] object.
7552         *   The function can perform actions, and/or return a value.
7553         *
7554         * #### Example:
7555         * When no other url rule matches, manually trigger a transition to the `home` state
7556         * ```js
7557         * .otherwise((matchValue, urlParts, router) => {
7558         *   router.stateService.go('home');
7559         * });
7560         * ```
7561         *
7562         * #### Example:
7563         * When no other url rule matches, go to `home` state
7564         * ```js
7565         * .otherwise((matchValue, urlParts, router) => {
7566         *   return { state: 'home' };
7567         * });
7568         * ```
7569         *
7570         * @param handler The url path to redirect to, or a function which returns the url path (or performs custom logic).
7571         */
7572        UrlRules.prototype.otherwise = function (handler) {
7573            var handlerFn = getHandlerFn(handler);
7574            this._otherwiseFn = this.urlRuleFactory.create(val(true), handlerFn);
7575            this._sorted = false;
7576        };
7577        /**
7578         * Remove a rule previously registered
7579         *
7580         * @param rule the matcher rule that was previously registered using [[rule]]
7581         */
7582        UrlRules.prototype.removeRule = function (rule) {
7583            removeFrom(this._rules, rule);
7584        };
7585        /**
7586         * Manually adds a URL Rule.
7587         *
7588         * Usually, a url rule is added using [[StateDeclaration.url]] or [[when]].
7589         * This api can be used directly for more control (to register a [[BaseUrlRule]], for example).
7590         * Rules can be created using [[urlRuleFactory]], or created manually as simple objects.
7591         *
7592         * A rule should have a `match` function which returns truthy if the rule matched.
7593         * It should also have a `handler` function which is invoked if the rule is the best match.
7594         *
7595         * @return a function that deregisters the rule
7596         */
7597        UrlRules.prototype.rule = function (rule) {
7598            var _this = this;
7599            if (!UrlRuleFactory.isUrlRule(rule))
7600                throw new Error('invalid rule');
7601            rule.$id = this._id++;
7602            rule.priority = rule.priority || 0;
7603            this._rules.push(rule);
7604            this._sorted = false;
7605            return function () { return _this.removeRule(rule); };
7606        };
7607        /**
7608         * Gets all registered rules
7609         *
7610         * @returns an array of all the registered rules
7611         */
7612        UrlRules.prototype.rules = function () {
7613            this.ensureSorted();
7614            return this._rules.concat(this._otherwiseFn ? [this._otherwiseFn] : []);
7615        };
7616        /**
7617         * Defines URL Rule priorities
7618         *
7619         * More than one rule ([[UrlRule]]) might match a given URL.
7620         * This `compareFn` is used to sort the rules by priority.
7621         * Higher priority rules should sort earlier.
7622         *
7623         * The [[defaultRuleSortFn]] is used by default.
7624         *
7625         * You only need to call this function once.
7626         * The `compareFn` will be used to sort the rules as each is registered.
7627         *
7628         * If called without any parameter, it will re-sort the rules.
7629         *
7630         * ---
7631         *
7632         * Url rules may come from multiple sources: states's urls ([[StateDeclaration.url]]), [[when]], and [[rule]].
7633         * Each rule has a (user-provided) [[UrlRule.priority]], a [[UrlRule.type]], and a [[UrlRule.$id]]
7634         * The `$id` is is the order in which the rule was registered.
7635         *
7636         * The sort function should use these data, or data found on a specific type
7637         * of [[UrlRule]] (such as [[StateRule.state]]), to order the rules as desired.
7638         *
7639         * #### Example:
7640         * This compare function prioritizes rules by the order in which the rules were registered.
7641         * A rule registered earlier has higher priority.
7642         *
7643         * ```js
7644         * function compareFn(a, b) {
7645         *   return a.$id - b.$id;
7646         * }
7647         * ```
7648         *
7649         * @param compareFn a function that compares to [[UrlRule]] objects.
7650         *    The `compareFn` should abide by the `Array.sort` compare function rules.
7651         *    Given two rules, `a` and `b`, return a negative number if `a` should be higher priority.
7652         *    Return a positive number if `b` should be higher priority.
7653         *    Return `0` if the rules are identical.
7654         *
7655         *    See the [mozilla reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Description)
7656         *    for details.
7657         */
7658        UrlRules.prototype.sort = function (compareFn) {
7659            var sorted = this.stableSort(this._rules, (this._sortFn = compareFn || this._sortFn));
7660            // precompute _sortGroup values and apply to each rule
7661            var group = 0;
7662            for (var i = 0; i < sorted.length; i++) {
7663                sorted[i]._group = group;
7664                if (i < sorted.length - 1 && this._sortFn(sorted[i], sorted[i + 1]) !== 0) {
7665                    group++;
7666                }
7667            }
7668            this._rules = sorted;
7669            this._sorted = true;
7670        };
7671        /** @internal */
7672        UrlRules.prototype.ensureSorted = function () {
7673            this._sorted || this.sort();
7674        };
7675        /** @internal */
7676        UrlRules.prototype.stableSort = function (arr, compareFn) {
7677            var arrOfWrapper = arr.map(function (elem, idx) { return ({ elem: elem, idx: idx }); });
7678            arrOfWrapper.sort(function (wrapperA, wrapperB) {
7679                var cmpDiff = compareFn(wrapperA.elem, wrapperB.elem);
7680                return cmpDiff === 0 ? wrapperA.idx - wrapperB.idx : cmpDiff;
7681            });
7682            return arrOfWrapper.map(function (wrapper) { return wrapper.elem; });
7683        };
7684        /**
7685         * Registers a `matcher` and `handler` for custom URLs handling.
7686         *
7687         * The `matcher` can be:
7688         *
7689         * - a [[UrlMatcher]]: See: [[UrlMatcherFactory.compile]]
7690         * - a `string`: The string is compiled to a [[UrlMatcher]]
7691         * - a `RegExp`: The regexp is used to match the url.
7692         *
7693         * The `handler` can be:
7694         *
7695         * - a string: The url is redirected to the value of the string.
7696         * - a function: The url is redirected to the return value of the function.
7697         *
7698         * ---
7699         *
7700         * When the `handler` is a `string` and the `matcher` is a `UrlMatcher` (or string), the redirect
7701         * string is interpolated with parameter values.
7702         *
7703         * #### Example:
7704         * When the URL is `/foo/123` the rule will redirect to `/bar/123`.
7705         * ```js
7706         * .when("/foo/:param1", "/bar/:param1")
7707         * ```
7708         *
7709         * ---
7710         *
7711         * When the `handler` is a string and the `matcher` is a `RegExp`, the redirect string is
7712         * interpolated with capture groups from the RegExp.
7713         *
7714         * #### Example:
7715         * When the URL is `/foo/123` the rule will redirect to `/bar/123`.
7716         * ```js
7717         * .when(new RegExp("^/foo/(.*)$"), "/bar/$1");
7718         * ```
7719         *
7720         * ---
7721         *
7722         * When the handler is a function, it receives the matched value, the current URL, and the `UIRouter` object (See [[UrlRuleHandlerFn]]).
7723         * The "matched value" differs based on the `matcher`.
7724         * For [[UrlMatcher]]s, it will be the matched state params.
7725         * For `RegExp`, it will be the match array from `regexp.exec()`.
7726         *
7727         * If the handler returns a string, the URL is redirected to the string.
7728         *
7729         * #### Example:
7730         * When the URL is `/foo/123` the rule will redirect to `/bar/123`.
7731         * ```js
7732         * .when(new RegExp("^/foo/(.*)$"), match => "/bar/" + match[1]);
7733         * ```
7734         *
7735         * Note: the `handler` may also invoke arbitrary code, such as `$state.go()`
7736         *
7737         * @param matcher A pattern `string` to match, compiled as a [[UrlMatcher]], or a `RegExp`.
7738         * @param handler The path to redirect to, or a function that returns the path.
7739         * @param options `{ priority: number }`
7740         *
7741         * @return the registered [[UrlRule]]
7742         */
7743        UrlRules.prototype.when = function (matcher, handler, options) {
7744            var rule = this.urlRuleFactory.create(matcher, handler);
7745            if (isDefined(options && options.priority))
7746                rule.priority = options.priority;
7747            this.rule(rule);
7748            return rule;
7749        };
7750        return UrlRules;
7751    }());
7752
7753    /**
7754     * An API to customize the URL behavior and retrieve URL configuration
7755     *
7756     * This API is used to customize the behavior of the URL.
7757     * This includes optional trailing slashes ([[strictMode]]), case sensitivity ([[caseInsensitive]]),
7758     * and custom parameter encoding (custom [[type]]).
7759     *
7760     * It also has information about the location (url) configuration such as [[port]] and [[baseHref]].
7761     * This information can be used to build absolute URLs, such as
7762     * `https://example.com:443/basepath/state/substate?param1=a#hashvalue`;
7763     *
7764     * This API is found at `router.urlService.config` (see: [[UIRouter.urlService]], [[URLService.config]])
7765     */
7766    var UrlConfig = /** @class */ (function () {
7767        /** @internal */ function UrlConfig(/** @internal */ router) {
7768            var _this = this;
7769            this.router = router;
7770            /** @internal */ this.paramTypes = new ParamTypes();
7771            /** @internal */ this._decodeParams = true;
7772            /** @internal */ this._isCaseInsensitive = false;
7773            /** @internal */ this._isStrictMode = true;
7774            /** @internal */ this._defaultSquashPolicy = false;
7775            /** @internal */ this.dispose = function () { return _this.paramTypes.dispose(); };
7776            // Delegate these calls to the current LocationConfig implementation
7777            /**
7778             * Gets the base Href, e.g., `http://localhost/approot/`
7779             *
7780             * @return the application's base href
7781             */
7782            this.baseHref = function () { return _this.router.locationConfig.baseHref(); };
7783            /**
7784             * Gets or sets the hashPrefix
7785             *
7786             * This only applies when not running in [[html5Mode]] (pushstate mode)
7787             *
7788             * If the current url is `http://localhost/app#!/uirouter/path/#anchor`, it returns `!` which is the prefix for the "hashbang" portion.
7789             *
7790             * @return the hash prefix
7791             */
7792            this.hashPrefix = function (newprefix) { return _this.router.locationConfig.hashPrefix(newprefix); };
7793            /**
7794             * Gets the host, e.g., `localhost`
7795             *
7796             * @return the protocol
7797             */
7798            this.host = function () { return _this.router.locationConfig.host(); };
7799            /**
7800             * Returns true when running in pushstate mode
7801             *
7802             * @return true when running in html5 mode (pushstate mode).
7803             */
7804            this.html5Mode = function () { return _this.router.locationConfig.html5Mode(); };
7805            /**
7806             * Gets the port, e.g., `80`
7807             *
7808             * @return the port number
7809             */
7810            this.port = function () { return _this.router.locationConfig.port(); };
7811            /**
7812             * Gets the protocol, e.g., `http`
7813             *
7814             * @return the protocol
7815             */
7816            this.protocol = function () { return _this.router.locationConfig.protocol(); };
7817        }
7818        /**
7819         * Defines whether URL matching should be case sensitive (the default behavior), or not.
7820         *
7821         * #### Example:
7822         * ```js
7823         * // Allow case insensitive url matches
7824         * urlService.config.caseInsensitive(true);
7825         * ```
7826         *
7827         * @param value `false` to match URL in a case sensitive manner; otherwise `true`;
7828         * @returns the current value of caseInsensitive
7829         */
7830        UrlConfig.prototype.caseInsensitive = function (value) {
7831            return (this._isCaseInsensitive = isDefined(value) ? value : this._isCaseInsensitive);
7832        };
7833        /**
7834         * Sets the default behavior when generating or matching URLs with default parameter values.
7835         *
7836         * #### Example:
7837         * ```js
7838         * // Remove default parameter values from the url
7839         * urlService.config.defaultSquashPolicy(true);
7840         * ```
7841         *
7842         * @param value A string that defines the default parameter URL squashing behavior.
7843         *    - `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL
7844         *    - `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the
7845         *      parameter is surrounded by slashes, squash (remove) one slash from the URL
7846         *    - any other string, e.g. "~": When generating an href with a default parameter value, squash (remove)
7847         *      the parameter value from the URL and replace it with this string.
7848         * @returns the current value of defaultSquashPolicy
7849         */
7850        UrlConfig.prototype.defaultSquashPolicy = function (value) {
7851            if (isDefined(value) && value !== true && value !== false && !isString(value))
7852                throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string");
7853            return (this._defaultSquashPolicy = isDefined(value) ? value : this._defaultSquashPolicy);
7854        };
7855        /**
7856         * Defines whether URLs should match trailing slashes, or not (the default behavior).
7857         *
7858         * #### Example:
7859         * ```js
7860         * // Allow optional trailing slashes
7861         * urlService.config.strictMode(false);
7862         * ```
7863         *
7864         * @param value `false` to match trailing slashes in URLs, otherwise `true`.
7865         * @returns the current value of strictMode
7866         */
7867        UrlConfig.prototype.strictMode = function (value) {
7868            return (this._isStrictMode = isDefined(value) ? value : this._isStrictMode);
7869        };
7870        /**
7871         * Creates and registers a custom [[ParamType]] object
7872         *
7873         * A custom parameter type can be used to generate URLs with typed parameters or custom encoding/decoding.
7874         *
7875         * #### Note: Register custom types *before using them* in a state definition.
7876         *
7877         * #### Example:
7878         * ```js
7879         * // Encode object parameter as JSON string
7880         * urlService.config.type('myjson', {
7881         *   encode: (obj) => JSON.stringify(obj),
7882         *   decode: (str) => JSON.parse(str),
7883         *   is: (val) => typeof(val) === 'object',
7884         *   pattern: /[^/]+/,
7885         *   equals: (a, b) => _.isEqual(a, b),
7886         * });
7887         * ```
7888         *
7889         * See [[ParamTypeDefinition]] for more examples
7890         *
7891         * @param name The type name.
7892         * @param definition The type definition. See [[ParamTypeDefinition]] for information on the values accepted.
7893         * @param definitionFn A function that is injected before the app runtime starts.
7894         *        The result of this function should be a [[ParamTypeDefinition]].
7895         *        The result is merged into the existing `definition`.
7896         *        See [[ParamType]] for information on the values accepted.
7897         *
7898         * @returns if only the `name` parameter was specified: the currently registered [[ParamType]] object, or undefined
7899         */
7900        UrlConfig.prototype.type = function (name, definition, definitionFn) {
7901            var type = this.paramTypes.type(name, definition, definitionFn);
7902            return !isDefined(definition) ? type : this;
7903        };
7904        return UrlConfig;
7905    }());
7906
7907    /**
7908     * API for URL management
7909     */
7910    var UrlService = /** @class */ (function () {
7911        /** @internal */
7912        function UrlService(/** @internal */ router) {
7913            var _this = this;
7914            this.router = router;
7915            /** @internal */ this.interceptDeferred = false;
7916            /**
7917             * The nested [[UrlRules]] API for managing URL rules and rewrites
7918             *
7919             * See: [[UrlRules]] for details
7920             */
7921            this.rules = new UrlRules(this.router);
7922            /**
7923             * The nested [[UrlConfig]] API to configure the URL and retrieve URL information
7924             *
7925             * See: [[UrlConfig]] for details
7926             */
7927            this.config = new UrlConfig(this.router);
7928            // Delegate these calls to the current LocationServices implementation
7929            /**
7930             * Gets the current url, or updates the url
7931             *
7932             * ### Getting the current URL
7933             *
7934             * When no arguments are passed, returns the current URL.
7935             * The URL is normalized using the internal [[path]]/[[search]]/[[hash]] values.
7936             *
7937             * For example, the URL may be stored in the hash ([[HashLocationServices]]) or
7938             * have a base HREF prepended ([[PushStateLocationServices]]).
7939             *
7940             * The raw URL in the browser might be:
7941             *
7942             * ```
7943             * http://mysite.com/somepath/index.html#/internal/path/123?param1=foo#anchor
7944             * ```
7945             *
7946             * or
7947             *
7948             * ```
7949             * http://mysite.com/basepath/internal/path/123?param1=foo#anchor
7950             * ```
7951             *
7952             * then this method returns:
7953             *
7954             * ```
7955             * /internal/path/123?param1=foo#anchor
7956             * ```
7957             *
7958             *
7959             * #### Example:
7960             * ```js
7961             * locationServices.url(); // "/some/path?query=value#anchor"
7962             * ```
7963             *
7964             * ### Updating the URL
7965             *
7966             * When `newurl` arguments is provided, changes the URL to reflect `newurl`
7967             *
7968             * #### Example:
7969             * ```js
7970             * locationServices.url("/some/path?query=value#anchor", true);
7971             * ```
7972             *
7973             * @param newurl The new value for the URL.
7974             *               This url should reflect only the new internal [[path]], [[search]], and [[hash]] values.
7975             *               It should not include the protocol, site, port, or base path of an absolute HREF.
7976             * @param replace When true, replaces the current history entry (instead of appending it) with this new url
7977             * @param state The history's state object, i.e., pushState (if the LocationServices implementation supports it)
7978             *
7979             * @return the url (after potentially being processed)
7980             */
7981            this.url = function (newurl, replace, state) {
7982                return _this.router.locationService.url(newurl, replace, state);
7983            };
7984            /**
7985             * Gets the path part of the current url
7986             *
7987             * If the current URL is `/some/path?query=value#anchor`, this returns `/some/path`
7988             *
7989             * @return the path portion of the url
7990             */
7991            this.path = function () { return _this.router.locationService.path(); };
7992            /**
7993             * Gets the search part of the current url as an object
7994             *
7995             * If the current URL is `/some/path?query=value#anchor`, this returns `{ query: 'value' }`
7996             *
7997             * @return the search (query) portion of the url, as an object
7998             */
7999            this.search = function () { return _this.router.locationService.search(); };
8000            /**
8001             * Gets the hash part of the current url
8002             *
8003             * If the current URL is `/some/path?query=value#anchor`, this returns `anchor`
8004             *
8005             * @return the hash (anchor) portion of the url
8006             */
8007            this.hash = function () { return _this.router.locationService.hash(); };
8008            /**
8009             * @internal
8010             *
8011             * Registers a low level url change handler
8012             *
8013             * Note: Because this is a low level handler, it's not recommended for general use.
8014             *
8015             * #### Example:
8016             * ```js
8017             * let deregisterFn = locationServices.onChange((evt) => console.log("url change", evt));
8018             * ```
8019             *
8020             * @param callback a function that will be called when the url is changing
8021             * @return a function that de-registers the callback
8022             */
8023            this.onChange = function (callback) { return _this.router.locationService.onChange(callback); };
8024        }
8025        /** @internal */
8026        UrlService.prototype.dispose = function () {
8027            this.listen(false);
8028            this.rules.dispose();
8029        };
8030        /**
8031         * Gets the current URL parts
8032         *
8033         * This method returns the different parts of the current URL (the [[path]], [[search]], and [[hash]]) as a [[UrlParts]] object.
8034         */
8035        UrlService.prototype.parts = function () {
8036            return { path: this.path(), search: this.search(), hash: this.hash() };
8037        };
8038        /**
8039         * Activates the best rule for the current URL
8040         *
8041         * Checks the current URL for a matching [[UrlRule]], then invokes that rule's handler.
8042         * This method is called internally any time the URL has changed.
8043         *
8044         * This effectively activates the state (or redirect, etc) which matches the current URL.
8045         *
8046         * #### Example:
8047         * ```js
8048         * urlService.deferIntercept();
8049         *
8050         * fetch('/states.json').then(resp => resp.json()).then(data => {
8051         *   data.forEach(state => $stateRegistry.register(state));
8052         *   urlService.listen();
8053         *   // Find the matching URL and invoke the handler.
8054         *   urlService.sync();
8055         * });
8056         * ```
8057         */
8058        UrlService.prototype.sync = function (evt) {
8059            if (evt && evt.defaultPrevented)
8060                return;
8061            var _a = this.router, urlService = _a.urlService, stateService = _a.stateService;
8062            var url = { path: urlService.path(), search: urlService.search(), hash: urlService.hash() };
8063            var best = this.match(url);
8064            var applyResult = pattern([
8065                [isString, function (newurl) { return urlService.url(newurl, true); }],
8066                [TargetState.isDef, function (def) { return stateService.go(def.state, def.params, def.options); }],
8067                [is(TargetState), function (target) { return stateService.go(target.state(), target.params(), target.options()); }],
8068            ]);
8069            applyResult(best && best.rule.handler(best.match, url, this.router));
8070        };
8071        /**
8072         * Starts or stops listening for URL changes
8073         *
8074         * Call this sometime after calling [[deferIntercept]] to start monitoring the url.
8075         * This causes UI-Router to start listening for changes to the URL, if it wasn't already listening.
8076         *
8077         * If called with `false`, UI-Router will stop listening (call listen(true) to start listening again).
8078         *
8079         * #### Example:
8080         * ```js
8081         * urlService.deferIntercept();
8082         *
8083         * fetch('/states.json').then(resp => resp.json()).then(data => {
8084         *   data.forEach(state => $stateRegistry.register(state));
8085         *   // Start responding to URL changes
8086         *   urlService.listen();
8087         *   urlService.sync();
8088         * });
8089         * ```
8090         *
8091         * @param enabled `true` or `false` to start or stop listening to URL changes
8092         */
8093        UrlService.prototype.listen = function (enabled) {
8094            var _this = this;
8095            if (enabled === false) {
8096                this._stopListeningFn && this._stopListeningFn();
8097                delete this._stopListeningFn;
8098            }
8099            else {
8100                return (this._stopListeningFn =
8101                    this._stopListeningFn || this.router.urlService.onChange(function (evt) { return _this.sync(evt); }));
8102            }
8103        };
8104        /**
8105         * Disables monitoring of the URL.
8106         *
8107         * Call this method before UI-Router has bootstrapped.
8108         * It will stop UI-Router from performing the initial url sync.
8109         *
8110         * This can be useful to perform some asynchronous initialization before the router starts.
8111         * Once the initialization is complete, call [[listen]] to tell UI-Router to start watching and synchronizing the URL.
8112         *
8113         * #### Example:
8114         * ```js
8115         * // Prevent UI-Router from automatically intercepting URL changes when it starts;
8116         * urlService.deferIntercept();
8117         *
8118         * fetch('/states.json').then(resp => resp.json()).then(data => {
8119         *   data.forEach(state => $stateRegistry.register(state));
8120         *   urlService.listen();
8121         *   urlService.sync();
8122         * });
8123         * ```
8124         *
8125         * @param defer Indicates whether to defer location change interception.
8126         *        Passing no parameter is equivalent to `true`.
8127         */
8128        UrlService.prototype.deferIntercept = function (defer) {
8129            if (defer === undefined)
8130                defer = true;
8131            this.interceptDeferred = defer;
8132        };
8133        /**
8134         * Matches a URL
8135         *
8136         * Given a URL (as a [[UrlParts]] object), check all rules and determine the best matching rule.
8137         * Return the result as a [[MatchResult]].
8138         */
8139        UrlService.prototype.match = function (url) {
8140            var _this = this;
8141            url = extend({ path: '', search: {}, hash: '' }, url);
8142            var rules = this.rules.rules();
8143            // Checks a single rule. Returns { rule: rule, match: match, weight: weight } if it matched, or undefined
8144            var checkRule = function (rule) {
8145                var match = rule.match(url, _this.router);
8146                return match && { match: match, rule: rule, weight: rule.matchPriority(match) };
8147            };
8148            // The rules are pre-sorted.
8149            // - Find the first matching rule.
8150            // - Find any other matching rule that sorted *exactly the same*, according to `.sort()`.
8151            // - Choose the rule with the highest match weight.
8152            var best;
8153            for (var i = 0; i < rules.length; i++) {
8154                // Stop when there is a 'best' rule and the next rule sorts differently than it.
8155                if (best && best.rule._group !== rules[i]._group)
8156                    break;
8157                var current = checkRule(rules[i]);
8158                // Pick the best MatchResult
8159                best = !best || (current && current.weight > best.weight) ? current : best;
8160            }
8161            return best;
8162        };
8163        return UrlService;
8164    }());
8165
8166    /** @internal */
8167    var _routerInstance = 0;
8168    /** @internal */
8169    var locSvcFns = ['url', 'path', 'search', 'hash', 'onChange'];
8170    /** @internal */
8171    var locCfgFns = ['port', 'protocol', 'host', 'baseHref', 'html5Mode', 'hashPrefix'];
8172    /** @internal */
8173    var locationServiceStub = makeStub('LocationServices', locSvcFns);
8174    /** @internal */
8175    var locationConfigStub = makeStub('LocationConfig', locCfgFns);
8176    /**
8177     * An instance of UI-Router.
8178     *
8179     * This object contains references to service APIs which define your application's routing behavior.
8180     */
8181    var UIRouter = /** @class */ (function () {
8182        /**
8183         * Creates a new `UIRouter` object
8184         *
8185         * @param locationService a [[LocationServices]] implementation
8186         * @param locationConfig a [[LocationConfig]] implementation
8187         * @internal
8188         */
8189        function UIRouter(locationService, locationConfig) {
8190            if (locationService === void 0) { locationService = locationServiceStub; }
8191            if (locationConfig === void 0) { locationConfig = locationConfigStub; }
8192            this.locationService = locationService;
8193            this.locationConfig = locationConfig;
8194            /** @internal */ this.$id = _routerInstance++;
8195            /** @internal */ this._disposed = false;
8196            /** @internal */ this._disposables = [];
8197            /** Enable/disable tracing to the javascript console */
8198            this.trace = trace;
8199            /** Provides services related to ui-view synchronization */
8200            this.viewService = new ViewService(this);
8201            /** An object that contains global router state, such as the current state and params */
8202            this.globals = new UIRouterGlobals();
8203            /** A service that exposes global Transition Hooks */
8204            this.transitionService = new TransitionService(this);
8205            /**
8206             * Deprecated for public use. Use [[urlService]] instead.
8207             * @deprecated Use [[urlService]] instead
8208             */
8209            this.urlMatcherFactory = new UrlMatcherFactory(this);
8210            /**
8211             * Deprecated for public use. Use [[urlService]] instead.
8212             * @deprecated Use [[urlService]] instead
8213             */
8214            this.urlRouter = new UrlRouter(this);
8215            /** Provides services related to the URL */
8216            this.urlService = new UrlService(this);
8217            /** Provides a registry for states, and related registration services */
8218            this.stateRegistry = new StateRegistry(this);
8219            /** Provides services related to states */
8220            this.stateService = new StateService(this);
8221            /** @internal plugin instances are registered here */
8222            this._plugins = {};
8223            this.viewService._pluginapi._rootViewContext(this.stateRegistry.root());
8224            this.globals.$current = this.stateRegistry.root();
8225            this.globals.current = this.globals.$current.self;
8226            this.disposable(this.globals);
8227            this.disposable(this.stateService);
8228            this.disposable(this.stateRegistry);
8229            this.disposable(this.transitionService);
8230            this.disposable(this.urlService);
8231            this.disposable(locationService);
8232            this.disposable(locationConfig);
8233        }
8234        /** Registers an object to be notified when the router is disposed */
8235        UIRouter.prototype.disposable = function (disposable) {
8236            this._disposables.push(disposable);
8237        };
8238        /**
8239         * Disposes this router instance
8240         *
8241         * When called, clears resources retained by the router by calling `dispose(this)` on all
8242         * registered [[disposable]] objects.
8243         *
8244         * Or, if a `disposable` object is provided, calls `dispose(this)` on that object only.
8245         *
8246         * @internal
8247         * @param disposable (optional) the disposable to dispose
8248         */
8249        UIRouter.prototype.dispose = function (disposable) {
8250            var _this = this;
8251            if (disposable && isFunction(disposable.dispose)) {
8252                disposable.dispose(this);
8253                return undefined;
8254            }
8255            this._disposed = true;
8256            this._disposables.slice().forEach(function (d) {
8257                try {
8258                    typeof d.dispose === 'function' && d.dispose(_this);
8259                    removeFrom(_this._disposables, d);
8260                }
8261                catch (ignored) { }
8262            });
8263        };
8264        /**
8265         * Adds a plugin to UI-Router
8266         *
8267         * This method adds a UI-Router Plugin.
8268         * A plugin can enhance or change UI-Router behavior using any public API.
8269         *
8270         * #### Example:
8271         * ```js
8272         * import { MyCoolPlugin } from "ui-router-cool-plugin";
8273         *
8274         * var plugin = router.addPlugin(MyCoolPlugin);
8275         * ```
8276         *
8277         * ### Plugin authoring
8278         *
8279         * A plugin is simply a class (or constructor function) which accepts a [[UIRouter]] instance and (optionally) an options object.
8280         *
8281         * The plugin can implement its functionality using any of the public APIs of [[UIRouter]].
8282         * For example, it may configure router options or add a Transition Hook.
8283         *
8284         * The plugin can then be published as a separate module.
8285         *
8286         * #### Example:
8287         * ```js
8288         * export class MyAuthPlugin implements UIRouterPlugin {
8289         *   constructor(router: UIRouter, options: any) {
8290         *     this.name = "MyAuthPlugin";
8291         *     let $transitions = router.transitionService;
8292         *     let $state = router.stateService;
8293         *
8294         *     let authCriteria = {
8295         *       to: (state) => state.data && state.data.requiresAuth
8296         *     };
8297         *
8298         *     function authHook(transition: Transition) {
8299         *       let authService = transition.injector().get('AuthService');
8300         *       if (!authService.isAuthenticated()) {
8301         *         return $state.target('login');
8302         *       }
8303         *     }
8304         *
8305         *     $transitions.onStart(authCriteria, authHook);
8306         *   }
8307         * }
8308         * ```
8309         *
8310         * @param plugin one of:
8311         *        - a plugin class which implements [[UIRouterPlugin]]
8312         *        - a constructor function for a [[UIRouterPlugin]] which accepts a [[UIRouter]] instance
8313         *        - a factory function which accepts a [[UIRouter]] instance and returns a [[UIRouterPlugin]] instance
8314         * @param options options to pass to the plugin class/factory
8315         * @returns the registered plugin instance
8316         */
8317        UIRouter.prototype.plugin = function (plugin, options) {
8318            if (options === void 0) { options = {}; }
8319            var pluginInstance = new plugin(this, options);
8320            if (!pluginInstance.name)
8321                throw new Error('Required property `name` missing on plugin: ' + pluginInstance);
8322            this._disposables.push(pluginInstance);
8323            return (this._plugins[pluginInstance.name] = pluginInstance);
8324        };
8325        UIRouter.prototype.getPlugin = function (pluginName) {
8326            return pluginName ? this._plugins[pluginName] : values(this._plugins);
8327        };
8328        return UIRouter;
8329    }());
8330
8331    function addCoreResolvables(trans) {
8332        trans.addResolvable(Resolvable.fromData(UIRouter, trans.router), '');
8333        trans.addResolvable(Resolvable.fromData(Transition, trans), '');
8334        trans.addResolvable(Resolvable.fromData('$transition$', trans), '');
8335        trans.addResolvable(Resolvable.fromData('$stateParams', trans.params()), '');
8336        trans.entering().forEach(function (state) {
8337            trans.addResolvable(Resolvable.fromData('$state$', state), state);
8338        });
8339    }
8340    var registerAddCoreResolvables = function (transitionService) {
8341        return transitionService.onCreate({}, addCoreResolvables);
8342    };
8343    var TRANSITION_TOKENS = ['$transition$', Transition];
8344    var isTransition = inArray(TRANSITION_TOKENS);
8345    // References to Transition in the treeChanges pathnodes makes all
8346    // previous Transitions reachable in memory, causing a memory leak
8347    // This function removes resolves for '$transition$' and `Transition` from the treeChanges.
8348    // Do not use this on current transitions, only on old ones.
8349    var treeChangesCleanup = function (trans) {
8350        var nodes = values(trans.treeChanges()).reduce(unnestR, []).reduce(uniqR, []);
8351        // If the resolvable is a Transition, return a new resolvable with null data
8352        var replaceTransitionWithNull = function (r) {
8353            return isTransition(r.token) ? Resolvable.fromData(r.token, null) : r;
8354        };
8355        nodes.forEach(function (node) {
8356            node.resolvables = node.resolvables.map(replaceTransitionWithNull);
8357        });
8358    };
8359
8360    /**
8361     * A [[TransitionHookFn]] that redirects to a different state or params
8362     *
8363     * Registered using `transitionService.onStart({ to: (state) => !!state.redirectTo }, redirectHook);`
8364     *
8365     * See [[StateDeclaration.redirectTo]]
8366     */
8367    var redirectToHook = function (trans) {
8368        var redirect = trans.to().redirectTo;
8369        if (!redirect)
8370            return;
8371        var $state = trans.router.stateService;
8372        function handleResult(result) {
8373            if (!result)
8374                return;
8375            if (result instanceof TargetState)
8376                return result;
8377            if (isString(result))
8378                return $state.target(result, trans.params(), trans.options());
8379            if (result['state'] || result['params'])
8380                return $state.target(result['state'] || trans.to(), result['params'] || trans.params(), trans.options());
8381        }
8382        if (isFunction(redirect)) {
8383            return services.$q.when(redirect(trans)).then(handleResult);
8384        }
8385        return handleResult(redirect);
8386    };
8387    var registerRedirectToHook = function (transitionService) {
8388        return transitionService.onStart({ to: function (state) { return !!state.redirectTo; } }, redirectToHook);
8389    };
8390
8391    /**
8392     * A factory which creates an onEnter, onExit or onRetain transition hook function
8393     *
8394     * The returned function invokes the (for instance) state.onEnter hook when the
8395     * state is being entered.
8396     */
8397    function makeEnterExitRetainHook(hookName) {
8398        return function (transition, state) {
8399            var _state = state.$$state();
8400            var hookFn = _state[hookName];
8401            return hookFn(transition, state);
8402        };
8403    }
8404    /**
8405     * The [[TransitionStateHookFn]] for onExit
8406     *
8407     * When the state is being exited, the state's .onExit function is invoked.
8408     *
8409     * Registered using `transitionService.onExit({ exiting: (state) => !!state.onExit }, onExitHook);`
8410     *
8411     * See: [[IHookRegistry.onExit]]
8412     */
8413    var onExitHook = makeEnterExitRetainHook('onExit');
8414    var registerOnExitHook = function (transitionService) {
8415        return transitionService.onExit({ exiting: function (state) { return !!state.onExit; } }, onExitHook);
8416    };
8417    /**
8418     * The [[TransitionStateHookFn]] for onRetain
8419     *
8420     * When the state was already entered, and is not being exited or re-entered, the state's .onRetain function is invoked.
8421     *
8422     * Registered using `transitionService.onRetain({ retained: (state) => !!state.onRetain }, onRetainHook);`
8423     *
8424     * See: [[IHookRegistry.onRetain]]
8425     */
8426    var onRetainHook = makeEnterExitRetainHook('onRetain');
8427    var registerOnRetainHook = function (transitionService) {
8428        return transitionService.onRetain({ retained: function (state) { return !!state.onRetain; } }, onRetainHook);
8429    };
8430    /**
8431     * The [[TransitionStateHookFn]] for onEnter
8432     *
8433     * When the state is being entered, the state's .onEnter function is invoked.
8434     *
8435     * Registered using `transitionService.onEnter({ entering: (state) => !!state.onEnter }, onEnterHook);`
8436     *
8437     * See: [[IHookRegistry.onEnter]]
8438     */
8439    var onEnterHook = makeEnterExitRetainHook('onEnter');
8440    var registerOnEnterHook = function (transitionService) {
8441        return transitionService.onEnter({ entering: function (state) { return !!state.onEnter; } }, onEnterHook);
8442    };
8443
8444    var RESOLVE_HOOK_PRIORITY = 1000;
8445    /**
8446     * A [[TransitionHookFn]] which resolves all EAGER Resolvables in the To Path
8447     *
8448     * Registered using `transitionService.onStart({}
8448, eagerResolvePath, { priority: 1000 });`
8449     *
8450     * When a Transition starts, this hook resolves all the EAGER Resolvables, which the transition then waits for.
8451     *
8452     * See [[StateDeclaration.resolve]]
8453     */
8454    var eagerResolvePath = function (trans) {
8455        return new ResolveContext(trans.treeChanges().to).resolvePath('EAGER', trans).then(noop);
8456    };
8457    var registerEagerResolvePath = function (transitionService) {
8458        return transitionService.onStart({}, eagerResolvePath, { priority: RESOLVE_HOOK_PRIORITY });
8459    };
8460    /**
8461     * A [[TransitionHookFn]] which resolves all LAZY Resolvables for the state (and all its ancestors) in the To Path
8462     *
8463     * Registered using `transitionService.onEnter({ entering: () => true }, lazyResolveState, { priority: 1000 });`
8464     *
8465     * When a State is being entered, this hook resolves all the Resolvables for this state, which the transition then waits for.
8466     *
8467     * See [[StateDeclaration.resolve]]
8468     */
8469    var lazyResolveState = function (trans, state) {
8470        return new ResolveContext(trans.treeChanges().to).subContext(state.$$state()).resolvePath('LAZY', trans).then(noop);
8471    };
8472    var registerLazyResolveState = function (transitionService) {
8473        return transitionService.onEnter({ entering: val(true) }, lazyResolveState, { priority: RESOLVE_HOOK_PRIORITY });
8474    };
8475    /**
8476     * A [[TransitionHookFn]] which resolves any dynamically added (LAZY or EAGER) Resolvables.
8477     *
8478     * Registered using `transitionService.onFinish({}
8478, eagerResolvePath, { priority: 1000 });`
8479     *
8480     * After all entering states have been entered, this hook resolves any remaining Resolvables.
8481     * These are typically dynamic resolves which were added by some Transition Hook using [[Transition.addResolvable]].
8482     *
8483     * See [[StateDeclaration.resolve]]
8484     */
8485    var resolveRemaining = function (trans) {
8486        return new ResolveContext(trans.treeChanges().to).resolvePath('LAZY', trans).then(noop);
8487    };
8488    var registerResolveRemaining = function (transitionService) {
8489        return transitionService.onFinish({}, resolveRemaining, { priority: RESOLVE_HOOK_PRIORITY });
8490    };
8491
8492    /**
8493     * A [[TransitionHookFn]] which waits for the views to load
8494     *
8495     * Registered using `transitionService.onStart({}, loadEnteringViews);`
8496     *
8497     * Allows the views to do async work in [[ViewConfig.load]] before the transition continues.
8498     * In angular 1, this includes loading the templates.
8499     */
8500    var loadEnteringViews = function (transition) {
8501        var $q = services.$q;
8502        var enteringViews = transition.views('entering');
8503        if (!enteringViews.length)
8504            return;
8505        return $q.all(enteringViews.map(function (view) { return $q.when(view.load()); })).then(noop);
8506    };
8507    var registerLoadEnteringViews = function (transitionService) {
8508        return transitionService.onFinish({}, loadEnteringViews);
8509    };
8510    /**
8511     * A [[TransitionHookFn]] which activates the new views when a transition is successful.
8512     *
8513     * Registered using `transitionService.onSuccess({}, activateViews);`
8514     *
8515     * After a transition is complete, this hook deactivates the old views from the previous state,
8516     * and activates the new views from the destination state.
8517     *
8518     * See [[ViewService]]
8519     */
8520    var activateViews = function (transition) {
8521        var enteringViews = transition.views('entering');
8522        var exitingViews = transition.views('exiting');
8523        if (!enteringViews.length && !exitingViews.length)
8524            return;
8525        var $view = transition.router.viewService;
8526        exitingViews.forEach(function (vc) { return $view.deactivateViewConfig(vc); });
8527        enteringViews.forEach(function (vc) { return $view.activateViewConfig(vc); });
8528        $view.sync();
8529    };
8530    var registerActivateViews = function (transitionService) {
8531        return transitionService.onSuccess({}, activateViews);
8532    };
8533
8534    /**
8535     * A [[TransitionHookFn]] which updates global UI-Router state
8536     *
8537     * Registered using `transitionService.onBefore({}, updateGlobalState);`
8538     *
8539     * Before a [[Transition]] starts, updates the global value of "the current transition" ([[Globals.transition]]).
8540     * After a successful [[Transition]], updates the global values of "the current state"
8541     * ([[Globals.current]] and [[Globals.$current]]) and "the current param values" ([[Globals.params]]).
8542     *
8543     * See also the deprecated properties:
8544     * [[StateService.transition]], [[StateService.current]], [[StateService.params]]
8545     */
8546    var updateGlobalState = function (trans) {
8547        var globals = trans.router.globals;
8548        var transitionSuccessful = function () {
8549            globals.successfulTransitions.enqueue(trans);
8550            globals.$current = trans.$to();
8551            globals.current = globals.$current.self;
8552            copy(trans.params(), globals.params);
8553        };
8554        var clearCurrentTransition = function () {
8555            // Do not clear globals.transition if a different transition has started in the meantime
8556            if (globals.transition === trans)
8557                globals.transition = null;
8558        };
8559        trans.onSuccess({}, transitionSuccessful, { priority: 10000 });
8560        trans.promise.then(clearCurrentTransition, clearCurrentTransition);
8561    };
8562    var registerUpdateGlobalState = function (transitionService) {
8563        return transitionService.onCreate({}, updateGlobalState);
8564    };
8565
8566    /**
8567     * A [[TransitionHookFn]] which updates the URL after a successful transition
8568     *
8569     * Registered using `transitionService.onSuccess({}, updateUrl);`
8570     */
8571    var updateUrl = function (transition) {
8572        var options = transition.options();
8573        var $state = transition.router.stateService;
8574        var $urlRouter = transition.router.urlRouter;
8575        // Dont update the url in these situations:
8576        // The transition was triggered by a URL sync (options.source === 'url')
8577        // The user doesn't want the url to update (options.location === false)
8578        // The destination state, and all parents have no navigable url
8579        if (options.source !== 'url' && options.location && $state.$current.navigable) {
8580            var urlOptions = { replace: options.location === 'replace' };
8581            $urlRouter.push($state.$current.navigable.url, $state.params, urlOptions);
8582        }
8583        $urlRouter.update(true);
8584    };
8585    var registerUpdateUrl = function (transitionService) {
8586        return transitionService.onSuccess({}, updateUrl, { priority: 9999 });
8587    };
8588
8589    /**
8590     * A [[TransitionHookFn]] that performs lazy loading
8591     *
8592     * When entering a state "abc" which has a `lazyLoad` function defined:
8593     * - Invoke the `lazyLoad` function (unless it is already in process)
8594     *   - Flag the hook function as "in process"
8595     *   - The function should return a promise (that resolves when lazy loading is complete)
8596     * - Wait for the promise to settle
8597     *   - If the promise resolves to a [[LazyLoadResult]], then register those states
8598     *   - Flag the hook function as "not in process"
8599     * - If the hook was successful
8600     *   - Remove the `lazyLoad` function from the state declaration
8601     * - If all the hooks were successful
8602     *   - Retry the transition (by returning a TargetState)
8603     *
8604     * ```
8605     * .state('abc', {
8606     *   component: 'fooComponent',
8607     *   lazyLoad: () => import('./fooComponent')
8608     *   });
8609     * ```
8610     *
8611     * See [[StateDeclaration.lazyLoad]]
8612     */
8613    var lazyLoadHook = function (transition) {
8614        var router = transition.router;
8615        function retryTransition() {
8616            if (transition.originalTransition().options().source !== 'url') {
8617                // The original transition was not triggered via url sync
8618                // The lazy state should be loaded now, so re-try the original transition
8619                var orig = transition.targetState();
8620                return router.stateService.target(orig.identifier(), orig.params(), orig.options());
8621            }
8622            // The original transition was triggered via url sync
8623            // Run the URL rules and find the best match
8624            var $url = router.urlService;
8625            var result = $url.match($url.parts());
8626            var rule = result && result.rule;
8627            // If the best match is a state, redirect the transition (instead
8628            // of calling sync() which supersedes the current transition)
8629            if (rule && rule.type === 'STATE') {
8630                var state = rule.state;
8631                var params = result.match;
8632                return router.stateService.target(state, params, transition.options());
8633            }
8634            // No matching state found, so let .sync() choose the best non-state match/otherwise
8635            router.urlService.sync();
8636        }
8637        var promises = transition
8638            .entering()
8639            .filter(function (state) { return !!state.$$state().lazyLoad; })
8640            .map(function (state) { return lazyLoadState(transition, state); });
8641        return services.$q.all(promises).then(retryTransition);
8642    };
8643    var registerLazyLoadHook = function (transitionService) {
8644        return transitionService.onBefore({ entering: function (state) { return !!state.lazyLoad; } }, lazyLoadHook);
8645    };
8646    /**
8647     * Invokes a state's lazy load function
8648     *
8649     * @param transition a Transition context
8650     * @param state the state to lazy load
8651     * @returns A promise for the lazy load result
8652     */
8653    function lazyLoadState(transition, state) {
8654        var lazyLoadFn = state.$$state().lazyLoad;
8655        // Store/get the lazy load promise on/from the hookfn so it doesn't get re-invoked
8656        var promise = lazyLoadFn['_promise'];
8657        if (!promise) {
8658            var success = function (result) {
8659                delete state.lazyLoad;
8660                delete state.$$state().lazyLoad;
8661                delete lazyLoadFn['_promise'];
8662                return result;
8663            };
8664            var error = function (err) {
8665                delete lazyLoadFn['_promise'];
8666                return services.$q.reject(err);
8667            };
8668            promise = lazyLoadFn['_promise'] = services.$q
8669                .when(lazyLoadFn(transition, state))
8670                .then(updateStateRegistry)
8671                .then(success, error);
8672        }
8673        /** Register any lazy loaded state definitions */
8674        function updateStateRegistry(result) {
8675            if (result && Array.isArray(result.states)) {
8676                result.states.forEach(function (_state) { return transition.router.stateRegistry.register(_state); });
8677            }
8678            return result;
8679        }
8680        return promise;
8681    }
8682
8683    /**
8684     * This class defines a type of hook, such as `onBefore` or `onEnter`.
8685     * Plugins can define custom hook types, such as sticky states does for `onInactive`.
8686     */
8687    var TransitionEventType = /** @class */ (function () {
8688        /* tslint:disable:no-inferrable-types */
8689        function TransitionEventType(name, hookPhase, hookOrder, criteriaMatchPath, reverseSort, getResultHandler, getErrorHandler, synchronous) {
8690            if (reverseSort === void 0) { reverseSort = false; }
8691            if (getResultHandler === void 0) { getResultHandler = TransitionHook.HANDLE_RESULT; }
8692            if (getErrorHandler === void 0) { getErrorHandler = TransitionHook.REJECT_ERROR; }
8693            if (synchronous === void 0) { synchronous = false; }
8694            this.name = name;
8695            this.hookPhase = hookPhase;
8696            this.hookOrder = hookOrder;
8697            this.criteriaMatchPath = criteriaMatchPath;
8698            this.reverseSort = reverseSort;
8699            this.getResultHandler = getResultHandler;
8700            this.getErrorHandler = getErrorHandler;
8701            this.synchronous = synchronous;
8702        }
8703        return TransitionEventType;
8704    }());
8705
8706    /**
8707     * A [[TransitionHookFn]] that skips a transition if it should be ignored
8708     *
8709     * This hook is invoked at the end of the onBefore phase.
8710     *
8711     * If the transition should be ignored (because no parameter or states changed)
8712     * then the transition is ignored and not processed.
8713     */
8714    function ignoredHook(trans) {
8715        var ignoredReason = trans._ignoredReason();
8716        if (!ignoredReason)
8717            return;
8718        trace.traceTransitionIgnored(trans);
8719        var pending = trans.router.globals.transition;
8720        // The user clicked a link going back to the *current state* ('A')
8721        // However, there is also a pending transition in flight (to 'B')
8722        // Abort the transition to 'B' because the user now wants to be back at 'A'.
8723        if (ignoredReason === 'SameAsCurrent' && pending) {
8724            pending.abort();
8725        }
8726        return Rejection.ignored().toPromise();
8727    }
8728    var registerIgnoredTransitionHook = function (transitionService) {
8729        return transitionService.onBefore({}, ignoredHook, { priority: -9999 });
8730    };
8731
8732    /**
8733     * A [[TransitionHookFn]] that rejects the Transition if it is invalid
8734     *
8735     * This hook is invoked at the end of the onBefore phase.
8736     * If the transition is invalid (for example, param values do not validate)
8737     * then the transition is rejected.
8738     */
8739    function invalidTransitionHook(trans) {
8740        if (!trans.valid()) {
8741            throw new Error(trans.error().toString());
8742        }
8743    }
8744    var registerInvalidTransitionHook = function (transitionService) {
8745        return transitionService.onBefore({}, invalidTransitionHook, { priority: -10000 });
8746    };
8747
8748    /**
8749     * The default [[Transition]] options.
8750     *
8751     * Include this object when applying custom defaults:
8752     * let reloadOpts = { reload: true, notify: true }
8753     * let options = defaults(theirOpts, customDefaults, defaultOptions);
8754     */
8755    var defaultTransOpts = {
8756        location: true,
8757        relative: null,
8758        inherit: false,
8759        notify: true,
8760        reload: false,
8761        supercede: true,
8762        custom: {},
8763        current: function () { return null; },
8764        source: 'unknown',
8765    };
8766    /**
8767     * This class provides services related to Transitions.
8768     *
8769     * - Most importantly, it allows global Transition Hooks to be registered.
8770     * - It allows the default transition error handler to be set.
8771     * - It also has a factory function for creating new [[Transition]] objects, (used internally by the [[StateService]]).
8772     *
8773     * At bootstrap, [[UIRouter]] creates a single instance (singleton) of this class.
8774     *
8775     * This API is located at `router.transitionService` ([[UIRouter.transitionService]])
8776     */
8777    var TransitionService = /** @class */ (function () {
8778        /** @internal */
8779        function TransitionService(_router) {
8780            /** @internal */
8781            this._transitionCount = 0;
8782            /** The transition hook types, such as `onEnter`, `onStart`, etc */
8783            this._eventTypes = [];
8784            /** @internal The registered transition hooks */
8785            this._registeredHooks = {};
8786            /** The  paths on a criteria object */
8787            this._criteriaPaths = {};
8788            this._router = _router;
8789            this.$view = _router.viewService;
8790            this._deregisterHookFns = {};
8791            this._pluginapi = (createProxyFunctions(val(this), {}, val(this), [
8792                '_definePathType',
8793                '_defineEvent',
8794                '_getPathTypes',
8795                '_getEvents',
8796                'getHooks',
8797            ]));
8798            this._defineCorePaths();
8799            this._defineCoreEvents();
8800            this._registerCoreTransitionHooks();
8801            _router.globals.successfulTransitions.onEvict(treeChangesCleanup);
8802        }
8803        /**
8804         * Registers a [[TransitionHookFn]], called *while a transition is being constructed*.
8805         *
8806         * Registers a transition lifecycle hook, which is invoked during transition construction.
8807         *
8808         * This low level hook should only be used by plugins.
8809         * This can be a useful time for plugins to add resolves or mutate the transition as needed.
8810         * The Sticky States plugin uses this hook to modify the treechanges.
8811         *
8812         * ### Lifecycle
8813         *
8814         * `onCreate` hooks are invoked *while a transition is being constructed*.
8815         *
8816         * ### Return value
8817         *
8818         * The hook's return value is ignored
8819         *
8820         * @internal
8821         * @param criteria defines which Transitions the Hook should be invoked for.
8822         * @param callback the hook function which will be invoked.
8823         * @param options the registration options
8824         * @returns a function which deregisters the hook.
8825         */
8826        TransitionService.prototype.onCreate = function (criteria, callback, options) {
8827            return;
8828        };
8829        /** @inheritdoc */
8830        TransitionService.prototype.onBefore = function (criteria, callback, options) {
8831            return;
8832        };
8833        /** @inheritdoc */
8834        TransitionService.prototype.onStart = function (criteria, callback, options) {
8835            return;
8836        };
8837        /** @inheritdoc */
8838        TransitionService.prototype.onExit = function (criteria, callback, options) {
8839            return;
8840        };
8841        /** @inheritdoc */
8842        TransitionService.prototype.onRetain = function (criteria, callback, options) {
8843            return;
8844        };
8845        /** @inheritdoc */
8846        TransitionService.prototype.onEnter = function (criteria, callback, options) {
8847            return;
8848        };
8849        /** @inheritdoc */
8850        TransitionService.prototype.onFinish = function (criteria, callback, options) {
8851            return;
8852        };
8853        /** @inheritdoc */
8854        TransitionService.prototype.onSuccess = function (criteria, callback, options) {
8855            return;
8856        };
8857        /** @inheritdoc */
8858        TransitionService.prototype.onError = function (criteria, callback, options) {
8859            return;
8860        };
8861        /**
8862         * dispose
8863         * @internal
8864         */
8865        TransitionService.prototype.dispose = function (router) {
8866            values(this._registeredHooks).forEach(function (hooksArray) {
8867                return hooksArray.forEach(function (hook) {
8868                    hook._deregistered = true;
8869                    removeFrom(hooksArray, hook);
8870                });
8871            });
8872        };
8873        /**
8874         * Creates a new [[Transition]] object
8875         *
8876         * This is a factory function for creating new Transition objects.
8877         * It is used internally by the [[StateService]] and should generally not be called by application code.
8878         *
8879         * @internal
8880         * @param fromPath the path to the current state (the from state)
8881         * @param targetState the target state (destination)
8882         * @returns a Transition
8883         */
8884        TransitionService.prototype.create = function (fromPath, targetState) {
8885            return new Transition(fromPath, targetState, this._router);
8886        };
8887        /** @internal */
8888        TransitionService.prototype._defineCoreEvents = function () {
8889            var Phase = exports.TransitionHookPhase;
8890            var TH = TransitionHook;
8891            var paths = this._criteriaPaths;
8892            var NORMAL_SORT = false, REVERSE_SORT = true;
8893            var SYNCHRONOUS = true;
8894            this._defineEvent('onCreate', Phase.CREATE, 0, paths.to, NORMAL_SORT, TH.LOG_REJECTED_RESULT, TH.THROW_ERROR, SYNCHRONOUS);
8895            this._defineEvent('onBefore', Phase.BEFORE, 0, paths.to);
8896            this._defineEvent('onStart', Phase.RUN, 0, paths.to);
8897            this._defineEvent('onExit', Phase.RUN, 100, paths.exiting, REVERSE_SORT);
8898            this._defineEvent('onRetain', Phase.RUN, 200, paths.retained);
8899            this._defineEvent('onEnter', Phase.RUN, 300, paths.entering);
8900            this._defineEvent('onFinish', Phase.RUN, 400, paths.to);
8901            this._defineEvent('onSuccess', Phase.SUCCESS, 0, paths.to, NORMAL_SORT, TH.LOG_REJECTED_RESULT, TH.LOG_ERROR, SYNCHRONOUS);
8902            this._defineEvent('onError', Phase.ERROR, 0, paths.to, NORMAL_SORT, TH.LOG_REJECTED_RESULT, TH.LOG_ERROR, SYNCHRONOUS);
8903        };
8904        /** @internal */
8905        TransitionService.prototype._defineCorePaths = function () {
8906            var STATE = exports.TransitionHookScope.STATE, TRANSITION = exports.TransitionHookScope.TRANSITION;
8907            this._definePathType('to', TRANSITION);
8908            this._definePathType('from', TRANSITION);
8909            this._definePathType('exiting', STATE);
8910            this._definePathType('retained', STATE);
8911            this._definePathType('entering', STATE);
8912        };
8913        /** @internal */
8914        TransitionService.prototype._defineEvent = function (name, hookPhase, hookOrder, criteriaMatchPath, reverseSort, getResultHandler, getErrorHandler, synchronous) {
8915            if (reverseSort === void 0) { reverseSort = false; }
8916            if (getResultHandler === void 0) { getResultHandler = TransitionHook.HANDLE_RESULT; }
8917            if (getErrorHandler === void 0) { getErrorHandler = TransitionHook.REJECT_ERROR; }
8918            if (synchronous === void 0) { synchronous = false; }
8919            var eventType = new TransitionEventType(name, hookPhase, hookOrder, criteriaMatchPath, reverseSort, getResultHandler, getErrorHandler, synchronous);
8920            this._eventTypes.push(eventType);
8921            makeEvent(this, this, eventType);
8922        };
8923        /** @internal */
8924        TransitionService.prototype._getEvents = function (phase) {
8925            var transitionHookTypes = isDefined(phase)
8926                ? this._eventTypes.filter(function (type) { return type.hookPhase === phase; })
8927                : this._eventTypes.slice();
8928            return transitionHookTypes.sort(function (l, r) {
8929                var cmpByPhase = l.hookPhase - r.hookPhase;
8930                return cmpByPhase === 0 ? l.hookOrder - r.hookOrder : cmpByPhase;
8931            });
8932        };
8933        /**
8934         * Adds a Path to be used as a criterion against a TreeChanges path
8935         *
8936         * For example: the `exiting` path in [[HookMatchCriteria]] is a STATE scoped path.
8937         * It was defined by calling `defineTreeChangesCriterion('exiting', TransitionHookScope.STATE)`
8938         * Each state in the exiting path is checked against the criteria and returned as part of the match.
8939         *
8940         * Another example: the `to` path in [[HookMatchCriteria]] is a TRANSITION scoped path.
8941         * It was defined by calling `defineTreeChangesCriterion('to', TransitionHookScope.TRANSITION)`
8942         * Only the tail of the `to` path is checked against the criteria and returned as part of the match.
8943         *
8944         * @internal
8945         */
8946        TransitionService.prototype._definePathType = function (name, hookScope) {
8947            this._criteriaPaths[name] = { name: name, scope: hookScope };
8948        };
8949        /** @internal */
8950        // tslint:disable-next-line
8951        TransitionService.prototype._getPathTypes = function () {
8952            return this._criteriaPaths;
8953        };
8954        /** @internal */
8955        TransitionService.prototype.getHooks = function (hookName) {
8956            return this._registeredHooks[hookName];
8957        };
8958        /** @internal */
8959        TransitionService.prototype._registerCoreTransitionHooks = function () {
8960            var fns = this._deregisterHookFns;
8961            fns.addCoreResolves = registerAddCoreResolvables(this);
8962            fns.ignored = registerIgnoredTransitionHook(this);
8963            fns.invalid = registerInvalidTransitionHook(this);
8964            // Wire up redirectTo hook
8965            fns.redirectTo = registerRedirectToHook(this);
8966            // Wire up onExit/Retain/Enter state hooks
8967            fns.onExit = registerOnExitHook(this);
8968            fns.onRetain = registerOnRetainHook(this);
8969            fns.onEnter = registerOnEnterHook(this);
8970            // Wire up Resolve hooks
8971            fns.eagerResolve = registerEagerResolvePath(this);
8972            fns.lazyResolve = registerLazyResolveState(this);
8973            fns.resolveAll = registerResolveRemaining(this);
8974            // Wire up the View management hooks
8975            fns.loadViews = registerLoadEnteringViews(this);
8976            fns.activateViews = registerActivateViews(this);
8977            // Updates global state after a transition
8978            fns.updateGlobals = registerUpdateGlobalState(this);
8979            // After globals.current is updated at priority: 10000
8980            fns.updateUrl = registerUpdateUrl(this);
8981            // Lazy load state trees
8982            fns.lazyLoad = registerLazyLoadHook(this);
8983        };
8984        return TransitionService;
8985    }());
8986
8987    /**
8988     * Provides services related to ui-router states.
8989     *
8990     * This API is located at `router.stateService` ([[UIRouter.stateService]])
8991     */
8992    var StateService = /** @class */ (function () {
8993        /** @internal */
8994        function StateService(/** @internal */ router) {
8995            this.router = router;
8996            /** @internal */
8997            this.invalidCallbacks = [];
8998            /** @internal */
8999            this._defaultErrorHandler = function $defaultErrorHandler($error$) {
9000                if ($error$ instanceof Error && $error$.stack) {
9001                    console.error($error$);
9002                    console.error($error$.stack);
9003                }
9004                else if ($error$ instanceof Rejection) {
9005                    console.error($error$.toString());
9006                    if ($error$.detail && $error$.detail.stack)
9007                        console.error($error$.detail.stack);
9008                }
9009                else {
9010                    console.error($error$);
9011                }
9012            };
9013            var getters = ['current', '$current', 'params', 'transition'];
9014            var boundFns = Object.keys(StateService.prototype).filter(not(inArray(getters)));
9015            createProxyFunctions(val(StateService.prototype), this, val(this), boundFns);
9016        }
9017        Object.defineProperty(StateService.prototype, "transition", {
9018            /**
9019             * The [[Transition]] currently in progress (or null)
9020             *
9021             * @deprecated This is a passthrough through to [[UIRouterGlobals.transition]]
9022             */
9023            get: function () {
9024                return this.router.globals.transition;
9025            },
9026            enumerable: false,
9027            configurable: true
9028        });
9029        Object.defineProperty(StateService.prototype, "params", {
9030            /**
9031             * The latest successful state parameters
9032             *
9033             * @deprecated This is a passthrough through to [[UIRouterGlobals.params]]
9034             */
9035            get: function () {
9036                return this.router.globals.params;
9037            },
9038            enumerable: false,
9039            configurable: true
9040        });
9041        Object.defineProperty(StateService.prototype, "current", {
9042            /**
9043             * The current [[StateDeclaration]]
9044             *
9045             * @deprecated This is a passthrough through to [[UIRouterGlobals.current]]
9046             */
9047            get: function () {
9048                return this.router.globals.current;
9049            },
9050            enumerable: false,
9051            configurable: true
9052        });
9053        Object.defineProperty(StateService.prototype, "$current", {
9054            /**
9055             * The current [[StateObject]] (an internal API)
9056             *
9057             * @deprecated This is a passthrough through to [[UIRouterGlobals.$current]]
9058             */
9059            get: function () {
9060                return this.router.globals.$current;
9061            },
9062            enumerable: false,
9063            configurable: true
9064        });
9065        /** @internal */
9066        StateService.prototype.dispose = function () {
9067            this.defaultErrorHandler(noop);
9068            this.invalidCallbacks = [];
9069        };
9070        /**
9071         * Handler for when [[transitionTo]] is called with an invali
9071d state.
9072         *
9073         * Invokes the [[onInvalid]] callbacks, in natural order.
9074         * Each callback's return value is checked in sequence until one of them returns an instance of TargetState.
9075         * The results of the callbacks are wrapped in $q.when(), so the callbacks may return promises.
9076         *
9077         * If a callback returns an TargetState, then it is used as arguments to $state.transitionTo() and the result returned.
9078         *
9079         * @internal
9080         */
9081        StateService.prototype._handleInvalidTargetState = function (fromPath, toState) {
9082            var _this = this;
9083            var fromState = PathUtils.makeTargetState(this.router.stateRegistry, fromPath);
9084            var globals = this.router.globals;
9085            var latestThing = function () { return globals.transitionHistory.peekTail(); };
9086            var latest = latestThing();
9087            var callbackQueue = new Queue(this.invalidCallbacks.slice());
9088            var injector = new ResolveContext(fromPath).injector();
9089            var checkForRedirect = function (result) {
9090                if (!(result instanceof TargetState)) {
9091                    return;
9092                }
9093                var target = result;
9094                // Recreate the TargetState, in case the state is now defined.
9095                target = _this.target(target.identifier(), target.params(), target.options());
9096                if (!target.valid()) {
9097                    return Rejection.invalid(target.error()).toPromise();
9098                }
9099                if (latestThing() !== latest) {
9100                    return Rejection.superseded().toPromise();
9101                }
9102                return _this.transitionTo(target.identifier(), target.params(), target.options());
9103            };
9104            function invokeNextCallback() {
9105                var nextCallback = callbackQueue.dequeue();
9106                if (nextCallback === undefined)
9107                    return Rejection.invalid(toState.error()).toPromise();
9108                var callbackResult = services.$q.when(nextCallback(toState, fromState, injector));
9109                return callbackResult.then(checkForRedirect).then(function (result) { return result || invokeNextCallback(); });
9110            }
9111            return invokeNextCallback();
9112        };
9113        /**
9114         * Registers an Invalid State handler
9115         *
9116         * Registers a [[OnInvalidCallback]] function to be invoked when [[StateService.transitionTo]]
9117         * has been called with an invalid state reference parameter
9118         *
9119         * Example:
9120         * ```js
9121         * stateService.onInvalid(function(to, from, injector) {
9122         *   if (to.name() === 'foo') {
9123         *     let lazyLoader = injector.get('LazyLoadService');
9124         *     return lazyLoader.load('foo')
9125         *         .then(() => stateService.target('foo'));
9126         *   }
9127         * });
9128         * ```
9129         *
9130         * @param {function} callback invoked when the toState is invalid
9131         *   This function receives the (invalid) toState, the fromState, and an injector.
9132         *   The function may optionally return a [[TargetState]] or a Promise for a TargetState.
9133         *   If one is returned, it is treated as a redirect.
9134         *
9135         * @returns a function which deregisters the callback
9136         */
9137        StateService.prototype.onInvalid = function (callback) {
9138            this.invalidCallbacks.push(callback);
9139            return function deregisterListener() {
9140                removeFrom(this.invalidCallbacks)(callback);
9141            }.bind(this);
9142        };
9143        /**
9144         * Reloads the current state
9145         *
9146         * A method that force reloads the current state, or a partial state hierarchy.
9147         * All resolves are re-resolved, and components reinstantiated.
9148         *
9149         * #### Example:
9150         * ```js
9151         * let app angular.module('app', ['ui.router']);
9152         *
9153         * app.controller('ctrl', function ($scope, $state) {
9154         *   $scope.reload = function(){
9155         *     $state.reload();
9156         *   }
9157         * });
9158         * ```
9159         *
9160         * Note: `reload()` is just an alias for:
9161         *
9162         * ```js
9163         * $state.transitionTo($state.current, $state.params, {
9164         *   reload: true, inherit: false
9165         * });
9166         * ```
9167         *
9168         * @param reloadState A state name or a state object.
9169         *    If present, this state and all its children will be reloaded, but ancestors will not reload.
9170         *
9171         * #### Example:
9172         * ```js
9173         * //assuming app application consists of 3 states: 'contacts', 'contacts.detail', 'contacts.detail.item'
9174         * //and current state is 'contacts.detail.item'
9175         * let app angular.module('app', ['ui.router']);
9176         *
9177         * app.controller('ctrl', function ($scope, $state) {
9178         *   $scope.reload = function(){
9179         *     //will reload 'contact.detail' and nested 'contact.detail.item' states
9180         *     $state.reload('contact.detail');
9181         *   }
9182         * });
9183         * ```
9184         *
9185         * @returns A promise representing the state of the new transition. See [[StateService.go]]
9186         */
9187        StateService.prototype.reload = function (reloadState) {
9188            return this.transitionTo(this.current, this.params, {
9189                reload: isDefined(reloadState) ? reloadState : true,
9190                inherit: false,
9191                notify: false,
9192            });
9193        };
9194        /**
9195         * Transition to a different state and/or parameters
9196         *
9197         * Convenience method for transitioning to a new state.
9198         *
9199         * `$state.go` calls `$state.transitionTo` internally but automatically sets options to
9200         * `{ location: true, inherit: true, relative: router.globals.$current, notify: true }`.
9201         * This allows you to use either an absolute or relative `to` argument (because of `relative: router.globals.$current`).
9202         * It also allows you to specify * only the parameters you'd like to update, while letting unspecified parameters
9203         * inherit from the current parameter values (because of `inherit: true`).
9204         *
9205         * #### Example:
9206         * ```js
9207         * let app = angular.module('app', ['ui.router']);
9208         *
9209         * app.controller('ctrl', function ($scope, $state) {
9210         *   $scope.changeState = function () {
9211         *     $state.go('contact.detail');
9212         *   };
9213         * });
9214         * ```
9215         *
9216         * @param to Absolute state name, state object, or relative state path (relative to current state).
9217         *
9218         * Some examples:
9219         *
9220         * - `$state.go('contact.detail')` - will go to the `contact.detail` state
9221         * - `$state.go('^')` - will go to the parent state
9222         * - `$state.go('^.sibling')` - if current state is `home.child`, will go to the `home.sibling` state
9223         * - `$state.go('.child.grandchild')` - if current state is home, will go to the `home.child.grandchild` state
9224         *
9225         * @param params A map of the parameters that will be sent to the state, will populate $stateParams.
9226         *
9227         *    Any parameters that are not specified will be inherited from current parameter values (because of `inherit: true`).
9228         *    This allows, for example, going to a sibling state that shares parameters defined by a parent state.
9229         *
9230         * @param options Transition options
9231         *
9232         * @returns {promise} A promise representing the state of the new transition.
9233         */
9234        StateService.prototype.go = function (to, params, options) {
9235            var defautGoOpts = { relative: this.$current, inherit: true };
9236            var transOpts = defaults(options, defautGoOpts, defaultTransOpts);
9237            return this.transitionTo(to, params, transOpts);
9238        };
9239        /**
9240         * Creates a [[TargetState]]
9241         *
9242         * This is a factory method for creating a TargetState
9243         *
9244         * This may be returned from a Transition Hook to redirect a transition, for example.
9245         */
9246        StateService.prototype.target = function (identifier, params, options) {
9247            if (options === void 0) { options = {}; }
9248            // If we're reloading, find the state object to reload from
9249            if (isObject(options.reload) && !options.reload.name)
9250                throw new Error('Invalid reload state object');
9251            var reg = this.router.stateRegistry;
9252            options.reloadState =
9253                options.reload === true ? reg.root() : reg.matcher.find(options.reload, options.relative);
9254            if (options.reload && !options.reloadState)
9255                throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'");
9256            return new TargetState(this.router.stateRegistry, identifier, params, options);
9257        };
9258        /** @internal */
9259        StateService.prototype.getCurrentPath = function () {
9260            var _this = this;
9261            var globals = this.router.globals;
9262            var latestSuccess = globals.successfulTransitions.peekTail();
9263            var rootPath = function () { return [new PathNode(_this.router.stateRegistry.root())]; };
9264            return latestSuccess ? latestSuccess.treeChanges().to : rootPath();
9265        };
9266        /**
9267         * Low-level method for transitioning to a new state.
9268         *
9269         * The [[go]] method (which uses `transitionTo` internally) is recommended in most situations.
9270         *
9271         * #### Example:
9272         * ```js
9273         * let app = angular.module('app', ['ui.router']);
9274         *
9275         * app.controller('ctrl', function ($scope, $state) {
9276         *   $scope.changeState = function () {
9277         *     $state.transitionTo('contact.detail');
9278         *   };
9279         * });
9280         * ```
9281         *
9282         * @param to State name or state object.
9283         * @param toParams A map of the parameters that will be sent to the state,
9284         *      will populate $stateParams.
9285         * @param options Transition options
9286         *
9287         * @returns A promise representing the state of the new transition. See [[go]]
9288         */
9289        StateService.prototype.transitionTo = function (to, toParams, options) {
9290            var _this = this;
9291            if (toParams === void 0) { toParams = {}; }
9292            if (options === void 0) { options = {}; }
9293            var router = this.router;
9294            var globals = router.globals;
9295            options = defaults(options, defaultTransOpts);
9296            var getCurrent = function () { return globals.transition; };
9297            options = extend(options, { current: getCurrent });
9298            var ref = this.target(to, toParams, options);
9299            var currentPath = this.getCurrentPath();
9300            if (!ref.exists())
9301                return this._handleInvalidTargetState(currentPath, ref);
9302            if (!ref.valid())
9303                return silentRejection(ref.error());
9304            if (options.supercede === false && getCurrent()) {
9305                return (Rejection.ignored('Another transition is in progress and supercede has been set to false in TransitionOptions for the transition. So the transition was ignored in favour of the existing one in progress.').toPromise());
9306            }
9307            /**
9308             * Special handling for Ignored, Aborted, and Redirected transitions
9309             *
9310             * The semantics for the transition.run() promise and the StateService.transitionTo()
9311             * promise differ. For instance, the run() promise may be rejected because it was
9312             * IGNORED, but the transitionTo() promise is resolved because from the user perspective
9313             * no error occurred.  Likewise, the transition.run() promise may be rejected because of
9314             * a Redirect, but the transitionTo() promise is chained to the new Transition's promise.
9315             */
9316            var rejectedTransitionHandler = function (trans) { return function (error) {
9317                if (error instanceof Rejection) {
9318                    var isLatest = router.globals.lastStartedTransitionId <= trans.$id;
9319                    if (error.type === exports.RejectType.IGNORED) {
9320                        isLatest && router.urlRouter.update();
9321                        // Consider ignored `Transition.run()` as a successful `transitionTo`
9322                        return services.$q.when(globals.current);
9323                    }
9324                    var detail = error.detail;
9325                    if (error.type === exports.RejectType.SUPERSEDED && error.redirected && detail instanceof TargetState) {
9326                        // If `Transition.run()` was redirected, allow the `transitionTo()` promise to resolve successfully
9327                        // by returning the promise for the new (redirect) `Transition.run()`.
9328                        var redirect = trans.redirect(detail);
9329                        return redirect.run().catch(rejectedTransitionHandler(redirect));
9330                    }
9331                    if (error.type === exports.RejectType.ABORTED) {
9332                        isLatest && router.urlRouter.update();
9333                        return services.$q.reject(error);
9334                    }
9335                }
9336                var errorHandler = _this.defaultErrorHandler();
9337                errorHandler(error);
9338                return services.$q.reject(error);
9339            }; };
9340            var transition = this.router.transitionService.create(currentPath, ref);
9341            var transitionToPromise = transition.run().catch(rejectedTransitionHandler(transition));
9342            silenceUncaughtInPromise(transitionToPromise); // issue #2676
9343            // Return a promise for the transition, which also has the transition object on it.
9344            return extend(transitionToPromise, { transition: transition });
9345        };
9346        /**
9347         * Checks if the current state *is* the provided state
9348         *
9349         * Similar to [[includes]] but only checks for the full state name.
9350         * If params is supplied then it will be tested for strict equality against the current
9351         * active params object, so all params must match with none missing and no extras.
9352         *
9353         * #### Example:
9354         * ```js
9355         * $state.$current.name = 'contacts.details.item';
9356         *
9357         * // absolute name
9358         * $state.is('contact.details.item'); // returns true
9359         * $state.is(contactDetailItemStateObject); // returns true
9360         * ```
9361         *
9362         * // relative name (. and ^), typically from a template
9363         * // E.g. from the 'contacts.details' template
9364         * ```html
9365         * <div ng-class="{highlighted: $state.is('.item')}">Item</div>
9366         * ```
9367         *
9368         * @param stateOrName The state name (absolute or relative) or state object you'd like to check.
9369         * @param params A param object, e.g. `{sectionId: section.id}`, that you'd like
9370         * to test against the current active state.
9371         * @param options An options object. The options are:
9372         *   - `relative`: If `stateOrName` is a relative state name and `options.relative` is set, .is will
9373         *     test relative to `options.relative` state (or name).
9374         *
9375         * @returns Returns true if it is the state.
9376         */
9377        StateService.prototype.is = function (stateOrName, params, options) {
9378            options = defaults(options, { relative: this.$current });
9379            var state = this.router.stateRegistry.matcher.find(stateOrName, options.relative);
9380            if (!isDefined(state))
9381                return undefined;
9382            if (this.$current !== state)
9383                return false;
9384            if (!params)
9385                return true;
9386            var schema = state.parameters({ inherit: true, matchingKeys: params });
9387            return Param.equals(schema, Param.values(schema, params), this.params);
9388        };
9389        /**
9390         * Checks if the current state *includes* the provided state
9391         *
9392         * A method to determine if the current active state is equal to or is the child of the
9393         * state stateName. If any params are passed then they will be tested for a match as well.
9394         * Not all the parameters need to be passed, just the ones you'd like to test for equality.
9395         *
9396         * #### Example when `$state.$current.name === 'contacts.details.item'`
9397         * ```js
9398         * // Using partial names
9399         * $state.includes("contacts"); // returns true
9400         * $state.includes("contacts.details"); // returns true
9401         * $state.includes("contacts.details.item"); // returns true
9402         * $state.includes("contacts.list"); // returns false
9403         * $state.includes("about"); // returns false
9404         * ```
9405         *
9406         * #### Glob Examples when `* $state.$current.name === 'contacts.details.item.url'`:
9407         * ```js
9408         * $state.includes("*.details.*.*"); // returns true
9409         * $state.includes("*.details.**"); // returns true
9410         * $state.includes("**.item.**"); // returns true
9411         * $state.includes("*.details.item.url"); // returns true
9412         * $state.includes("*.details.*.url"); // returns true
9413         * $state.includes("*.details.*"); // returns false
9414         * $state.includes("item.**"); // returns false
9415         * ```
9416         *
9417         * @param stateOrName A partial name, relative name, glob pattern,
9418         *   or state object to be searched for within the current state name.
9419         * @param params A param object, e.g. `{sectionId: section.id}`,
9420         *   that you'd like to test against the current active state.
9421         * @param options An options object. The options are:
9422         *   - `relative`: If `stateOrName` is a relative state name and `options.relative` is set, .is will
9423         *     test relative to `options.relative` state (or name).
9424         *
9425         * @returns {boolean} Returns true if it does include the state
9426         */
9427        StateService.prototype.includes = function (stateOrName, params, options) {
9428            options = defaults(options, { relative: this.$current });
9429            var glob = isString(stateOrName) && Glob.fromString(stateOrName);
9430            if (glob) {
9431                if (!glob.matches(this.$current.name))
9432                    return false;
9433                stateOrName = this.$current.name;
9434            }
9435            var state = this.router.stateRegistry.matcher.find(stateOrName, options.relative), include = this.$current.includes;
9436            if (!isDefined(state))
9437                return undefined;
9438            if (!isDefined(include[state.name]))
9439                return false;
9440            if (!params)
9441                return true;
9442            var schema = state.parameters({ inherit: true, matchingKeys: params });
9443            return Param.equals(schema, Param.values(schema, params), this.params);
9444        };
9445        /**
9446         * Generates a URL for a state and parameters
9447         *
9448         * Returns the url for the given state populated with the given params.
9449         *
9450         * #### Example:
9451         * ```js
9452         * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
9453         * ```
9454         *
9455         * @param stateOrName The state name or state object you'd like to generate a url from.
9456         * @param params An object of parameter values to fill the state's required parameters.
9457         * @param options Options object. The options are:
9458         *
9459         * @returns {string} compiled state url
9460         */
9461        StateService.prototype.href = function (stateOrName, params, options) {
9462            var defaultHrefOpts = {
9463                lossy: true,
9464                inherit: true,
9465                absolute: false,
9466                relative: this.$current,
9467            };
9468            options = defaults(options, defaultHrefOpts);
9469            params = params || {};
9470            var state = this.router.stateRegistry.matcher.find(stateOrName, options.relative);
9471            if (!isDefined(state))
9472                return null;
9473            if (options.inherit)
9474                params = this.params.$inherit(params, this.$current, state);
9475            var nav = state && options.lossy ? state.navigable : state;
9476            if (!nav || nav.url === undefined || nav.url === null) {
9477                return null;
9478            }
9479            return this.router.urlRouter.href(nav.url, params, { absolute: options.absolute });
9480        };
9481        /**
9482         * Sets or gets the default [[transitionTo]] error handler.
9483         *
9484         * The error handler is called when a [[Transition]] is rejected or when any error occurred during the Transition.
9485         * This includes errors caused by resolves and transition hooks.
9486         *
9487         * Note:
9488         * This handler does not receive certain Transition rejections.
9489         * Redirected and Ignored Transitions are not considered to be errors by [[StateService.transitionTo]].
9490         *
9491         * The built-in default error handler logs the error to the console.
9492         *
9493         * You can provide your own custom handler.
9494         *
9495         * #### Example:
9496         * ```js
9497         * stateService.defaultErrorHandler(function() {
9498         *   // Do not log transitionTo errors
9499         * });
9500         * ```
9501         *
9502         * @param handler a global error handler function
9503         * @returns the current global error handler
9504         */
9505        StateService.prototype.defaultErrorHandler = function (handler) {
9506            return (this._defaultErrorHandler = handler || this._defaultErrorHandler);
9507        };
9508        StateService.prototype.get = function (stateOrName, base) {
9509            var reg = this.router.stateRegistry;
9510            if (arguments.length === 0)
9511                return reg.get();
9512            return reg.get(stateOrName, base || this.$current);
9513        };
9514        /**
9515         * Lazy loads a state
9516         *
9517         * Explicitly runs a state's [[StateDeclaration.lazyLoad]] function.
9518         *
9519         * @param stateOrName the state that should be lazy loaded
9520         * @param transition the optional Transition context to use (if the lazyLoad function requires an injector, etc)
9521         * Note: If no transition is provided, a noop transition is created using the from the current state to the current state.
9522         * This noop transition is not actually run.
9523         *
9524         * @returns a promise to lazy load
9525         */
9526        StateService.prototype.lazyLoad = function (stateOrName, transition) {
9527            var state = this.get(stateOrName);
9528            if (!state || !state.lazyLoad)
9529                throw new Error('Can not lazy load ' + stateOrName);
9530            var currentPath = this.getCurrentPath();
9531            var target = PathUtils.makeTargetState(this.router.stateRegistry, currentPath);
9532            transition = transition || this.router.transitionService.create(currentPath, target);
9533            return lazyLoadState(transition, state);
9534        };
9535        return StateService;
9536    }());
9537
9538    /**
9539     * An angular1-like promise api
9540     *
9541     * This object implements four methods similar to the
9542     * [angular 1 promise api](https://docs.angularjs.org/api/ng/service/$q)
9543     *
9544     * UI-Router evolved from an angular 1 library to a framework agnostic library.
9545     * However, some of the `@uirouter/core` code uses these ng1 style APIs to support ng1 style dependency injection.
9546     *
9547     * This API provides native ES6 promise support wrapped as a $q-like API.
9548     * Internally, UI-Router uses this $q object to perform promise operations.
9549     * The `angular-ui-router` (ui-router for angular 1) uses the $q API provided by angular.
9550     *
9551     * $q-like promise api
9552     */
9553    var $q = {
9554        /** Normalizes a value as a promise */
9555        when: function (val) { return new Promise(function (resolve, reject) { return resolve(val); }); },
9556        /** Normalizes a value as a promise rejection */
9557        reject: function (val) {
9558            return new Promise(function (resolve, reject) {
9559                reject(val);
9560            });
9561        },
9562        /** @returns a deferred object, which has `resolve` and `reject` functions */
9563        defer: function () {
9564            var deferred = {};
9565            deferred.promise = new Promise(function (resolve, reject) {
9566                deferred.resolve = resolve;
9567                deferred.reject = reject;
9568            });
9569            return deferred;
9570        },
9571        /** Like Promise.all(), but also supports object key/promise notation like $q */
9572        all: function (promises) {
9573            if (isArray(promises)) {
9574                return Promise.all(promises);
9575            }
9576            if (isObject(promises)) {
9577                // Convert promises map to promises array.
9578                // When each promise resolves, map it to a tuple { key: key, val: val }
9579                var chain = Object.keys(promises).map(function (key) { return promises[key].then(function (val) { return ({ key: key, val: val }); }); });
9580                // Then wait for all promises to resolve, and convert them back to an object
9581                return $q.all(chain).then(function (values) {
9582                    return values.reduce(function (acc, tuple) {
9583                        acc[tuple.key] = tuple.val;
9584                        return acc;
9585                    }, {});
9586                });
9587            }
9588        },
9589    };
9590
9591    // globally available injectables
9592    var globals = {};
9593    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
9594    var ARGUMENT_NAMES = /([^\s,]+)/g;
9595    /**
9596     * A basic angular1-like injector api
9597     *
9598     * This object implements four methods similar to the
9599     * [angular 1 dependency injector](https://docs.angularjs.org/api/auto/service/$injector)
9600     *
9601     * UI-Router evolved from an angular 1 library to a framework agnostic library.
9602     * However, some of the `@uirouter/core` code uses these ng1 style APIs to support ng1 style dependency injection.
9603     *
9604     * This object provides a naive implementation of a globally scoped dependency injection system.
9605     * It supports the following DI approaches:
9606     *
9607     * ### Function parameter names
9608     *
9609     * A function's `.toString()` is called, and the parameter names are parsed.
9610     * This only works when the parameter names aren't "mangled" by a minifier such as UglifyJS.
9611     *
9612     * ```js
9613     * function injectedFunction(FooService, BarService) {
9614     *   // FooService and BarService are injected
9615     * }
9616     * ```
9617     *
9618     * ### Function annotation
9619     *
9620     * A function may be annotated with an array of dependency names as the `$inject` property.
9621     *
9622     * ```js
9623     * injectedFunction.$inject = [ 'FooService', 'BarService' ];
9624     * function injectedFunction(fs, bs) {
9625     *   // FooService and BarService are injected as fs and bs parameters
9626     * }
9627     * ```
9628     *
9629     * ### Array notation
9630     *
9631     * An array provides the names of the dependencies to inject (as strings).
9632     * The function is the last element of the array.
9633     *
9634     * ```js
9635     * [ 'FooService', 'BarService', function (fs, bs) {
9636     *   // FooService and BarService are injected as fs and bs parameters
9637     * }]
9638     * ```
9639     *
9640     * @type {$InjectorLike}
9641     */
9642    var $injector = {
9643        /** Gets an object from DI based on a string token */
9644        get: function (name) { return globals[name]; },
9645        /** Returns true if an object named `name` exists in global DI */
9646        has: function (name) { return $injector.get(name) != null; },
9647        /**
9648         * Injects a function
9649         *
9650         * @param fn the function to inject
9651         * @param context the function's `this` binding
9652         * @param locals An object with additional DI tokens and values, such as `{ someToken: { foo: 1 } }`
9653         */
9654        invoke: function (fn, context, locals) {
9655            var all = extend({}, globals, locals || {});
9656            var params = $injector.annotate(fn);
9657            var ensureExist = assertPredicate(function (key) { return all.hasOwnProperty(key); }, function (key) { return "DI can't find injectable: '" + key + "'"; });
9658            var args = params.filter(ensureExist).map(function (x) { return all[x]; });
9659            if (isFunction(fn))
9660                return fn.apply(context, args);
9661            else
9662                return fn.slice(-1)[0].apply(context, args);
9663        },
9664        /**
9665         * Returns a function's dependencies
9666         *
9667         * Analyzes a function (or array) and returns an array of DI tokens that the function requires.
9668         * @return an array of `string`s
9669         */
9670        annotate: function (fn) {
9671            if (!isInjectable(fn))
9672                throw new Error("Not an injectable function: " + fn);
9673            if (fn && fn.$inject)
9674                return fn.$inject;
9675            if (isArray(fn))
9676                return fn.slice(0, -1);
9677            var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
9678            var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
9679            return result || [];
9680        },
9681    };
9682
9683    var keyValsToObjectR = function (accum, _a) {
9684        var key = _a[0], val = _a[1];
9685        if (!accum.hasOwnProperty(key)) {
9686            accum[key] = val;
9687        }
9688        else if (isArray(accum[key])) {
9689            accum[key].push(val);
9690        }
9691        else {
9692            accum[key] = [accum[key], val];
9693        }
9694        return accum;
9695    };
9696    var getParams = function (queryString) {
9697        return queryString.split('&').filter(identity).map(splitEqual).reduce(keyValsToObjectR, {});
9698    };
9699    function parseUrl$1(url) {
9700        var orEmptyString = function (x) { return x || ''; };
9701        var _a = splitHash(url).map(orEmptyString), beforehash = _a[0], hash = _a[1];
9702        var _b = splitQuery(beforehash).map(orEmptyString), path = _b[0], search = _b[1];
9703        return { path: path, search: search, hash: hash, url: url };
9704    }
9705    var buildUrl = function (loc) {
9706        var path = loc.path();
9707        var searchObject = loc.search();
9708        var hash = loc.hash();
9709        var search = Object.keys(searchObject)
9710            .map(function (key) {
9711            var param = searchObject[key];
9712            var vals = isArray(param) ? param : [param];
9713            return vals.map(function (val) { return key + '=' + val; });
9714        })
9715            .reduce(unnestR, [])
9716            .join('&');
9717        return path + (search ? '?' + search : '') + (hash ? '#' + hash : '');
9718    };
9719    function locationPluginFactory(name, isHtml5, serviceClass, configurationClass) {
9720        return function (uiRouter) {
9721            var service = (uiRouter.locationService = new serviceClass(uiRouter));
9722            var configuration = (uiRouter.locationConfig = new configurationClass(uiRouter, isHtml5));
9723            function dispose(router) {
9724                router.dispose(service);
9725                router.dispose(configuration);
9726            }
9727            return { name: name, service: service, configuration: configuration, dispose: dispose };
9728        };
9729    }
9730
9731    /** A base `LocationServices` */
9732    var BaseLocationServices = /** @class */ (function () {
9733        function BaseLocationServices(router, fireAfterUpdate) {
9734            var _this = this;
9735            this.fireAfterUpdate = fireAfterUpdate;
9736            this._listeners = [];
9737            this._listener = function (evt) { return _this._listeners.forEach(function (cb) { return cb(evt); }); };
9738            this.hash = function () { return parseUrl$1(_this._get()).hash; };
9739            this.path = function () { return parseUrl$1(_this._get()).path; };
9740            this.search = function () { return getParams(parseUrl$1(_this._get()).search); };
9741            this._location = root.location;
9742            this._history = root.history;
9743        }
9744        BaseLocationServices.prototype.url = function (url, replace) {
9745            if (replace === void 0) { replace = true; }
9746            if (isDefined(url) && url !== this._get()) {
9747                this._set(null, null, url, replace);
9748                if (this.fireAfterUpdate) {
9749                    this._listeners.forEach(function (cb) { return cb({ url: url }); });
9750                }
9751            }
9752            return buildUrl(this);
9753        };
9754        BaseLocationServices.prototype.onChange = function (cb) {
9755            var _this = this;
9756            this._listeners.push(cb);
9757            return function () { return removeFrom(_this._listeners, cb); };
9758        };
9759        BaseLocationServices.prototype.dispose = function (router) {
9760            deregAll(this._listeners);
9761        };
9762        return BaseLocationServices;
9763    }());
9764
9765    var __extends = (undefined && undefined.__extends) || (function () {
9766        var extendStatics = function (d, b) {
9767            extendStatics = Object.setPrototypeOf ||
9768                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
9769                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
9770            return extendStatics(d, b);
9771        };
9772        return function (d, b) {
9773            extendStatics(d, b);
9774            function __() { this.constructor = d; }
9775            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9776        };
9777    })();
9778    /** A `LocationServices` that uses the browser hash "#" to get/set the current location */
9779    var HashLocationService = /** @class */ (function (_super) {
9780        __extends(HashLocationService, _super);
9781        function HashLocationService(router) {
9782            var _this = _super.call(this, router, false) || this;
9783            root.addEventListener('hashchange', _this._listener, false);
9784            return _this;
9785        }
9786        HashLocationService.prototype._get = function () {
9787            return trimHashVal(this._location.hash);
9788        };
9789        HashLocationService.prototype._set = function (state, title, url, replace) {
9790            this._location.hash = url;
9791        };
9792        HashLocationService.prototype.dispose = function (router) {
9793            _super.prototype.dispose.call(this, router);
9794            root.removeEventListener('hashchange', this._listener);
9795        };
9796        return HashLocationService;
9797    }(BaseLocationServices));
9798
9799    var __extends$1 = (undefined && undefined.__extends) || (function () {
9800        var extendStatics = function (d, b) {
9801            extendStatics = Object.setPrototypeOf ||
9802                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
9803                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
9804            return extendStatics(d, b);
9805        };
9806        return function (d, b) {
9807            extendStatics(d, b);
9808            function __() { this.constructor = d; }
9809            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9810        };
9811    })();
9812    /** A `LocationServices` that gets/sets the current location from an in-memory object */
9813    var MemoryLocationService = /** @class */ (function (_super) {
9814        __extends$1(MemoryLocationService, _super);
9815        function MemoryLocationService(router) {
9816            return _super.call(this, router, true) || this;
9817        }
9818        MemoryLocationService.prototype._get = function () {
9819            return this._url;
9820        };
9821        MemoryLocationService.prototype._set = function (state, title, url, replace) {
9822            this._url = url;
9823        };
9824        return MemoryLocationService;
9825    }(BaseLocationServices));
9826
9827    var __extends$2 = (undefined && undefined.__extends) || (function () {
9828        var extendStatics = function (d, b) {
9829            extendStatics = Object.setPrototypeOf ||
9830                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
9831                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
9832            return extendStatics(d, b);
9833        };
9834        return function (d, b) {
9835            extendStatics(d, b);
9836            function __() { this.constructor = d; }
9837            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9838        };
9839    })();
9840    /**
9841     * A `LocationServices` that gets/sets the current location using the browser's `location` and `history` apis
9842     *
9843     * Uses `history.pushState` and `history.replaceState`
9844     */
9845    var PushStateLocationService = /** @class */ (function (_super) {
9846        __extends$2(PushStateLocationService, _super);
9847        function PushStateLocationService(router) {
9848            var _this = _super.call(this, router, true) || this;
9849            _this._config = router.urlService.config;
9850            root.addEventListener('popstate', _this._listener, false);
9851            return _this;
9852        }
9853        /**
9854         * Gets the base prefix without:
9855         * - trailing slash
9856         * - trailing filename
9857         * - protocol and hostname
9858         *
9859         * If <base href='/base/'>, this returns '/base'.
9860         * If <base href='/foo/base/'>, this returns '/foo/base'.
9861         * If <base href='/base/index.html'>, this returns '/base'.
9862         * If <base href='http://localhost:8080/base/index.html'>, this returns '/base'.
9863         * If <base href='/base'>, this returns ''.
9864         * If <base href='http://localhost:8080'>, this returns ''.
9865         * If <base href='http://localhost:8080/'>, this returns ''.
9866         *
9867         * See: https://html.spec.whatwg.org/dev/semantics.html#the-base-element
9868         */
9869        PushStateLocationService.prototype._getBasePrefix = function () {
9870            return stripLastPathElement(this._config.baseHref());
9871        };
9872        PushStateLocationService.prototype._get = function () {
9873            var _a = this._location, pathname = _a.pathname, hash = _a.hash, search = _a.search;
9874            search = splitQuery(search)[1]; // strip ? if found
9875            hash = splitHash(hash)[1]; // strip # if found
9876            var basePrefix = this._getBasePrefix();
9877            var exactBaseHrefMatch = pathname === this._config.baseHref();
9878            var startsWithBase = pathname.substr(0, basePrefix.length) === basePrefix;
9879            pathname = exactBaseHrefMatch ? '/' : startsWithBase ? pathname.substring(basePrefix.length) : pathname;
9880            return pathname + (search ? '?' + search : '') + (hash ? '#' + hash : '');
9881        };
9882        PushStateLocationService.prototype._set = function (state, title, url, replace) {
9883            var basePrefix = this._getBasePrefix();
9884            var slash = url && url[0] !== '/' ? '/' : '';
9885            var fullUrl = url === '' || url === '/' ? this._config.baseHref() : basePrefix + slash + url;
9886            if (replace) {
9887                this._history.replaceState(state, title, fullUrl);
9888            }
9889            else {
9890                this._history.pushState(state, title, fullUrl);
9891            }
9892        };
9893        PushStateLocationService.prototype.dispose = function (router) {
9894            _super.prototype.dispose.call(this, router);
9895            root.removeEventListener('popstate', this._listener);
9896        };
9897        return PushStateLocationService;
9898    }(BaseLocationServices));
9899
9900    /** A `LocationConfig` mock that gets/sets all config from an in-memory object */
9901    var MemoryLocationConfig = /** @class */ (function () {
9902        function MemoryLocationConfig() {
9903            var _this = this;
9904            this.dispose = noop;
9905            this._baseHref = '';
9906            this._port = 80;
9907            this._protocol = 'http';
9908            this._host = 'localhost';
9909            this._hashPrefix = '';
9910            this.port = function () { return _this._port; };
9911            this.protocol = function () { return _this._protocol; };
9912            this.host = function () { return _this._host; };
9913            this.baseHref = function () { return _this._baseHref; };
9914            this.html5Mode = function () { return false; };
9915            this.hashPrefix = function (newval) { return (isDefined(newval) ? (_this._hashPrefix = newval) 
9915: _this._hashPrefix); };
9916        }
9917        return MemoryLocationConfig;
9918    }());
9919
9920    /** A `LocationConfig` that delegates to the browser's `location` object */
9921    var BrowserLocationConfig = /** @class */ (function () {
9922        function BrowserLocationConfig(router, _isHtml5) {
9923            if (_isHtml5 === void 0) { _isHtml5 = false; }
9924            this._isHtml5 = _isHtml5;
9925            this._baseHref = undefined;
9926            this._hashPrefix = '';
9927        }
9928        BrowserLocationConfig.prototype.port = function () {
9929            if (location.port) {
9930                return Number(location.port);
9931            }
9932            return this.protocol() === 'https' ? 443 : 80;
9933        };
9934        BrowserLocationConfig.prototype.protocol = function () {
9935            return location.protocol.replace(/:/g, '');
9936        };
9937        BrowserLocationConfig.prototype.host = function () {
9938            return location.hostname;
9939        };
9940        BrowserLocationConfig.prototype.html5Mode = function () {
9941            return this._isHtml5;
9942        };
9943        BrowserLocationConfig.prototype.hashPrefix = function (newprefix) {
9944            return isDefined(newprefix) ? (this._hashPrefix = newprefix) : this._hashPrefix;
9945        };
9946        BrowserLocationConfig.prototype.baseHref = function (href) {
9947            if (isDefined(href))
9948                this._baseHref = href;
9949            if (isUndefined(this._baseHref))
9950                this._baseHref = this.getBaseHref();
9951            return this._baseHref;
9952        };
9953        BrowserLocationConfig.prototype.getBaseHref = function () {
9954            var baseTag = document.getElementsByTagName('base')[0];
9955            if (baseTag && baseTag.href) {
9956                return baseTag.href.replace(/^([^/:]*:)?\/\/[^/]*/, '');
9957            }
9958            return this._isHtml5 ? '/' : location.pathname || '/';
9959        };
9960        BrowserLocationConfig.prototype.dispose = function () { };
9961        return BrowserLocationConfig;
9962    }());
9963
9964    function servicesPlugin(router) {
9965        services.$injector = $injector;
9966        services.$q = $q;
9967        return { name: 'vanilla.services', $q: $q, $injector: $injector, dispose: function () { return null; } };
9968    }
9969    /** A `UIRouterPlugin` uses the browser hash to get/set the current location */
9970    var hashLocationPlugin = locationPluginFactory('vanilla.hashBangLocation', false, HashLocationService, BrowserLocationConfig);
9971    /** A `UIRouterPlugin` that gets/sets the current location using the browser's `location` and `history` apis */
9972    var pushStateLocationPlugin = locationPluginFactory('vanilla.pushStateLocation', true, PushStateLocationService, BrowserLocationConfig);
9973    /** A `UIRouterPlugin` that gets/sets the current location from an in-memory object */
9974    var memoryLocationPlugin = locationPluginFactory('vanilla.memoryLocation', false, MemoryLocationService, MemoryLocationConfig);
9975
9976    var UIRouterPluginBase = /** @class */ (function () {
9977        function UIRouterPluginBase() {
9978        }
9979        UIRouterPluginBase.prototype.dispose = function (router) { };
9980        return UIRouterPluginBase;
9981    }());
9982
9983    var index = /*#__PURE__*/Object.freeze({
9984        __proto__: null,
9985        root: root,
9986        fromJson: fromJson,
9987        toJson: toJson,
9988        forEach: forEach,
9989        extend: extend,
9990        equals: equals,
9991        identity: identity,
9992        noop: noop,
9993        createProxyFunctions: createProxyFunctions,
9994        inherit: inherit,
9995        inArray: inArray,
9996        _inArray: _inArray,
9997        removeFrom: removeFrom,
9998        _removeFrom: _removeFrom,
9999        pushTo: pushTo,
10000        _pushTo: _pushTo,
10001        deregAll: deregAll,
10002        defaults: defaults,
10003        mergeR: mergeR,
10004        ancestors: ancestors,
10005        pick: pick,
10006        omit: omit,
10007        pluck: pluck,
10008        filter: filter,
10009        find: find,
10010        mapObj: mapObj,
10011        map: map,
10012        values: values,
10013        allTrueR: allTrueR,
10014        anyTrueR: anyTrueR,
10015        unnestR: unnestR,
10016        flattenR: flattenR,
10017        pushR: pushR,
10018        uniqR: uniqR,
10019        unnest: unnest,
10020        flatten: flatten,
10021        assertPredicate: assertPredicate,
10022        assertMap: assertMap,
10023        assertFn: assertFn,
10024        pairs: pairs,
10025        arrayTuples: arrayTuples,
10026        applyPairs: applyPairs,
10027        tail: tail,
10028        copy: copy,
10029        _extend: _extend,
10030        silenceUncaughtInPromise: silenceUncaughtInPromise,
10031        silentRejection: silentRejection,
10032        makeStub: makeStub,
10033        services: services,
10034        Glob: Glob,
10035        curry: curry,
10036        compose: compose,
10037        pipe: pipe,
10038        prop: prop,
10039        propEq: propEq,
10040        parse: parse,
10041        not: not,
10042        and: and,
10043        or: or,
10044        all: all,
10045        any: any,
10046        is: is,
10047        eq: eq,
10048        val: val,
10049        invoke: invoke,
10050        pattern: pattern,
10051        isUndefined: isUndefined,
10052        isDefined: isDefined,
10053        isNull: isNull,
10054        isNullOrUndefined: isNullOrUndefined,
10055        isFunction: isFunction,
10056        isNumber: isNumber,
10057        isString: isString,
10058        isObject: isObject,
10059        isArray: isArray,
10060        isDate: isDate,
10061        isRegExp: isRegExp,
10062        isInjectable: isInjectable,
10063        isPromise: isPromise,
10064        Queue: Queue,
10065        maxLength: maxLength,
10066        padString: padString,
10067        kebobString: kebobString,
10068        functionToString: functionToString,
10069        fnToString: fnToString,
10070        stringify: stringify,
10071        beforeAfterSubstr: beforeAfterSubstr,
10072        hostRegex: hostRegex,
10073        stripLastPathElement: stripLastPathElement,
10074        splitHash: splitHash,
10075        splitQuery: splitQuery,
10076        splitEqual: splitEqual,
10077        trimHashVal: trimHashVal,
10078        splitOnDelim: splitOnDelim,
10079        joinNeighborsR: joinNeighborsR,
10080        get Category () { return exports.Category; },
10081        Trace: Trace,
10082        trace: trace,
10083        get DefType () { return exports.DefType; },
10084        Param: Param,
10085        ParamTypes: ParamTypes,
10086        StateParams: StateParams,
10087        ParamType: ParamType,
10088        PathNode: PathNode,
10089        PathUtils: PathUtils,
10090        resolvePolicies: resolvePolicies,
10091        defaultResolvePolicy: defaultResolvePolicy,
10092        Resolvable: Resolvable,
10093        NATIVE_INJECTOR_TOKEN: NATIVE_INJECTOR_TOKEN,
10094        ResolveContext: ResolveContext,
10095        resolvablesBuilder: resolvablesBuilder,
10096        StateBuilder: StateBuilder,
10097        StateObject: StateObject,
10098        StateMatcher: StateMatcher,
10099        StateQueueManager: StateQueueManager,
10100        StateRegistry: StateRegistry,
10101        StateService: StateService,
10102        TargetState: TargetState,
10103        get TransitionHookPhase () { return exports.TransitionHookPhase; },
10104        get TransitionHookScope () { return exports.TransitionHookScope; },
10105        HookBuilder: HookBuilder,
10106        matchState: matchState,
10107        RegisteredHook: RegisteredHook,
10108        makeEvent: makeEvent,
10109        get RejectType () { return exports.RejectType; },
10110        Rejection: Rejection,
10111        Transition: Transition,
10112        TransitionHook: TransitionHook,
10113        TransitionEventType: TransitionEventType,
10114        defaultTransOpts: defaultTransOpts,
10115        TransitionService: TransitionService,
10116        UrlRules: UrlRules,
10117        UrlConfig: UrlConfig,
10118        UrlMatcher: UrlMatcher,
10119        ParamFactory: ParamFactory,
10120        UrlMatcherFactory: UrlMatcherFactory,
10121        UrlRouter: UrlRouter,
10122        UrlRuleFactory: UrlRuleFactory,
10123        BaseUrlRule: BaseUrlRule,
10124        UrlService: UrlService,
10125        ViewService: ViewService,
10126        UIRouterGlobals: UIRouterGlobals,
10127        UIRouter: UIRouter,
10128        $q: $q,
10129        $injector: $injector,
10130        BaseLocationServices: BaseLocationServices,
10131        HashLocationService: HashLocationService,
10132        MemoryLocationService: MemoryLocationService,
10133        PushStateLocationService: PushStateLocationService,
10134        MemoryLocationConfig: MemoryLocationConfig,
10135        BrowserLocationConfig: BrowserLocationConfig,
10136        keyValsToObjectR: keyValsToObjectR,
10137        getParams: getParams,
10138        parseUrl: parseUrl$1,
10139        buildUrl: buildUrl,
10140        locationPluginFactory: locationPluginFactory,
10141        servicesPlugin: servicesPlugin,
10142        hashLocationPlugin: hashLocationPlugin,
10143        pushStateLocationPlugin: pushStateLocationPlugin,
10144        memoryLocationPlugin: memoryLocationPlugin,
10145        UIRouterPluginBase: UIRouterPluginBase
10146    });
10147
10148    /** @publicapi @module ng1 */ /** */
10149    /** @internalapi */
10150    function getNg1ViewConfigFactory() {
10151        var templateFactory = null;
10152        return function (path, view) {
10153            templateFactory = templateFactory || services.$injector.get('$templateFactory');
10154            return [new Ng1ViewConfig(path, view, templateFactory)];
10155        };
10156    }
10157    /** @internalapi */
10158    var hasAnyKey = function (keys, obj) { return keys.reduce(function (acc, key) { return acc || isDefined(obj[key]); }, false); };
10159    /**
10160     * This is a [[StateBuilder.builder]] function for angular1 `views`.
10161     *
10162     * When the [[StateBuilder]] builds a [[StateObject]] object from a raw [[StateDeclaration]], this builder
10163     * handles the `views` property with logic specific to @uirouter/angularjs (ng1).
10164     *
10165     * If no `views: {}` property exists on the [[StateDeclaration]], then it creates the `views` object
10166     * and applies the state-level configuration to a view named `$default`.
10167     *
10168     * @internalapi
10169     */
10170    function ng1ViewsBuilder(state) {
10171        // Do not process root state
10172        if (!state.parent)
10173            return {};
10174        var tplKeys = ['templateProvider', 'templateUrl', 'template', 'notify', 'async'], ctrlKeys = ['controller', 'controllerProvider', 'controllerAs', 'resolveAs'], compKeys = ['component', 'bindings', 'componentProvider'], nonCompKeys = tplKeys.concat(ctrlKeys), allViewKeys = compKeys.concat(nonCompKeys);
10175        // Do not allow a state to have both state-level props and also a `views: {}` property.
10176        // A state without a `views: {}` property can declare properties for the `$default` view as properties of the state.
10177        // However, the `$default` approach should not be mixed with a separate `views: ` block.
10178        if (isDefined(state.views) && hasAnyKey(allViewKeys, state)) {
10179            throw new Error("State '" + state.name + "' has a 'views' object. " +
10180                "It cannot also have \"view properties\" at the state level.  " +
10181                "Move the following properties into a view (in the 'views' object): " +
10182                (" " + allViewKeys.filter(function (key) { return isDefined(state[key]); }).join(', ')));
10183        }
10184        var views = {}, viewsObject = state.views || { $default: pick(state, allViewKeys) };
10185        forEach(viewsObject, function (config, name) {
10186            // Account for views: { "": { template... } }
10187            name = name || '$default';
10188            // Account for views: { header: "headerComponent" }
10189            if (isString(config))
10190                config = { component: config };
10191            // Make a shallow copy of the config object
10192            config = extend({}, config);
10193            // Do not allow a view to mix props for component-style view with props for template/controller-style view
10194            if (hasAnyKey(compKeys, config) && hasAnyKey(nonCompKeys, config)) {
10195                throw new Error("Cannot combine: " + compKeys.join('|') + " with: " + nonCompKeys.join('|') + " in stateview: '" + name + "@" + state.name + "'");
10196            }
10197            config.resolveAs = config.resolveAs || '$resolve';
10198            config.$type = 'ng1';
10199            config.$context = state;
10200            config.$name = name;
10201            var normalized = ViewService.normalizeUIViewTarget(config.$context, config.$name);
10202            config.$uiViewName = normalized.uiViewName;
10203            config.$uiViewContextAnchor = normalized.uiViewContextAnchor;
10204            views[name] = config;
10205        });
10206        return views;
10207    }
10208    /** @hidden */
10209    var id$1 = 0;
10210    /** @internalapi */
10211    var Ng1ViewConfig = /** @class */ (function () {
10212        function Ng1ViewConfig(path, viewDecl, factory) {
10213            var _this = this;
10214            this.path = path;
10215            this.viewDecl = viewDecl;
10216            this.factory = factory;
10217            this.$id = id$1++;
10218            this.loaded = false;
10219            this.getTemplate = function (uiView, context) {
10220                return _this.component
10221                    ? _this.factory.makeComponentTemplate(uiView, context, _this.component, _this.viewDecl.bindings)
10222                    : _this.template;
10223            };
10224        }
10225        Ng1ViewConfig.prototype.load = function () {
10226            var _this = this;
10227            var $q = services.$q;
10228            var context = new ResolveContext(this.path);
10229            var params = this.path.reduce(function (acc, node) { return extend(acc, node.paramValues); }, {});
10230            var promises = {
10231                template: $q.when(this.factory.fromConfig(this.viewDecl, params, context)),
10232                controller: $q.when(this.getController(context)),
10233            };
10234            return $q.all(promises).then(function (results) {
10235                trace.traceViewServiceEvent('Loaded', _this);
10236                _this.controller = results.controller;
10237                extend(_this, results.template); // Either { template: "tpl" } or { component: "cmpName" }
10238                return _this;
10239            });
10240        };
10241        /**
10242         * Gets the controller for a view configuration.
10243         *
10244         * @returns {Function|Promise.<Function>} Returns a controller, or a promise that resolves to a controller.
10245         */
10246        Ng1ViewConfig.prototype.getController = function (context) {
10247            var provider = this.viewDecl.controllerProvider;
10248            if (!isInjectable(provider))
10249                return this.viewDecl.controller;
10250            var deps = services.$injector.annotate(provider);
10251            var providerFn = isArray(provider) ? tail(provider) : provider;
10252            var resolvable = new Resolvable('', providerFn, deps);
10253            return resolvable.get(context);
10254        };
10255        return Ng1ViewConfig;
10256    }());
10257
10258    /** @publicapi @module view */ /** */
10259    /**
10260     * Service which manages loading of templates from a ViewConfig.
10261     */
10262    var TemplateFactory = /** @class */ (function () {
10263        function TemplateFactory() {
10264            var _this = this;
10265            /** @hidden */ this._useHttp = ng.version.minor < 3;
10266            /** @hidden */ this.$get = [
10267                '$http',
10268                '$templateCache',
10269                '$injector',
10270                function ($http, $templateCache, $injector) {
10271                    _this.$templateRequest = $injector.has && $injector.has('$templateRequest') && $injector.get('$templateRequest');
10272                    _this.$http = $http;
10273                    _this.$templateCache = $templateCache;
10274                    return _this;
10275                },
10276            ];
10277        }
10278        /** @hidden */
10279        TemplateFactory.prototype.useHttpService = function (value) {
10280            this._useHttp = value;
10281        };
10282        /**
10283         * Creates a template from a configuration object.
10284         *
10285         * @param config Configuration object for which to load a template.
10286         * The following properties are search in the specified order, and the first one
10287         * that is defined is used to create the template:
10288         *
10289         * @param params  Parameters to pass to the template function.
10290         * @param context The resolve context associated with the template's view
10291         *
10292         * @return {string|object}  The template html as a string, or a promise for
10293         * that string,or `null` if no template is configured.
10294         */
10295        TemplateFactory.prototype.fromConfig = function (config, params, context) {
10296            var defaultTemplate = '<ui-view></ui-view>';
10297            var asTemplate = function (result) { return services.$q.when(result).then(function (str) { return ({ template: str }); }); };
10298            var asComponent = function (result) { return services.$q.when(result).then(function (str) { return ({ component: str }); }); };
10299            return isDefined(config.template)
10300                ? asTemplate(this.fromString(config.template, params))
10301                : isDefined(config.templateUrl)
10302                    ? asTemplate(this.fromUrl(config.templateUrl, params))
10303                    : isDefined(config.templateProvider)
10304                        ? asTemplate(this.fromProvider(config.templateProvider, params, context))
10305                        : isDefined(config.component)
10306                            ? asComponent(config.component)
10307                            : isDefined(config.componentProvider)
10308                                ? asComponent(this.fromComponentProvider(config.componentProvider, params, context))
10309                                : asTemplate(defaultTemplate);
10310        };
10311        /**
10312         * Creates a template from a string or a function returning a string.
10313         *
10314         * @param template html template as a string or function that returns an html template as a string.
10315         * @param params Parameters to pass to the template function.
10316         *
10317         * @return {string|object} The template html as a string, or a promise for that
10318         * string.
10319         */
10320        TemplateFactory.prototype.fromString = function (template, params) {
10321            return isFunction(template) ? template(params) : template;
10322        };
10323        /**
10324         * Loads a template from the a URL via `$http` and `$templateCache`.
10325         *
10326         * @param {string|Function} url url of the template to load, or a function
10327         * that returns a url.
10328         * @param {Object} params Parameters to pass to the url function.
10329         * @return {string|Promise.<string>} The template html as a string, or a promise
10330         * for that string.
10331         */
10332        TemplateFactory.prototype.fromUrl = function (url, params) {
10333            if (isFunction(url))
10334                url = url(params);
10335            if (url == null)
10336                return null;
10337            if (this._useHttp) {
10338                return this.$http
10339                    .get(url, { cache: this.$templateCache, headers: { Accept: 'text/html' } })
10340                    .then(function (response) {
10341                    return response.data;
10342                });
10343            }
10344            return this.$templateRequest(url);
10345        };
10346        /**
10347         * Creates a template by invoking an injectable provider function.
10348         *
10349         * @param provider Function to invoke via `locals`
10350         * @param {Function} injectFn a function used to invoke the template provider
10351         * @return {string|Promise.<string>} The template html as a string, or a promise
10352         * for that string.
10353         */
10354        TemplateFactory.prototype.fromProvider = function (provider, params, context) {
10355            var deps = services.$injector.annotate(provider);
10356            var providerFn = isArray(provider) ? tail(provider) : provider;
10357            var resolvable = new Resolvable('', providerFn, deps);
10358            return resolvable.get(context);
10359        };
10360        /**
10361         * Creates a component's template by invoking an injectable provider function.
10362         *
10363         * @param provider Function to invoke via `locals`
10364         * @param {Function} injectFn a function used to invoke the template provider
10365         * @return {string} The template html as a string: "<component-name input1='::$resolve.foo'></component-name>".
10366         */
10367        TemplateFactory.prototype.fromComponentProvider = function (provider, params, context) {
10368            var deps = services.$injector.annotate(provider);
10369            var providerFn = isArray(provider) ? tail(provider) : provider;
10370            var resolvable = new Resolvable('', providerFn, deps);
10371            return resolvable.get(context);
10372        };
10373        /**
10374         * Creates a template from a component's name
10375         *
10376         * This implements route-to-component.
10377         * It works by retrieving the component (directive) metadata from the injector.
10378         * It analyses the component's bindings, then constructs a template that instantiates the component.
10379         * The template wires input and output bindings to resolves or from the parent component.
10380         *
10381         * @param uiView {object} The parent ui-view (for binding outputs to callbacks)
10382         * @param context The ResolveContext (for binding outputs to callbacks returned from resolves)
10383         * @param component {string} Component's name in camel case.
10384         * @param bindings An object defining the component's bindings: {foo: '<'}
10385         * @return {string} The template as a string: "<component-name input1='::$resolve.foo'></component-name>".
10386         */
10387        TemplateFactory.prototype.makeComponentTemplate = function (uiView, context, component, bindings) {
10388            bindings = bindings || {};
10389            // Bind once prefix
10390            var prefix = ng.version.minor >= 3 ? '::' : '';
10391            // Convert to kebob name. Add x- prefix if the string starts with `x-` or `data-`
10392            var kebob = function (camelCase) {
10393                var kebobed = kebobString(camelCase);
10394                return /^(x|data)-/.exec(kebobed) ? "x-" + kebobed : kebobed;
10395            };
10396            var attributeTpl = function (input) {
10397                var name = input.name, type = input.type;
10398                var attrName = kebob(name);
10399                // If the ui-view has an attribute which matches a binding on the routed component
10400                // then pass that attribute through to the routed component template.
10401                // Prefer ui-view wired mappings to resolve data, unless the resolve was explicitly bound using `bindings:`
10402                if (uiView.attr(attrName) && !bindings[name])
10403                    return attrName + "='" + uiView.attr(attrName) + "'";
10404                var resolveName = bindings[name] || name;
10405                // Pre-evaluate the expression for "@" bindings by enclosing in {{ }}
10406                // some-attr="{{ ::$resolve.someResolveName }}"
10407                if (type === '@')
10408                    return attrName + "='{{" + prefix + "$resolve." + resolveName + "}}'";
10409                // Wire "&" callbacks to resolves that return a callback function
10410                // Get the result of the resolve (should be a function) and annotate it to get its arguments.
10411                // some-attr="$resolve.someResolveResultName(foo, bar)"
10412                if (type === '&') {
10413                    var res = context.getResolvable(resolveName);
10414                    var fn = res && res.data;
10415                    var args = (fn && services.$injector.annotate(fn)) || [];
10416                    // account for array style injection, i.e., ['foo', function(foo) {}]
10417                    var arrayIdxStr = isArray(fn) ? "[" + (fn.length - 1) + "]" : '';
10418                    return attrName + "='$resolve." + resolveName + arrayIdxStr + "(" + args.join(',') + ")'";
10419                }
10420                // some-attr="::$resolve.someResolveName"
10421                return attrName + "='" + prefix + "$resolve." + resolveName + "'";
10422            };
10423            var attrs = getComponentBindings(component).map(attributeTpl).join(' ');
10424            var kebobName = kebob(component);
10425            return "<" + kebobName + " " + attrs + "></" + kebobName + ">";
10426        };
10427        return TemplateFactory;
10428    }());
10429    // Gets all the directive(s)' inputs ('@', '=', and '<') and outputs ('&')
10430    function getComponentBindings(name) {
10431        var cmpDefs = services.$injector.get(name + 'Directive'); // could be multiple
10432        if (!cmpDefs || !cmpDefs.length)
10433            throw new Error("Unable to find component named '" + name + "'");
10434        return cmpDefs.map(getBindings).reduce(unnestR, []);
10435    }
10436    // Given a directive definition, find its object input attributes
10437    // Use different properties, depending on the type of directive (component, bindToController, normal)
10438    var getBindings = function (def) {
10439        if (isObject(def.bindToController))
10440            return scopeBindings(def.bindToController);
10441        return scopeBindings(def.scope);
10442    };
10443    // for ng 1.2 style, process the scope: { input: "=foo" }
10444    // for ng 1.3 through ng 1.5, process the component's bindToController: { input: "=foo" } object
10445    var scopeBindings = function (bindingsObj) {
10446        return Object.keys(bindingsObj || {})
10447            // [ 'input', [ '=foo', '=', 'foo' ] ]
10448            .map(function (key) { return [key, /^([=<@&])[?]?(.*)/.exec(bindingsObj[key])]; })
10449            // skip malformed values
10450            .filter(function (tuple) { return isDefined(tuple) && isArray(tuple[1]); })
10451            // { name: ('foo' || 'input'), type: '=' }
10452            .map(function (tuple) { return ({ name: tuple[1][2] || tuple[0], type: tuple[1][1] }); });
10453    };
10454
10455    /** @publicapi @module ng1 */ /** */
10456    /**
10457     * The Angular 1 `StateProvider`
10458     *
10459     * The `$stateProvider` works similar to Angular's v1 router, but it focuses purely
10460     * on state.
10461     *
10462     * A state corresponds to a "place" in the application in terms of the overall UI and
10463     * navigation. A state describes (via the controller / template / view properties) what
10464     * the UI looks like and does at that place.
10465     *
10466     * States often have things in common, and the primary way of factoring out these
10467     * commonalities in this model is via the state hierarchy, i.e. parent/child states aka
10468     * nested states.
10469     *
10470     * The `$stateProvider` provides interfaces to declare these states for your app.
10471     */
10472    var StateProvider = /** @class */ (function () {
10473        function StateProvider(stateRegistry, stateService) {
10474            this.stateRegistry = stateRegistry;
10475            this.stateService = stateService;
10476            createProxyFunctions(val(StateProvider.prototype), this, val(this));
10477        }
10478        /**
10479         * Decorates states when they are registered
10480         *
10481         * Allows you to extend (carefully) or override (at your own peril) the
10482         * `stateBuilder` object used internally by [[StateRegistry]].
10483         * This can be used to add custom functionality to ui-router,
10484         * for example inferring templateUrl based on the state name.
10485         *
10486         * When passing only a name, it returns the current (original or decorated) builder
10487         * function that matches `name`.
10488         *
10489         * The builder functions that can be decorated are listed below. Though not all
10490         * necessarily have a good use case for decoration, that is up to you to decide.
10491         *
10492         * In addition, users can attach custom decorators, which will generate new
10493         * properties within the state's internal definition. There is currently no clear
10494         * use-case for this beyond accessing internal states (i.e. $state.$current),
10495         * however, expect this to become increasingly relevant as we introduce additional
10496         * meta-programming features.
10497         *
10498         * **Warning**: Decorators should not be interdependent because the order of
10499         * execution of the builder functions in non-deterministic. Builder functions
10500         * should only be dependent on the state definition object and super function.
10501         *
10502         *
10503         * Existing builder functions and current return values:
10504         *
10505         * - **parent** `{object}` - returns the parent state object.
10506         * - **data** `{object}` - returns state data, including any inherited data that is not
10507         *   overridden by own values (if any).
10508         * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
10509         *   or `null`.
10510         * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
10511         *   navigable).
10512         * - **params** `{object}` - returns an array of state params that are ensured to
10513         *   be a super-set of parent's params.
10514         * - **views** `{object}` - returns a views object where each key is an absolute view
10515         *   name (i.e. "viewName@stateName") and each value is the config object
10516         *   (template, controller) for the view. Even when you don't use the views object
10517         *   explicitly on a state config, one is still created for you internally.
10518         *   So by decorating this builder function you have access to decorating template
10519         *   and controller properties.
10520         * - **ownParams** `{object}` - returns an array of params that belong to the state,
10521         *   not including any params defined by ancestor states.
10522         * - **path** `{string}` - returns the full path from the root down to this state.
10523         *   Needed for state activation.
10524         * - **includes** `{object}` - returns an object that includes every state that
10525         *   would pass a `$state.includes()` test.
10526         *
10527         * #### Example:
10528         * Override the internal 'views' builder with a function that takes the state
10529         * definition, and a reference to the internal function being overridden:
10530         * ```js
10531         * $stateProvider.decorator('views', function (state, parent) {
10532         *   let result = {},
10533         *       views = parent(state);
10534         *
10535         *   angular.forEach(views, function (config, name) {
10536         *     let autoName = (state.name + '.' + name).replace('.', '/');
10537         *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
10538         *     result[name] = config;
10539         *   });
10540         *   return result;
10541         * });
10542         *
10543         * $stateProvider.state('home', {
10544         *   views: {
10545         *     'contact.list': { controller: 'ListController' },
10546         *     'contact.item': { controller: 'ItemController' }
10547         *   }
10548         * });
10549         * ```
10550         *
10551         *
10552         * ```js
10553         * // Auto-populates list and item views with /partials/home/contact/list.html,
10554         * // and /partials/home/contact/item.html, respectively.
10555         * $state.go('home');
10556         * ```
10557         *
10558         * @param {string} name The name of the builder function to decorate.
10559         * @param {object} func A function that is responsible for decorating the original
10560         * builder function. The function receives two parameters:
10561         *
10562         *   - `{object}` - state - The state config object.
10563         *   - `{object}` - super - The original builder function.
10564         *
10565         * @return {object} $stateProvider - $stateProvider instance
10566         */
10567        StateProvider.prototype.decorator = function (name, func) {
10568            return this.stateRegistry.decorator(name, func) || this;
10569        };
10570        StateProvider.prototype.state = function (name, definition) {
10571            if (isObject(name)) {
10572                definition = name;
10573            }
10574            else {
10575                definition.name = name;
10576            }
10577            this.stateRegistry.register(definition);
10578            return this;
10579        };
10580        /**
10581         * Registers an invalid state handler
10582         *
10583         * This is a passthrough to [[StateService.onInvalid]] for ng1.
10584         */
10585        StateProvider.prototype.onInvalid = function (callback) {
10586            return this.stateService.onInvalid(callback);
10587        };
10588        return StateProvider;
10589    }());
10590
10591    /** @publicapi @module ng1 */ /** */
10592    /**
10593     * This is a [[StateBuilder.builder]] function for angular1 `onEnter`, `onExit`,
10594     * `onRetain` callback hooks on a [[Ng1StateDeclaration]].
10595     *
10596     * When the [[StateBuilder]] builds a [[StateObject]] object from a raw [[StateDeclaration]], this builder
10597     * ensures that those hooks are injectable for @uirouter/angularjs (ng1).
10598     *
10599     * @internalapi
10600     */
10601    var getStateHookBuilder = function (hookName) {
10602        return function stateHookBuilder(stateObject) {
10603            var hook = stateObject[hookName];
10604            var pathname = hookName === 'onExit' ? 'from' : 'to';
10605            function decoratedNg1Hook(trans, state) {
10606                var resolveContext = new ResolveContext(trans.treeChanges(pathname));
10607                var subContext = resolveContext.subContext(state.$$state());
10608                var locals = extend(getLocals(subContext), { $state$: state, $transition$: trans });
10609                return services.$injector.invoke(hook, this, locals);
10610            }
10611            return hook ? decoratedNg1Hook : undefined;
10612        };
10613    };
10614
10615    /** @publicapi @module ng1 */ /** */
10616    /**
10617     * Implements UI-Router LocationServices and LocationConfig using Angular 1's $location service
10618     * @internalapi
10619     */
10620    var Ng1LocationServices = /** @class */ (function () {
10621        function Ng1LocationServices($locationProvider) {
10622            // .onChange() registry
10623            this._urlListeners = [];
10624            this.$locationProvider = $locationProvider;
10625            var _lp = val($locationProvider);
10626            createProxyFunctions(_lp, this, _lp, ['hashPrefix']);
10627        }
10628        /**
10629         * Applys ng1-specific path parameter encoding
10630         *
10631         * The Angular 1 `$location` service is a bit weird.
10632         * It doesn't allow slashes to be encoded/decoded bi-directionally.
10633         *
10634         * See the writeup at https://github.com/angular-ui/ui-router/issues/2598
10635         *
10636         * This code patches the `path` parameter type so it encoded/decodes slashes as ~2F
10637         *
10638         * @param router
10639         */
10640        Ng1LocationServices.monkeyPatchPathParameterType = function (router) {
10641            var pathType = router.urlMatcherFactory.type('path');
10642            pathType.encode = function (x) {
10643                return x != null ? x.toString().replace(/(~|\/)/g, function (m) { return ({ '~': '~~', '/': '~2F' }[m]); }) : x;
10644            };
10645            pathType.decode = function (x) {
10646                return x != null ? x.toString().replace(/(~~|~2F)/g, function (m) { return ({ '~~': '~', '~2F': '/' }[m]); }) : x;
10647            };
10648        };
10649        // eslint-disable-next-line @typescript-eslint/no-empty-function
10650        Ng1LocationServices.prototype.dispose = function () { };
10651        Ng1LocationServices.prototype.onChange = function (callback) {
10652            var _this = this;
10653            this._urlListeners.push(callback);
10654            return function () { return removeFrom(_this._urlListeners)(callback); };
10655        };
10656        Ng1LocationServices.prototype.html5Mode = function () {
10657            var html5Mode = this.$locationProvider.html5Mode();
10658            html5Mode = isObject(html5Mode) ? html5Mode.enabled : html5Mode;
10659            return html5Mode && this.$sniffer.history;
10660        };
10661        Ng1LocationServices.prototype.baseHref = function () {
10662            return this._baseHref || (this._baseHref = this.$browser.baseHref() || this.$window.location.pathname);
10663        };
10664        Ng1LocationServices.prototype.url = function (newUrl, replace, state) {
10665            if (replace === void 0) { replace = false; }
10666            if (isDefined(newUrl))
10667                this.$location.url(newUrl);
10668            if (replace)
10669                this.$location.replace();
10670            if (state)
10671                this.$location.state(state);
10672            return this.$location.url();
10673        };
10674        Ng1LocationServices.prototype._runtimeServices = function ($rootScope, $location, $sniffer, $browser, $window) {
10675            var _this = this;
10676            this.$location = $location;
10677            this.$sniffer = $sniffer;
10678            this.$browser = $browser;
10679            this.$window = $window;
10680            // Bind $locationChangeSuccess to the listeners registered in LocationService.onChange
10681            $rootScope.$on('$locationChangeSuccess', function (evt) { return _this._urlListeners.forEac
10681h(function (fn) { return fn(evt); }); });
10682            var _loc = val($location);
10683            // Bind these LocationService functions to $location
10684            createProxyFunctions(_loc, this, _loc, ['replace', 'path', 'search', 'hash']);
10685            // Bind these LocationConfig functions to $location
10686            createProxyFunctions(_loc, this, _loc, ['port', 'protocol', 'host']);
10687        };
10688        return Ng1LocationServices;
10689    }());
10690
10691    /** @publicapi @module url */ /** */
10692    /**
10693     * Manages rules for client-side URL
10694     *
10695     * ### Deprecation warning:
10696     * This class is now considered to be an internal API
10697     * Use the [[UrlService]] instead.
10698     * For configuring URL rules, use the [[UrlRulesApi]] which can be found as [[UrlService.rules]].
10699     *
10700     * This class manages the router rules for what to do when the URL changes.
10701     *
10702     * This provider remains for backwards compatibility.
10703     *
10704     * @internalapi
10705     * @deprecated
10706     */
10707    var UrlRouterProvider = /** @class */ (function () {
10708        /** @hidden */
10709        function UrlRouterProvider(/** @hidden */ router) {
10710            this.router = router;
10711        }
10712        UrlRouterProvider.injectableHandler = function (router, handler) {
10713            return function (match) { return services.$injector.invoke(handler, null, { $match: match, $stateParams: router.globals.params }); };
10714        };
10715        /** @hidden */
10716        UrlRouterProvider.prototype.$get = function () {
10717            var urlService = this.router.urlService;
10718            this.router.urlRouter.update(true);
10719            if (!urlService.interceptDeferred)
10720                urlService.listen();
10721            return this.router.urlRouter;
10722        };
10723        /**
10724         * Registers a url handler function.
10725         *
10726         * Registers a low level url handler (a `rule`).
10727         * A rule detects specific URL patterns and returns a redirect, or performs s
10727ome action.
10728         *
10729         * If a rule returns a string, the URL is replaced with the string, and all rules are fired again.
10730         *
10731         * #### Example:
10732         * ```js
10733         * var app = angular.module('app', ['ui.router.router']);
10734         *
10735         * app.config(function ($urlRouterProvider) {
10736         *   // Here's an example of how you might allow case insensitive urls
10737         *   $urlRouterProvider.rule(function ($injector, $location) {
10738         *     var path = $location.path(),
10739         *         normalized = path.toLowerCase();
10740         *
10741         *     if (path !== normalized) {
10742         *       return normalized;
10743         *     }
10744         *   });
10745         * });
10746         * ```
10747         *
10748         * @param ruleFn
10749         * Handler function that takes `$injector` and `$location` services as arguments.
10750         * You can use them to detect a url and return a different url as a string.
10751         *
10752         * @return [[UrlRouterProvider]] (`this`)
10753         */
10754        UrlRouterProvider.prototype.rule = function (ruleFn) {
10755            var _this = this;
10756            if (!isFunction(ruleFn))
10757                throw new Error("'rule' must be a function");
10758            var match = function () { return ruleFn(services.$injector, _this.router.locationService); };
10759            var rule = new BaseUrlRule(match, identity);
10760            this.router.urlService.rules.rule(rule);
10761            return this;
10762        };
10763        /**
10764         * Defines the path or behavior to use when no url can be matched.
10765         *
10766         * #### Example:
10767         * ```js
10768         * var app = angular.module('app', ['ui.router.router']);
10769         *
10770         * app.config(function ($urlRouterProvider) {
10771         *   // if the path doesn't match any of the urls you configured
10772         *   // otherwise will take care of routing the user to the
10773         *   // specified url
10774         *   $urlRouterProvider.otherwise('/index');
10775         *
10776         *   // Example of using function rule as param
10777         *   $urlRouterProvider.otherwise(function ($injector, $location) {
10778         *     return '/a/valid/url';
10779         *   });
10780         * });
10781         * ```
10782         *
10783         * @param rule
10784         * The url path you want to redirect to or a function rule that returns the url path or performs a `$state.go()`.
10785         * The function version is passed two params: `$injector` and `$location` services, and should return a url string.
10786         *
10787         * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
10788         */
10789        UrlRouterProvider.prototype.otherwise = function (rule) {
10790            var _this = this;
10791            var urlRules = this.router.urlService.rules;
10792            if (isString(rule)) {
10793                urlRules.otherwise(rule);
10794            }
10795            else if (isFunction(rule)) {
10796                urlRules.otherwise(function () { return rule(services.$injector, _this.router.locationService); });
10797            }
10798            else {
10799                throw new Error("'rule' must be a string or function");
10800            }
10801            return this;
10802        };
10803        /**
10804         * Registers a handler for a given url matching.
10805         *
10806         * If the handler is a string, it is
10807         * treated as a redirect, and is interpolated according to the syntax of match
10808         * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).
10809         *
10810         * If the handler is a function, it is injectable.
10811         * It gets invoked if `$location` matches.
10812         * You have the option of inject the match object as `$match`.
10813         *
10814         * The handler can return
10815         *
10816         * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
10817         *   will continue trying to find another one that matches.
10818         * - **string** which is treated as a redirect and passed to `$location.url()`
10819         * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
10820         *
10821         * #### Example:
10822         * ```js
10823         * var app = angular.module('app', ['ui.router.router']);
10824         *
10825         * app.config(function ($urlRouterProvider) {
10826         *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
10827         *     if ($state.$current.navigable !== state ||
10828         *         !equalForKeys($match, $stateParams) {
10829         *      $state.transitionTo(state, $match, false);
10830         *     }
10831         *   });
10832         * });
10833         * ```
10834         *
10835         * @param what A pattern string to match, compiled as a [[UrlMatcher]].
10836         * @param handler The path (or function that returns a path) that you want to redirect your user to.
10837         * @param ruleCallback [optional] A callback that receives the `rule` registered with [[UrlMatcher.rule]]
10838         *
10839         * Note: the handler may also invoke arbitrary code, such as `$state.go()`
10840         */
10841        UrlRouterProvider.prototype.when = function (what, handler) {
10842            if (isArray(handler) || isFunction(handler)) {
10843                handler = UrlRouterProvider.injectableHandler(this.router, handler);
10844            }
10845            this.router.urlService.rules.when(what, handler);
10846            return this;
10847        };
10848        /**
10849         * Disables monitoring of the URL.
10850         *
10851         * Call this method before UI-Router has bootstrapped.
10852         * It will stop UI-Router from performing the initial url sync.
10853         *
10854         * This can be useful to perform some asynchronous initialization before the router starts.
10855         * Once the initialization is complete, call [[listen]] to tell UI-Router to start watching and synchronizing the URL.
10856         *
10857         * #### Example:
10858         * ```js
10859         * var app = angular.module('app', ['ui.router']);
10860         *
10861         * app.config(function ($urlRouterProvider) {
10862         *   // Prevent $urlRouter from automatically intercepting URL changes;
10863         *   $urlRouterProvider.deferIntercept();
10864         * })
10865         *
10866         * app.run(function (MyService, $urlRouter, $http) {
10867         *   $http.get("/stuff").then(function(resp) {
10868         *     MyService.doStuff(resp.data);
10869         *     $urlRouter.listen();
10870         *     $urlRouter.sync();
10871         *   });
10872         * });
10873         * ```
10874         *
10875         * @param defer Indicates whether to defer location change interception.
10876         *        Passing no parameter is equivalent to `true`.
10877         */
10878        UrlRouterProvider.prototype.deferIntercept = function (defer) {
10879            this.router.urlService.deferIntercept(defer);
10880        };
10881        return UrlRouterProvider;
10882    }());
10883
10884    /* eslint-disable @typescript-eslint/no-empty-function */
10885    ng.module('ui.router.angular1', []);
10886    var mod_init = ng.module('ui.router.init', ['ng']);
10887    var mod_util = ng.module('ui.router.util', ['ui.router.init']);
10888    var mod_rtr = ng.module('ui.router.router', ['ui.router.util']);
10889    var mod_state = ng.module('ui.router.state', ['ui.router.router', 'ui.router.util', 'ui.router.angular1']);
10890    var mod_main = ng.module('ui.router', ['ui.router.init', 'ui.router.state', 'ui.router.angular1']);
10891    var mod_cmpt = ng.module('ui.router.compat', ['ui.router']);
10892    var router = null;
10893    $uiRouterProvider.$inject = ['$locationProvider'];
10894    /** This angular 1 provider instantiates a Router and exposes its services via the angular injector */
10895    function $uiRouterProvider($locationProvider) {
10896        // Create a new instance of the Router when the $uiRouterProvider is 
10896initialized
10897        router = this.router = new UIRouter();
10898        router.stateProvider = new StateProvider(router.stateRegistry, router.stateService);
10899        // Apply ng1 specific StateBuilder code for `views`, `resolve`, and `onExit/Retain/Enter` properties
10900        router.stateRegistry.decorator('views', ng1ViewsBuilder);
10901        router.stateRegistry.decorator('onExit', getStateHookBuilder('onExit'));
10902        router.stateRegistry.decorator('onRetain', getStateHookBuilder('onRetain'));
10903        router.stateRegistry.decorator('onEnter', getStateHookBuilder('onEnter'));
10904        router.viewService._pluginapi._viewConfigFactory('ng1', getNg1ViewConfigFactory());
10905        // Disable decoding of params by UrlMatcherFactory because $location already handles this
10906        router.urlService.config._decodeParams = false;
10907        var ng1LocationService = (router.locationService = router.locationConfig = new Ng1LocationServices($locationProvider));
10908        Ng1LocationServices.monkeyPatchPathParameterType(router);
10909        // backwards compat: also expose router instance as $uiRouterProvider.router
10910        router['router'] = router;
10911        router['$get'] = $get;
10912        $get.$inject = ['$location', '$browser', '$window', '$sniffer', '$rootScope', '$http', '$templateCache'];
10913        function $get($location, $browser, $window, $sniffer, $rootScope, $http, $templateCache) {
10914            ng1LocationService._runtimeServices($rootScope, $location, $sniffer, $browser, $window);
10915            delete router['router'];
10916            delete router['$get'];
10917            return router;
10918        }
10919        return router;
10920    }
10921    var getProviderFor = function (serviceName) { return [
10922        '$uiRouterProvider',
10923        function ($urp) {
10924            var service = $urp.router[serviceName];
10925            service['$get'] = function () { return service; };
10926            return service;
10927        },
10928    ]; };
10929    // This effectively calls $get() on `$uiRouterProvider` to trigger init (when ng enters runtime)
10930    runBlock.$inject = ['$injector', '$q', '$uiRouter'];
10931    function runBlock($injector, $q, $uiRouter) {
10932        services.$injector = $injector;
10933        services.$q = $q;
10934        // https://github.com/angular-ui/ui-router/issues/3678
10935        if (!Object.prototype.hasOwnProperty.call($injector, 'strictDi')) {
10936            try {
10937                $injector.invoke(function (checkStrictDi) { });
10938            }
10939            catch (error) {
10940                $injector.strictDi = !!/strict mode/.exec(error && error.toString());
10941            }
10942        }
10943        // The $injector is now available.
10944        // Find any resolvables that had dependency annotation deferred
10945        $uiRouter.stateRegistry
10946            .get()
10947            .map(function (x) { return x.$$state().resolvables; })
10948            .reduce(unnestR, [])
10949            .filter(function (x) { return x.deps === 'deferred'; })
10950            .forEach(function (resolvable) { return (resolvable.deps = $injector.annotate(resolvable.resolveFn, $injector.strictDi)); });
10951    }
10952    // $urlRouter service and $urlRouterProvider
10953    var getUrlRouterProvider = function (uiRouter) { return (uiRouter.urlRouterProvider = new UrlRouterProvider(uiRouter)); };
10954    // $state service and $stateProvider
10955    // $urlRouter service and $urlRouterProvider
10956    var getStateProvider = function () { return extend(router.stateProvider, { $get: function () { return router.stateService; } }); };
10957    watchDigests.$inject = ['$rootScope'];
10958    function watchDigests($rootScope) {
10959        $rootScope.$watch(function () {
10960            trace.approximateDigests++;
10961        });
10962    }
10963    mod_init.provider('$uiRouter', $uiRouterProvider);
10964    mod_rtr.provider('$urlRouter', ['$uiRouterProvider', getUrlRouterProvider]);
10965    mod_util.provider('$urlService', getProviderFor('urlService'));
10966    mod_util.provider('$urlMatcherFactory', ['$uiRouterProvider', function () { return router.urlMatcherFactory; }]);
10967    mod_util.provider('$templateFactory', function () { return new TemplateFactory(); });
10968    mod_state.provider('$stateRegistry', getProviderFor('stateRegistry'));
10969    mod_state.provider('$uiRouterGlobals', getProviderFor('globals'));
10970    mod_state.provider('$transitions', getProviderFor('transitionService'));
10971    mod_state.provider('$state', ['$uiRouterProvider', getStateProvider]);
10972    mod_state.factory('$stateParams', ['$uiRouter', function ($uiRouter) { return $uiRouter.globals.params; }]);
10973    mod_main.factory('$view', function () { return router.viewService; });
10974    mod_main.service('$trace', function () { return trace; });
10975    mod_main.run(watchDigests);
10976    mod_util.run(['$urlMatcherFactory', function ($urlMatcherFactory) { }]);
10977    mod_state.run(['$state', function ($state) { }]);
10978    mod_rtr.run(['$urlRouter', function ($urlRouter) { }]);
10979    mod_init.run(runBlock);
10980    /** @hidden TODO: find a place to move this */
10981    var getLocals = function (ctx) {
10982        var tokens = ctx.getTokens().filter(isString);
10983        var tuples = tokens.map(function (key) {
10984            var resolvable = ctx.getResolvable(key);
10985            var waitPolicy = ctx.getPolicy(resolvable).async;
10986            return [key, waitPolicy === 'NOWAIT' ? resolvable.promise : resolvable.data];
10987        });
10988        return tuples.reduce(applyPairs, {});
10989    };
10990
10991    /* eslint-disable @typescript-eslint/no-empty-interface */
10992    /** @hidden */
10993    function parseStateRef(ref) {
10994        var paramsOnly = ref.match(/^\s*({[^}]*})\s*$/);
10995        if (paramsOnly)
10996            ref = '(' + paramsOnly[1] + ')';
10997        var parsed = ref.replace(/\n/g, ' ').match(/^\s*([^(]*?)\s*(\((.*)\))?\s*$/);
10998        if (!parsed || parsed.length !== 4)
10999            throw new Error("Invalid state ref '" + ref + "'");
11000        return { state: parsed[1] || null, paramExpr: parsed[3] || null };
11001    }
11002    /** @hidden */
11003    function stateContext(el) {
11004        var $uiView = el.parent().inheritedData('$uiView');
11005        var path = parse('$cfg.path')($uiView);
11006        return path ? tail(path).state.name : undefined;
11007    }
11008    /** @hidden */
11009    function processedDef($state, $element, def) {
11010        var uiState = def.uiState || $state.current.name;
11011        var uiStateOpts = extend(defaultOpts($element, $state), def.uiStateOpts || {});
11012        var href = $state.href(uiState, def.uiStateParams, uiStateOpts);
11013        return { uiState: uiState, uiStateParams: def.uiStateParams, uiStateOpts: uiStateOpts, href: href };
11014    }
11015    /** @hidden */
11016    function getTypeInfo(el) {
11017        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
11018        var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
11019        var isForm = el[0].nodeName === 'FORM';
11020        return {
11021            attr: isForm ? 'action' : isSvg ? 'xlink:href' : 'href',
11022            isAnchor: el.prop('tagName').toUpperCase() === 'A',
11023            clickable: !isForm,
11024        };
11025    }
11026    /** @hidden */
11027    function clickHook(el, $state, $timeout, type, getDef) {
11028        return function (e) {
11029            var button = e.which || e.button, target = getDef();
11030            if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || el.attr('target'))) {
11031                // HACK: This is to allow ng-clicks to be processed before the transition is initiated:
11032                var transition_1 = $timeout(function () {
11033                    if (!el.attr('disabled')) {
11034                        $state.go(target.uiState, target.uiStateParams, target.uiStateOpts);
11035                    }
11036                });
11037                e.preventDefault();
11038                // if the state has no URL, ignore one preventDefault from the <a> directive.
11039                var ignorePreventDefaultCount_1 = type.isAnchor && !target.href ? 1 : 0;
11040                e.preventDefault = function () {
11041                    if (ignorePreventDefaultCount_1-- <= 0)
11042                        $timeout.cancel(transition_1);
11043                };
11044            }
11045        };
11046    }
11047    /** @hidden */
11048    function defaultOpts(el, $state) {
11049        return {
11050            relative: stateContext(el) || $state.$current,
11051            inherit: true,
11052            source: 'sref',
11053        };
11054    }
11055    /** @hidden */
11056    function bindEvents(element, scope, hookFn, uiStateOpts) {
11057        var events;
11058        if (uiStateOpts) {
11059            events = uiStateOpts.events;
11060        }
11061        if (!isArray(events)) {
11062            events = ['click'];
11063        }
11064        var on = element.on ? 'on' : 'bind';
11065        for (var _i = 0, events_1 = events; _i < events_1.length; _i++) {
11066            var event_1 = events_1[_i];
11067            element[on](event_1, hookFn);
11068        }
11069        scope.$on('$destroy', function () {
11070            var off = element.off ? 'off' : 'unbind';
11071            for (var _i = 0, events_2 = events; _i < events_2.length; _i++) {
11072                var event_2 = events_2[_i];
11073                element[off](event_2, hookFn);
11074            }
11075        });
11076    }
11077    /**
11078     * `ui-sref`: A directive for linking to a state
11079     *
11080     * A directive which links to a state (and optionally, parameters).
11081     * When clicked, this directive activates the linked state with the supplied parameter values.
11082     *
11083     * ### Linked State
11084     * The attribute value of the `ui-sref` is the name of the state to link to.
11085     *
11086     * #### Example:
11087     * This will activate the `home` state when the link is clicked.
11088     * ```html
11089     * <a ui-sref="home">Home</a>
11090     * ```
11091     *
11092     * ### Relative Links
11093     * You can also use relative state paths within `ui-sref`, just like a relative path passed to `$state.go()` ([[StateService.go]]).
11094     * You just need to be aware that the path is relative to the state that *created* the link.
11095     * This allows a state to create a relative `ui-sref` which always targets the same destination.
11096     *
11097     * #### Example:
11098     * Both these links are relative to the parent state, even when a child state is currently active.
11099     * ```html
11100     * <a ui-sref=".child1">child 1 state</a>
11101     * <a ui-sref=".child2">child 2 state</a>
11102     * ```
11103     *
11104     * This link activates the parent state.
11105     * ```html
11106     * <a ui-sref="^">Return</a>
11107     * ```
11108     *
11109     * ### hrefs
11110     * If the linked state has a URL, the directive will automatically generate and
11111     * update the `href` attribute (using the [[StateService.href]]  method).
11112     *
11113     * #### Example:
11114     * Assuming the `users` state has a url of `/users/`
11115     * ```html
11116     * <a ui-sref="users" href="/users/">Users</a>
11117     * ```
11118     *
11119     * ### Parameter Values
11120     * In addition to the state name, a `ui-sref` can include parameter values which are applied when activating the state.
11121     * Param values can be provided in the `ui-sref` value after the state name, enclosed by parentheses.
11122     * The content inside the parentheses is an expression, evaluated to the parameter values.
11123     *
11124     * #### Example:
11125     * This example renders a list of links to users.
11126     * The state's `userId` parameter value comes from each user's `user.id` property.
11127     * ```html
11128     * <li ng-repeat="user in users">
11129     *   <a ui-sref="users.detail({ userId: user.id })">{{ user.displayName }}</a>
11130     * </li>
11131     * ```
11132     *
11133     * Note:
11134     * The parameter values expression is `$watch`ed for updates.
11135     *
11136     * ### Transition Options
11137     * You can specify [[TransitionOptions]] to pass to [[StateService.go]] by using the `ui-sref-opts` attribute.
11138     * Options are restricted to `location`, `inherit`, and `reload`.
11139     *
11140     * #### Example:
11141     * ```html
11142     * <a ui-sref="home" ui-sref-opts="{ reload: true }">Home</a>
11143     * ```
11144     *
11145     * ### Other DOM Events
11146     *
11147     * You can also customize which DOM events to respond to (instead of `click`) by
11148     * providing an `events` array in the `ui-sref-opts` attribute.
11149     *
11150     * #### Example:
11151     * ```html
11152     * <input type="text" ui-sref="contacts" ui-sref-opts="{ events: ['change', 'blur'] }">
11153     * ```
11154     *
11155     * ### Highlighting the active link
11156     * This directive can be used in conjunction with [[uiSrefActive]] to highlight the active link.
11157     *
11158     * ### Examples
11159     * If you have the following template:
11160     *
11161     * ```html
11162     * <a ui-sref="home">Home</a>
11163     * <a ui-sref="about">About</a>
11164     * <a ui-sref="{page: 2}">Next page</a>
11165     *
11166     * <ul>
11167     *     <li ng-repeat="contact in contacts">
11168     *         <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
11169     *     </li>
11170     * </ul>
11171     * ```
11172     *
11173     * Then (assuming the current state is `contacts`) the rendered html including hrefs would be:
11174     *
11175     * ```html
11176     * <a href="#/home" ui-sref="home">Home</a>
11177     * <a href="#/about" ui-sref="about">About</a>
11178     * <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
11179     *
11180     * <ul>
11181     *     <li ng-repeat="contact in contacts">
11182     *         <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
11183     *     </li>
11184     *     <li ng-repeat="contact in contacts">
11185     *         <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
11186     *     </li>
11187     *     <li ng-repeat="contact in contacts">
11188     *         <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
11189     *     </li>
11190     * </ul>
11191     *
11192     * <a href="#/home" ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
11193     * ```
11194     *
11195     * ### Notes
11196     *
11197     * - You can use `ui-sref` to change **only the parameter values** by omitting the state name and parentheses.
11198     * #### Example:
11199     * Sets the `lang` parameter to `en` and remains on the same state.
11200     *
11201     * ```html
11202     * <a ui-sref="{ lang: 'en' }">English</a>
11203     * ```
11204     *
11205     * - A middle-click, right-click, or ctrl-click is handled (natively) by the browser to open the href in a 
11205new window, for example.
11206     *
11207     * - Unlike the parameter values expression, the state name is not `$watch`ed (for performance reasons).
11208     * If you need to dynamically update the state being linked to, use the fully dynamic [[uiState]] directive.
11209     */
11210    var uiSrefDirective;
11211    uiSrefDirective = [
11212        '$uiRouter',
11213        '$timeout',
11214        function $StateRefDirective($uiRouter, $timeout) {
11215            var $state = $uiRouter.stateService;
11216            return {
11217                restrict: 'A',
11218                require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
11219                link: function (scope, element, attrs, uiSrefActive) {
11220                    var type = getTypeInfo(element);
11221                    var active = uiSrefActive[1] || uiSrefActive[0];
11222                    var unlinkInfoFn = null;
11223                    var rawDef = {};
11224                    var getDef = function () { return processedDef($state, element, rawDef); };
11225                    var ref = parseStateRef(attrs.uiSref);
11226                    rawDef.uiState = ref.state;
11227                    rawDef.uiStateOpts = attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {};
11228                    function update() {
11229                        var def = getDef();
11230                        if (unlinkInfoFn)
11231                            unlinkInfoFn();
11232                        if (active)
11233                            unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
11234                        if (def.href != null)
11235                            attrs.$set(type.attr, def.href);
11236                    }
11237                    if (ref.paramExpr) {
11238                        scope.$watch(ref.paramExpr, function (val) {
11239                            rawDef.uiStateParams = extend({}, val);
11240                            update();
11241                        }, true);
11242                        rawDef.uiStateParams = extend({}, scope.$eval(ref.paramExpr));
11243                    }
11244                    update();
11245                    scope.$on('$destroy', $uiRouter.stateRegistry.onStatesChanged(update));
11246                    scope.$on('$destroy', $uiRouter.transitionService.onSuccess({}, update));
11247                    if (!type.clickable)
11248                        return;
11249                    var hookFn = clickHook(element, $state, $timeout, type, getDef);
11250                    bindEvents(element, scope, hookFn, rawDef.uiStateOpts);
11251                },
11252            };
11253        },
11254    ];
11255    /**
11256     * `ui-state`: A fully dynamic directive for linking to a state
11257     *
11258     * A directive which links to a state (and optionally, parameters).
11259     * When clicked, this directive activates the linked state with the supplied parameter values.
11260     *
11261     * **This directive is very similar to [[uiSref]], but it `$observe`s and `$watch`es/evaluates all its inputs.**
11262     *
11263     * A directive which links to a state (and optionally, parameters).
11264     * When clicked, this directive activates the linked state with the supplied parameter values.
11265     *
11266     * ### Linked State
11267     * The attribute value of `ui-state` is an expression which is `$watch`ed and evaluated as the state to link to.
11268     * **This is in contrast with `ui-sref`, which takes a state name as a string literal.**
11269     *
11270     * #### Example:
11271     * Create a list of links.
11272     * ```html
11273     * <li ng-repeat="link in navlinks">
11274     *   <a ui-state="link.state">{{ link.displayName }}</a>
11275     * </li>
11276     * ```
11277     *
11278     * ### Relative Links
11279     * If the expression evaluates to a relative path, it is processed like [[uiSref]].
11280     * You just need to be aware that the path is relative to the state that *created* the link.
11281     * This allows a state to create relative `ui-state` which always targets the same destination.
11282     *
11283     * ### hrefs
11284     * If the linked state has a URL, the directive will automatically generate and
11285     * update the `href` attribute (using the [[StateService.href]]  method).
11286     *
11287     * ### Parameter Values
11288     * In addition to the state name expression, a `ui-state` can include parameter values which are applied when activating the state.
11289     * Param values should be provided using the `ui-state-params` attribute.
11290     * The `ui-state-params` attribute value is `$watch`ed and evaluated as an expression.
11291     *
11292     * #### Example:
11293     * This example renders a list of links with param values.
11294     * The state's `userId` parameter value comes from each user's `user.id` property.
11295     * ```html
11296     * <li ng-repeat="link in navlinks">
11297     *   <a ui-state="link.state" ui-state-params="link.params">{{ link.displayName }}</a>
11298     * </li>
11299     * ```
11300     *
11301     * ### Transition Options
11302     * You can specify [[TransitionOptions]] to pass to [[StateService.go]] by using the `ui-state-opts` attribute.
11303     * Options are restricted to `location`, `inherit`, and `reload`.
11304     * The value of the `ui-state-opts` is `$watch`ed and evaluated as an expression.
11305     *
11306     * #### Example:
11307     * ```html
11308     * <a ui-state="returnto.state" ui-state-opts="{ reload: true }">Home</a>
11309     * ```
11310     *
11311     * ### Other DOM Events
11312     *
11313     * You can also customize which DOM events to respond to (instead of `click`) by
11314     * providing an `events` array in the `ui-state-opts` attribute.
11315     *
11316     * #### Example:
11317     * ```html
11318     * <input type="text" ui-state="contacts" ui-state-opts="{ events: ['change', 'blur'] }">
11319     * ```
11320     *
11321     * ### Highlighting the active link
11322     * This directive can be used in conjunction with [[uiSrefActive]] to highlight the active link.
11323     *
11324     * ### Notes
11325     *
11326     * - You can use `ui-params` to change **only the parameter values** by omitting the state name and supplying only `ui-state-params`.
11327     *   However, it might be simpler to use [[uiSref]] parameter-only links.
11328     *
11329     * #### Example:
11330     * Sets the `lang` parameter to `en` and remains on the same state.
11331     *
11332     * ```html
11333     * <a ui-state="" ui-state-params="{ lang: 'en' }">English</a>
11334     * ```
11335     *
11336     * - A middle-click, right-click, or ctrl-click is handled (natively) by the browser to open the href in a new window, for example.
11337     * ```
11338     */
11339    var uiStateDirective;
11340    uiStateDirective = [
11341        '$uiRouter',
11342        '$timeout',
11343        function $StateRefDynamicDirective($uiRouter, $timeout) {
11344            var $state = $uiRouter.stateService;
11345            return {
11346                restrict: 'A',
11347                require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
11348                link: function (scope, element, attrs, uiSrefActive) {
11349                    var type = getTypeInfo(element);
11350                    var active = uiSrefActive[1] || uiSrefActive[0];
11351                    var unlinkInfoFn = null;
11352                    var hookFn;
11353                    var rawDef = {};
11354                    var getDef = function () { return processedDef($state, element, rawDef); };
11355                    var inputAttrs = ['uiState', 'uiStateParams', 'uiStateOpts'];
11356                    var watchDeregFns = inputAttrs.reduce(function (acc, attr) { return ((acc[attr] = noop), acc); }, {});
11357                    function update() {
11358                        var def = getDef();
11359                        if (unlinkInfoFn)
11360                            unlinkInfoFn();
11361                        if (active)
11362                            unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
11363                        if (def.href != null)
11364                            attrs.$set(type.attr, def.href);
11365                    }
11366                    inputAttrs.forEach(function (field) {
11367                        rawDef[field] = attrs[field] ? scope.$eval(attrs[field]) : null;
11368                        attrs.$observe(field, function (expr) {
11369                            watchDeregFns[field]();
11370                            watchDeregFns[field] = scope.$watch(expr, function (newval) {
11371                                rawDef[field] = newval;
11372                                update();
11373                            }, true);
11374                        });
11375                    });
11376                    update();
11377                    scope.$on('$destroy', $uiRouter.stateRegistry.onStatesChanged(update));
11378                    scope.$on('$destroy', $uiRouter.transitionService.onSuccess({}, update));
11379                    if (!type.clickable)
11380                        return;
11381                    hookFn = clickHook(element, $state, $timeout, type, getDef);
11382                    bindEvents(element, scope, hookFn, rawDef.uiStateOpts);
11383                },
11384            };
11385        },
11386    ];
11387    /**
11388     * `ui-sref-active` and `ui-sref-active-eq`: A directive that adds a CSS class when a `ui-sref` is active
11389     *
11390     * A directive working alongside [[uiSref]] and [[uiState]] to add classes to an element when the
11391     * related directive's state is active (and remove them when it is inactive).
11392     *
11393     * The primary use-case is to highlight the active link in navigation menus,
11394     * distinguishing it from the inactive menu items.
11395     *
11396     * ### Linking to a `ui-sref` or `ui-state`
11397     * `ui-sref-active` can live on the same element as `ui-sref`/`ui-state`, or it can be on a parent element.
11398     * 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**.
11399     *
11400     * ### Matching
11401     *
11402     * The `ui-sref-active` directive applies the CSS class when the `ui-sref`/`ui-state`'s target state **or any child state is active**.
11403     * This is a "fuzzy match" which uses [[StateService.includes]].
11404     *
11405     * 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).
11406     * This is an "exact match" which uses [[StateService.is]].
11407     *
11408     * ### Parameter values
11409     * 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.
11410     * This allows a list of links to the same state with different parameters to be rendered, and the correct one highlighted.
11411     *
11412     * #### Example:
11413     * ```html
11414     * <li ng-repeat="user in users" ui-sref-active="active">
11415     *   <a ui-sref="user.details({ userId: user.id })">{{ user.lastName }}</a>
11416     * </li>
11417     * ```
11418     *
11419     * ### Examples
11420     *
11421     * Given the following template:
11422     * #### Example:
11423     * ```html
11424     * <ul>
11425     *   <li ui-sref-active="active" class="item">
11426     *     <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
11427     *   </li>
11428     * </ul>
11429     * ```
11430     *
11431     * When the app state is `app.user` (or any child state),
11432     * and contains the state parameter "user" with value "bilbobaggins",
11433     * the resulting HTML will appear as (note the 'active' class):
11434     *
11435     * ```html
11436     * <ul>
11437     *   <li ui-sref-active="active" class="item active">
11438     *     <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
11439     *   </li>
11440     * </ul>
11441     * ```
11442     *
11443     * ### Glob mode
11444     *
11445     * It is possible to pass `ui-sref-active` an expression that evaluates to an object.
11446     * The objects keys represent active class names and values represent the respective state names/globs.
11447     * `ui-sref-active` will match if the current active state **includes** any of
11448     * the specified state names/globs, even the abstract ones.
11449     *
11450     * #### Example:
11451     * Given the following template, with "admin" being an abstract state:
11452     * ```html
11453     * <div ui-sref-active="{'active': 'admin.**'}">
11454     *   <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
11455     * </div>
11456     * ```
11457     *
11458     * Arrays are also supported as values in the `ngClass`-like interface.
11459     * This allows multiple states to add `active` class.
11460     *
11461     * #### Example:
11462     * Given the following template, with "admin.roles" being the current state, the class will be added too:
11463     * ```html
11464     * <div ui-sref-active="{'active': ['owner.**', 'admin.**']}">
11465     *   <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
11466     * </div>
11467     * ```
11468     *
11469     * When the current state is "admin.roles" the "active" class will be applied to both the `<div>` and `<a>` elements.
11470     * It is important to note that the state names/globs passed to `ui-sref-active` override any state provided by a linked `ui-sref`.
11471     *
11472     * ### Notes:
11473     *
11474     * - The class name is interpolated **once** during the directives link time (any further changes to the
11475     * interpolated value are ignored).
11476     *
11477     * - Multiple classes may be specified in a space-separated format: `ui-sref-active='class1 class2 class3'`
11478     */
11479    var uiSrefActiveDirective;
11480    uiSrefActiveDirective = [
11481        '$state',
11482        '$stateParams',
11483        '$interpolate',
11484        '$uiRouter',
11485        function $StateRefActiveDirective($state, $stateParams, $interpolate, $uiRouter) {
11486            return {
11487                restrict: 'A',
11488                controller: [
11489                    '$scope',
11490                    '$element',
11491                    '$attrs',
11492                    function ($scope, $element, $attrs) {
11493                        var states = [];
11494                        var activeEqClass;
11495                        var uiSrefActive;
11496                        // There probably isn't much point in $observing this
11497                        // uiSrefActive and uiSrefActiveEq share the same directive object with some
11498                        // slight difference in logic routing
11499                        activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
11500                        try {
11501                            uiSrefActive = $scope.$eval($attrs.uiSrefActive);
11502                        }
11503                        catch (e) {
11504                            // Do nothing. uiSrefActive is not a valid expression.
11505                            // Fall back to using $interpolate below
11506                        }
11507                        uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
11508                        setStatesFromDefinitionObject(uiSrefActive);
11509                        // Allow uiSref to communicate with uiSrefActive[Equals]
11510                        this.$$addStateInfo = function (newState, newParams) {
11511                            // we already got an explicit state provided by ui-sref-active, so we
11512                            // shadow the one that comes from ui-sref
11513                            if (isObject(uiSrefActive) && states.length > 0) {
11514                                return;
11515                            }
11516                            var deregister = addState(newState, newParams, uiSrefActive);
11517                            update();
11518                            return deregister;
11519                        };
11520                        function updateAfterTransition(trans) {
11521                            trans.promise.then(update, noop);
11522                        }
11523                        $scope.$on('$destroy', setupEventListeners());
11524                        if ($uiRouter.globals.transition) {
11525                            updateAfterTransition($uiRouter.globals.transition);
11526                        }
11527                        function setupEventListeners() {
11528                            var deregisterStatesChangedListener = $uiRouter.stateRegistry.onStatesChanged(handleStatesChanged);
11529                            var deregisterOnStartListener = $uiRouter.transitionService.onStart({}, updateAfterTransition);
11530                            var deregisterStateChangeSuccessListener = $scope.$on('$stateChangeSuccess', update);
11531                            return function cleanUp() {
11532                                deregisterStatesChangedListener();
11533                                deregisterOnStartListener();
11534                                deregisterStateChangeSuccessListener();
11535                            };
11536                        }
11537                        function handleStatesChanged() {
11538                            setStatesFromDefinitionObject(uiSrefActive);
11539                        }
11540                        function setStatesFromDefinitionObject(statesDefinition) {
11541                            if (isObject(statesDefinition)) {
11542                                states = [];
11543                                forEach(statesDefinition, function (stateOrName, activeClass) {
11544                                    // Helper function to abstract adding state.
11545                                    var addStateForClass = function (stateOrName, activeClass) {
11546                                        var ref = parseStateRef(stateOrName);
11547                                        addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
11548                                    };
11549                                    if (isString(stateOrName)) {
11550                                        // If state is string, just add it.
11551                                        addStateForClass(stateOrName, activeClass);
11552                                    }
11553                                    else if (isArray(stateOrName)) {
11554                                        // If state is an array, iterate over it and add each array item individually.
11555                                        forEach(stateOrName, function (stateOrName) {
11556                                            addStateForClass(stateOrName, activeClass);
11557                                        });
11558                                    }
11559                                });
11560                            }
11561                        }
11562                        function addState(stateName, stateParams, activeClass) {
11563                            var state = $state.get(stateName, stateContext($element));
11564                            var stateInfo = {
11565                                state: state || { name: stateName },
11566                                params: stateParams,
11567                                activeClass: activeClass,
11568                            };
11569                            states.push(stateInfo);
11570                            return function removeState() {
11571                                removeFrom(states)(stateInfo);
11572                            };
11573                        }
11574                        // Update route state
11575                        function update() {
11576                            var splitClasses = function (str) { return str.split(/\s/).filter(identity); };
11577                            var getClasses = function (stateList) {
11578                                return stateList
11579                                    .map(function (x) { return x.activeClass; })
11580                                    .map(splitClasses)
11581                                    .reduce(unnestR, []);
11582                            };
11583                            var allClasses = getClasses(states).concat(splitClasses(activeEqClass)).reduce(uniqR, []);
11584                            var fuzzyClasses = getClasses(states.filter(function (x) { return $state.includes(x.state.name, x.params); }));
11585                            var exactlyMatchesAny = !!states.filter(function (x) { return $state.is(x.state.name, x.params); }).length;
11586                            var exactClasses = exactlyMatchesAny ? splitClasses(activeEqClass) : [];
11587                            var addClasses = fuzzyClasses.concat(exactClasses).reduce(uniqR, []);
11588                            var removeClasses = allClasses.filter(function (cls) { return !inArray(addClasses, cls); });
11589                            $scope.$evalAsync(function () {
11590                                addClasses.forEach(function (className) { return $element.addClass(className); });
11591                                removeClasses.forEach(function (className) { return $element.removeClass(className); });
11592                            });
11593                        }
11594                        update();
11595                    },
11596                ],
11597            };
11598        },
11599    ];
11600    ng
11601        .module('ui.router.state')
11602        .directive('uiSref', uiSrefDirective)
11603        .directive('uiSrefActive', uiSrefActiveDirective)
11604        .directive('uiSrefActiveEq', uiSrefActiveDirective)
11605        .directive('uiState', uiStateDirective);
11606
11607    /** @publicapi @module ng1 */ /** */
11608    /**
11609     * `isState` Filter: truthy if the current state is the parameter
11610     *
11611     * Translates to [[StateService.is]] `$state.is("stateName")`.
11612     *
11613     * #### Example:
11614     * ```html
11615     * <div ng-if="'stateName' | isState">show if state is 'stateName'</div>
11616     * ```
11617     */
11618    $IsStateFilter.$inject = ['$state'];
11619    function $IsStateFilter($state) {
11620        var isFilter = function (state, params, options) {
11621            return $state.is(state, params, options);
11622        };
11623        isFilter.$stateful = true;
11624        return isFilter;
11625    }
11626    /**
11627     * `includedByState` Filter: truthy if the current state includes the parameter
11628     *
11629     * Translates to [[StateService.includes]]` $state.is("fullOrPartialStateName")`.
11630     *
11631     * #### Example:
11632     * ```html
11633     * <div ng-if="'fullOrPartialStateName' | includedByState">show if state includes 'fullOrPartialStateName'</div>
11634     * ```
11635     */
11636    $IncludedByStateFilter.$inject = ['$state'];
11637    function $IncludedByStateFilter($state) {
11638        var includesFilter = function (state, params, options) {
11639            return $state.includes(state, params, options);
11640        };
11641        includesFilter.$stateful = true;
11642        return includesFilter;
11643    }
11644    ng.module('ui.router.state').filter('isState', $IsStateFilter).filter('includedByState', $IncludedByStateFilter);
11645
11646    /** @publicapi @module directives */ /** */
11647    /**
11648     * `ui-view`: A viewport directive which is filled in by a view from the active state.
11649     *
11650     * ### Attributes
11651     *
11652     * - `name`: (Optional) A view name.
11653     *   The name should be unique amongst the other views in the same state.
11654     *   You can have views of the same name that live in different states.
11655     *   The ui-view can be targeted in a View using the name ([[Ng1StateDeclaration.views]]).
11656     *
11657     * - `autoscroll`: an expression. When it evaluates to true, the `ui-view` will be scrolled into view when it is activated.
11658     *   Uses [[$uiViewScroll]] to do the scrolling.
11659     *
11660     * - `onload`: Expression to evaluate whenever the view updates.
11661     *
11662     * #### Example:
11663     * A view can be unnamed or named.
11664     * ```html
11665     * <!-- Unnamed -->
11666     * <div ui-view></div>
11667     *
11668     * <!-- Named -->
11669     * <div ui-view="viewName"></div>
11670     *
11671     * <!-- Named (different style) -->
11672     * <ui-view name="viewName"></ui-view>
11673     * ```
11674     *
11675     * You can only have one unnamed view within any template (or root html). If you are only using a
11676     * single view and it is unnamed then you can populate it like so:
11677     *
11678     * ```html
11679     * <div ui-view></div>
11680     * $stateProvider.state("home", {
11681     *   template: "<h1>HELLO!</h1>"
11682     * })
11683     * ```
11684     *
11685     * The above is a convenient shortcut equivalent to specifying your view explicitly with the
11686     * [[Ng1StateDeclaration.views]] config property, by name, in this case an empty name:
11687     *
11688     * ```js
11689     * $stateProvider.state("home", {
11690     *   views: {
11691     *     "": {
11692     *       template: "<h1>HELLO!</h1>"
11693     *     }
11694     *   }
11695     * })
11696     * ```
11697     *
11698     * But typically you'll only use the views property if you name your view or have more than one view
11699     * in the same template. There's not really a compelling reason to name a view if its the only one,
11700     * but you could if you wanted, like so:
11701     *
11702     * ```html
11703     * <div ui-view="main"></div>
11704     * ```
11705     *
11706     * ```js
11707     * $stateProvider.state("home", {
11708     *   views: {
11709     *     "main": {
11710     *       template: "<h1>HELLO!</h1>"
11711     *     }
11712     *   }
11713     * })
11714     * ```
11715     *
11716     * Really though, you'll use views to set up multiple views:
11717     *
11718     * ```html
11719     * <div ui-view></div>
11720     * <div ui-view="chart"></div>
11721     * <div ui-view="data"></div>
11722     * ```
11723     *
11724     * ```js
11725     * $stateProvider.state("home", {
11726     *   views: {
11727     *     "": {
11728     *       template: "<h1>HELLO!</h1>"
11729     *     },
11730     *     "chart": {
11731     *       template: "<chart_thing/>"
11732     *     },
11733     *     "data": {
11734     *       template: "<data_thing/>"
11735     *     }
11736     *   }
11737     * })
11738     * ```
11739     *
11740     * #### Examples for `autoscroll`:
11741     * ```html
11742     * <!-- If autoscroll present with no expression,
11743     *      then scroll ui-view into view -->
11744     * <ui-view autoscroll/>
11745     *
11746     * <!-- If autoscroll present with valid expression,
11747     *      then scroll ui-view into view if expression evaluates to true -->
11748     * <ui-view autoscroll='true'/>
11749     * <ui-view autoscroll='false'/>
11750     * <ui-view autoscroll='scopeVariable'/>
11751     * ```
11752     *
11753     * Resolve data:
11754     *
11755     * The resolved data from the state's `resolve` block is placed on the scope as `$resolve` (this
11756     * can be customized using [[Ng1ViewDeclaration.resolveAs]]).  This can be then accessed from the template.
11757     *
11758     * Note that when `controllerAs` is being used, `$resolve` is set on the controller instance *after* the
11759     * controller is instantiated.  The `$onInit()` hook can be used to perform initialization code which
11760     * depends on `$resolve` data.
11761     *
11762     * #### Example:
11763     * ```js
11764     * $stateProvider.state('home', {
11765     *   template: '<my-component user="$resolve.user"></my-component>',
11766     *   resolve: {
11767     *     user: function(UserService) { return UserService.fetchUser(); }
11768     *   }
11769     * });
11770     * ```
11771     */
11772    var uiView;
11773    // eslint-disable-next-line prefer-const
11774    uiView = [
11775        '$view',
11776        '$animate',
11777        '$uiViewScroll',
11778        '$interpolate',
11779        '$q',
11780        function $ViewDirective($view, $animate, $uiViewScroll, $interpolate, $q) {
11781            function getRenderer() {
11782                return {
11783                    enter: function (element, target, cb) {
11784                        if (ng.version.minor > 2) {
11785                            $animate.enter(element, null, target).then(cb);
11786                        }
11787                        else {
11788                            $animate.enter(element, null, target, cb);
11789                        }
11790                    },
11791                    leave: function (element, cb) {
11792                        if (ng.version.minor > 2) {
11793                            $animate.leave(element).then(cb);
11794                        }
11795                        else {
11796                            $animate.leave(element, cb);
11797                        }
11798                    },
11799                };
11800            }
11801            function configsEqual(config1, config2) {
11802                return config1 === config2;
11803            }
11804            var rootData = {
11805                $cfg: { viewDecl: { $context: $view._pluginapi._rootViewContext() } },
11806                $uiView: {},
11807            };
11808            var directive = {
11809                count: 0,
11810                restrict: 'ECA',
11811                terminal: true,
11812                priority: 400,
11813                transclude: 'element',
11814                compile: function (tElement, tAttrs, $transclude) {
11815                    return function (scope, $element, attrs) {
11816                        var onloadExp = attrs['onload'] || '', autoScrollExp = attrs['autoscroll'], renderer = getRenderer(), inherited = $element.inheritedData('$uiView') || rootData, name = $interpolate(attrs['uiView'] || attrs['name'] || '')(scope) || '$default';
11817                        var previousEl, currentEl, currentScope, viewConfig;
11818                        var activeUIView = {
11819                            $type: 'ng1',
11820                            id: directive.count++,
11821                            name: name,
11822                            fqn: inherited.$uiView.fqn ? inherited.$uiView.fqn + '.' + name : name,
11823                            config: null,
11824                            configUpdated: configUpdatedCallback,
11825                            get creationContext() {
11826                                // The context in which this ui-view "tag" was created
11827                                var fromParentTagConfig = parse('$cfg.viewDecl.$context')(inherited);
11828                                // Allow <ui-view name="foo"><ui-view name="bar"></ui-view></ui-view>
11829                                // See https://github.com/angular-ui/ui-router/issues/3355
11830                                var fromParentTag = parse('$uiView.creationContext')(inherited);
11831                                return fromParentTagConfig || fromParentTag;
11832                            },
11833                        };
11834                        trace.traceUIViewEvent('Linking', activeUIView);
11835                        function configUpdatedCallback(config) {
11836                            if (config && !(config instanceof Ng1ViewConfig))
11837                                return;
11838                            if (configsEqual(viewConfig, config))
11839                                return;
11840                            trace.traceUIViewConfigUpdated(activeUIView, config && config.viewDecl && config.viewDecl.$context);
11841                            viewConfig = config;
11842                            updateView(config);
11843                        }
11844                        $element.data('$uiView', { $uiView: activeUIView });
11845                        updateView();
11846                        var unregister = $view.registerUIView(activeUIView);
11847                        scope.$on('$destroy', function () {
11848                            trace.traceUIViewEvent('Destroying/Unregistering', activeUIView);
11849                            unregister();
11850                        });
11851                        function cleanupLastView() {
11852                            if (previousEl) {
11853                                trace.traceUIViewEvent('Removing (previous) el', previousEl.data('$uiView'));
11854                                previousEl.remove();
11855                                previousEl = null;
11856                            }
11857                            if (currentScope) {
11858                                trace.traceUIViewEvent('Destroying scope', activeUIView);
11859                                currentScope.$destroy();
11860                                currentScope = null;
11861                            }
11862                            if (currentEl) {
11863                                var _viewData_1 = currentEl.data('$uiViewAnim');
11864                                trace.traceUIViewEvent('Animate out', _viewData_1);
11865                                renderer.leave(currentEl, function () {
11866                                    _viewData_1.$$animLeave.resolve();
11867                                    previousEl = null;
11868                                });
11869                                previousEl = currentEl;
11870                                currentEl = null;
11871                            }
11872                        }
11873                        function updateView(config) {
11874                            var newScope = scope.$new();
11875                            var animEnter = $q.defer(), animLeave = $q.defer();
11876                            var $uiViewData = {
11877                                $cfg: config,
11878                                $uiView: activeUIView,
11879                            };
11880                            var $uiViewAnim = {
11881                                $animEnter: animEnter.promise,
11882                                $animLeave: animLeave.promise,
11883                                $$animLeave: animLeave,
11884                            };
11885                            /**
11886                             * @ngdoc event
11887                             * @name ui.router.state.directive:ui-view#$viewContentLoading
11888                             * @eventOf ui.router.state.directive:ui-view
11889                             * @eventType emits on ui-view directive scope
11890                             * @description
11891                             *
11892                             * Fired once the view **begins loading**, *before* the DOM is rendered.
11893                             *
11894                             * @param {Object} event Event object.
11895                             * @param {string} viewName Name of the view.
11896                             */
11897                            newScope.$emit('$viewContentLoading', name);
11898                            var cloned = $transclude(newScope, function (clone) {
11899                                clone.data('$uiViewAnim', $uiViewAnim);
11900                                clone.data('$uiView', $uiViewData);
11901                                renderer.enter(clone, $element, function onUIViewEnter() {
11902                                    animEnter.resolve();
11903                                    if (currentScope)
11904                                        currentScope.$emit('$viewContentAnimationEnded');
11905                                    if ((isDefined(autoScrollExp) && !autoScrollExp) || scope.$eval(autoScrollExp)) {
11906                                        $uiViewScroll(clone);
11907                                    }
11908                                });
11909                                cleanupLastView();
11910                            });
11911                            currentEl = cloned;
11912                            currentScope = newScope;
11913                            /**
11914                             * @ngdoc event
11915                             * @name ui.router.state.directive:ui-view#$viewContentLoaded
11916                             * @eventOf ui.router.state.directive:ui-view
11917                             * @eventType emits on ui-view directive scope
11918                             * @description           *
11919                             * Fired once the view is **loaded**, *after* the DOM is rendered.
11920                             *
11921                             * @param {Object} event Event object.
11922                             */
11923                            currentScope.$emit('$viewContentLoaded', config || viewConfig);
11924                            currentScope.$eval(onloadExp);
11925                        }
11926                    };
11927                },
11928            };
11929            return directive;
11930        },
11931    ];
11932    $ViewDirectiveFill.$inject = ['$compile', '$controller', '$transitions', '$view', '$q'];
11933    /** @hidden */
11934    function $ViewDirectiveFill($compile, $controller, $transitions, $view, $q) {
11935        var getControllerAs = parse('viewDecl.controllerAs');
11936        var getResolveAs = parse('viewDecl.resolveAs');
11937        return {
11938            restrict: 'ECA',
11939            priority: -400,
11940            compile: function (tElement) {
11941                var initial = tElement.html();
11942                tElement.empty();
11943                return function (scope, $element) {
11944                    var data = $element.data('$uiView');
11945                    if (!data) {
11946                        $element.html(initial);
11947                        $compile($element.contents())(scope);
11948                        return;
11949                    }
11950                    var cfg = data.$cfg || { viewDecl: {}, getTemplate: noop };
11951                    var resolveCtx = cfg.path && new ResolveContext(cfg.path);
11952                    $element.html(cfg.getTemplate($element, resolveCtx) || initial);
11953                    trace.traceUIViewFill(data.$uiView, $element.html());
11954                    var link = $compile($element.contents());
11955                    var controller = cfg.controller;
11956                    var controllerAs = getControllerAs(cfg);
11957                    var resolveAs = getResolveAs(cfg);
11958                    var locals = resolveCtx && getLocals(resolveCtx);
11959                    scope[resolveAs] = locals;
11960                    if (controller) {
11961                        var controllerInstance = ($controller(controller, extend({}, locals, { $scope: scope, $element: $element })));
11962                        if (controllerAs) {
11963                            scope[controllerAs] = controllerInstance;
11964                            scope[controllerAs][resolveAs] = locals;
11965                        }
11966                        // TODO: Use $view service as a central point for registering component-level hooks
11967                        // Then, when a component is created, tell the $view service, so it can invoke hooks
11968                        // $view.componentLoaded(controllerInstance, { $scope: scope, $element: $element });
11969                        // scope.$on('$destroy', () => $view.componentUnloaded(controllerInstance, { $scope: scope, $element: $element }));
11970                        $element.data('$ngControllerController', controllerInstance);
11971                        $element.children().data('$ngControllerController', controllerInstance);
11972                        registerControllerCallbacks($q, $transitions, controllerInstance, scope, cfg);
11973                    }
11974                    // Wait for the component to appear in the DOM
11975                    if (isString(cfg.component)) {
11976                        var kebobName = kebobString(cfg.component);
11977                        var tagRegexp_1 = new RegExp("^(x-|data-)?" + kebobName + "$", 'i');
11978                        var getComponentController = function () {
11979                            var directiveEl = [].slice
11980                                .call($element[0].children)
11981                                .filter(function (el) { return el && el.tagName && tagRegexp_1.exec(el.tagName); });
11982                            return directiveEl && ng.element(directiveEl).data("$" + cfg.component + "Controller");
11983                        };
11984                        var deregisterWatch_1 = scope.$watch(getComponentController, function (ctrlInstance) {
11985                            if (!ctrlInstance)
11986                                return;
11987                            registerControllerCallbacks($q, $transitions, ctrlInstance, scope, cfg);
11988                            deregisterWatch_1();
11989                        });
11990                    }
11991                    link(scope);
11992                };
11993            },
11994        };
11995    }
11996    /** @hidden */
11997    var hasComponentImpl = typeof ng.module('ui.router')['component'] === 'function';
11998    /** @hidden incrementing id */
11999    var _uiCanExitId = 0;
12000    /** @hidden TODO: move these callbacks to $view and/or `/hooks/components.ts` or something */
12001    function registerControllerCallbacks($q, $transitions, controllerInstance, $scope, cfg) {
12002        // Call $onInit() ASAP
12003        if (isFunction(controllerInstance.$onInit) &&
12004            !((cfg.viewDecl.component || cfg.viewDecl.componentProvider) && hasComponentImpl)) {
12005            controllerInstance.$onInit();
12006        }
12007        var viewState = tail(cfg.path).state.self;
12008        var hookOptions = { bind: controllerInstance };
12009        // Add component-level hook for onUiParamsChanged
12010        if (isFunction(controllerInstance.uiOnParamsChanged)) {
12011            var resolveContext = new ResolveContext(cfg.path);
12012            var viewCreationTrans_1 = resolveContext.getResolvable('$transition$').data;
12013            // Fire callback on any successful transition
12014            var paramsUpdated = function ($transition$) {
12015                // Exit early if the $transition$ is the same as the view was created within.
12016                // Exit early if the $transition$ will exit the state the view is for.
12017                if ($transition$ === viewCreationTrans_1 || $transition$.exiting().indexOf(viewState) !== -1)
12018                    return;
12019                var toParams = $transition$.params('to');
12020                var fromParams = $transition$.params('from');
12021                var getNodeSchema = function (node) { return node.paramSchema; };
12022                var toSchema = $transition$.treeChanges('to').map(getNodeSchema).reduce(unnestR, []);
12023                var fromSchema = $transition$.treeChanges('from').map(getNodeSchema).reduce(unnestR, []);
12024                // Find the to params that have different values than the from params
12025                var changedToParams = toSchema.filter(function (param) {
12026                    var idx = fromSchema.indexOf(param);
12027                    return idx === -1 || !fromSchema[idx].type.equals(toParams[param.id], fromParams[param.id]);
12028                });
12029                // Only trigger callback if a to param has changed or is new
12030                if (changedToParams.length) {
12031                    var changedKeys_1 = changedToParams.map(function (x) { return x.id; });
12032                    // Filter the params to only changed/new to params.  `$transition$.params()` may be used to get all params.
12033                    var newValues = filter(toParams, function (val, key) { return changedKeys_1.indexOf(key) !== -1; });
12034                    controllerInstance.uiOnParamsChanged(newValues, $transition$);
12035                }
12036            };
12037            $scope.$on('$destroy', $transitions.onSuccess({}, paramsUpdated, hookOptions));
12038        }
12039        // Add component-level hook for uiCanExit
12040        if (isFunction(controllerInstance.uiCanExit)) {
12041            var id_1 = _uiCanExitId++;
12042            var cacheProp_1 = '_uiCanExitIds';
12043            // Returns true if a redirect transition already answered truthy
12044            var prevTruthyAnswer_1 = function (trans) {
12045                return !!trans && ((trans[cacheProp_1] && trans[cacheProp_1][id_1] === true) || prevTruthyAnswer_1(trans.redirectedFrom()));
12046            };
12047            // If a user answered yes, but the transition was later redirected, don't also ask for the new redirect transition
12048            var wrappedHook = function (trans) {
12049                var promise;
12050                var ids = (trans[cacheProp_1] = trans[cacheProp_1] || {});
12051                if (!prevTruthyAnswer_1(trans)) {
12052                    promise = $q.when(controllerInstance.uiCanExit(trans));
12053                    promise.then(function (val) { return (ids[id_1] = val !== false); });
12054                }
12055                return promise;
12056            };
12057            var criteria = { exiting: viewState.name };
12058            $scope.$on('$destroy', $transitions.onBefore(criteria, wrappedHook, hookOptions));
12059        }
12060    }
12061    ng.module('ui.router.state').directive('uiView', uiView);
12062    ng.module('ui.router.state').directive('uiView', $ViewDirectiveFill);
12063
12064    /** @publicapi @module ng1 */ /** */
12065    /** @hidden */
12066    function $ViewScrollProvider() {
12067        var useAnchorScroll = false;
12068        this.useAnchorScroll = function () {
12069            useAnchorScroll = true;
12070        };
12071        this.$get = [
12072            '$anchorScroll',
12073            '$timeout',
12074            function ($anchorScroll, $timeout) {
12075                if (useAnchorScroll) {
12076                    return $anchorScroll;
12077                }
12078                return function ($element) {
12079                    return $timeout(function () {
12080                        $element[0].scrollIntoView();
12081                    }, 0, false);
12082                };
12083            },
12084        ];
12085    }
12086    ng.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);
12087
12088    /**
12089     * Main entry point for angular 1.x build
12090     * @publicapi @module ng1
12091     */ /** */
12092    var index$1 = 'ui.router';
12093
12094    exports.$injector = $injector;
12095    exports.$q = $q;
12096    exports.BaseLocationServices = BaseLocationServices;
12097    exports.BaseUrlRule = BaseUrlRule;
12098    exports.BrowserLocationConfig = BrowserLocationConfig;
12099    exports.Glob = Glob;
12100    exports.HashLocationService = HashLocationService;
12101    exports.HookBuilder = HookBuilder;
12102    exports.MemoryLocationConfig = MemoryLocationConfig;
12103    exports.MemoryLocationService = MemoryLocationService;
12104    exports.NATIVE_INJECTOR_TOKEN = NATIVE_INJECTOR_TOKEN;
12105    exports.Ng1ViewConfig = Ng1ViewConfig;
12106    exports.Param = Param;
12107    exports.ParamFactory = ParamFactory;
12108    exports.ParamType = ParamType;
12109    exports.ParamTypes = ParamTypes;
12110    exports.PathNode = PathNode;
12111    exports.PathUtils = PathUtils;
12112    exports.PushStateLocationService = PushStateLocationService;
12113    exports.Queue = Queue;
12114    exports.RegisteredHook = RegisteredHook;
12115    exports.Rejection = Rejection;
12116    exports.Resolvable = Resolvable;
12117    exports.ResolveContext = ResolveContext;
12118    exports.StateBuilder = StateBuilder;
12119    exports.StateMatcher = StateMatcher;
12120    exports.StateObject = StateObject;
12121    exports.StateParams = StateParams;
12122    exports.StateProvider = StateProvider;
12123    exports.StateQueueManager = StateQueueManager;
12124    exports.StateRegistry = StateRegistry;
12125    exports.StateService = StateService;
12126    exports.TargetState = TargetState;
12127    exports.Trace = Trace;
12128    exports.Transition = Transition;
12129    exports.TransitionEventType = TransitionEventType;
12130    exports.TransitionHook = TransitionHook;
12131    exports.TransitionService = TransitionService;
12132    exports.UIRouter = UIRouter;
12133    exports.UIRouterGlobals = UIRouterGlobals;
12134    exports.UIRouterPluginBase = UIRouterPluginBase;
12135    exports.UrlConfig = UrlConfig;
12136    exports.UrlMatcher = UrlMatcher;
12137    exports.UrlMatcherFactory = UrlMatcherFactory;
12138    exports.UrlRouter = UrlRouter;
12139    exports.UrlRouterProvider = UrlRouterProvider;
12140    exports.UrlRuleFactory = UrlRuleFactory;
12141    exports.UrlRules = UrlRules;
12142    exports.UrlService = UrlService;
12143    exports.ViewService = ViewService;
12144    exports._extend = _extend;
12145    exports._inArray = _inArray;
12146    exports._pushTo = _pushTo;
12147    exports._removeFrom = _removeFrom;
12148    exports.all = all;
12149    exports.allTrueR = allTrueR;
12150    exports.ancestors = ancestors;
12151    exports.and = and;
12152    exports.any = any;
12153    exports.anyTrueR = anyTrueR;
12154    exports.applyPairs = applyPairs;
12155    exports.arrayTuples = arrayTuples;
12156    exports.assertFn = assertFn;
12157    exports.assertMap = assertMap;
12158    exports.assertPredicate = assertPredicate;
12159    exports.beforeAfterSubstr = beforeAfterSubstr;
12160    exports.buildUrl = buildUrl;
12161    exports.compose = compose;
12162    exports.copy = copy;
12163    exports.core = index;
12164    exports.createProxyFunctions = createProxyFunctions;
12165    exports.curry = curry;
12166    exports.default = index$1;
12167    exports.defaultResolvePolicy = defaultResolvePolicy;
12168    exports.defaultTransOpts = defaultTransOpts;
12169    exports.defaults = defaults;
12170    exports.deregAll = deregAll;
12171    exports.eq = eq;
12172    exports.equals = equals;
12173    exports.extend = extend;
12174    exports.filter = filter;
12175    exports.find = find;
12176    exports.flatten = flatten;
12177    exports.flattenR = flattenR;
12178    exports.fnToString = fnToString;
12179    exports.forEach = forEach;
12180    exports.fromJson = fromJson;
12181    exports.functionToString = functionToString;
12182    exports.getLocals = getLocals;
12183    exports.getNg1ViewConfigFactory = getNg1ViewConfigFactory;
12184    exports.getParams = getParams;
12185    exports.hashLocationPlugin = hashLocationPlugin;
12186    exports.hostRegex = hostRegex;
12187    exports.identity = identity;
12188    exports.inArray = inArray;
12189    exports.inherit = inherit;
12190    exports.invoke = invoke;
12191    exports.is = is;
12192    exports.isArray = isArray;
12193    exports.isDate = isDate;
12194    exports.isDefined = isDefined;
12195    exports.isFunction = isFunction;
12196    exports.isInjectable = isInjectable;
12197    exports.isNull = isNull;
12198    exports.isNullOrUndefined = isNullOrUndefined;
12199    exports.isNumber = isNumber;
12200    exports.isObject = isObject;
12201    exports.isPromise = isPromise;
12202    exports.isRegExp = isRegExp;
12203    exports.isString = isString;
12204    exports.isUndefined = isUndefined;
12205    exports.joinNeighborsR = joinNeighborsR;
12206    exports.kebobString = kebobString;
12207    exports.keyValsToObjectR = keyValsToObjectR;
12208    exports.locationPluginFactory = locationPluginFactory;
12209    exports.makeEvent = makeEvent;
12210    exports.makeStub = makeStub;
12211    exports.map = map;
12212    exports.mapObj = mapObj;
12213    exports.matchState = matchState;
12214    exports.maxLength = maxLength;
12215    exports.memoryLocationPlugin = memoryLocationPlugin;
12216    exports.mergeR = mergeR;
12217    exports.ng1ViewsBuilder = ng1ViewsBuilder;
12218    exports.noop = noop;
12219    exports.not = not;
12220    exports.omit = omit;
12221    exports.or = or;
12222    exports.padString = padString;
12223    exports.pairs = pairs;
12224    exports.parse = parse;
12225    exports.parseUrl = parseUrl$1;
12226    exports.pattern = pattern;
12227    exports.pick = pick;
12228    exports.pipe = pipe;
12229    exports.pluck = pluck;
12230    exports.prop = prop;
12231    exports.propEq = propEq;
12232    exports.pushR = pushR;
12233    exports.pushStateLocationPlugin = pushStateLocationPlugin;
12234    exports.pushTo = pushTo;
12235    exports.removeFrom = removeFrom;
12236    exports.resolvablesBuilder = resolvablesBuilder;
12237    exports.resolvePolicies = resolvePolicies;
12238    exports.root = root;
12239    exports.services = services;
12240    exports.servicesPlugin = servicesPlugin;
12241    exports.silenceUncaughtInPromise = silenceUncaughtInPromise;
12242    exports.silentRejection = silentRejection;
12243    exports.splitEqual = splitEqual;
12244    exports.splitHash = splitHash;
12245    exports.splitOnDelim = splitOnDelim;
12246    exports.splitQuery = splitQuery;
12247    exports.stringify = stringify;
12248    exports.stripLastPathElement = stripLastPathElement;
12249    exports.tail = tail;
12250    exports.toJson = toJson;
12251    exports.trace = trace;
12252    exports.trimHashVal = trimHashVal;
12253    exports.uniqR = uniqR;
12254    exports.unnest = unnest;
12255    exports.unnestR = unnestR;
12256    exports.val = val;
12257    exports.values = values;
12258    exports.watchDigests = watchDigests;
12259
12260    Object.defineProperty(exports, '__esModule', { value: true });
12261
12262})));
12263//# sourceMappingURL=angular-ui-router.js.map
12264
12265(function() {
12266    "use strict";
12267
12268    angular.module("PricingApp", ["ui.router", "WebnamesError", "WebnamesCommon", "WebnamesAnalytics", "WebnamesGridHelper"])
12269        .config(["$stateProvider", "$urlRouterProvider", "$locationProvider", function ($stateProvider, $urlRouterProvider, $locationProvider) {
12270            $urlRouterProvider.otherwise("/domains");
12271            
12272            $locationProvider.hashPrefix("!");
12273
12274            $stateProvider
12275                .state("none", {
12276                    url: "/none"
12277                })
12278                .state("domains", {
12279                    url: "/domains",
12280                    templateUrl: "Domains.cshtml",
12281                    controller: "DomainsController as domCtrl",
12282                })
12283                .state("hosting", {
12284                    url: "/hosting",
12285                    templateUrl: "Hosting.cshtml",
12286                    controller: "HostingController as hostCtrl"
12287                })
12288                .state("email", {
12289                    url: "/email",
12290                    templateUrl: "Email.cshtml",
12291                    controller: "EmailController as emailCtrl"
12292                })
12293                .state("ssl", {
12294                    url: "/ssl",
12295                    templateUrl: "Ssl.cshtml",
12296                    controller: "SSLController as sslCtrl"
12297                })
12298                .state("other", {
12299                    url: "/other",
12300                    templateUrl: "Other.cshtml"
12301                });
12302
12303        }])
12304        .service("PricingStore", ["$window", "$http", "$timeout", "CustomerType", "CustomerSubType", function ($window, $http, $timeout, CustomerType, CustomerSubType) {
12305            var service = this;
12306
12307            var domainPricingsCache = {};
12308            
12309            /**
12310             * Queries domain pricings and returns them. Caches values locally.
12311             * @param {string} customerSubType optional to get pricing for a subtype other than current
12312             * @returns {Promise} a promise which will resolve to the domain pricing
12313             */
12314            service.QueryDomainPricings = function (customerSubType) {
12315                var requestPath = $window._SmartURL + "pricing/ExtensionPricing";
12316
12317                if (!!customerSubType && angular.isString(customerSubType) && customerSubType !== CustomerSubType) {
12318                    requestPath += "/" + CustomerType + "?subType=" + customerSubType;
12319                }
12320                
12321                if (angular.isArray(domainPricingsCache[customerSubType]) && domainPricingsCache[customerSubType].length > 0) {
12322                    return $timeout(function() { return domainPricingsCache[customerSubType] });
12323                }
12324
12325                return $http.get(requestPath).then(function (resp) {
12326                    domainPricingsCache[customerSubType] = resp.data;
12327                    return resp.data;
12328                });
12329            }
12330
12331            var nonDomainPricings = {};
12332            service.QueryPromise = null;
12333            service.ExchangeRatePromise = null;
12334            service.PlanCodes = {};
12335
12336            /**
12337             * Queries pricings based on the PlanCodes. Does not return data, pricing can be retrieved using GetNonDomainPricing()
12338             * @returns {Promise} a promise to indicate when query is done
12339             */
12340            service.QueryPricings = function () {
12341                if (service.QueryPromise) return service.QueryPromise;
12342
12343                var lsMissingPricingCodes = _.difference(_.keys(service.PlanCodes), _.keys(nonDomainPricings));
12344                
12345                if (lsMissingPricingCodes.length < 1) return $timeout(function(){ return "done"});
12346                
12347                service.QueryPromise = $http.post($window._SmartURL + "pricing/NonDomainPricing", { packageCodes: lsMissingPricingCodes }).then(function (resp) {
12348                    nonDomainPricings = _.extend(nonDomainPricings, resp.data);
12349                    service.QueryPromise = null;
12350                    return "done";
12351                });
12352
12353                return service.QueryPromise;
12354            }
12355
12356            /**
12357             * Gets pricing from local pricing cache. Make sure plan code is in PlanCodes and QueryPricings is called to cache it.
12358             * @param {string} packageCode 
12359             * @returns {object} pricing object to assign to directive
12360             */
12361            service.GetNonDomainPricing = function(packageCode) {
12362                return nonDomainPricings[packageCode];
12363            }
12364
12365            service.GetExchangeRate = function() {
12366                if (service.ExchangeRatePromise) return service.ExchangeRatePromise;
12367
12368                service.ExchangeRatePromise = $http.get($window._SmartURL + "pricing/ExchangeRate").then(function (resp) { return resp.data; });
12369
12370                return service.ExchangeRatePromise;
12371            }
12372        }])
12373        .run(["$state", function ($state) {
12374            // If we are in the 'none' state while resizing to tab view, default to domains
12375            $(window).resize(function () {
12376                var viewport = $(window).width();
12377
12378                if (viewport > 767 && $state.current.name === "none") $state.go("domains");
12379            });
12380        }])
12381        .controller("MainController", ["$state", "$rootScope", "$log", function ($state, $rootScope, $log) {
12382            this.state = $state;
12383            this.isLoading = true;
12384            var vm = this;
12385            $rootScope.$on("ShowHideLoadingAnimation", function (event, bShowHide) {
12386                vm.isLoading = bShowHide;
12387            });
12388        }])
12389        .controller("DomainsController", ["$scope", "$rootScope", "$window", "$http", "$location", "PricingStore", "CustomerType", "CustomerSubType", "CustomerTypeStore", function ($scope, $rootScope, $window, $http, $location, PricingStore, CustomerType, CustomerSubType, CustomerTypeStore) {
12390            var vm = this;
12391
12392            vm.bShowExchangeRate = false;
12393            vm.ExchangeRate = PricingStore.GetExchangeRate().then(function (data) {
12394                vm.ExchangeRate = data;
12395                vm.bShowExchangeRate = true;
12396            });
12397
12398            $rootScope.$emit("ShowHideLoadingAnimation", true);
12399
12400            PricingStore.QueryDomainPricings().then(function (aPricing) {
12401                vm.pricings = aPricing;
12402                $rootScope.$emit("ShowHideLoadingAnimation", false);
12403            });
12404
12405            vm.ordering = {
12406                predicate: "ExtensionSortOrder",
12407                reverse: false
12408            }
12409
12410            vm.extensionFilter = "";
12411
12412            vm.yearSelect = "3";
12413
12414            vm.showTiers = !!$location.search()["showTiers"];
12415
12416            vm.toggleTiers = function() {
12417                vm.showTiers = !vm.showTiers
12418                $location.search("showTiers", vm.showTiers ? true : null);
12419            }
12420
12421            $scope.$on("$locationChangeSuccess", function () { vm.showTiers = $location.search()["showTiers"] });
12422
12423            vm.currentCustomerType = CustomerType;
12424            vm.currentCustomerSubType = CustomerSubType;
12425            vm.selectedCustomerSubType = vm.currentCustomerSubType;
12426
12427            vm.pricingTierNames = CustomerTypeStore;
12428
12429            vm.getTierButtonText = function (customerSubType) {
12430                return vm.selectedCustomerSubType === customerSubType ? "Currently viewing" : "Preview prices below";
12431            }
12432
12433            /**
12434             * Get pricing for a specific customerSubType
12435             * If called without params, gets cached (faster) for current acc
12436             * @param {string} customerSubType Only allows subtypes associated with correct customerTypes
12437             */
12438            vm.getPricing = function (customerSubType) {
12439                vm.selectedCustomerSubType = customerSubType || CustomerSubType;
12440                $rootScope.$emit("ShowHideLoadingAnimation", true);
12441
12442                PricingStore.QueryDomainPricings(vm.selectedCustomerSubType).then(function (pricings) {
12443                    $rootScope.$emit("ShowHideLoadingAnimation", false);
12444                    vm.pricings = pricings;
12445                });
12446            }
12447        }])
12448        .controller("HostingController", ["$scope", "$rootScope", function ($scope, $rootScope) {
12449            var vm = this;
12450
12451            vm.termSelect = "12";
12452            $rootScope.$emit("ShowHideLoadingAnimation", false);
12453        }])
12454        .controller("SSLController", ["$scope", "$rootScope", function ($scope, $rootScope) {
12455            var vm = this;
12456            $rootScope.$emit("ShowHideLoadingAnimation", false);
12457        }])
12458        .controller("EmailController", ["$scope", "$rootScope", "$timeout", "$log", "PricingStore", function ($scope, $rootScope, $timeout, $log, PricingStore) {
12459            var vm = this;
12460            vm.termSelect = "12";
12461
12462            var emailCodes = [
12463                "EMACTL3Q0001",
12464                "EMACTL3Q0002",
12465                "EMACTL3Q0005",
12466                "EMACTL3Q0010",
12467                "EMACTL4Q0001",
12468                "EMACTL4Q0002",
12469                "EMACTL4Q0005",
12470                "EMACTL4Q0010"
12471            ];
12472
12473            vm.showTermDropdown = false;
12474
12475            $timeout(function() {
12476                if (PricingStore.QueryPromise) {
12477                    PricingStore.QueryPromise.then(function () {
12478                        shouldShowTermDropdown();
12479                        $rootScope.$emit("ShowHideLoadingAnimation", false);
12480                    });
12481                } else {
12482                    shouldShowTermDropdown();
12483                }
12484            });
12485        
12486            // The pricing dropdown should only be shown if any of the plans' smallest term's price per term is not the same as its largest counterpart
12487            function shouldShowTermDropdown() {
12488                _.each(emailCodes, function (code) {
12489                    var pricing = PricingStore.GetNonDomainPricing(code);
12490                    var terms = _.map(_.keys(pricing.NEW), function (key) { return parseInt(key) }).sort(function (a, b) { return a - b });
12491                    if (pricing.NEW[terms[0].toString()].Price !== pricing.NEW[terms[terms.length - 1].toString()].Price) {
12492                        vm.showTermDropdown = true;
12493                        return;
12494                    }
12495                });
12496            }
12497        }])
12498        .directive("priceRow", ["PricingStore", function (PricingStore) {
12499            return {
12500                restrict: "A",
12501                template: "<tr>" +
12502                    "<td>{{displayName}}</td>" +
12503                    "<td ng-if='pricing[\"NEW\"][planTerm]'><small>{{pricing['NEW'][planTerm].DisplayedCurrency}}</small><span class='price'>{{pricing['NEW'][planTerm].DisplayedPrice | currency}}</span><small>/month<span class='on-sale bg-yellow border-rounded text-bold ml5' ng-if='pricing[\"NEW\"][planTerm].PromoCode'>On Sale</span></td>" +
12504                    "<td ng-if='!pricing[\"NEW\"][planTerm]'><small>N/A</small></td>" +
12505                    "<td ng-if='pricing[\"RENEW\"][planTerm]'><small>{{pricing['NEW'][planTerm].DisplayedCurrency}}</small><span class='price'>{{pricing['RENEW'][planTerm].DisplayedPrice | currency}}</span><small>/month</span><span class='on-sale bg-yellow border-rounded text-bold ml5' ng-if='pricing[\"RENEW\"][planTerm].PromoCode'>On Sale</span></td>" +
12506                    "<td ng-if='!pricing[\"RENEW\"][planTerm]'><small>N/A</small></td>" +
12507                    "</tr>",
12508                replace: true,
12509                scope: {
12510                    displayName: "@",
12511                    planCode: "@",
12512                    planTerm: "="
12513                },
12514                link: function(scope, elem, attrs) {
12515                    PricingStore.PlanCodes[attrs.planCode] = true;
12516                    scope.pricing = {};
12517                    scope.$watch("planCode", function () {
12518                        PricingStore.QueryPricings().then(function() {
12519                            scope.pricing = PricingStore.GetNonDomainPricing(scope.planCode);
12520                        });
12521                    });
12522                }
12523            }
12524        }])
12525        .filter("extensionLandingPageUrl", ["$window", function ($window) {
12526            return function(extension) {
12527                return $window._SmartURL + "domain-registration/register-" + extension.substring(1) + "-domain-names/default.aspx";
12528            }    
12529        }])
12530        .filter("orderExtensionsToTop", [function() {
12531            return function(pricings, ordering, extensions) {
12532                if (ordering.predicate !== "Extension" || pricings.length === 0) return pricings;
12533
12534                var oExtensions = {};
12535                var i;
12536                for (i = 0; i < extensions.length; i++) {
12537                    oExtensions[extensions[i]] = { extIndex: i };
12538                }
12539
12540                var sortedPricings = [];
12541                for (i = 0; i < pricings.length; i++) {
12542                    if (!!oExtensions[pricings[i].Extension]) {
12543                        oExtensions[pricings[i].Extension].pricingIndex = i;
12544                    } else {
12545                        sortedPricings.push(pricings[i]);
12546                    }
12547                }
12548                for (i = extensions.length - 1; i >= 0; --i) {
12549                    if (oExtensions[extensions[i]].pricingIndex === undefined) continue;
12550                    if (!ordering.reverse) {
12551                        sortedPricings.unshift(pricings[oExtensions[extensions[i]].pricingIndex]);
12552                    } else {
12553                        sortedPricings.push(pricings[oExtensions[extensions[i]].pricingIndex]);
12554                    }       
12555                }
12556                
12557                return sortedPricings;
12558            }
12559        }]);
12560})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.