text: ;(function(define){define(function(require,exports,module){
  'use strict';
  
  /**
   * Locals
   */
  
  var textContent = Object.getOwnPropertyDescriptor(Node.prototype, 'textContent');
  var innerHTML = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
  var removeAttribute = Element.prototype.removeAttribute;
  var setAttribute = Element.prototype.setAttribute;
  var noop  = function() {};
  
  /**
   * Register a new component.
   *
   * @param  {String} name
   * @param  {Object} props
   * @return {constructor}
   * @public
   */
  exports.register = function(name, props) {
    var baseProto = getBaseProto(props.extends);
  
    // Clean up
    delete props.extends;
  
    // Pull out CSS that needs to be in the light-dom
    if (props.template) {
      var output = processCss(props.template, name);
  
      props.template = document.createElement('template');
      props.template.innerHTML = output.template;
      props.lightCss = output.lightCss;
  
      props.globalCss = props.globalCss || '';
      props.globalCss += output.globalCss;
    }
  
    // Inject global CSS into the document,
    // and delete as no longer needed
    injectGlobalCss(props.globalCss);
    delete props.globalCss;
  
    // Merge base getter/setter attributes with the user's,
    // then define the property descriptors on the prototype.
    var descriptors = Object.assign(props.attrs || {}, base.descriptors);
  
    // Store the orginal descriptors somewhere
    // a little more private and delete the original
    props._attrs = props.attrs;
    delete props.attrs;
  
    // Create the prototype, extended from base and
    // define the descriptors directly on the prototype
    var proto = createProto(baseProto, props);
    Object.defineProperties(proto, descriptors);
  
    // Register the custom-element and return the constructor
    return document.registerElement(name, { prototype: proto });
  };
  
  var base = {
    properties: {
      GaiaComponent: true,
      attributeChanged: noop,
      attached: noop,
      detached: noop,
      created: noop,
  
      createdCallback: function() {
        if (this.rtl) { addDirObserver(); }
        injectLightCss(this);
        this.created();
      },
  
      /**
       * It is very common to want to keep object
       * properties in-sync with attributes,
       * for example:
       *
       *   el.value = 'foo';
       *   el.setAttribute('value', 'foo');
       *
       * So we support an object on the prototype
       * named 'attrs' to provide a consistent
       * way for component authors to define
       * these properties. When an attribute
       * changes we keep the attr[name]
       * up-to-date.
       *
       * @param  {String} name
       * @param  {String||null} from
       * @param  {String||null} to
       */
      attributeChangedCallback: function(name, from, to) {
        var prop = toCamelCase(name);
        if (this._attrs && this._attrs[prop]) { this[prop] = to; }
        this.attributeChanged(name, from, to);
      },
  
      attachedCallback: function() { this.attached(); },
      detachedCallback: function() { this.detached(); },
  
      /**
       * A convenient method for setting up
       * a shadow-root using the defined template.
       *
       * @return {ShadowRoot}
       */
      setupShadowRoot: function() {
        if (!this.template) { return; }
        var node = document.importNode(this.template.content, true);
        this.createShadowRoot().appendChild(node);
        return this.shadowRoot;
      },
  
      /**
       * Sets an attribute internally
       * and externally. This is so that
       * we can style internal shadow-dom
       * content.
       *
       * @param {String} name
       * @param {String} value
       */
      setAttr: function(name, value) {
        var internal = this.shadowRoot.firstElementChild;
        setAttribute.call(internal, name, value);
        setAttribute.call(this, name, value);
      },
  
      /**
       * Removes an attribute internally
       * and externally. This is so that
       * we can style internal shadow-dom
       * content.
       *
       * @param {String} name
       * @param {String} value
       */
      removeAttr: function(name) {
        var internal = this.shadowRoot.firstElementChild;
        removeAttribute.call(internal, name);
        removeAttribute.call(this, name);
      }
    },
  
    descriptors: {
      textContent: {
        set: function(value) {
          textContent.set.call(this, value);
          if (this.lightStyle) { this.appendChild(this.lightStyle); }
        },
  
        get: textContent.get
      },
  
      innerHTML: {
        set: function(value) {
          innerHTML.set.call(this, value);
          if (this.lightStyle) { this.appendChild(this.lightStyle); }
        },
  
        get: innerHTML.get
      }
    }
  };
  
  /**
   * The default base prototype to use
   * when `extends` is undefined.
   *
   * @type {Object}
   */
  var defaultPrototype = createProto(HTMLElement.prototype, base.properties);
  
  /**
   * Returns a suitable prototype based
   * on the object passed.
   *
   * @param  {HTMLElementPrototype|undefined} proto
   * @return {HTMLElementPrototype}
   * @private
   */
  function getBaseProto(proto) {
    if (!proto) { return defaultPrototype; }
    proto = proto.prototype || proto;
    return !proto.GaiaComponent
      ? createProto(proto, base.properties)
      : proto;
  }
  
  /**
   * Extends the given proto and mixes
   * in the given properties.
   *
   * @param  {Object} proto
   * @param  {Object} props
   * @return {Object}
   */
  function createProto(proto, props) {
    return Object.assign(Object.create(proto), props);
  }
  
  /**
   * Detects presence of shadow-dom
   * CSS selectors.
   *
   * @return {Boolean}
   */
  var hasShadowCSS = (function() {
    var div = document.createElement('div');
    try { div.querySelector(':host'); return true; }
    catch (e) { return false; }
  })();
  
  /**
   * Regexs used to extract shadow-css
   *
   * @type {Object}
   */
  var regex = {
    shadowCss: /(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,
    ':host': /(?:\:host)/g,
    ':host()': /\:host\((.+)\)(?: \:\:content)?/g,
    ':host-context': /\:host-context\((.+)\)([^{,]+)?/g,
    '::content': /(?:\:\:content)/g
  };
  
  /**
   * Extracts the :host and ::content rules
   * from the shadow-dom CSS and rewrites
   * them to work from the <style scoped>
   * injected at the root of the component.
   *
   * @return {String}
   */
  function processCss(template, name) {
    var globalCss = '';
    var lightCss = '';
  
    if (!hasShadowCSS) {
      template = template.replace(regex.shadowCss, function(match) {
        var hostContext = regex[':host-context'].exec(match);
  
        if (hostContext) {
          globalCss += match
            .replace(regex['::content'], '')
            .replace(regex[':host-context'], '$1 ' + name + '$2')
            .replace(/ +/g, ' '); // excess whitespace
        } else {
          lightCss += match
            .replace(regex[':host()'], name + '$1')
            .replace(regex[':host'], name)
            .replace(regex['::content'], name);
        }
  
        return '';
      });
    }
  
    return {
      template: template,
      lightCss: lightCss,
      globalCss: globalCss
    };
  }
  
  /**
   * Some CSS rules, such as @keyframes
   * and @font-face don't work inside
   * scoped or shadow <style>. So we
   * have to put them into 'global'
   * <style> in the head of the
   * document.
   *
   * @param  {String} css
   */
  function injectGlobalCss(css) {
    if (!css) return;
    var style = document.createElement('style');
    style.innerHTML = css.trim();
    headReady().then(() => {
      document.head.appendChild(style)
    });
  }
  
  
  /**
   * Resolves a promise once document.head is ready.
   *
   * @private
   */
  function headReady() {
    return new Promise(resolve => {
      if (document.head) { return resolve(); }
      window.addEventListener('load', function fn() {
        window.removeEventListener('load', fn);
        resolve();
      });
    });
  }
  
  
  /**
   * The Gecko platform doesn't yet have
   * `::content` or `:host`, selectors,
   * without these we are unable to style
   * user-content in the light-dom from
   * within our shadow-dom style-sheet.
   *
   * To workaround this, we clone the <style>
   * node into the root of the component,
   * so our selectors are able to target
   * light-dom content.
   *
   * @private
   */
  function injectLightCss(el) {
    if (hasShadowCSS) { return; }
    el.lightStyle = document.createElement('style');
    el.lightStyle.setAttribute('scoped', '');
    el.lightStyle.innerHTML = el.lightCss;
    el.appendChild(el.lightStyle);
  }
  
  /**
   * Convert hyphen separated
   * string to camel-case.
   *
   * Example:
   *
   *   toCamelCase('foo-bar'); //=> 'fooBar'
   *
   * @param  {Sring} string
   * @return {String}
   */
  function toCamelCase(string) {
    return string.replace(/-(.)/g, function replacer(string, p1) {
      return p1.toUpperCase();
    });
  }
  
  /**
   * Observer (singleton)
   *
   * @type {MutationObserver|undefined}
   */
  var dirObserver;
  
  /**
   * Observes the document `dir` (direction)
   * attribute and dispatches a global event
   * when it changes.
   *
   * Components can listen to this event and
   * make internal changes if need be.
   *
   * @private
   */
  function addDirObserver() {
    if (dirObserver) { return; }
  
    dirObserver = new MutationObserver(onChanged);
    dirObserver.observe(document.documentElement, {
      attributeFilter: ['dir'],
      attributes: true
    });
  
    function onChanged(mutations) {
      document.dispatchEvent(new Event('dirchanged'));
    }
  }
  
  });})(typeof define=='function'&&define.amd?define
  :(function(n,w){'use strict';return typeof module=='object'?function(c){
  c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){
  return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));