UNPKG

8.3 kBJavaScriptView Raw
1import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
3import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4import * as React from 'react';
5import classNames from 'classnames';
6import raf from "rc-util/es/raf";
7function getPageXY(e, horizontal) {
8 var obj = 'touches' in e ? e.touches[0] : e;
9 return obj[horizontal ? 'pageX' : 'pageY'];
10}
11var ScrollBar = /*#__PURE__*/React.forwardRef(function (props, ref) {
12 var prefixCls = props.prefixCls,
13 rtl = props.rtl,
14 scrollOffset = props.scrollOffset,
15 scrollRange = props.scrollRange,
16 onStartMove = props.onStartMove,
17 onStopMove = props.onStopMove,
18 onScroll = props.onScroll,
19 horizontal = props.horizontal,
20 spinSize = props.spinSize,
21 containerSize = props.containerSize,
22 style = props.style,
23 propsThumbStyle = props.thumbStyle;
24 var _React$useState = React.useState(false),
25 _React$useState2 = _slicedToArray(_React$useState, 2),
26 dragging = _React$useState2[0],
27 setDragging = _React$useState2[1];
28 var _React$useState3 = React.useState(null),
29 _React$useState4 = _slicedToArray(_React$useState3, 2),
30 pageXY = _React$useState4[0],
31 setPageXY = _React$useState4[1];
32 var _React$useState5 = React.useState(null),
33 _React$useState6 = _slicedToArray(_React$useState5, 2),
34 startTop = _React$useState6[0],
35 setStartTop = _React$useState6[1];
36 var isLTR = !rtl;
37
38 // ========================= Refs =========================
39 var scrollbarRef = React.useRef();
40 var thumbRef = React.useRef();
41
42 // ======================= Visible ========================
43 var _React$useState7 = React.useState(false),
44 _React$useState8 = _slicedToArray(_React$useState7, 2),
45 visible = _React$useState8[0],
46 setVisible = _React$useState8[1];
47 var visibleTimeoutRef = React.useRef();
48 var delayHidden = function delayHidden() {
49 clearTimeout(visibleTimeoutRef.current);
50 setVisible(true);
51 visibleTimeoutRef.current = setTimeout(function () {
52 setVisible(false);
53 }, 3000);
54 };
55
56 // ======================== Range =========================
57 var enableScrollRange = scrollRange - containerSize || 0;
58 var enableOffsetRange = containerSize - spinSize || 0;
59
60 // ========================= Top ==========================
61 var top = React.useMemo(function () {
62 if (scrollOffset === 0 || enableScrollRange === 0) {
63 return 0;
64 }
65 var ptg = scrollOffset / enableScrollRange;
66 return ptg * enableOffsetRange;
67 }, [scrollOffset, enableScrollRange, enableOffsetRange]);
68
69 // ====================== Container =======================
70 var onContainerMouseDown = function onContainerMouseDown(e) {
71 e.stopPropagation();
72 e.preventDefault();
73 };
74
75 // ======================== Thumb =========================
76 var stateRef = React.useRef({
77 top: top,
78 dragging: dragging,
79 pageY: pageXY,
80 startTop: startTop
81 });
82 stateRef.current = {
83 top: top,
84 dragging: dragging,
85 pageY: pageXY,
86 startTop: startTop
87 };
88 var onThumbMouseDown = function onThumbMouseDown(e) {
89 setDragging(true);
90 setPageXY(getPageXY(e, horizontal));
91 setStartTop(stateRef.current.top);
92 onStartMove();
93 e.stopPropagation();
94 e.preventDefault();
95 };
96
97 // ======================== Effect ========================
98
99 // React make event as passive, but we need to preventDefault
100 // Add event on dom directly instead.
101 // ref: https://github.com/facebook/react/issues/9809
102 React.useEffect(function () {
103 var onScrollbarTouchStart = function onScrollbarTouchStart(e) {
104 e.preventDefault();
105 };
106 var scrollbarEle = scrollbarRef.current;
107 var thumbEle = thumbRef.current;
108 scrollbarEle.addEventListener('touchstart', onScrollbarTouchStart);
109 thumbEle.addEventListener('touchstart', onThumbMouseDown);
110 return function () {
111 scrollbarEle.removeEventListener('touchstart', onScrollbarTouchStart);
112 thumbEle.removeEventListener('touchstart', onThumbMouseDown);
113 };
114 }, []);
115
116 // Pass to effect
117 var enableScrollRangeRef = React.useRef();
118 enableScrollRangeRef.current = enableScrollRange;
119 var enableOffsetRangeRef = React.useRef();
120 enableOffsetRangeRef.current = enableOffsetRange;
121 React.useEffect(function () {
122 if (dragging) {
123 var moveRafId;
124 var onMouseMove = function onMouseMove(e) {
125 var _stateRef$current = stateRef.current,
126 stateDragging = _stateRef$current.dragging,
127 statePageY = _stateRef$current.pageY,
128 stateStartTop = _stateRef$current.startTop;
129 raf.cancel(moveRafId);
130 if (stateDragging) {
131 var offset = getPageXY(e, horizontal) - statePageY;
132 var newTop = stateStartTop;
133 if (!isLTR && horizontal) {
134 newTop -= offset;
135 } else {
136 newTop += offset;
137 }
138 var tmpEnableScrollRange = enableScrollRangeRef.current;
139 var tmpEnableOffsetRange = enableOffsetRangeRef.current;
140 var ptg = tmpEnableOffsetRange ? newTop / tmpEnableOffsetRange : 0;
141 var newScrollTop = Math.ceil(ptg * tmpEnableScrollRange);
142 newScrollTop = Math.max(newScrollTop, 0);
143 newScrollTop = Math.min(newScrollTop, tmpEnableScrollRange);
144 moveRafId = raf(function () {
145 onScroll(newScrollTop, horizontal);
146 });
147 }
148 };
149 var onMouseUp = function onMouseUp() {
150 setDragging(false);
151 onStopMove();
152 };
153 window.addEventListener('mousemove', onMouseMove);
154 window.addEventListener('touchmove', onMouseMove);
155 window.addEventListener('mouseup', onMouseUp);
156 window.addEventListener('touchend', onMouseUp);
157 return function () {
158 window.removeEventListener('mousemove', onMouseMove);
159 window.removeEventListener('touchmove', onMouseMove);
160 window.removeEventListener('mouseup', onMouseUp);
161 window.removeEventListener('touchend', onMouseUp);
162 raf.cancel(moveRafId);
163 };
164 }
165 }, [dragging]);
166 React.useEffect(function () {
167 delayHidden();
168 }, [scrollOffset]);
169
170 // ====================== Imperative ======================
171 React.useImperativeHandle(ref, function () {
172 return {
173 delayHidden: delayHidden
174 };
175 });
176
177 // ======================== Render ========================
178 var scrollbarPrefixCls = "".concat(prefixCls, "-scrollbar");
179 var containerStyle = {
180 position: 'absolute',
181 visibility: visible ? null : 'hidden'
182 };
183 var thumbStyle = {
184 position: 'absolute',
185 background: 'rgba(0, 0, 0, 0.5)',
186 borderRadius: 99,
187 cursor: 'pointer',
188 userSelect: 'none'
189 };
190 if (horizontal) {
191 // Container
192 containerStyle.height = 8;
193 containerStyle.left = 0;
194 containerStyle.right = 0;
195 containerStyle.bottom = 0;
196
197 // Thumb
198 thumbStyle.height = '100%';
199 thumbStyle.width = spinSize;
200 if (isLTR) {
201 thumbStyle.left = top;
202 } else {
203 thumbStyle.right = top;
204 }
205 } else {
206 // Container
207 containerStyle.width = 8;
208 containerStyle.top = 0;
209 containerStyle.bottom = 0;
210 if (isLTR) {
211 containerStyle.right = 0;
212 } else {
213 containerStyle.left = 0;
214 }
215
216 // Thumb
217 thumbStyle.width = '100%';
218 thumbStyle.height = spinSize;
219 thumbStyle.top = top;
220 }
221 return /*#__PURE__*/React.createElement("div", {
222 ref: scrollbarRef,
223 className: classNames(scrollbarPrefixCls, _defineProperty(_defineProperty(_defineProperty({}, "".concat(scrollbarPrefixCls, "-horizontal"), horizontal), "".concat(scrollbarPrefixCls, "-vertical"), !horizontal), "".concat(scrollbarPrefixCls, "-visible"), visible)),
224 style: _objectSpread(_objectSpread({}, containerStyle), style),
225 onMouseDown: onContainerMouseDown,
226 onMouseMove: delayHidden
227 }, /*#__PURE__*/React.createElement("div", {
228 ref: thumbRef,
229 className: classNames("".concat(scrollbarPrefixCls, "-thumb"), _defineProperty({}, "".concat(scrollbarPrefixCls, "-thumb-moving"), dragging)),
230 style: _objectSpread(_objectSpread({}, thumbStyle), propsThumbStyle),
231 onMouseDown: onThumbMouseDown
232 }));
233});
234if (process.env.NODE_ENV !== 'production') {
235 ScrollBar.displayName = 'ScrollBar';
236}
237export default ScrollBar;
\No newline at end of file