"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = _interopRequireDefault(require("react"));
var _reactNative = require("react-native");
var _recyclerlistview = require("recyclerlistview");
var _sticky = _interopRequireDefault(require("recyclerlistview/sticky"));
var _AutoLayoutView = _interopRequireDefault(require("./native/auto-layout/AutoLayoutView"));
var _CellContainer = _interopRequireDefault(require("./native/cell-container/CellContainer"));
var _PureComponentWrapper = require("./PureComponentWrapper");
var _GridLayoutProviderWithProps = _interopRequireDefault(require("./GridLayoutProviderWithProps"));
var _CustomError = _interopRequireDefault(require("./errors/CustomError"));
var _ExceptionList = _interopRequireDefault(require("./errors/ExceptionList"));
var _Warnings = _interopRequireDefault(require("./errors/Warnings"));
var _ViewabilityManager = _interopRequireDefault(require("./viewability/ViewabilityManager"));
var _FlashListProps = require("./FlashListProps");
var _PlatformHelper = require("./native/config/PlatformHelper");
var _ContentContainerUtils = require("./utils/ContentContainerUtils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } // @ts-nocheck
const StickyHeaderContainer = _sticky.default;
class FlashList extends _react.default.PureComponent {
  constructor(_props) {
    var _props$estimatedFirst;
    super(_props);
    _defineProperty(this, "rlvRef", void 0);
    _defineProperty(this, "stickyContentContainerRef", void 0);
    _defineProperty(this, "listFixedDimensionSize", 0);
    _defineProperty(this, "transformStyle", _PlatformHelper.PlatformConfig.invertedTransformStyle);
    _defineProperty(this, "transformStyleHorizontal", _PlatformHelper.PlatformConfig.invertedTransformStyleHorizontal);
    _defineProperty(this, "distanceFromWindow", 0);
    _defineProperty(this, "contentStyle", {
      paddingBottom: 0,
      paddingTop: 0,
      paddingLeft: 0,
      paddingRight: 0
    });
    _defineProperty(this, "loadStartTime", 0);
    _defineProperty(this, "isListLoaded", false);
    _defineProperty(this, "windowCorrectionConfig", {
      value: {
        windowShift: 0,
        startCorrection: 0,
        endCorrection: 0
      },
      applyToItemScroll: true,
      applyToInitialOffset: true
    });
    _defineProperty(this, "postLoadTimeoutId", void 0);
    _defineProperty(this, "sizeWarningTimeoutId", void 0);
    _defineProperty(this, "isEmptyList", false);
    _defineProperty(this, "viewabilityManager", void 0);
    _defineProperty(this, "itemAnimator", void 0);
    _defineProperty(this, "onEndReached", () => {
      var _this$props$onEndReac, _this$props;
      (_this$props$onEndReac = (_this$props = this.props).onEndReached) === null || _this$props$onEndReac === void 0 ? void 0 : _this$props$onEndReac.call(_this$props);
    });
    _defineProperty(this, "getRefreshControl", () => {
      if (this.props.onRefresh) {
        return /*#__PURE__*/_react.default.createElement(_reactNative.RefreshControl, {
          refreshing: Boolean(this.props.refreshing),
          progressViewOffset: this.props.progressViewOffset,
          onRefresh: this.props.onRefresh
        });
      }
    });
    _defineProperty(this, "onScrollBeginDrag", event => {
      var _this$props$onScrollB, _this$props2;
      this.recordInteraction();
      (_this$props$onScrollB = (_this$props2 = this.props).onScrollBeginDrag) === null || _this$props$onScrollB === void 0 ? void 0 : _this$props$onScrollB.call(_this$props2, event);
    });
    _defineProperty(this, "onScroll", event => {
      var _this$props$onScroll, _this$props3;
      this.recordInteraction();
      this.viewabilityManager.updateViewableItems();
      (_this$props$onScroll = (_this$props3 = this.props).onScroll) === null || _this$props$onScroll === void 0 ? void 0 : _this$props$onScroll.call(_this$props3, event);
    });
    _defineProperty(this, "handleSizeChange", event => {
      this.validateListSize(event);
      const newSize = this.props.horizontal ? event.nativeEvent.layout.height : event.nativeEvent.layout.width;
      const oldSize = this.listFixedDimensionSize;
      this.listFixedDimensionSize = newSize;

      // >0 check is to avoid rerender on mount where it would be redundant
      if (oldSize > 0 && oldSize !== newSize) {
        var _this$rlvRef;
        (_this$rlvRef = this.rlvRef) === null || _this$rlvRef === void 0 ? void 0 : _this$rlvRef.forceRerender();
      }
      if (this.props.onLayout) {
        this.props.onLayout(event);
      }
    });
    _defineProperty(this, "container", (props, children) => {
      this.clearPostLoadTimeout();
      return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_PureComponentWrapper.PureComponentWrapper, {
        enabled: this.isListLoaded || children.length > 0 || this.isEmptyList,
        contentStyle: this.props.contentContainerStyle,
        horizontal: this.props.horizontal,
        header: this.props.ListHeaderComponent,
        extraData: this.state.extraData,
        headerStyle: this.props.ListHeaderComponentStyle,
        inverted: this.props.inverted,
        renderer: this.header
      }), /*#__PURE__*/_react.default.createElement(_AutoLayoutView.default, _extends({}, props, {
        onBlankAreaEvent: this.props.onBlankArea,
        onLayout: this.updateDistanceFromWindow,
        disableAutoLayout: this.props.disableAutoLayout
      }), children), this.isEmptyList ? this.getValidComponent(this.props.ListEmptyComponent) : null, /*#__PURE__*/_react.default.createElement(_PureComponentWrapper.PureComponentWrapper, {
        enabled: this.isListLoaded || children.length > 0 || this.isEmptyList,
        contentStyle: this.props.contentContainerStyle,
        horizontal: this.props.horizontal,
        header: this.props.ListFooterComponent,
        extraData: this.state.extraData,
        headerStyle: this.props.ListFooterComponentStyle,
        inverted: this.props.inverted,
        renderer: this.footer
      }), this.getComponentForHeightMeasurement());
    });
    _defineProperty(this, "itemContainer", (props, parentProps) => {
      var _this$props$CellRende;
      const CellRendererComponent = (_this$props$CellRende = this.props.CellRendererComponent) !== null && _this$props$CellRende !== void 0 ? _this$props$CellRende : _CellContainer.default;
      return /*#__PURE__*/_react.default.createElement(CellRendererComponent, _extends({}, props, {
        style: {
          ...props.style,
          flexDirection: this.props.horizontal ? "row" : "column",
          alignItems: "stretch",
          ...this.getTransform(),
          ...(0, _PlatformHelper.getCellContainerPlatformStyles)(this.props.inverted, parentProps)
        },
        index: parentProps.index
      }), /*#__PURE__*/_react.default.createElement(_PureComponentWrapper.PureComponentWrapper, {
        extendedState: parentProps.extendedState,
        internalSnapshot: parentProps.internalSnapshot,
        data: parentProps.data,
        arg: parentProps.index,
        renderer: this.getCellContainerChild
      }));
    });
    _defineProperty(this, "updateDistanceFromWindow", event => {
      const newDistanceFromWindow = this.props.horizontal ? event.nativeEvent.layout.x : event.nativeEvent.layout.y;
      if (this.distanceFromWindow !== newDistanceFromWindow) {
        this.distanceFromWindow = newDistanceFromWindow;
        this.windowCorrectionConfig.value.windowShift = -this.distanceFromWindow;
        this.viewabilityManager.updateViewableItems();
      }
    });
    _defineProperty(this, "separator", index => {
      // Make sure we have data and don't read out of bounds
      if (this.props.data === null || this.props.data === undefined || index + 1 >= this.props.data.length) {
        return null;
      }
      const leadingItem = this.props.data[index];
      const trailingItem = this.props.data[index + 1];
      const props = {
        leadingItem,
        trailingItem
        // TODO: Missing sections as we don't have this feature implemented yet. Implement section, leadingSection and trailingSection.
        // https://github.com/facebook/react-native/blob/8bd3edec88148d0ab1f225d2119435681fbbba33/Libraries/Lists/VirtualizedSectionList.js#L285-L294
      };

      const Separator = this.props.ItemSeparatorComponent;
      return Separator && /*#__PURE__*/_react.default.createElement(Separator, props);
    });
    _defineProperty(this, "header", () => {
      return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
        style: {
          paddingTop: this.contentStyle.paddingTop,
          paddingLeft: this.contentStyle.paddingLeft
        }
      }), /*#__PURE__*/_react.default.createElement(_reactNative.View, {
        style: [this.props.ListHeaderComponentStyle, this.getTransform()]
      }, this.getValidComponent(this.props.ListHeaderComponent)));
    });
    _defineProperty(this, "footer", () => {
      var _getFooterContainer;
      /** The web version of CellContainer uses a div directly which doesn't compose styles the way a View does.
       * We will skip using CellContainer on web to avoid this issue. `getFooterContainer` on web will
       * return a View. */
      const FooterContainer = (_getFooterContainer = (0, _PlatformHelper.getFooterContainer)()) !== null && _getFooterContainer !== void 0 ? _getFooterContainer : _CellContainer.default;
      return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(FooterContainer, {
        index: -1,
        style: [this.props.ListFooterComponentStyle, this.getTransform()]
      }, this.getValidComponent(this.props.ListFooterComponent)), /*#__PURE__*/_react.default.createElement(_reactNative.View, {
        style: {
          paddingBottom: this.contentStyle.paddingBottom,
          paddingRight: this.contentStyle.paddingRight
        }
      }));
    });
    _defineProperty(this, "getComponentForHeightMeasurement", () => {
      return this.props.horizontal && !this.props.disableHorizontalListHeightMeasurement && !this.isListLoaded && this.state.dataProvider.getSize() > 0 ? /*#__PURE__*/_react.default.createElement(_reactNative.View, {
        style: {
          opacity: 0
        },
        pointerEvents: "none"
      }, this.rowRendererWithIndex(Math.min(this.state.dataProvider.getSize() - 1, 1), _FlashListProps.RenderTargetOptions.Measurement)) : null;
    });
    _defineProperty(this, "applyWindowCorrection", (_, __, correctionObject) => {
      var _this$stickyContentCo;
      correctionObject.windowShift = -this.distanceFromWindow;
      (_this$stickyContentCo = this.stickyContentContainerRef) === null || _this$stickyContentCo === void 0 ? void 0 : _this$stickyContentCo.setEnabled(this.isStickyEnabled);
    });
    _defineProperty(this, "rowRendererSticky", index => {
      return this.rowRendererWithIndex(index, _FlashListProps.RenderTargetOptions.StickyHeader);
    });
    _defineProperty(this, "rowRendererWithIndex", (index, target) => {
      var _this$props$renderIte, _this$props4, _this$state$extraData;
      // known issue: expected to pass separators which isn't available in RLV
      return (_this$props$renderIte = (_this$props4 = this.props).renderItem) === null || _this$props$renderIte === void 0 ? void 0 : _this$props$renderIte.call(_this$props4, {
        item: this.props.data[index],
        index,
        target,
        extraData: (_this$state$extraData = this.state.extraData) === null || _this$state$extraData === void 0 ? void 0 : _this$state$extraData.value
      });
    });
    /**
     * This will prevent render item calls unless data changes.
     * Output of this method is received as children object so returning null here is no issue as long as we handle it inside our child container.
     * @module getCellContainerChild acts as the new rowRenderer and is called directly from our child container.
     */
    _defineProperty(this, "emptyRowRenderer", () => {
      return null;
    });
    _defineProperty(this, "getCellContainerChild", index => {
      return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
        style: {
          flexDirection: this.props.horizontal || this.props.numColumns === 1 ? "column" : "row"
        }
      }, this.rowRendererWithIndex(index, _FlashListProps.RenderTargetOptions.Cell)), this.separator(index));
    });
    _defineProperty(this, "recyclerRef", ref => {
      this.rlvRef = ref;
    });
    _defineProperty(this, "stickyContentRef", ref => {
      this.stickyContentContainerRef = ref;
    });
    _defineProperty(this, "stickyOverrideRowRenderer", (_, __, index, ___) => {
      return /*#__PURE__*/_react.default.createElement(_PureComponentWrapper.PureComponentWrapper, {
        ref: this.stickyContentRef,
        enabled: this.isStickyEnabled,
        arg: index,
        renderer: this.rowRendererSticky
      });
    });
    _defineProperty(this, "onItemLayout", index => {
      // Informing the layout provider about change to an item's layout. It already knows the dimensions so there's not need to pass them.
      this.state.layoutProvider.reportItemLayout(index);
      this.raiseOnLoadEventIfNeeded();
    });
    _defineProperty(this, "raiseOnLoadEventIfNeeded", () => {
      if (!this.isListLoaded) {
        var _this$props$onLoad, _this$props5;
        this.isListLoaded = true;
        (_this$props$onLoad = (_this$props5 = this.props).onLoad) === null || _this$props$onLoad === void 0 ? void 0 : _this$props$onLoad.call(_this$props5, {
          elapsedTimeInMs: Date.now() - this.loadStartTime
        });
        this.runAfterOnLoad();
      }
    });
    _defineProperty(this, "runAfterOnLoad", () => {
      if (this.props.estimatedItemSize === undefined) {
        this.sizeWarningTimeoutId = setTimeout(() => {
          const averageItemSize = Math.floor(this.state.layoutProvider.averageItemSize);
          console.warn(_Warnings.default.estimatedItemSizeMissingWarning.replace("@size", averageItemSize.toString()));
        }, 1000);
      }
      this.postLoadTimeoutId = setTimeout(() => {
        // This force update is required to remove dummy element rendered to measure horizontal list height when  the list doesn't update on its own.
        // In most cases this timeout will never be triggered because list usually updates atleast once and this timeout is cleared on update.
        if (this.props.horizontal) {
          this.forceUpdate();
        }
      }, 500);
    });
    _defineProperty(this, "clearPostLoadTimeout", () => {
      if (this.postLoadTimeoutId !== undefined) {
        clearTimeout(this.postLoadTimeoutId);
        this.postLoadTimeoutId = undefined;
      }
    });
    /**
     * Tells the list an interaction has occurred, which should trigger viewability calculations, e.g. if waitForInteractions is true and the user has not scrolled.
     * This is typically called by taps on items or by navigation actions.
     */
    _defineProperty(this, "recordInteraction", () => {
      this.viewabilityManager.recordInteraction();
    });
    this.loadStartTime = Date.now();
    this.validateProps();
    if (_props.estimatedListSize) {
      if (_props.horizontal) {
        this.listFixedDimensionSize = _props.estimatedListSize.height;
      } else {
        this.listFixedDimensionSize = _props.estimatedListSize.width;
      }
    }
    this.distanceFromWindow = (_props$estimatedFirst = _props.estimatedFirstItemOffset) !== null && _props$estimatedFirst !== void 0 ? _props$estimatedFirst : _props.ListHeaderComponent && 1 || 0;
    // eslint-disable-next-line react/state-in-constructor
    this.state = FlashList.getInitialMutableState(this);
    this.viewabilityManager = new _ViewabilityManager.default(this);
    this.itemAnimator = (0, _PlatformHelper.getItemAnimator)();
  }
  validateProps() {
    var _this$props$stickyHea, _this$props$style;
    if (this.props.onRefresh && typeof this.props.refreshing !== "boolean") {
      throw new _CustomError.default(_ExceptionList.default.refreshBooleanMissing);
    }
    if (Number((_this$props$stickyHea = this.props.stickyHeaderIndices) === null || _this$props$stickyHea === void 0 ? void 0 : _this$props$stickyHea.length) > 0 && this.props.horizontal) {
      throw new _CustomError.default(_ExceptionList.default.stickyWhileHorizontalNotSupported);
    }
    if (Number(this.props.numColumns) > 1 && this.props.horizontal) {
      throw new _CustomError.default(_ExceptionList.default.columnsWhileHorizontalNotSupported);
    }

    // `createAnimatedComponent` always passes a blank style object. To avoid warning while using AnimatedFlashList we've modified the check
    // `style` prop can be an array. So we need to validate every object in array. Check: https://github.com/Shopify/flash-list/issues/651
    if (__DEV__ && Object.keys(_reactNative.StyleSheet.flatten((_this$props$style = this.props.style) !== null && _this$props$style !== void 0 ? _this$props$style : {})).length > 0) {
      console.warn(_Warnings.default.styleUnsupported);
    }
    if ((0, _ContentContainerUtils.hasUnsupportedKeysInContentContainerStyle)(this.props.contentContainerStyle)) {
      console.warn(_Warnings.default.styleContentContainerUnsupported);
    }
  }

  // Some of the state variables need to update when props change
  static getDerivedStateFromProps(nextProps, prevState) {
    var _prevState$extraData;
    const newState = {
      ...prevState
    };
    if (prevState.numColumns !== nextProps.numColumns) {
      newState.numColumns = nextProps.numColumns || 1;
      newState.layoutProvider = FlashList.getLayoutProvider(newState.numColumns, nextProps);
    } else if (prevState.layoutProvider.updateProps(nextProps).hasExpired) {
      newState.layoutProvider = FlashList.getLayoutProvider(newState.numColumns, nextProps);
      // RLV retries to reposition the first visible item on layout provider change.
      // It's not required in our case so we're disabling it
      newState.layoutProvider.shouldRefreshWithAnchoring = false;
    }
    if (nextProps.data !== prevState.data) {
      newState.data = nextProps.data;
      newState.dataProvider = prevState.dataProvider.cloneWithRows(nextProps.data);
      if (nextProps.renderItem !== prevState.renderItem) {
        newState.extraData = {
          ...prevState.extraData
        };
      }
    }
    if (nextProps.extraData !== ((_prevState$extraData = prevState.extraData) === null || _prevState$extraData === void 0 ? void 0 : _prevState$extraData.value)) {
      newState.extraData = {
        value: nextProps.extraData
      };
    }
    newState.renderItem = nextProps.renderItem;
    return newState;
  }
  static getInitialMutableState(flashList) {
    let getStableId;
    if (flashList.props.keyExtractor !== null && flashList.props.keyExtractor !== undefined) {
      getStableId = index =>
      // We assume `keyExtractor` function will never change from being `null | undefined` to defined and vice versa.
      // Similarly, data should never be `null | undefined` when `getStableId` is called.
      flashList.props.keyExtractor(flashList.props.data[index], index).toString();
    }
    return {
      data: null,
      layoutProvider: null,
      dataProvider: new _recyclerlistview.DataProvider((r1, r2) => {
        return r1 !== r2;
      }, getStableId),
      numColumns: 0
    };
  }

  // Using only grid layout provider as it can also act as a listview, sizeProvider is a function to support future overrides
  static getLayoutProvider(numColumns, flashListProps) {
    return new _GridLayoutProviderWithProps.default(
    // max span or, total columns
    numColumns, (index, props) => {
      var _props$getItemType;
      // type of the item for given index
      const type = (_props$getItemType = props.getItemType) === null || _props$getItemType === void 0 ? void 0 : _props$getItemType.call(props, props.data[index], index, props.extraData);
      return type || 0;
    }, (index, props, mutableLayout) => {
      var _props$overrideItemLa, _mutableLayout$span;
      // span of the item at given index, item can choose to span more than one column
      (_props$overrideItemLa = props.overrideItemLayout) === null || _props$overrideItemLa === void 0 ? void 0 : _props$overrideItemLa.call(props, mutableLayout, props.data[index], index, numColumns, props.extraData);
      return (_mutableLayout$span = mutableLayout === null || mutableLayout === void 0 ? void 0 : mutableLayout.span) !== null && _mutableLayout$span !== void 0 ? _mutableLayout$span : 1;
    }, (index, props, mutableLayout) => {
      var _props$overrideItemLa2;
      // estimated size of the item an given index
      (_props$overrideItemLa2 = props.overrideItemLayout) === null || _props$overrideItemLa2 === void 0 ? void 0 : _props$overrideItemLa2.call(props, mutableLayout, props.data[index], index, numColumns, props.extraData);
      return mutableLayout === null || mutableLayout === void 0 ? void 0 : mutableLayout.size;
    }, flashListProps);
  }
  componentDidMount() {
    var _this$props$data;
    if (((_this$props$data = this.props.data) === null || _this$props$data === void 0 ? void 0 : _this$props$data.length) === 0) {
      this.raiseOnLoadEventIfNeeded();
    }
  }
  componentWillUnmount() {
    this.viewabilityManager.dispose();
    this.clearPostLoadTimeout();
    if (this.sizeWarningTimeoutId !== undefined) {
      clearTimeout(this.sizeWarningTimeoutId);
    }
  }
  render() {
    this.isEmptyList = this.state.dataProvider.getSize() === 0;
    (0, _ContentContainerUtils.updateContentStyle)(this.contentStyle, this.props.contentContainerStyle);
    const {
      drawDistance,
      removeClippedSubviews,
      stickyHeaderIndices,
      horizontal,
      onEndReachedThreshold,
      estimatedListSize,
      initialScrollIndex,
      style,
      contentContainerStyle,
      renderScrollComponent,
      ...restProps
    } = this.props;

    // RecyclerListView simply ignores if initialScrollIndex is set to 0 because it doesn't understand headers
    // Using initialOffset to force RLV to scroll to the right place
    const initialOffset = this.isInitialScrollIndexInFirstRow() && this.distanceFromWindow || undefined;
    const finalDrawDistance = drawDistance === undefined ? _PlatformHelper.PlatformConfig.defaultDrawDistance : drawDistance;
    return /*#__PURE__*/_react.default.createElement(StickyHeaderContainer, {
      overrideRowRenderer: this.stickyOverrideRowRenderer,
      applyWindowCorrection: this.applyWindowCorrection,
      stickyHeaderIndices: stickyHeaderIndices,
      style: this.props.horizontal ? {
        ...this.getTransform()
      } : {
        flex: 1,
        overflow: "hidden",
        ...this.getTransform()
      }
    }, /*#__PURE__*/_react.default.createElement(_recyclerlistview.ProgressiveListView, _extends({}, restProps, {
      ref: this.recyclerRef,
      layoutProvider: this.state.layoutProvider,
      dataProvider: this.state.dataProvider,
      rowRenderer: this.emptyRowRenderer,
      canChangeSize: true,
      isHorizontal: Boolean(horizontal),
      scrollViewProps: {
        onScrollBeginDrag: this.onScrollBeginDrag,
        onLayout: this.handleSizeChange,
        refreshControl: this.props.refreshControl || this.getRefreshControl(),
        // Min values are being used to suppress RLV's bounded exception
        style: {
          minHeight: 1,
          minWidth: 1
        },
        contentContainerStyle: {
          backgroundColor: this.contentStyle.backgroundColor,
          // Required to handle a scrollview bug. Check: https://github.com/Shopify/flash-list/pull/187
          minHeight: 1,
          minWidth: 1,
          ...(0, _ContentContainerUtils.getContentContainerPadding)(this.contentStyle, horizontal)
        },
        ...this.props.overrideProps
      },
      forceNonDeterministicRendering: true,
      renderItemContainer: this.itemContainer,
      renderContentContainer: this.container,
      onEndReached: this.onEndReached,
      onEndReachedThresholdRelative: onEndReachedThreshold || undefined,
      extendedState: this.state.extraData,
      layoutSize: estimatedListSize,
      maxRenderAhead: 3 * finalDrawDistance,
      finalRenderAheadOffset: finalDrawDistance,
      renderAheadStep: finalDrawDistance,
      initialRenderIndex: !this.isInitialScrollIndexInFirstRow() && initialScrollIndex || undefined,
      initialOffset: initialOffset,
      onItemLayout: this.onItemLayout,
      onScroll: this.onScroll,
      onVisibleIndicesChanged: this.viewabilityManager.shouldListenToVisibleIndices ? this.viewabilityManager.onVisibleIndicesChanged : undefined,
      windowCorrectionConfig: this.getUpdatedWindowCorrectionConfig(),
      itemAnimator: this.itemAnimator,
      suppressBoundedSizeException: true,
      externalScrollView: renderScrollComponent
    })));
  }
  getUpdatedWindowCorrectionConfig() {
    // If the initial scroll index is in the first row then we're forcing RLV to use initialOffset and thus we need to disable window correction
    // This isn't clean but it's the only way to get RLV to scroll to the right place
    // TODO: Remove this when RLV fixes this. Current implementation will also fail if column span is overridden in the first row.
    if (this.isInitialScrollIndexInFirstRow()) {
      this.windowCorrectionConfig.applyToInitialOffset = false;
    } else {
      this.windowCorrectionConfig.applyToInitialOffset = true;
    }
    this.windowCorrectionConfig.value.windowShift = -this.distanceFromWindow;
    return this.windowCorrectionConfig;
  }
  isInitialScrollIndexInFirstRow() {
    var _this$props$initialSc;
    return ((_this$props$initialSc = this.props.initialScrollIndex) !== null && _this$props$initialSc !== void 0 ? _this$props$initialSc : this.state.numColumns) < this.state.numColumns;
  }
  validateListSize(event) {
    const {
      height,
      width
    } = event.nativeEvent.layout;
    if (Math.floor(height) <= 1 || Math.floor(width) <= 1) {
      console.warn(_Warnings.default.unusableRenderedSize);
    }
  }
  getTransform() {
    const transformStyle = this.props.horizontal ? this.transformStyleHorizontal : this.transformStyle;
    return this.props.inverted && transformStyle || undefined;
  }
  getValidComponent(component) {
    const PassedComponent = component;
    return /*#__PURE__*/_react.default.isValidElement(PassedComponent) && PassedComponent || PassedComponent && /*#__PURE__*/_react.default.createElement(PassedComponent, null) || null;
  }
  get isStickyEnabled() {
    var _this$rlvRef2;
    const currentOffset = ((_this$rlvRef2 = this.rlvRef) === null || _this$rlvRef2 === void 0 ? void 0 : _this$rlvRef2.getCurrentScrollOffset()) || 0;
    return currentOffset >= this.distanceFromWindow;
  }
  /**
   * Disables recycling for the next frame so that layout animations run well.
   * Warning: Avoid this when making large changes to the data as the list might draw too much to run animations. Single item insertions/deletions
   * should be good. With recycling paused the list cannot do much optimization.
   * The next render will run as normal and reuse items.
   */
  prepareForLayoutAnimationRender() {
    if (this.props.keyExtractor === null || this.props.keyExtractor === undefined) {
      console.warn(_Warnings.default.missingKeyExtractor);
    } else {
      var _this$rlvRef3;
      (_this$rlvRef3 = this.rlvRef) === null || _this$rlvRef3 === void 0 ? void 0 : _this$rlvRef3.prepareForLayoutAnimationRender();
    }
  }
  scrollToEnd(params) {
    var _this$rlvRef4;
    (_this$rlvRef4 = this.rlvRef) === null || _this$rlvRef4 === void 0 ? void 0 : _this$rlvRef4.scrollToEnd(Boolean(params === null || params === void 0 ? void 0 : params.animated));
  }
  scrollToIndex(params) {
    var _this$rlvRef5, _this$rlvRef6;
    const layout = (_this$rlvRef5 = this.rlvRef) === null || _this$rlvRef5 === void 0 ? void 0 : _this$rlvRef5.getLayout(params.index);
    const listSize = (_this$rlvRef6 = this.rlvRef) === null || _this$rlvRef6 === void 0 ? void 0 : _this$rlvRef6.getRenderedSize();
    if (layout && listSize) {
      var _params$viewPosition, _params$viewOffset, _this$rlvRef7;
      const itemOffset = this.props.horizontal ? layout.x : layout.y;
      const fixedDimension = this.props.horizontal ? listSize.width : listSize.height;
      const itemSize = this.props.horizontal ? layout.width : layout.height;
      const scrollOffset = Math.max(0, itemOffset - ((_params$viewPosition = params.viewPosition) !== null && _params$viewPosition !== void 0 ? _params$viewPosition : 0) * (fixedDimension - itemSize)) - ((_params$viewOffset = params.viewOffset) !== null && _params$viewOffset !== void 0 ? _params$viewOffset : 0);
      (_this$rlvRef7 = this.rlvRef) === null || _this$rlvRef7 === void 0 ? void 0 : _this$rlvRef7.scrollToOffset(scrollOffset, scrollOffset, Boolean(params.animated), true);
    }
  }
  scrollToItem(params) {
    var _this$props$data$inde, _this$props$data2;
    const index = (_this$props$data$inde = (_this$props$data2 = this.props.data) === null || _this$props$data2 === void 0 ? void 0 : _this$props$data2.indexOf(params.item)) !== null && _this$props$data$inde !== void 0 ? _this$props$data$inde : -1;
    if (index >= 0) {
      this.scrollToIndex({
        ...params,
        index
      });
    }
  }
  scrollToOffset(params) {
    var _this$rlvRef8;
    const x = this.props.horizontal ? params.offset : 0;
    const y = this.props.horizontal ? 0 : params.offset;
    (_this$rlvRef8 = this.rlvRef) === null || _this$rlvRef8 === void 0 ? void 0 : _this$rlvRef8.scrollToOffset(x, y, Boolean(params.animated));
  }
  getScrollableNode() {
    var _this$rlvRef9, _this$rlvRef9$getScro;
    return ((_this$rlvRef9 = this.rlvRef) === null || _this$rlvRef9 === void 0 ? void 0 : (_this$rlvRef9$getScro = _this$rlvRef9.getScrollableNode) === null || _this$rlvRef9$getScro === void 0 ? void 0 : _this$rlvRef9$getScro.call(_this$rlvRef9)) || null;
  }

  /**
   * Allows access to internal recyclerlistview. This is useful for enabling access to its public APIs.
   * Warning: We may swap recyclerlistview for something else in the future. Use with caution.
   */
  /* eslint-disable @typescript-eslint/naming-convention */
  get recyclerlistview_unsafe() {
    return this.rlvRef;
  }

  /**
   * Specifies how far the first item is from top of the list. This would normally be a sum of header size and top/left padding applied to the list.
   */
  get firstItemOffset() {
    return this.distanceFromWindow;
  }
}
_defineProperty(FlashList, "defaultProps", {
  data: [],
  numColumns: 1
});
var _default = FlashList;
exports.default = _default;
//# sourceMappingURL=FlashList.js.map