UNPKG

@nutui/nutui-react-taro

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

186 lines (185 loc) 7.72 kB
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; import { _ as _define_property } from "@swc/helpers/_/_define_property"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import classNames from "classnames"; import { getEnv, usePageScroll } from "@tarojs/taro"; import { View } from "@tarojs/components"; import { getWindowInfo } from "../../utils/taro/get-system-info"; import { ComponentDefaults } from "../../utils/typings"; import { useWatch } from "../../hooks/use-watch"; import { getRectInMultiPlatform } from "../../utils/taro/get-rect"; import { getScrollParent } from "../../utils/get-scroll-parent"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { position: 'top', zIndex: 900 }); var classPrefix = 'nut-sticky'; export var Sticky = function(props) { var _ref = _object_spread({}, defaultProps, props), position = _ref.position, zIndex = _ref.zIndex, threshold = _ref.threshold, style = _ref.style, children = _ref.children, container = _ref.container, className = _ref.className, onChange = _ref.onChange, rest = _object_without_properties(_ref, [ "position", "zIndex", "threshold", "style", "children", "container", "className", "onChange" ]); var stickyRef = useRef(null); var rootRef = useRef(null); var _useState = _sliced_to_array(useState({}), 2), rootRect = _useState[0], setRootRect = _useState[1]; var _useState1 = _sliced_to_array(useState(false), 2), fixed = _useState1[0], setFixed = _useState1[1]; var _useState2 // 相对容器偏移距离 = _sliced_to_array(useState(0), 2), transform = _useState2[0], setTransform = _useState2[1]; useWatch(fixed, function() { onChange && onChange(fixed); }); var rootStyle = useMemo(function() { if (!fixed) { return { height: '', width: '' }; } var _rootRect_height, _rootRect_width; var style = { height: (_rootRect_height = rootRect.height) !== null && _rootRect_height !== void 0 ? _rootRect_height : '', width: (_rootRect_width = rootRect.width) !== null && _rootRect_width !== void 0 ? _rootRect_width : '' }; return style; }, [ fixed, rootRect.height, rootRect.width ]); var stickyStyle = useMemo(function() { if (!fixed) { return _define_property({ height: '', width: '' }, position, ''); } var _rootRect_height, _rootRect_width; var _obj; var style = (_obj = { height: (_rootRect_height = rootRect.height) !== null && _rootRect_height !== void 0 ? _rootRect_height : '', width: (_rootRect_width = rootRect.width) !== null && _rootRect_width !== void 0 ? _rootRect_width : '', transform: "translate3d(0, ".concat(transform, "px, 0)") }, _define_property(_obj, position, threshold), _define_property(_obj, "zIndex", zIndex), _obj); return style; }, [ fixed, rootRect.height, rootRect.width, transform, position, threshold, zIndex ]); var handleScroll = function(scrollTop) { return _async_to_generator(function() { var curRootRect, stickyRect, containerRect, difference, curTransform, curFixed, windowHeight; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: return [ 4, getRectInMultiPlatform(rootRef.current) ]; case 1: curRootRect = _state.sent(); return [ 4, getRectInMultiPlatform(stickyRef.current) ]; case 2: stickyRect = _state.sent(); if (!curRootRect || !stickyRect) { console.warn('getRectByTaro获取失败', { stickyRect: stickyRect, curRootRect: curRootRect }); return [ 2 ]; } setRootRect(curRootRect); if (!(position === 'top')) return [ 3, 6 ]; if (!container) return [ 3, 4 ]; return [ 4, getRectInMultiPlatform(container.current) ]; case 3: containerRect = _state.sent(); difference = containerRect.bottom - threshold - curRootRect.height; curTransform = difference < 0 ? difference : 0; setTransform(curTransform); curFixed = threshold > curRootRect.top && containerRect.bottom > 0; setFixed(curFixed); return [ 3, 5 ]; case 4: setFixed(threshold > curRootRect.top); _state.label = 5; case 5: return [ 3, 7 ]; case 6: windowHeight = getWindowInfo().windowHeight; setFixed(windowHeight - threshold < curRootRect.bottom); _state.label = 7; case 7: return [ 2 ]; } }); })(); }; var getElement = useCallback(function() { return getScrollParent(rootRef.current); }, []); useEffect(function() { if (getEnv() === 'WEB' && getElement() !== window) { window.addEventListener('touchmove', handleScroll, true); window.addEventListener('scroll', handleScroll, true); return function() { window.removeEventListener('touchmove', handleScroll); window.removeEventListener('scroll', handleScroll); }; } }, []); usePageScroll(function(res) { if (getEnv() !== 'WEB') { handleScroll(res.scrollTop); } }); return /*#__PURE__*/ React.createElement("div", _object_spread({ ref: rootRef, style: rootStyle, className: classNames(classPrefix, className) }, rest), /*#__PURE__*/ React.createElement(View, { className: classNames('nut-sticky-box', { 'nut-sticky-fixed': fixed }), ref: stickyRef, style: stickyStyle }, children)); }; Sticky.displayName = 'NutSticky';