text: (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Abyssa = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  
  var _anchors = require('./anchors');
  
  var _anchors2 = _interopRequireDefault(_anchors);
  
  var _StateWithParams = require('./StateWithParams');
  
  var _StateWithParams2 = _interopRequireDefault(_StateWithParams);
  
  var _Transition = require('./Transition');
  
  var _Transition2 = _interopRequireDefault(_Transition);
  
  var _util = require('./util');
  
  var util = _interopRequireWildcard(_util);
  
  var _State = require('./State');
  
  var _State2 = _interopRequireDefault(_State);
  
  var _api = require('./api');
  
  var _api2 = _interopRequireDefault(_api);
  
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var defaultOptions = {
    enableLogs: false,
    interceptAnchors: true,
    notFound: null,
    urlSync: 'history',
    hashPrefix: ''
  };
  
  /*
  * Create a new Router instance, passing any state defined declaratively.
  * More states can be added using addState().
  *
  * Because a router manages global state (the URL), only one instance of Router
  * should be used inside an application.
  */
  function Router(declarativeStates) {
    var router = {};
    var states = stateTrees(declarativeStates);
    var eventCallbacks = {};
  
    var options = util.copyObject(defaultOptions);
    var firstTransition = true;
    var ignoreNextURLChange = false;
    var currentPathQuery = void 0;
    var currentParamsDiff = {};
    var currentState = void 0;
    var previousState = void 0;
    var transition = void 0;
    var leafStates = void 0;
    var urlChanged = void 0;
    var initialized = void 0;
    var hashSlashString = void 0;
  
    /*
    * Setting a new state will start a transition from the current state to the target state.
    * A successful transition will result in the URL being changed.
    * A failed transition will leave the router in its current state.
    */
    function setState(state, params, acc) {
      var fromState = transition ? (0, _StateWithParams2.default)(transition.currentState, transition.toParams) : currentState;
  
      var diff = util.objectDiff(fromState && fromState.params, params);
  
      var toState = (0, _StateWithParams2.default)(state, params, currentPathQuery, diff);
  
      if (preventTransition(fromState, toState, diff)) {
        if (transition && transition.exiting) cancelTransition();
        return;
      }
  
      if (transition) cancelTransition();
  
      // While the transition is running, any code asking the router about the previous/current state should
      // get the end result state.
      previousState = currentState;
      currentState = toState;
      currentParamsDiff = diff;
  
      transition = (0, _Transition2.default)(fromState, toState, diff, acc, router, logger);
  
      startingTransition(fromState, toState);
  
      // In case of a redirect() called from 'startingTransition', the transition already ended.
      if (transition) transition.run();
  
      // In case of a redirect() called from the transition itself, the transition already ended
      if (transition) {
        if (transition.cancelled) currentState = fromState;else endingTransition(fromState, toState);
      }
  
      transition = null;
    }
  
    function cancelTransition() {
      logger.log('Cancelling existing transition from {0} to {1}', transition.from, transition.to);
  
      transition.cancel();
  
      firstTransition = false;
    }
  
    function startingTransition(fromState, toState) {
      logger.log('Starting transition from {0} to {1}', fromState, toState);
  
      var from = fromState ? fromState.asPublic : null;
      var to = toState.asPublic;
  
      eventCallbacks.started && eventCallbacks.started(to, from);
    }
  
    function endingTransition(fromState, toState) {
      if (!urlChanged && !firstTransition) {
        logger.log('Updating URL: {0}', currentPathQuery);
        updateURLFromState(currentPathQuery, document.title, currentPathQuery);
      }
  
      firstTransition = false;
  
      logger.log('Transition from {0} to {1} ended', fromState, toState);
  
      toState.state.lastParams = toState.params;
  
      var from = fromState ? fromState.asPublic : null;
      var to = toState.asPublic;
      eventCallbacks.ended && eventCallbacks.ended(to, from);
    }
  
    function updateURLFromState(state, title, url) {
      if (isHashMode()) {
        ignoreNextURLChange = true;
        location.hash = options.hashPrefix + url;
      } else history.pushState(state, title, url);
    }
  
    /*
    * Return whether the passed state is the same as the current one
    * in which case the router can ignore the change.
    */
    function preventTransition(current, newState, diff) {
      if (!current) return false;
  
      return newState.state == current.state && Object.keys(diff.all).length == 0;
    }
  
    /*
    * The state wasn't found
    * Transition to the 'notFound' state if the developer specified it or else throw an error.
    */
    function notFound(state) {
      logger.log('State not found: {0}', state);
  
      if (options.notFound) return setState(leafStates[options.notFound], {});else throw new Error('State "' + state + '" could not be found');
    }
  
    /*
    * Configure the router before its initialization.
    * The available options are:
    *   enableLogs: Whether (debug and error) console logs should be enabled. Defaults to false.
    *   interceptAnchors: Whether anchor mousedown/clicks should be intercepted and trigger a state change. Defaults to true.
    *   notFound: The State to enter when no state matching the current path query or name could be found. Defaults to null.
    *   urlSync: How should the router maintain the current state and the url in sync. Defaults to true (history API).
    *   hashPrefix: Customize the hash separator. Set to '!' in order to have a hashbang like '/#!/'. Defaults to empty string.
    */
    function configure(withOptions) {
      util.mergeObjects(options, withOptions);
      return router;
    }
  
    /*
    * Initialize the router.
    * The router will immediately initiate a transition to, in order of priority:
    * 1) The init state passed as an argument
    * 2) The state captured by the current URL
    */
    function init(initState, initParams) {
      if (options.enableLogs || Router.log) Router.enableLogs();
  
      if (options.interceptAnchors) (0, _anchors2.default)(router);
  
      hashSlashString = '#' + options.hashPrefix + '/';
  
      logger.log('Router init');
  
      initStates();
      logStateTree();
  
      initState = initState !== undefined ? initState : urlPathQuery();
  
      logger.log('Initializing to state {0}', initState || '""');
      transitionTo(initState, initParams);
  
      listenToURLChanges();
  
      initialized = true;
      return router;
    }
  
    /*
    * Remove any possibility of side effect this router instance might cause.
    * Used for testing purposes where we keep reusing the same router instance.
    */
    function terminate() {
      window.onhashchange = null;
      window.onpopstate = null;
      options = util.copyObject(defaultOptions);
      logger.enabled = false;
      logger.log = logger.error = util.noop;
    }
  
    function listenToURLChanges() {
  
      function onURLChange(evt) {
        if (ignoreNextURLChange) {
          ignoreNextURLChange = false;
          return;
        }
  
        var newState = evt.state || urlPathQuery();
  
        logger.log('URL changed: {0}', newState);
        urlChanged = true;
        setStateForPathQuery(newState);
      }
  
      window[isHashMode() ? 'onhashchange' : 'onpopstate'] = onURLChange;
    }
  
    function initStates() {
      var stateArray = util.objectToArray(states);
  
      addDefaultStates(stateArray);
  
      eachRootState(function (name, state) {
        state.init(router, name);
      });
  
      assertPathUniqueness(stateArray);
  
      leafStates = registerLeafStates(stateArray, {});
  
      assertNoAmbiguousPaths();
    }
  
    function assertPathUniqueness(states) {
      var paths = {};
  
      states.forEach(function (state) {
        if (paths[state.path]) {
          var fullPaths = states.map(function (s) {
            return s.fullPath() || 'empty';
          });
          throw new Error('Two sibling states have the same path (' + fullPaths + ')');
        }
  
        paths[state.path] = 1;
        assertPathUniqueness(state.children);
      });
    }
  
    function assertNoAmbiguousPaths() {
      var paths = {};
  
      for (var name in leafStates) {
        var path = util.normalizePathQuery(leafStates[name].fullPath());
        if (paths[path]) throw new Error('Ambiguous state paths: ' + path);
        paths[path] = 1;
      }
    }
  
    function addDefaultStates(states) {
      states.forEach(function (state) {
        var children = util.objectToArray(state.states);
  
        // This is a parent state: Add a default state to it if there isn't already one
        if (children.length) {
          addDefaultStates(children);
  
          var hasDefaultState = children.reduce(function (result, state) {
            return state.path == '' || result;
          }, false);
  
          if (hasDefaultState) return;
  
          var defaultState = (0, _State2.default)({ uri: '' });
          state.states._default_ = defaultState;
        }
      });
    }
  
    function eachRootState(callback) {
      for (var name in states) {
        callback(name, states[name]);
      }
    }
  
    function registerLeafStates(states, leafStates) {
      return states.reduce(function (leafStates, state) {
        if (state.children.length) return registerLeafStates(state.children, leafStates);else {
          leafStates[state.fullName] = state;
          state.paths = util.parsePaths(state.fullPath());
          return leafStates;
        }
      }, leafStates);
    }
  
    /*
    * Request a programmatic state change.
    *
    * Two notations are supported:
    * transitionTo('my.target.state', {id: 33, filter: 'desc'})
    * transitionTo('target/33?filter=desc')
    */
    function transitionTo(pathQueryOrName) {
      var name = leafStates[pathQueryOrName];
      var params = (name ? arguments[1] : null) || {};
      var acc = name ? arguments[2] : arguments[1];
  
      logger.log('Changing state to {0}', pathQueryOrName || '""');
  
      urlChanged = false;
  
      if (name) setStateByName(name, params, acc);else setStateForPathQuery(pathQueryOrName, acc);
    }
  
    /*
     * Replaces the current state's params in the history with new params.
     * The state is NOT exited/re-entered.
     */
    function replaceParams(newParams) {
      if (!currentState) return;
  
      var newUri = router.link(currentState.state.fullName, newParams);
  
      currentState = (0, _StateWithParams2.default)(currentState.state, newParams, newUri);
  
      history.replaceState(newUri, document.title, newUri);
    }
  
    /*
    * Attempt to navigate to 'stateName' with its previous params or
    * fallback to the defaultParams parameter if the state was never entered.
    */
    function backTo(stateName, defaultParams, acc) {
      var params = leafStates[stateName].lastParams || defaultParams;
      transitionTo(stateName, params, acc);
    }
  
    function setStateForPathQuery(pathQuery, acc) {
      var state = void 0,
          params = void 0,
          _state = void 0,
          _params = void 0;
  
      currentPathQuery = util.normalizePathQuery(pathQuery);
  
      var pq = currentPathQuery.split('?');
      var path = pq[0];
      var query = pq[1];
      var paths = util.parsePaths(path);
      var queryParams = util.parseQueryParams(query);
  
      for (var name in leafStates) {
        _state = leafStates[name];
        _params = _state.matches(paths);
  
        if (_params) {
          state = _state;
          params = util.mergeObjects(_params, queryParams);
          break;
        }
      }
  
      if (state) setState(state, params, acc);else notFound(currentPathQuery);
    }
  
    function setStateByName(name, params, acc) {
      var state = leafStates[name];
  
      if (!state) return notFound(name);
  
      var pathQuery = interpolate(state, params);
      setStateForPathQuery(pathQuery, acc);
    }
  
    /*
    * Add a new root state to the router.
    * The name must be unique among root states.
    */
    function addState(name, state) {
      if (states[name]) throw new Error('A state already exist in the router with the name ' + name);
  
      state = stateTree(state);
  
      states[name] = state;
  
      // The router is already initialized: Hot patch this state in.
      if (initialized) {
        state.init(router, name);
        registerLeafStates([state], leafStates);
      }
  
      return router;
    }
  
    /*
    * Read the path/query from the URL.
    */
    function urlPathQuery() {
      var hashSlash = location.href.indexOf(hashSlashString);
      var pathQuery = void 0;
  
      if (hashSlash > -1) pathQuery = location.href.slice(hashSlash + hashSlashString.length);else if (isHashMode()) pathQuery = '/';else pathQuery = (location.pathname + location.search).slice(1);
  
      return util.normalizePathQuery(pathQuery);
    }
  
    function isHashMode() {
      return options.urlSync == 'hash';
    }
  
    /*
    * Compute a link that can be used in anchors' href attributes
    * from a state name and a list of params, a.k.a reverse routing.
    */
    function link(stateName, params) {
      var state = leafStates[stateName];
      if (!state) throw new Error('Cannot find state ' + stateName);
  
      var interpolated = interpolate(state, params);
      var uri = util.normalizePathQuery(interpolated);
  
      return isHashMode() ? '#' + options.hashPrefix + uri : uri;
    }
  
    function interpolate(state, params) {
      var encodedParams = {};
  
      for (var key in params) {
        if (params[key] !== undefined) encodedParams[key] = encodeURIComponent(params[key]);
      }
  
      return state.interpolate(encodedParams);
    }
  
    /*
    * Returns an object representing the current state of the router.
    */
    function getCurrent() {
      return currentState && currentState.asPublic;
    }
  
    /*
    * Returns an object representing the previous state of the router
    * or null if the router is still in its initial state.
    */
    function getPrevious() {
      return previousState && previousState.asPublic;
    }
  
    /*
    * Returns the diff between the current params and the previous ones.
    */
    function getParamsDiff() {
      return currentParamsDiff;
    }
  
    function allStatesRec(states, acc) {
      acc.push.apply(acc, states);
      states.forEach(function (state) {
        return allStatesRec(state.children, acc);
      });
      return acc;
    }
  
    function allStates() {
      return allStatesRec(util.objectToArray(states), []);
    }
  
    /*
    * Returns the state object that was built with the given options object or that has the given fullName.
    * Returns undefined if the state doesn't exist.
    */
    function findState(by) {
      var filterFn = (typeof by === 'undefined' ? 'undefined' : _typeof(by)) === 'object' ? function (state) {
        return by === state.options;
      } : function (state) {
        return by === state.fullName;
      };
  
      var state = allStates().filter(filterFn)[0];
      return state && state.asPublic;
    }
  
    /*
    * Returns whether the router is executing its first transition.
    */
    function isFirstTransition() {
      return previousState == null;
    }
  
    function on(eventName, cb) {
      eventCallbacks[eventName] = cb;
      return router;
    }
  
    function stateTrees(states) {
      return util.mapValues(states, stateTree);
    }
  
    /*
    * Creates an internal State object from a specification POJO.
    */
    function stateTree(state) {
      if (state.children) state.children = stateTrees(state.children);
      return (0, _State2.default)(state);
    }
  
    function logStateTree() {
      if (!logger.enabled) return;
  
      function indent(level) {
        if (level == 0) return '';
        return new Array(2 + (level - 1) * 4).join(' ') + '── ';
      }
  
      var stateTree = function stateTree(state) {
        var path = util.normalizePathQuery(state.fullPath());
        var pathStr = state.children.length == 0 ? ' (@ path)'.replace('path', path) : '';
        var str = indent(state.parents.length) + state.name + pathStr + '\n';
        return str + state.children.map(stateTree).join('');
      };
  
      var msg = '\nState tree\n\n';
      msg += util.objectToArray(states).map(stateTree).join('');
      msg += '\n';
  
      logger.log(msg);
    }
  
    // Public methods
  
    router.configure = configure;
    router.init = init;
    router.transitionTo = transitionTo;
    router.replaceParams = replaceParams;
    router.backTo = backTo;
    router.addState = addState;
    router.link = link;
    router.current = getCurrent;
    router.previous = getPrevious;
    router.findState = findState;
    router.isFirstTransition = isFirstTransition;
    router.paramsDiff = getParamsDiff;
    router.options = options;
    router.on = on;
  
    // Used for testing purposes only
    router.urlPathQuery = urlPathQuery;
    router.terminate = terminate;
  
    util.mergeObjects(_api2.default, router);
  
    return router;
  }
  
  // Logging
  
  var logger = {
    log: util.noop,
    error: util.noop,
    enabled: false
  };
  
  Router.enableLogs = function () {
    logger.enabled = true;
  
    logger.log = function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
  
      var message = util.makeMessage.apply(null, args);
      console.log(message);
    };
  
    logger.error = function () {
      for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }
  
      var message = util.makeMessage.apply(null, args);
      console.error(message);
    };
  };
  
  exports.default = Router;
  
  },{"./State":2,"./StateWithParams":3,"./Transition":4,"./anchors":5,"./api":6,"./util":8}],2:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _util = require('./util');
  
  var util = _interopRequireWildcard(_util);
  
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  
  var PARAMS = /:[^\\?\/]*/g;
  
  /*
  * Creates a new State instance from a {uri, enter, exit, update, children} object.
  * This is the internal representation of a state used by the router.
  */
  function State(options) {
    var state = { options: options };
    var states = options.children;
  
    state.path = pathFromURI(options.uri);
    state.params = paramsFromURI(options.uri);
    state.queryParams = queryParamsFromURI(options.uri);
    state.states = states;
    state.data = options.data;
  
    state.enter = options.enter || util.noop;
    state.update = options.update;
    state.exit = options.exit || util.noop;
  
    /*
    * Initialize and freeze this state.
    */
    function init(router, name, parent) {
      state.router = router;
      state.name = name;
      state.isDefault = name == '_default_';
      state.parent = parent;
      state.parents = getParents();
      state.root = state.parent ? state.parents[state.parents.length - 1] : state;
      state.children = util.objectToArray(states);
      state.fullName = getFullName();
      state.asPublic = makePublicAPI();
  
      eachChildState(function (name, childState) {
        childState.init(router, name, state);
      });
    }
  
    /*
    * The full path, composed of all the individual paths of this state and its parents.
    */
    function fullPath() {
      var result = state.path;
      var stateParent = state.parent;
  
      while (stateParent) {
        if (stateParent.path) result = stateParent.path + '/' + result;
        stateParent = stateParent.parent;
      }
  
      return result;
    }
  
    /*
    * The list of all parents, starting from the closest ones.
    */
    function getParents() {
      var parents = [];
      var parent = state.parent;
  
      while (parent) {
        parents.push(parent);
        parent = parent.parent;
      }
  
      return parents;
    }
  
    /*
    * The fully qualified name of this state.
    * e.g granparentName.parentName.name
    */
    function getFullName() {
      var result = state.parents.reduceRight(function (acc, parent) {
        return acc + parent.name + '.';
      }, '') + state.name;
  
      return state.isDefault ? result.replace('._default_', '') : result;
    }
  
    function allQueryParams() {
      return state.parents.reduce(function (acc, parent) {
        return util.mergeObjects(acc, parent.queryParams);
      }, util.copyObject(state.queryParams));
    }
  
    function makePublicAPI() {
      return {
        name: state.name,
        fullName: state.fullName,
        data: options.data || {},
        parent: state.parent && state.parent.asPublic
      };
    }
  
    function eachChildState(callback) {
      for (var name in states) {
        callback(name, states[name]);
      }
    }
  
    /*
    * Returns whether this state matches the passed path Array.
    * In case of a match, the actual param values are returned.
    */
    function matches(paths) {
      var params = {};
      var nonRestStatePaths = state.paths.filter(function (p) {
        return p[p.length - 1] !== '*';
      });
  
      /* This state has more paths than the passed paths, it cannot be a match */
      if (nonRestStatePaths.length > paths.length) return false;
  
      /* Checks if the paths match one by one */
      for (var i = 0; i < paths.length; i++) {
        var path = paths[i];
        var thatPath = state.paths[i];
  
        /* This state has less paths than the passed paths, it cannot be a match */
        if (!thatPath) return false;
  
        var isRest = thatPath[thatPath.length - 1] === '*';
        if (isRest) {
          var name = paramName(thatPath);
          params[name] = paths.slice(i).join('/');
          return params;
        }
  
        var isDynamic = thatPath[0] === ':';
        if (isDynamic) {
          var _name = paramName(thatPath);
          params[_name] = path;
        } else if (thatPath != path) return false;
      }
  
      return params;
    }
  
    /*
    * Returns a URI built from this state and the passed params.
    */
    function interpolate(params) {
      var path = state.fullPath().replace(PARAMS, function (p) {
        return params[paramName(p)] || '';
      });
  
      var queryParams = allQueryParams();
      var passedQueryParams = Object.keys(params).filter(function (p) {
        return queryParams[p];
      });
  
      var query = passedQueryParams.map(function (p) {
        return p + '=' + params[p];
      }).join('&');
  
      return path + (query.length ? '?' + query : '');
    }
  
    function toString() {
      return state.fullName;
    }
  
    state.init = init;
    state.fullPath = fullPath;
    state.allQueryParams = allQueryParams;
    state.matches = matches;
    state.interpolate = interpolate;
    state.toString = toString;
  
    return state;
  }
  
  function paramName(param) {
    return param[param.length - 1] === '*' ? param.substr(1).slice(0, -1) : param.substr(1);
  }
  
  function pathFromURI(uri) {
    return (uri || '').split('?')[0];
  }
  
  function paramsFromURI(uri) {
    var matches = PARAMS.exec(uri);
    return matches ? util.arrayToObject(matches.map(paramName)) : {};
  }
  
  function queryParamsFromURI(uri) {
    var query = (uri || '').split('?')[1];
    return query ? util.arrayToObject(query.split('&')) : {};
  }
  
  exports.default = State;
  
  },{"./util":8}],3:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = StateWithParams;
  /*
  * Creates a new StateWithParams instance.
  *
  * StateWithParams is the merge between a State object (created and added to the router before init)
  * and params (both path and query params, extracted from the URL after init)
  *
  * This is an internal model The public model is the asPublic property.
  */
  function StateWithParams(state, params, pathQuery, diff) {
    return {
      state: state,
      params: params,
      toString: toString,
      asPublic: makePublicAPI(state, params, pathQuery, diff)
    };
  }
  
  function makePublicAPI(state, params, pathQuery, paramsDiff) {
  
    /*
    * Returns whether this state or any of its parents has the given fullName.
    */
    function isIn(fullStateName) {
      var current = state;
      while (current) {
        if (current.fullName == fullStateName) return true;
        current = current.parent;
      }
      return false;
    }
  
    return {
      uri: pathQuery,
      params: params,
      paramsDiff: paramsDiff,
      name: state ? state.name : '',
      fullName: state ? state.fullName : '',
      data: state ? state.data : {},
      isIn: isIn
    };
  }
  
  function toString() {
    var name = this.state && this.state.fullName;
    return name + ':' + JSON.stringify(this.params);
  }
  
  },{}],4:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  /*
  * Create a new Transition instance.
  */
  function Transition(fromStateWithParams, toStateWithParams, paramsDiff, acc, router, logger) {
    var root = { root: null, inclusive: true };
    var enters = void 0;
    var exits = void 0;
  
    var fromState = fromStateWithParams && fromStateWithParams.state;
    var toState = toStateWithParams.state;
    var params = toStateWithParams.params;
    var isUpdate = fromState == toState;
  
    var transition = {
      from: fromState,
      to: toState,
      toParams: params,
      cancel: cancel,
      run: run,
      cancelled: false,
      currentState: fromState
    };
  
    // The first transition has no fromState.
    if (fromState) root = transitionRoot(fromState, toState, isUpdate, paramsDiff);
  
    exits = fromState ? transitionStates(fromState, root) : [];
    enters = transitionStates(toState, root).reverse();
  
    function run() {
      startTransition(enters, exits, params, transition, isUpdate, acc, router, logger);
    }
  
    function cancel() {
      transition.cancelled = true;
    }
  
    return transition;
  }
  
  function startTransition(enters, exits, params, transition, isUpdate, acc, router, logger) {
    acc = acc || {};
  
    transition.exiting = true;
    exits.forEach(function (state) {
      if (isUpdate && state.update) return;
      runStep(state, 'exit', params, transition, acc, router, logger);
    });
    transition.exiting = false;
  
    enters.forEach(function (state) {
      var fn = isUpdate && state.update ? 'update' : 'enter';
      runStep(state, fn, params, transition, acc, router, logger);
    });
  }
  
  function runStep(state, stepFn, params, transition, acc, router, logger) {
    if (transition.cancelled) return;
  
    if (logger.enabled) {
      var capitalizedStep = stepFn[0].toUpperCase() + stepFn.slice(1);
      logger.log(capitalizedStep + ' ' + state.fullName);
    }
  
    var result = state[stepFn](params, acc, router);
  
    if (transition.cancelled) return;
  
    transition.currentState = stepFn == 'exit' ? state.parent : state;
  
    return result;
  }
  
  /*
  * The top-most fromState's parent that must be exited
  * or undefined if the two states are in distinct branches of the tree.
  */
  function transitionRoot(fromState, toState, isUpdate, paramsDiff) {
    var closestCommonParent = void 0;
  
    var parents = [fromState].concat(fromState.parents).reverse();
  
    // Find the closest common parent of the from/to states, if any.
    if (!isUpdate) {
      for (var i = 0; i < fromState.parents.length; i++) {
        var parent = fromState.parents[i];
  
        if (toState.parents.indexOf(parent) > -1) {
          closestCommonParent = parent;
          break;
        }
      }
    }
  
    // Find the top-most parent owning some updated param(s) or bail if we first reach the closestCommonParent
    for (var _i = 0; _i < parents.length; _i++) {
      var _parent = parents[_i];
  
      for (var param in paramsDiff.all) {
        if (_parent.params[param] || _parent.queryParams[param]) return { root: _parent, inclusive: true };
      }
  
      if (_parent === closestCommonParent) return { root: closestCommonParent, inclusive: false };
    }
  
    return closestCommonParent ? { root: closestCommonParent, inclusive: false } : { inclusive: true };
  }
  
  function transitionStates(state, _ref) {
    var root = _ref.root,
        inclusive = _ref.inclusive;
  
    root = root || state.root;
  
    var p = state.parents;
    var end = Math.min(p.length, p.indexOf(root) + (inclusive ? 1 : 0));
  
    return [state].concat(p.slice(0, end));
  }
  
  exports.default = Transition;
  
  },{}],5:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = interceptAnchors;
  
  var router = void 0;
  
  function onMouseDown(evt) {
    var href = hrefForEvent(evt);
  
    if (href !== undefined) router.transitionTo(href);
  }
  
  function onMouseClick(evt) {
    var href = hrefForEvent(evt);
  
    if (href !== undefined) {
      evt.preventDefault();
      router.transitionTo(href);
    }
  }
  
  function hrefForEvent(evt) {
    if (evt.defaultPrevented || evt.metaKey || evt.ctrlKey || !isLeftButton(evt)) return;
  
    var target = evt.target;
    var anchor = anchorTarget(target);
    if (!anchor) return;
  
    var dataNav = anchor.getAttribute('data-nav');
  
    if (dataNav == 'ignore') return;
    if (evt.type == 'mousedown' && dataNav != 'mousedown') return;
  
    var href = anchor.getAttribute('href');
  
    if (!href) return;
    if (href.charAt(0) == '#') {
      if (router.options.urlSync != 'hash') return;
      href = href.slice(1);
    }
    if (anchor.getAttribute('target') == '_blank') return;
    if (!isLocalLink(anchor)) return;
  
    // At this point, we have a valid href to follow.
    // Did the navigation already occur on mousedown though?
    if (evt.type == 'click' && dataNav == 'mousedown') {
      evt.preventDefault();
      return;
    }
  
    return href;
  }
  
  function isLeftButton(evt) {
    return evt.which == 1;
  }
  
  function anchorTarget(target) {
    while (target) {
      if (target.nodeName == 'A') return target;
      target = target.parentNode;
    }
  }
  
  function isLocalLink(anchor) {
    var hostname = anchor.hostname;
    var port = anchor.port;
    var protocol = anchor.protocol;
  
    // IE10 can lose the hostname/port property when setting a relative href from JS
    if (!hostname) {
      var tempAnchor = document.createElement("a");
      tempAnchor.href = anchor.href;
      hostname = tempAnchor.hostname;
      port = tempAnchor.port;
      protocol = tempAnchor.protocol;
    }
  
    var defaultPort = protocol.split(':')[0] === 'https' ? '443' : '80';
  
    var sameHostname = hostname == location.hostname;
    var samePort = (port || defaultPort) == (location.port || defaultPort);
  
    return sameHostname && samePort;
  }
  
  function interceptAnchors(forRouter) {
    router = forRouter;
  
    document.addEventListener('mousedown', onMouseDown);
    document.addEventListener('click', onMouseClick);
  }
  
  },{}],6:[function(require,module,exports){
  "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  /* Represents the public API of the last instanciated router; Useful to break circular dependencies between router and its states */
  var api = {};
  exports.default = api;
  
  },{}],7:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.util = exports.State = exports.api = exports.Router = undefined;
  
  var _util = require('./util');
  
  var util = _interopRequireWildcard(_util);
  
  var _Router = require('./Router');
  
  var _Router2 = _interopRequireDefault(_Router);
  
  var _api = require('./api');
  
  var _api2 = _interopRequireDefault(_api);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  
  var State = util.stateShorthand;
  
  exports.Router = _Router2.default;
  exports.api = _api2.default;
  exports.State = State;
  exports.util = util;
  
  },{"./Router":1,"./api":6,"./util":8}],8:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  
  exports.noop = noop;
  exports.arrayToObject = arrayToObject;
  exports.objectToArray = objectToArray;
  exports.copyObject = copyObject;
  exports.mergeObjects = mergeObjects;
  exports.mapValues = mapValues;
  exports.objectDiff = objectDiff;
  exports.makeMessage = makeMessage;
  exports.parsePaths = parsePaths;
  exports.parseQueryParams = parseQueryParams;
  exports.normalizePathQuery = normalizePathQuery;
  exports.stateShorthand = stateShorthand;
  function noop() {}
  
  function arrayToObject(array) {
    return array.reduce(function (obj, item) {
      obj[item] = 1;
      return obj;
    }, {});
  }
  
  function objectToArray(obj) {
    var array = [];
    for (var key in obj) {
      array.push(obj[key]);
    }return array;
  }
  
  function copyObject(obj) {
    var copy = {};
    for (var key in obj) {
      copy[key] = obj[key];
    }return copy;
  }
  
  function mergeObjects(to, from) {
    for (var key in from) {
      to[key] = from[key];
    }return to;
  }
  
  function mapValues(obj, fn) {
    var result = {};
    for (var key in obj) {
      result[key] = fn(obj[key]);
    }return result;
  }
  
  /*
  * Return the set of all the keys that changed (either added, removed or modified).
  */
  function objectDiff(obj1, obj2) {
    var update = {};
    var enter = {};
    var exit = {};
    var all = {};
  
    obj1 = obj1 || {};
  
    for (var name in obj1) {
      if (!(name in obj2)) exit[name] = all[name] = true;else if (obj1[name] != obj2[name]) update[name] = all[name] = true;
    }
  
    for (var _name in obj2) {
      if (!(_name in obj1)) enter[_name] = all[_name] = true;
    }
  
    return { all: all, update: update, enter: enter, exit: exit };
  }
  
  function makeMessage() {
    var message = arguments[0];
    var tokens = Array.prototype.slice.call(arguments, 1);
  
    for (var i = 0, l = tokens.length; i < l; i++) {
      message = message.replace('{' + i + '}', tokens[i]);
    }return message;
  }
  
  function parsePaths(path) {
    return path.split('/').filter(function (str) {
      return str.length;
    }).map(function (str) {
      return decodeURIComponent(str);
    });
  }
  
  function parseQueryParams(query) {
    return query ? query.split('&').reduce(function (res, paramValue) {
      var _paramValue$split = paramValue.split('='),
          _paramValue$split2 = _slicedToArray(_paramValue$split, 2),
          param = _paramValue$split2[0],
          value = _paramValue$split2[1];
  
      res[param] = decodeURIComponent(value);
      return res;
    }, {}) : {};
  }
  
  var LEADING_SLASHES = /^\/+/;
  var TRAILING_SLASHES = /^([^?]*?)\/+$/;
  var TRAILING_SLASHES_BEFORE_QUERY = /\/+\?/;
  function normalizePathQuery(pathQuery) {
    return '/' + pathQuery.replace(LEADING_SLASHES, '').replace(TRAILING_SLASHES, '$1').replace(TRAILING_SLASHES_BEFORE_QUERY, '?');
  }
  
  function stateShorthand(uri, options, children) {
    return mergeObjects({ uri: uri, children: children || {} }, options);
  }
  
  },{}]},{},[7])(7)
  });