text: define(["require", "exports", "tslib", "react", "prop-types", "../../Utilities"], function (require, exports, tslib_1, React, PropTypes, Utilities_1) {
      "use strict";
      Object.defineProperty(exports, "__esModule", { value: true });
      var RESIZE_DELAY = 16;
      /**
       * Returns a simple object is able to store measurements with a given key.
       */
      exports.getMeasurementCache = function () {
          var measurementsCache = {};
          return {
              /**
               * Checks if the provided data has a cacheKey. If it has a cacheKey and there is a
               * corresponding entry in the measurementsCache, then it will return that value.
               * Returns undefined otherwise.
               */
              getCachedMeasurement: function (data) {
                  if (data && data.cacheKey && measurementsCache.hasOwnProperty(data.cacheKey)) {
                      return measurementsCache[data.cacheKey];
                  }
                  return undefined;
              },
              /**
               * Should be called whenever there is a new measurement associated with a given data object.
               * If the data has a cacheKey, store that measurement in the measurementsCache.
               */
              addMeasurementToCache: function (data, measurement) {
                  if (data.cacheKey) {
                      measurementsCache[data.cacheKey] = measurement;
                  }
              }
          };
      };
      /**
       * Returns a function that is able to compute the next state for the ResizeGroup given the current
       * state and any measurement updates.
       */
      exports.getNextResizeGroupStateProvider = function (measurementCache) {
          if (measurementCache === void 0) { measurementCache = exports.getMeasurementCache(); }
          var _measurementCache = measurementCache;
          var _containerWidth;
          /**
           * Gets the width of the data rendered in a hidden div.
           * @param measuredData - The data corresponding to the measurement we wish to take.
           * @param getElementToMeasureWidth - A function that returns the measurement of the rendered data. Only called when the measurement
           * is not in the cache.
           */
          function _getMeasuredWidth(measuredData, getElementToMeasureWidth) {
              var cachedWidth = _measurementCache.getCachedMeasurement(measuredData);
              if (cachedWidth !== undefined) {
                  return cachedWidth;
              }
              var measuredWidth = getElementToMeasureWidth();
              _measurementCache.addMeasurementToCache(measuredData, measuredWidth);
              return measuredWidth;
          }
          /**
           * Will get the next IResizeGroupState based on the current data while trying to shrink contents
           * to fit in the container.
           * @param data - The initial data point to start measuring.
           * @param onReduceData - Function that transforms the data into something that should render with less width.
           * @param getElementToMeasureWidth - A function that returns the measurement of the rendered data. Only called when the measurement
           * is not in the cache.
           */
          function _shrinkContentsUntilTheyFit(data, onReduceData, getElementToMeasureWidth) {
              var dataToMeasure = data;
              var measuredWidth = _getMeasuredWidth(data, getElementToMeasureWidth);
              while (measuredWidth > _containerWidth) {
                  var nextMeasuredData = onReduceData(dataToMeasure);
                  // We don't want to get stuck in an infinite render loop when there are no more
                  // scaling steps, so implementations of onReduceData should return undefined when
                  // there are no more scaling states to apply.
                  if (nextMeasuredData === undefined) {
                      return {
                          renderedData: dataToMeasure,
                          resizeDirection: undefined,
                          dataToMeasure: undefined
                      };
                  }
                  measuredWidth = _measurementCache.getCachedMeasurement(nextMeasuredData);
                  // If the measurement isn't in the cache, we need to rerender with some data in a hidden div
                  if (measuredWidth === undefined) {
                      return {
                          dataToMeasure: nextMeasuredData,
                          resizeDirection: 'shrink'
                      };
                  }
                  dataToMeasure = nextMeasuredData;
              }
              return {
                  renderedData: dataToMeasure,
                  resizeDirection: undefined,
                  dataToMeasure: undefined
              };
          }
          /**
           * This function should be called when the state changes in a manner that might allow for more content to fit
           * on the screen, such as the window width growing.
           * @param data - The initial data point to start measuring.
           * @param onGrowData - Function that transforms the data into something that may take up more space when rendering.
           * @param getElementToMeasureWidth - A function that returns the measurement of the rendered data. Only called when the measurement
           * is not in the cache.
           */
          function _growDataUntilItDoesNotFit(data, onGrowData, getElementToMeasureWidth) {
              var dataToMeasure = data;
              var measuredWidth = _getMeasuredWidth(data, getElementToMeasureWidth);
              while (measuredWidth < _containerWidth) {
                  var nextMeasuredData = onGrowData(dataToMeasure);
                  // We don't want to get stuck in an infinite render loop when there are no more
                  // scaling steps, so implementations of onGrowData should return undefined when
                  // there are no more scaling states to apply.
                  if (nextMeasuredData === undefined) {
                      return {
                          renderedData: dataToMeasure,
                          resizeDirection: undefined,
                          dataToMeasure: undefined
                      };
                  }
                  measuredWidth = _measurementCache.getCachedMeasurement(nextMeasuredData);
                  // If the measurement isn't in the cache, we need to rerender with some data in a hidden div
                  if (measuredWidth === undefined) {
                      return {
                          dataToMeasure: nextMeasuredData
                      };
                  }
                  dataToMeasure = nextMeasuredData;
              }
              // Once the loop is done, we should now shrink until the contents fit.
              return {
                  dataToMeasure: dataToMeasure,
                  resizeDirection: 'shrink'
              };
          }
          /**
           * Handles an update to the container width. Should only be called when we knew the previous container width.
           * @param newWidth - The new width of the container.
           * @param fullWidthData - The initial data passed in as a prop to resizeGroup.
           * @param renderedData - The data that was rendered prior to the container size changing.
           * @param onGrowData - Set to true if the Resize group has an onGrowData function.
           */
          function _updateContainerWidth(newWidth, fullWidthData, renderedData, onGrowData) {
              var nextState;
              if (newWidth > _containerWidth) {
                  if (onGrowData) {
                      nextState = {
                          resizeDirection: 'grow',
                          dataToMeasure: onGrowData(renderedData)
                      };
                  }
                  else {
                      nextState = {
                          resizeDirection: 'shrink',
                          dataToMeasure: fullWidthData
                      };
                  }
              }
              else {
                  nextState = {
                      resizeDirection: 'shrink',
                      dataToMeasure: renderedData
                  };
              }
              _containerWidth = newWidth;
              return tslib_1.__assign({}, nextState, { measureContainer: false });
          }
          function getNextState(props, currentState, getElementToMeasureWidth, newContainerWidth) {
              // If there is no new container width or data to measure, there is no need for a new state update
              if (newContainerWidth === undefined && currentState.dataToMeasure === undefined) {
                  return undefined;
              }
              if (newContainerWidth) {
                  // If we know what the last container size was and we rendered data at that width, we can do an optimized render
                  if (_containerWidth && currentState.renderedData && !currentState.dataToMeasure) {
                      return tslib_1.__assign({}, currentState, _updateContainerWidth(newContainerWidth, props.data, currentState.renderedData, props.onGrowData));
                  }
                  // If we are just setting the container width for the first time, we can't do any optimizations
                  _containerWidth = newContainerWidth;
              }
              var nextState = tslib_1.__assign({}, currentState, { measureContainer: false });
              if (currentState.dataToMeasure) {
                  if (currentState.resizeDirection === 'grow' && props.onGrowData) {
                      nextState = tslib_1.__assign({}, nextState, _growDataUntilItDoesNotFit(currentState.dataToMeasure, props.onGrowData, getElementToMeasureWidth));
                  }
                  else {
                      nextState = tslib_1.__assign({}, nextState, _shrinkContentsUntilTheyFit(currentState.dataToMeasure, props.onReduceData, getElementToMeasureWidth));
                  }
              }
              return nextState;
          }
          function shouldRenderDataToMeasureInHiddenDiv(dataToMeasure) {
              if (!dataToMeasure || _measurementCache.getCachedMeasurement(dataToMeasure) !== undefined) {
                  return false;
              }
              return true;
          }
          return {
              getNextState: getNextState,
              shouldRenderDataToMeasureInHiddenDiv: shouldRenderDataToMeasureInHiddenDiv
          };
      };
      // Provides a context property that (if true) tells any child components that
      // they are only being used for measurement purposes and will not be visible.
      var MeasuredContext = Utilities_1.provideContext({
          isMeasured: PropTypes.bool
      }, function () {
          return { isMeasured: true };
      });
      var getClassNames = Utilities_1.classNamesFunction();
      var ResizeGroupBase = /** @class */ (function (_super) {
          tslib_1.__extends(ResizeGroupBase, _super);
          function ResizeGroupBase(props) {
              var _this = _super.call(this, props) || this;
              _this._nextResizeGroupStateProvider = exports.getNextResizeGroupStateProvider();
              _this._root = Utilities_1.createRef();
              _this._measured = Utilities_1.createRef();
              _this.state = {
                  dataToMeasure: tslib_1.__assign({}, _this.props.data),
                  resizeDirection: 'grow',
                  measureContainer: true,
              };
              return _this;
          }
          ResizeGroupBase.prototype.render = function () {
              var _a = this.props, onRenderData = _a.onRenderData, className = _a.className, getStyles = _a.getStyles, theme = _a.theme;
              var _b = this.state, dataToMeasure = _b.dataToMeasure, renderedData = _b.renderedData;
              var divProps = Utilities_1.getNativeProps(this.props, Utilities_1.divProperties, ['data']);
              var classNames = getClassNames(getStyles, { theme: theme, className: className });
              return (React.createElement("div", tslib_1.__assign({}, divProps, { className: classNames.root, ref: this._root }),
                  this._nextResizeGroupStateProvider.shouldRenderDataToMeasureInHiddenDiv(dataToMeasure) && (React.createElement("div", { style: { position: 'fixed', visibility: 'hidden' }, ref: this._measured },
                      React.createElement(MeasuredContext, null, onRenderData(dataToMeasure)))),
                  renderedData && onRenderData(renderedData)));
          };
          ResizeGroupBase.prototype.componentDidMount = function () {
              this._afterComponentRendered();
              this._events.on(window, 'resize', this._async.debounce(this._onResize, RESIZE_DELAY, { leading: true }));
          };
          ResizeGroupBase.prototype.componentWillReceiveProps = function (nextProps) {
              this.setState({
                  dataToMeasure: tslib_1.__assign({}, nextProps.data),
                  resizeDirection: 'grow',
                  measureContainer: true // Receiving new props means the parent might rerender and the root width might change
              });
          };
          ResizeGroupBase.prototype.componentDidUpdate = function (prevProps) {
              if (this.state.renderedData) {
                  if (this.props.dataDidRender) {
                      this.props.dataDidRender(this.state.renderedData);
                  }
              }
              this._afterComponentRendered();
          };
          ResizeGroupBase.prototype.remeasure = function () {
              if (this._root.current) {
                  this.setState({ measureContainer: true });
              }
          };
          ResizeGroupBase.prototype._afterComponentRendered = function () {
              var _this = this;
              this._async.requestAnimationFrame(function () {
                  var containerWidth = undefined;
                  if (_this.state.measureContainer && _this._root.current) {
                      containerWidth = _this._root.current.getBoundingClientRect().width;
                  }
                  var nextState = _this._nextResizeGroupStateProvider.getNextState(_this.props, _this.state, function () { return _this._measured.current ? _this._measured.current.scrollWidth : 0; }, containerWidth);
                  if (nextState) {
                      _this.setState(nextState);
                  }
              });
          };
          ResizeGroupBase.prototype._onResize = function () {
              if (this._root.current) {
                  this.setState({ measureContainer: true });
              }
          };
          ResizeGroupBase = tslib_1.__decorate([
              Utilities_1.customizable('ResizeGroup', ['theme'])
          ], ResizeGroupBase);
          return ResizeGroupBase;
      }(Utilities_1.BaseComponent));
      exports.ResizeGroupBase = ResizeGroupBase;
  });
  //# sourceMappingURL=ResizeGroup.base.js.map