UNPKG

@bytedance/mona-client-web

Version:

web for mona

152 lines 7.58 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import React, { useLayoutEffect, useMemo, useRef } from 'react'; import styles from './index.module.less'; import { useHandlers } from '../hooks'; import { formatSyntheticEvent } from '../utils'; //t = current time //b = start value //c = change in value //d = duration function easeInOutQuad(t, b, c, d) { t /= d / 2; if (t < 1) return c / 2 * t * t + b; t--; return -c / 2 * (t * (t - 2) - 1) + b; } ; function scrollToWithAnimation(element, to, duration, vertical) { var start = vertical ? element.scrollTop : element.scrollLeft; var change = to - start; var currentTime = 0; var increment = 20; var animateScroll = function () { currentTime += increment; var val = easeInOutQuad(currentTime, start, change, duration); if (vertical) { element.scrollTop = val; } else { element.scrollLeft = val; } if (currentTime < duration) { setTimeout(animateScroll, increment); } }; animateScroll(); } export var ScrollViewContext = React.createContext(null); var ScrollView = function (props) { var children = props.children, scrollIntoView = props.scrollIntoView, upperThreshold = props.upperThreshold, lowerThreshold = props.lowerThreshold, scrollWithAnimation = props.scrollWithAnimation, scrollTop = props.scrollTop, scrollLeft = props.scrollLeft, scrollX = props.scrollX, scrollY = props.scrollY, onScroll = props.onScroll, onScrollToUpper = props.onScrollToUpper, onScrollToLower = props.onScrollToLower, restProps = __rest(props, ["children", "scrollIntoView", "upperThreshold", "lowerThreshold", "scrollWithAnimation", "scrollTop", "scrollLeft", "scrollX", "scrollY", "onScroll", "onScrollToUpper", "onScrollToLower"]); var _a = useHandlers(restProps), handleClassName = _a.handleClassName, handleProps = __rest(_a, ["handleClassName"]); var scrollRef = useRef(null); var topPreRef = useRef(0); var leftPreRef = useRef(0); var cbRefs = useRef([]); var context = useMemo(function () { return ({ registerScrollCallback: function (callback) { cbRefs.current.push(callback); }, unregisterScrollCallback: function (callback) { var index = cbRefs.current.indexOf(callback); cbRefs.current.splice(index, 1); } }); }, []); var overflow = "".concat(scrollX ? 'auto' : 'hidden', " ").concat(scrollY ? 'auto' : 'hidden'); var handleScroll = function (e) { if (typeof onScroll === 'function') { onScroll(formatSyntheticEvent({ event: e })); } if (scrollRef.current) { cbRefs.current.forEach(function (cb) { return cb(scrollRef.current); }); var top_1 = scrollRef.current.scrollTop; var left = scrollRef.current.scrollLeft; var currentUpperThreshold = upperThreshold || 0; var currentLowerThreshold = lowerThreshold || 0; if (typeof onScrollToUpper === 'function') { if (scrollY && ((currentUpperThreshold > topPreRef.current && currentUpperThreshold <= top_1) || (currentUpperThreshold < topPreRef.current && currentUpperThreshold >= top_1))) { onScrollToUpper(formatSyntheticEvent({ event: e, type: 'scrolltoupper' })); } if (scrollX && ((currentUpperThreshold > leftPreRef.current && currentUpperThreshold <= left) || (currentUpperThreshold < leftPreRef.current && currentUpperThreshold >= left))) { onScrollToUpper(formatSyntheticEvent({ event: e, type: 'scrolltoupper' })); } } if (typeof onScrollToLower === 'function') { if (scrollY) { var clientHeight = scrollRef.current.clientHeight; var scrollHeight = scrollRef.current.scrollHeight; var currentLower = scrollHeight - clientHeight - top_1; var prevLower = scrollHeight - clientHeight - topPreRef.current; if ((currentLowerThreshold > prevLower && currentLowerThreshold <= currentLower) || (currentLowerThreshold < prevLower && currentLowerThreshold >= currentLower)) { onScrollToLower(formatSyntheticEvent({ event: e, type: 'scrolltolower' })); } } if (scrollX) { var clientWidth = scrollRef.current.clientWidth; var scrollWidth = scrollRef.current.scrollWidth; var currentLower = scrollWidth - clientWidth - left; var prevLower = scrollWidth - clientWidth - leftPreRef.current; if ((currentLowerThreshold > prevLower && currentLowerThreshold <= currentLower) || (currentLowerThreshold < prevLower && currentLowerThreshold >= currentLower)) { onScrollToLower(formatSyntheticEvent({ event: e, type: 'scrolltolower' })); } } } topPreRef.current = top_1; leftPreRef.current = left; } }; useLayoutEffect(function () { if (scrollY && scrollRef.current && scrollTop != null) { if (scrollWithAnimation) { scrollToWithAnimation(scrollRef.current, scrollTop, 300, true); } else { scrollRef.current.scrollTop = scrollTop; } } }, [scrollTop, scrollY, scrollWithAnimation]); useLayoutEffect(function () { if (scrollX && scrollRef.current && scrollLeft != null) { if (scrollWithAnimation) { scrollToWithAnimation(scrollRef.current, scrollLeft, 300, false); } else { scrollRef.current.scrollLeft = scrollLeft; } } }, [scrollLeft, scrollX, scrollWithAnimation]); useLayoutEffect(function () { if (scrollRef.current && scrollIntoView) { var $target = scrollRef.current.querySelector("#".concat(scrollIntoView)); if ($target) { $target.scrollIntoView({ behavior: scrollWithAnimation ? 'smooth' : 'auto', block: 'start', inline: 'start' }); } } }, [scrollIntoView, scrollWithAnimation]); return (React.createElement("div", __assign({}, handleProps, { className: handleClassName(styles.container) }), React.createElement("div", { ref: scrollRef, className: styles.container, onScroll: handleScroll, style: { overflow: overflow } }, React.createElement(ScrollViewContext.Provider, { value: context }, children)))); }; export default ScrollView; //# sourceMappingURL=index.js.map