text: import * as FreeStyle from "free-style";
  import { convertToStyles, convertToKeyframes } from './formatting';
  import { extend, raf } from './utilities';
  /**
   * Creates an instance of free style with our options
   */
  var createFreeStyle = function () { return FreeStyle.create(); };
  /**
   * Maintains a single stylesheet and keeps it in sync with requested styles
   */
  var TypeStyle = /** @class */ (function () {
      function TypeStyle(_a) {
          var _this = this;
          var autoGenerateTag = _a.autoGenerateTag;
          /**
           * Insert `raw` CSS as a string. This is useful for e.g.
           * - third party CSS that you are customizing with template strings
           * - generating raw CSS in JavaScript
           * - reset libraries like normalize.css that you can use without loaders
           */
          this.cssRaw = function (mustBeValidCSS) {
              if (!mustBeValidCSS) {
                  return;
              }
              _this._raw += mustBeValidCSS || '';
              _this._pendingRawChange = true;
              _this._styleUpdated();
          };
          /**
           * Takes CSSProperties and registers it to a global selector (body, html, etc.)
           */
          this.cssRule = function (selector) {
              var objects = [];
              for (var _i = 1; _i < arguments.length; _i++) {
                  objects[_i - 1] = arguments[_i];
              }
              var styles = convertToStyles(extend.apply(void 0, objects));
              _this._freeStyle.registerRule(selector, styles);
              _this._styleUpdated();
              return;
          };
          /**
           * Renders styles to the singleton tag imediately
           * NOTE: You should only call it on initial render to prevent any non CSS flash.
           * After that it is kept sync using `requestAnimationFrame` and we haven't noticed any bad flashes.
           **/
          this.forceRenderStyles = function () {
              var target = _this._getTag();
              if (!target) {
                  return;
              }
              target.textContent = _this.getStyles();
          };
          /**
           * Utility function to register an @font-face
           */
          this.fontFace = function () {
              var fontFace = [];
              for (var _i = 0; _i < arguments.length; _i++) {
                  fontFace[_i] = arguments[_i];
              }
              var freeStyle = _this._freeStyle;
              for (var _a = 0, _b = fontFace; _a < _b.length; _a++) {
                  var face = _b[_a];
                  freeStyle.registerRule('@font-face', face);
              }
              _this._styleUpdated();
              return;
          };
          /**
           * Allows use to use the stylesheet in a node.js environment
           */
          this.getStyles = function () {
              return (_this._raw || '') + _this._freeStyle.getStyles();
          };
          /**
           * Takes keyframes and returns a generated animationName
           */
          this.keyframes = function (frames) {
              var keyframes = convertToKeyframes(frames);
              // TODO: replace $debugName with display name
              var animationName = _this._freeStyle.registerKeyframes(keyframes);
              _this._styleUpdated();
              return animationName;
          };
          /**
           * Helps with testing. Reinitializes FreeStyle + raw
           */
          this.reinit = function () {
              /** reinit freestyle */
              var freeStyle = createFreeStyle();
              _this._freeStyle = freeStyle;
              _this._lastFreeStyleChangeId = freeStyle.changeId;
              /** reinit raw */
              _this._raw = '';
              _this._pendingRawChange = false;
              /** Clear any styles that were flushed */
              var target = _this._getTag();
              if (target) {
                  target.textContent = '';
              }
          };
          /** Sets the target tag where we write the css on style updates */
          this.setStylesTarget = function (tag) {
              /** Clear any data in any previous tag */
              if (_this._tag) {
                  _this._tag.textContent = '';
              }
              _this._tag = tag;
              /** This special time buffer immediately */
              _this.forceRenderStyles();
          };
          /**
           * Takes an object where property names are ideal class names and property values are CSSProperties, and
           * returns an object where property names are the same ideal class names and the property values are
           * the actual generated class names using the ideal class name as the $debugName
           */
          this.stylesheet = function (classes) {
              var classNames = Object.getOwnPropertyNames(classes);
              var result = {};
              for (var _i = 0, classNames_1 = classNames; _i < classNames_1.length; _i++) {
                  var className = classNames_1[_i];
                  var classDef = classes[className];
                  if (classDef) {
                      classDef.$debugName = className;
                      result[className] = _this.style(classDef);
                  }
              }
              return result;
          };
          var freeStyle = createFreeStyle();
          this._autoGenerateTag = autoGenerateTag;
          this._freeStyle = freeStyle;
          this._lastFreeStyleChangeId = freeStyle.changeId;
          this._pending = 0;
          this._pendingRawChange = false;
          this._raw = '';
          this._tag = undefined;
          // rebind prototype to TypeStyle.  It might be better to do a function() { return this.style.apply(this, arguments)}
          this.style = this.style.bind(this);
      }
      /**
       * Only calls cb all sync operations settle
       */
      TypeStyle.prototype._afterAllSync = function (cb) {
          var _this = this;
          this._pending++;
          var pending = this._pending;
          raf(function () {
              if (pending !== _this._pending) {
                  return;
              }
              cb();
          });
      };
      TypeStyle.prototype._getTag = function () {
          if (this._tag) {
              return this._tag;
          }
          if (this._autoGenerateTag) {
              var tag = typeof window === 'undefined'
                  ? { textContent: '' }
                  : document.createElement('style');
              if (typeof document !== 'undefined') {
                  document.head.appendChild(tag);
              }
              this._tag = tag;
              return tag;
          }
          return undefined;
      };
      /** Checks if the style tag needs updating and if so queues up the change */
      TypeStyle.prototype._styleUpdated = function () {
          var _this = this;
          var changeId = this._freeStyle.changeId;
          var lastChangeId = this._lastFreeStyleChangeId;
          if (!this._pendingRawChange && changeId === lastChangeId) {
              return;
          }
          this._lastFreeStyleChangeId = changeId;
          this._pendingRawChange = false;
          this._afterAllSync(function () { return _this.forceRenderStyles(); });
      };
      TypeStyle.prototype.style = function () {
          var className = this._freeStyle.registerStyle(convertToStyles(extend.apply(undefined, arguments)));
          this._styleUpdated();
          return className;
      };
      return TypeStyle;
  }());
  export { TypeStyle };
  