import _Reflect$construct from "@babel/runtime-corejs3/core-js-stable/reflect/construct";
import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from";
import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol";
import _getIteratorMethod from "@babel/runtime-corejs3/core-js/get-iterator-method";
import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray";
import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty";
import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck";
import _createClass from "@babel/runtime-corejs3/helpers/createClass";
import _inherits from "@babel/runtime-corejs3/helpers/inherits";
import _possibleConstructorReturn from "@babel/runtime-corejs3/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime-corejs3/helpers/getPrototypeOf";
import _extends from "@babel/runtime-corejs3/helpers/extends";

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { var _context2; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = _sliceInstanceProperty(_context2 = Object.prototype.toString.call(o)).call(_context2, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
import _flatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/flat";
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

import cx from 'classnames';
import React from 'react';
import { BehaviorSubject, combineLatest, noop, Subscription, Subject, from } from 'rxjs';
import * as op from 'rxjs/operators';
import { calculateRenderInfo } from './calculations';
import { EmptyHtmlTable } from './empty';
import TableHeader from './header';
import { getRichVisibleRectsStream } from './helpers/getRichVisibleRectsStream';
import { getFullRenderRange, makeRowHeightManager } from './helpers/rowHeightManager';
import { TableDOMHelper } from './helpers/TableDOMUtils';
import { HtmlTable } from './html-table';
import Loading from './loading';
import { Classes, LOCK_SHADOW_PADDING, StyledArtTableWrapper, defaultCSSVariables } from './styles';
import { addResizeObserver, getScrollbarSize, OVERSCAN_SIZE, shallowEqual, STYLED_REF_PROP, sum, syncScrollLeft, throttledWindowResize$, getTableScrollFooterDOM, getTableScrollHeaderDOM } from './utils';
import cssVars from 'css-vars-ponyfill';
import { console, browserType } from '../utils';
import getTableRenderTemplate from './renderTemplates';

var cssPolifill = function cssPolifill(_ref) {
  var variables = _ref.variables,
      enableCSSVariables = _ref.enableCSSVariables;

  // const style = document.createElement('style')
  // style.type = 'text/css'
  // style.innerHTML = '.aaa{ --color: red; }'
  // document.getElementsByTagName('head').item(0).appendChild(style)
  // const variableNames = variableConst.match(/--.*?(?=:)/g)
  // variables = variableNames.map((name) => rootElement.style[name])
  if (enableCSSVariables === false) {
    return;
  }

  cssVars({
    // exclude: 'link[href*="semantic-ui"]',
    // onlyLegacy: false,
    // rootElement: rootElement,
    include: 'style[data-styled]',
    variables: _extends({}, defaultCSSVariables, variables),
    watch: true,
    silent: true
  });
};

var propsDotEmptyContentDeprecatedWarned = false;

function warnPropsDotEmptyContentIsDeprecated() {
  if (!propsDotEmptyContentDeprecatedWarned) {
    propsDotEmptyContentDeprecatedWarned = true;
    console.warn('BaseTable props.emptyContent 已经过时，请使用 props.components.EmptyContent 来自定义数据为空时的表格表现');
  }
}

export var BaseTable = /*#__PURE__*/function (_React$Component) {
  _inherits(BaseTable, _React$Component);

  var _super = _createSuper(BaseTable);

  function BaseTable(props) {
    var _this;

    _classCallCheck(this, BaseTable);

    _this = _super.call(this, props);
    _this.rowHeightManager = makeRowHeightManager(_this.props.dataSource.length, _this.props.estimatedRowHeight);
    _this.artTableWrapperRef = /*#__PURE__*/React.createRef();
    _this.rootSubscription = new Subscription();
    _this.hasScrollY = false;
    _this.resizeSubject = new Subject();
    _this.offsetY = 0;

    _this.handleRowMouseEnter = function (e) {
      var nodeList = _this.domHelper.getRowNodeListByEvent(e);

      nodeList && nodeList.forEach(function (node) {
        node.classList.add('row-hover');
      });
    };

    _this.handleRowMouseLeave = function (e) {
      var nodeList = _this.domHelper.getRowNodeListByEvent(e);

      nodeList && nodeList.forEach(function (node) {
        node.classList.remove('row-hover');
      });
    };

    _this.renderTableBody = function (info) {
      // console.log('render body')
      var _this$props = _this.props,
          dataSource = _this$props.dataSource,
          getRowProps = _this$props.getRowProps,
          primaryKey = _this$props.primaryKey,
          isLoading = _this$props.isLoading,
          emptyCellHeight = _this$props.emptyCellHeight,
          footerDataSource = _this$props.footerDataSource;
      var tableBodyClassName = cx(Classes.tableBody, Classes.horizontalScrollContainer); // 低版本Edge浏览器下也会出现双滚动条，这里设置overflow: 'hidden'，先去掉edge的方向键控制滚动条的功能

      var virtualStyle = browserType.isIE || browserType.isEdge ? {
        overflow: 'hidden'
      } : {};

      if (dataSource.length === 0) {
        var _this$props2 = _this.props,
            components = _this$props2.components,
            emptyContent = _this$props2.emptyContent;
        var EmptyContent = components.EmptyContent;

        if (EmptyContent == null && emptyContent != null) {
          warnPropsDotEmptyContentIsDeprecated();

          EmptyContent = function EmptyContent() {
            return emptyContent;
          };
        }

        return /*#__PURE__*/React.createElement("div", {
          className: cx(tableBodyClassName, 'empty')
        }, /*#__PURE__*/React.createElement("div", {
          className: Classes.virtual,
          tabIndex: -1,
          style: virtualStyle
        }, /*#__PURE__*/React.createElement(EmptyHtmlTable, {
          descriptors: info.visible,
          isLoading: isLoading,
          EmptyContent: EmptyContent,
          emptyCellHeight: emptyCellHeight
        })));
      }

      var _info$verticalRenderR = info.verticalRenderRange,
          topIndex = _info$verticalRenderR.topIndex,
          bottomBlank = _info$verticalRenderR.bottomBlank,
          topBlank = _info$verticalRenderR.topBlank,
          bottomIndex = _info$verticalRenderR.bottomIndex;
      var stickyRightOffset = _this.hasScrollY ? _this.getScrollBarWidth() : 0;
      var renderBody = getTableRenderTemplate('body');

      if (typeof renderBody === 'function') {
        return renderBody(info, _this.props, {
          rowProps: {
            onMouseEnter: _this.handleRowMouseEnter,
            onMouseLeave: _this.handleRowMouseLeave
          },
          stickyRightOffset: stickyRightOffset
        });
      }

      return /*#__PURE__*/React.createElement("div", {
        className: tableBodyClassName
      }, /*#__PURE__*/React.createElement("div", {
        className: Classes.virtual,
        tabIndex: -1,
        style: virtualStyle
      }, topBlank > 0 && /*#__PURE__*/React.createElement("div", {
        key: "top-blank",
        className: cx(Classes.virtualBlank, 'top'),
        style: {
          height: topBlank
        }
      }), /*#__PURE__*/React.createElement(HtmlTable, {
        tbodyHtmlTag: "tbody",
        getRowProps: getRowProps,
        primaryKey: primaryKey,
        data: _sliceInstanceProperty(dataSource).call(dataSource, topIndex, bottomIndex),
        stickyRightOffset: stickyRightOffset,
        horizontalRenderInfo: info,
        verticalRenderInfo: {
          first: 0,
          offset: topIndex,
          limit: bottomIndex,
          last: dataSource.length - 1
        }
      }), bottomBlank > 0 && /*#__PURE__*/React.createElement("div", {
        key: "bottom-blank",
        className: cx(Classes.virtualBlank, 'bottom'),
        style: {
          height: bottomBlank
        }
      })));
    };

    _this.state = {
      hasScroll: true,
      hasScrollY: true,
      needRenderLock: true,
      offsetY: 0,
      offsetX: 0,
      // 因为 ResizeObserver 在一开始总是会调用一次所提供的回调函数
      // 故这里为 maxRenderHeight/maxRenderWidth 设置一个默认值即可（因为这两个默认值很快就会被覆盖）
      // https://stackoverflow.com/questions/60026223/does-resizeobserver-invokes-initially-on-page-load
      maxRenderHeight: 600,
      maxRenderWidth: 800
    };
    return _this;
  }
  /** @deprecated BaseTable.getDoms() 已经过时，请勿调用 */


  _createClass(BaseTable, [{
    key: "getDoms",
    value: function getDoms() {
      console.warn('[kd-table] BaseTable.getDoms() 已经过时');
      return this.domHelper;
    }
    /** 自定义滚动条宽度为table宽度，使滚动条滑块宽度相同 */

  }, {
    key: "updateStickyScroll",
    value: function updateStickyScroll() {
      var _a, _b;

      var _this$domHelper = this.domHelper,
          stickyScroll = _this$domHelper.stickyScroll,
          artTable = _this$domHelper.artTable,
          stickyScrollItem = _this$domHelper.stickyScrollItem;
      var _lastHasScrollY = this.hasScrollY;

      if (!artTable) {
        return;
      }

      var tableBodyHtmlTable = this.domHelper.getTableBodyHtmlTable();
      var innerTableWidth = tableBodyHtmlTable.offsetWidth;
      var artTableWidth = artTable.offsetWidth;
      var stickyScrollHeightProp = this.props.stickyScrollHeight;
      var stickyScrollHeight = stickyScrollHeightProp === 'auto' ? this.getScrollBarWidth() : stickyScrollHeightProp; // stickyScroll.style.marginTop = `-${stickyScrollHeight + 1}px`
      // 设置滚动条高度

      stickyScroll.style.height = "".concat(stickyScrollHeight, "px");

      if (artTableWidth >= innerTableWidth) {
        if (this.state.hasScroll) {
          this.setState({
            hasScroll: false
          });
        }
      } else {
        if (!this.state.hasScroll && stickyScrollHeight > 5) {
          // 考虑下mac下面隐藏滚动条的情况
          this.setState({
            hasScroll: true
          });
        }
      }

      if (this.domHelper.virtual.offsetHeight > this.domHelper.tableBody.offsetHeight) {
        //   if (!this.state.hasScroll) {
        //     this.setState({
        //       hasScrollY: true
        //     })
        //   }
        this.hasScrollY = true;
      } else {
        stickyScroll.style.paddingRight = "".concat(stickyScrollHeight, "px"); //   this.setState({
        //     hasScrollY: false
        //   })

        this.hasScrollY = false;
      }

      if (_lastHasScrollY !== this.hasScrollY) {
        (_b = (_a = this.props).setTableWidth) === null || _b === void 0 ? void 0 : _b.call(_a, this.domHelper.tableBody.clientWidth);
      } // 设置子节点宽度


      stickyScrollItem.style.width = "".concat(innerTableWidth, "px");
    }
  }, {
    key: "renderTableHeader",
    value: function renderTableHeader(info) {
      var _this$props3 = this.props,
          stickyTop = _this$props3.stickyTop,
          hasHeader = _this$props3.hasHeader;
      var renderHeader = getTableRenderTemplate('header');

      if (typeof renderHeader === 'function') {
        return renderHeader(info, this.props);
      }

      return /*#__PURE__*/React.createElement("div", {
        className: cx(Classes.tableHeader, 'no-scrollbar'),
        style: {
          top: stickyTop === 0 ? undefined : stickyTop,
          display: hasHeader ? undefined : 'none'
        }
      }, /*#__PURE__*/React.createElement(TableHeader, {
        info: info
      }), /*#__PURE__*/React.createElement("div", {
        className: Classes.verticalScrollPlaceholder,
        style: this.hasScrollY ? {
          width: this.getScrollBarWidth()
        } : undefined
      }));
    }
  }, {
    key: "updateOffsetX",
    value: function updateOffsetX(nextOffsetX) {
      if (this.lastInfo.useVirtual.horizontal) {
        if (Math.abs(nextOffsetX - this.state.offsetX) >= OVERSCAN_SIZE / 2) {
          this.setState({
            offsetX: nextOffsetX
          });
        }
      }
    }
  }, {
    key: "syncHorizontalScrollFromTableBody",
    value: function syncHorizontalScrollFromTableBody() {
      this.syncHorizontalScroll(this.domHelper.virtual.scrollLeft);
    }
    /** 同步横向滚动偏移量 */

  }, {
    key: "syncHorizontalScroll",
    value: function syncHorizontalScroll(x) {
      this.updateOffsetX(x);

      var flat = _flatInstanceProperty(this.lastInfo);

      var leftLockShadow = this.domHelper.getLeftLockShadow();

      if (leftLockShadow) {
        var shouldShowLeftLockShadow = flat.left.length > 0 && this.state.needRenderLock && x > 0;

        if (shouldShowLeftLockShadow) {
          leftLockShadow.classList.add('show-shadow');
        } else {
          leftLockShadow.classList.remove('show-shadow');
        }
      }

      var rightLockShadow = this.domHelper.getRightLockShadow();

      if (rightLockShadow) {
        var shouldShowRightLockShadow = flat.right.length > 0 && this.state.needRenderLock && x < this.domHelper.virtual.scrollWidth - this.domHelper.virtual.clientWidth;

        if (shouldShowRightLockShadow) {
          rightLockShadow.classList.add('show-shadow');
        } else {
          rightLockShadow.classList.remove('show-shadow');
        }
      }
    }
  }, {
    key: "getVerticalRenderRange",
    value: function getVerticalRenderRange(useVirtual) {
      var dataSource = this.props.dataSource;
      var _this$state = this.state,
          offsetY = _this$state.offsetY,
          maxRenderHeight = _this$state.maxRenderHeight;
      var rowCount = dataSource.length;

      if (useVirtual.vertical) {
        return this.rowHeightManager.getRenderRange(offsetY, maxRenderHeight, rowCount);
      } else {
        return getFullRenderRange(rowCount);
      }
    }
  }, {
    key: "renderTableFooter",
    value: function renderTableFooter(info) {
      // console.log('render footer')
      var _this$props4 = this.props,
          _this$props4$footerDa = _this$props4.footerDataSource,
          footerDataSource = _this$props4$footerDa === void 0 ? [] : _this$props4$footerDa,
          getRowProps = _this$props4.getRowProps,
          primaryKey = _this$props4.primaryKey,
          stickyBottom = _this$props4.stickyBottom;
      var renderFooter = getTableRenderTemplate('footer');

      if (typeof renderFooter === 'function') {
        return renderFooter(info, this.props, {
          rowProps: {
            onMouseEnter: this.handleRowMouseEnter,
            onMouseLeave: this.handleRowMouseLeave
          }
        });
      }

      return /*#__PURE__*/React.createElement("div", {
        className: cx(Classes.tableFooter, Classes.horizontalScrollContainer),
        style: {
          bottom: stickyBottom === 0 ? undefined : stickyBottom
        }
      }, /*#__PURE__*/React.createElement(HtmlTable, {
        tbodyHtmlTag: "tfoot",
        data: footerDataSource,
        horizontalRenderInfo: info,
        getRowProps: getRowProps,
        primaryKey: primaryKey,
        verticalRenderInfo: {
          offset: 0,
          first: 0,
          last: footerDataSource.length - 1,
          limit: Infinity
        }
      }), /*#__PURE__*/React.createElement("div", {
        className: Classes.verticalScrollPlaceholder,
        style: this.hasScrollY ? {
          width: this.getScrollBarWidth(),
          visibility: 'initial'
        } : undefined
      }));
    }
  }, {
    key: "renderLockShadows",
    value: function renderLockShadows(info) {
      // console.log('render LockShadows')
      return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
        className: Classes.lockShadowMask,
        style: {
          left: 0,
          width: info.leftLockTotalWidth + LOCK_SHADOW_PADDING
        }
      }, /*#__PURE__*/React.createElement("div", {
        className: cx(Classes.lockShadow, Classes.leftLockShadow)
      })), /*#__PURE__*/React.createElement("div", {
        className: Classes.lockShadowMask,
        style: {
          right: 0,
          width: info.rightLockTotalWidth + LOCK_SHADOW_PADDING
        }
      }, /*#__PURE__*/React.createElement("div", {
        className: cx(Classes.lockShadow, Classes.rightLockShadow)
      })));
    }
  }, {
    key: "renderStickyScroll",
    value: function renderStickyScroll(info) {
      // console.log('render stickyscroll')
      var _this$props5 = this.props,
          hasStickyScroll = _this$props5.hasStickyScroll,
          stickyBottom = _this$props5.stickyBottom;
      var hasScroll = this.state.hasScroll;
      return /*#__PURE__*/React.createElement("div", {
        className: cx(Classes.stickyScroll, Classes.horizontalScrollContainer),
        style: {
          display: hasStickyScroll && hasScroll ? 'block' : 'none',
          bottom: stickyBottom
        }
      }, /*#__PURE__*/React.createElement("div", {
        className: Classes.stickyScrollItem
      }));
    }
  }, {
    key: "getScrollBarWidth",
    value: function getScrollBarWidth() {
      return this.props.scrollbarWidth || getScrollbarSize().width;
    }
  }, {
    key: "render",
    value: function render() {
      // console.log('render table')
      var info = calculateRenderInfo(this);
      this.lastInfo = info;
      var _this$props6 = this.props,
          dataSource = _this$props6.dataSource,
          className = _this$props6.className,
          style = _this$props6.style,
          hasHeader = _this$props6.hasHeader,
          useOuterBorder = _this$props6.useOuterBorder,
          isStickyHead = _this$props6.isStickyHead,
          isStickyHeader = _this$props6.isStickyHeader,
          isStickyFooter = _this$props6.isStickyFooter,
          isLoading = _this$props6.isLoading,
          getTableProps = _this$props6.getTableProps,
          footerDataSource = _this$props6.footerDataSource,
          components = _this$props6.components;
      var artTableWrapperClassName = cx(Classes.artTableWrapper, {
        'use-outer-border': useOuterBorder,
        empty: dataSource.length === 0,
        lock: info.hasLockColumn,
        'has-header': hasHeader,
        'sticky-header': isStickyHeader !== null && isStickyHeader !== void 0 ? isStickyHeader : isStickyHead,
        'has-footer': footerDataSource.length > 0,
        'sticky-footer': isStickyFooter,
        'ie-polyfill-wrapper': browserType.isIE
      }, className);

      var artTableWrapperProps = _defineProperty({
        className: artTableWrapperClassName,
        style: style
      }, STYLED_REF_PROP, this.artTableWrapperRef);

      return /*#__PURE__*/React.createElement(StyledArtTableWrapper, _extends({}, artTableWrapperProps), /*#__PURE__*/React.createElement(Loading, {
        visible: isLoading,
        LoadingIcon: components.LoadingIcon,
        LoadingContentWrapper: components.LoadingContentWrapper
      }, /*#__PURE__*/React.createElement("div", _extends({
        className: Classes.artTable
      }, getTableProps()), this.renderTableHeader(info), this.renderTableBody(info), this.renderTableFooter(info), this.renderLockShadows(info)), this.renderStickyScroll(info)));
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      var _a, _b, _c, _d; // console.log('did mount start')
      // console.log('update dom helper start')


      this.updateDOMHelper(); // console.log('update dom helper end')

      this.props$ = new BehaviorSubject(this.props);
      this.initSubscriptions();
      this.didMountOrUpdate(); // console.log('did mount end')

      var _this$props7 = this.props,
          cssVariables = _this$props7.cssVariables,
          enableCSSVariables = _this$props7.enableCSSVariables;
      cssPolifill({
        variables: cssVariables || {},
        enableCSSVariables: enableCSSVariables
      });
      (_b = (_a = this.props).setTableWidth) === null || _b === void 0 ? void 0 : _b.call(_a, this.domHelper.tableBody.clientWidth);
      (_d = (_c = this.props).setTableDomHelper) === null || _d === void 0 ? void 0 : _d.call(_c, this.domHelper);
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      // console.log('did update start')
      this.updateDOMHelper();
      this.props$.next(this.props);
      this.didMountOrUpdate(prevProps, prevState); // console.log('did update end')
    }
  }, {
    key: "didMountOrUpdate",
    value: function didMountOrUpdate(prevProps, prevState) {
      this.syncHorizontalScrollFromTableBody();
      this.updateStickyScroll();
      this.adjustNeedRenderLock();
      this.updateRowHeightManager();
      this.updateScrollLeftWhenLayoutChanged(prevProps, prevState);
    }
  }, {
    key: "updateScrollLeftWhenLayoutChanged",
    value: function updateScrollLeftWhenLayoutChanged(prevProps, prevState) {
      if (prevState != null) {
        if (!prevState.hasScroll && this.state.hasScroll) {
          this.domHelper.stickyScroll.scrollLeft = 0;
        }
      }

      if (prevProps != null) {
        var prevHasFooter = prevProps.footerDataSource.length > 0;
        var currentHasFooter = this.props.footerDataSource.length > 0;

        if (!prevHasFooter && currentHasFooter) {
          getTableScrollFooterDOM(this.domHelper).scrollLeft = this.domHelper.tableBody.scrollLeft;
        }
      }
    }
  }, {
    key: "initSubscriptions",
    value: function initSubscriptions() {
      var _this2 = this;

      var _this$domHelper2 = this.domHelper,
          virtual = _this$domHelper2.virtual,
          stickyScroll = _this$domHelper2.stickyScroll;
      this.rootSubscription.add(throttledWindowResize$.subscribe(function () {
        _this2.updateStickyScroll();

        _this2.adjustNeedRenderLock();
      }));
      this.resizeSubject.pipe(op.debounceTime(100)).subscribe(function () {
        var _a, _b;

        (_b = (_a = _this2.props).setTableWidth) === null || _b === void 0 ? void 0 : _b.call(_a, _this2.domHelper.tableBody.clientWidth);
      });

      var handleTableWrapperResize = function handleTableWrapperResize() {
        _this2.resizeSubject.next();
      };

      this.resizeObserver = addResizeObserver(this.domHelper.artTableWrapper, handleTableWrapperResize); // 滚动同步

      this.rootSubscription.add(syncScrollLeft([getTableScrollHeaderDOM(this.domHelper), virtual, getTableScrollFooterDOM(this.domHelper), stickyScroll], function (scrollLeft) {
        _this2.syncHorizontalScroll(scrollLeft);
      }));
      var richVisibleRects$ = getRichVisibleRectsStream(this.domHelper.virtual, this.props$.pipe(op.skip(1), op.mapTo('structure-may-change')), this.props.virtualDebugLabel).pipe(op.shareReplay()); // 每当可见部分发生变化的时候，调整 loading icon 的未知（如果 loading icon 存在的话）

      this.rootSubscription.add(combineLatest([richVisibleRects$.pipe(op.map(function (p) {
        return p.clipRect;
      }), op.distinctUntilChanged(shallowEqual)), this.props$.pipe(op.startWith(null), op.pairwise(), op.filter(function (_ref2) {
        var _ref3 = _slicedToArray(_ref2, 2),
            prevProps = _ref3[0],
            props = _ref3[1];

        return prevProps == null || !prevProps.isLoading && props.isLoading;
      }))]).subscribe(function (_ref4) {
        var _ref5 = _slicedToArray(_ref4, 1),
            clipRect = _ref5[0];

        var loadingIndicator = _this2.domHelper.getLoadingIndicator();

        if (!loadingIndicator) {
          return;
        }

        var height = clipRect.bottom - clipRect.top; // fixme 这里的定位在有些特殊情况下可能会出错 see #132

        loadingIndicator.style.top = "".concat(height / 2, "px");
        loadingIndicator.style.marginTop = "".concat(height / 2, "px");
      })); // 每当可见部分发生变化的时候，如果开启了虚拟滚动，则重新触发 render

      this.rootSubscription.add(richVisibleRects$.pipe(op.filter(function () {
        var _this2$lastInfo$useVi = _this2.lastInfo.useVirtual,
            horizontal = _this2$lastInfo$useVi.horizontal,
            vertical = _this2$lastInfo$useVi.vertical;
        return horizontal || vertical;
      }), op.map(function (_ref6) {
        var clipRect = _ref6.clipRect,
            offsetY = _ref6.offsetY;
        return {
          maxRenderHeight: clipRect.bottom - clipRect.top,
          maxRenderWidth: clipRect.right - clipRect.left,
          offsetY: offsetY
        };
      }), op.distinctUntilChanged(function (x, y) {
        // 如果表格区域被隐藏， 不需要触发组件重渲染
        if (y.maxRenderHeight === 0 && y.maxRenderWidth === 0) {
          return true;
        } // 因为 overscan 的存在，滚动较小的距离时不需要触发组件重渲染


        return Math.abs(x.maxRenderWidth - y.maxRenderWidth) < OVERSCAN_SIZE / 2 && Math.abs(x.maxRenderHeight - y.maxRenderHeight) < OVERSCAN_SIZE / 2 && Math.abs(x.offsetY - y.offsetY) < OVERSCAN_SIZE / 2;
      })).subscribe(function (sizeAndOffset) {
        _this2.setState(sizeAndOffset);
      }));
      this.rootSubscription.add(richVisibleRects$.pipe(op.map(function (_ref7) {
        var clipRect = _ref7.clipRect,
            offsetY = _ref7.offsetY;
        return {
          maxRenderHeight: clipRect.bottom - clipRect.top,
          maxRenderWidth: clipRect.right - clipRect.left,
          offsetY: offsetY
        };
      }), op.distinctUntilChanged(function (x, y) {
        return x.offsetY - y.offsetY === 0;
      }), // 计算得到当前行索引对应的数据块，blocks改成数组的形式，兼容快速拖动可视区域出现两个数据块的情况
      op.map(function (sizeAndOffset) {
        var _a;

        var offsetY = sizeAndOffset.offsetY,
            maxRenderHeight = sizeAndOffset.maxRenderHeight;
        var scrollDirection = offsetY - _this2.offsetY >= 0 ? 'down' : 'up';
        _this2.offsetY = offsetY;
        var rowCount = _this2.props.dataSource.length;

        var vertical = _this2.rowHeightManager.getRenderRange(offsetY, maxRenderHeight, rowCount);

        var topIndex = vertical.topIndex,
            bottomIndex = vertical.bottomIndex;
        var blockSize = ((_a = _this2.props.scrollLoad) === null || _a === void 0 ? void 0 : _a.blockSize) || 200;
        var topBlockStartIndex = Math.floor(Math.max(topIndex - 1, 0) / blockSize) * blockSize;
        var bottomBlockStartIndex = Math.floor((bottomIndex + 1) / blockSize) * blockSize;
        return scrollDirection === 'down' ? [topBlockStartIndex, bottomBlockStartIndex] : [bottomBlockStartIndex, topBlockStartIndex];
      }), op.distinctUntilChanged(function (x, y) {
        return x[0] === y[0] && x[1] === y[1];
      }), op.switchMap(function (startIndexs) {
        var event$ = from(startIndexs);
        return event$.pipe(op.map(function (startIndex) {
          return startIndex;
        }));
      }), // 过滤掉重复掉值
      op.distinctUntilChanged()).subscribe(function (startIndex) {
        var _a;

        (_a = _this2.props.scrollLoad) === null || _a === void 0 ? void 0 : _a.callback(startIndex);
      }));
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      var _a;

      (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
      this.rootSubscription.unsubscribe();
      this.resizeSubject.unsubscribe();
    }
    /** 更新 DOM 节点的引用，方便其他方法直接操作 DOM */

  }, {
    key: "updateDOMHelper",
    value: function updateDOMHelper() {
      this.domHelper = new TableDOMHelper(this.artTableWrapperRef.current);
    }
  }, {
    key: "updateRowHeightManager",
    value: function updateRowHeightManager() {
      var _a;

      var virtualTop = this.domHelper.getVirtualTop();
      var virtualTopHeight = (_a = virtualTop === null || virtualTop === void 0 ? void 0 : virtualTop.clientHeight) !== null && _a !== void 0 ? _a : 0;
      var maxTrRowIndex = -1;
      var maxTrBottom = -1;
      var zeroHeightRowCount = 0;

      var _iterator = _createForOfIteratorHelper(this.domHelper.getTableRows()),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var tr = _step.value;
          var rowIndex = Number(tr.dataset.rowindex);

          if (isNaN(rowIndex)) {
            continue;
          }

          maxTrRowIndex = Math.max(maxTrRowIndex, rowIndex);
          var offset = tr.offsetTop + virtualTopHeight;
          var size = tr.offsetHeight;

          if (size === 0) {
            zeroHeightRowCount += 1;
          } else {
            // 渲染出来的行高度为0，说明是display=none情况，行高不存在该种异常情况，不保存当前的高度
            this.rowHeightManager.updateRow(rowIndex, offset, size);
          }

          maxTrBottom = Math.max(maxTrBottom, offset + size);
        } // 当 estimatedRowHeight 过大时，可能出现「渲染行数过少，无法覆盖可视范围」的情况
        // 出现这种情况时，我们判断「下一次渲染能够渲染更多行」是否满足，满足的话就直接调用 forceUpdate
        // zeroHeightRowCount === 0 用于确保当前没有 display=none 的情况

      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }

      if (maxTrRowIndex !== -1 && zeroHeightRowCount === 0) {
        if (maxTrBottom < this.state.offsetY + this.state.maxRenderHeight) {
          var vertical = this.getVerticalRenderRange(this.lastInfo.useVirtual);

          if (vertical.bottomIndex - 1 > maxTrRowIndex) {
            this.forceUpdate();
          }
        }
      }
    }
    /** 计算表格所有列的渲染宽度之和，判断表格是否需要渲染锁列 */

  }, {
    key: "adjustNeedRenderLock",
    value: function adjustNeedRenderLock() {
      var needRenderLock = this.state.needRenderLock;

      var _this$lastInfo = this.lastInfo,
          flat = _flatInstanceProperty(_this$lastInfo),
          hasLockColumn = _this$lastInfo.hasLockColumn;

      if (hasLockColumn) {
        var _context;

        var sumOfColWidth = sum(_mapInstanceProperty(_context = flat.full).call(_context, function (col) {
          return col.width;
        }));
        var nextNeedRenderLock = sumOfColWidth > this.domHelper.artTable.clientWidth;

        if (needRenderLock !== nextNeedRenderLock) {
          this.setState({
            needRenderLock: nextNeedRenderLock
          });
        }
      } else {
        if (needRenderLock) {
          this.setState({
            needRenderLock: false
          });
        }
      }
    }
  }]);

  return BaseTable;
}(React.Component);
BaseTable.defaultProps = {
  hasHeader: true,
  isStickyHeader: true,
  stickyTop: 0,
  footerDataSource: [],
  isStickyFooter: true,
  stickyBottom: 0,
  hasStickyScroll: true,
  stickyScrollHeight: 'auto',
  useVirtual: 'auto',
  estimatedRowHeight: 48,
  isLoading: false,
  components: {},
  getTableProps: noop,
  getRowProps: noop,
  dataSource: [],
  useOuterBorder: true
};