stickyScrollBar.js 6.93 KB
"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var React = _interopRequireWildcard(require("react"));

var _addEventListener = _interopRequireDefault(require("rc-util/lib/Dom/addEventListener"));

var _getScrollBarSize = _interopRequireDefault(require("rc-util/lib/getScrollBarSize"));

var _classnames = _interopRequireDefault(require("classnames"));

var _css = require("rc-util/lib/Dom/css");

var _TableContext = _interopRequireDefault(require("./context/TableContext"));

var _useFrame = require("./hooks/useFrame");

var StickyScrollBar = function StickyScrollBar(_ref, ref) {
  var _scrollBodyRef$curren, _scrollBodyRef$curren2;

  var scrollBodyRef = _ref.scrollBodyRef,
      onScroll = _ref.onScroll,
      offsetScroll = _ref.offsetScroll,
      container = _ref.container;

  var _React$useContext = React.useContext(_TableContext.default),
      prefixCls = _React$useContext.prefixCls;

  var bodyScrollWidth = ((_scrollBodyRef$curren = scrollBodyRef.current) === null || _scrollBodyRef$curren === void 0 ? void 0 : _scrollBodyRef$curren.scrollWidth) || 0;
  var bodyWidth = ((_scrollBodyRef$curren2 = scrollBodyRef.current) === null || _scrollBodyRef$curren2 === void 0 ? void 0 : _scrollBodyRef$curren2.clientWidth) || 0;
  var scrollBarWidth = bodyScrollWidth && bodyWidth * (bodyWidth / bodyScrollWidth);
  var scrollBarRef = React.useRef();

  var _useLayoutState = (0, _useFrame.useLayoutState)({
    scrollLeft: 0,
    isHiddenScrollBar: false
  }),
      _useLayoutState2 = (0, _slicedToArray2.default)(_useLayoutState, 2),
      scrollState = _useLayoutState2[0],
      setScrollState = _useLayoutState2[1];

  var refState = React.useRef({
    delta: 0,
    x: 0
  });

  var _React$useState = React.useState(false),
      _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
      isActive = _React$useState2[0],
      setActive = _React$useState2[1];

  var onMouseUp = function onMouseUp() {
    setActive(false);
  };

  var onMouseDown = function onMouseDown(event) {
    event.persist();
    refState.current.delta = event.pageX - scrollState.scrollLeft;
    refState.current.x = 0;
    setActive(true);
    event.preventDefault();
  };

  var onMouseMove = function onMouseMove(event) {
    var _window;

    // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
    var _ref2 = event || ((_window = window) === null || _window === void 0 ? void 0 : _window.event),
        buttons = _ref2.buttons;

    if (!isActive || buttons === 0) {
      // If out body mouse up, we can set isActive false when mouse move
      if (isActive) {
        setActive(false);
      }

      return;
    }

    var left = refState.current.x + event.pageX - refState.current.x - refState.current.delta;

    if (left <= 0) {
      left = 0;
    }

    if (left + scrollBarWidth >= bodyWidth) {
      left = bodyWidth - scrollBarWidth;
    }

    onScroll({
      scrollLeft: left / bodyWidth * (bodyScrollWidth + 2)
    });
    refState.current.x = event.pageX;
  };

  var onContainerScroll = function onContainerScroll() {
    var tableOffsetTop = (0, _css.getOffset)(scrollBodyRef.current).top;
    var tableBottomOffset = tableOffsetTop + scrollBodyRef.current.offsetHeight;
    var currentClientOffset = container === window ? document.documentElement.scrollTop + window.innerHeight : (0, _css.getOffset)(container).top + container.clientHeight;

    if (tableBottomOffset - (0, _getScrollBarSize.default)() <= currentClientOffset || tableOffsetTop >= currentClientOffset - offsetScroll) {
      setScrollState(function (state) {
        return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, state), {}, {
          isHiddenScrollBar: true
        });
      });
    } else {
      setScrollState(function (state) {
        return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, state), {}, {
          isHiddenScrollBar: false
        });
      });
    }
  };

  var setScrollLeft = function setScrollLeft(left) {
    setScrollState(function (state) {
      return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, state), {}, {
        scrollLeft: left / bodyScrollWidth * bodyWidth || 0
      });
    });
  };

  React.useImperativeHandle(ref, function () {
    return {
      setScrollLeft: setScrollLeft
    };
  });
  React.useEffect(function () {
    var onMouseUpListener = (0, _addEventListener.default)(document.body, 'mouseup', onMouseUp, false);
    var onMouseMoveListener = (0, _addEventListener.default)(document.body, 'mousemove', onMouseMove, false);
    onContainerScroll();
    return function () {
      onMouseUpListener.remove();
      onMouseMoveListener.remove();
    };
  }, [scrollBarWidth, isActive]);
  React.useEffect(function () {
    var onScrollListener = (0, _addEventListener.default)(container, 'scroll', onContainerScroll, false);
    var onResizeListener = (0, _addEventListener.default)(window, 'resize', onContainerScroll, false);
    return function () {
      onScrollListener.remove();
      onResizeListener.remove();
    };
  }, [container]);
  React.useEffect(function () {
    if (!scrollState.isHiddenScrollBar) {
      setScrollState(function (state) {
        var _scrollBodyRef$curren3, _scrollBodyRef$curren4;

        return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, state), {}, {
          scrollLeft: scrollBodyRef.current.scrollLeft / ((_scrollBodyRef$curren3 = scrollBodyRef.current) === null || _scrollBodyRef$curren3 === void 0 ? void 0 : _scrollBodyRef$curren3.scrollWidth) * ((_scrollBodyRef$curren4 = scrollBodyRef.current) === null || _scrollBodyRef$curren4 === void 0 ? void 0 : _scrollBodyRef$curren4.clientWidth)
        });
      });
    }
  }, [scrollState.isHiddenScrollBar]);

  if (bodyScrollWidth <= bodyWidth || !scrollBarWidth || scrollState.isHiddenScrollBar) {
    return null;
  }

  return React.createElement("div", {
    style: {
      height: (0, _getScrollBarSize.default)(),
      width: bodyWidth,
      bottom: offsetScroll
    },
    className: "".concat(prefixCls, "-sticky-scroll")
  }, React.createElement("div", {
    onMouseDown: onMouseDown,
    ref: scrollBarRef,
    className: (0, _classnames.default)("".concat(prefixCls, "-sticky-scroll-bar"), (0, _defineProperty2.default)({}, "".concat(prefixCls, "-sticky-scroll-bar-active"), isActive)),
    style: {
      width: "".concat(scrollBarWidth, "px"),
      transform: "translate3d(".concat(scrollState.scrollLeft, "px, 0, 0)")
    }
  }));
};

var _default = React.forwardRef(StickyScrollBar);

exports.default = _default;