UNPKG

@nutui/nutui-react-taro

Version:

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

138 lines (137 loc) 4.71 kB
import { _ as __rest, a as __awaiter } from "./tslib.es6-iWu3F_1J.js"; import React__default, { useRef, useEffect, useState, useMemo, useCallback } from "react"; import classNames from "classnames"; import { getEnv, usePageScroll } from "@tarojs/taro"; import { C as ComponentDefaults } from "./typings-DV9RBfhj.js"; import { g as getWindowInfo } from "./get-system-info-D27xNglo.js"; import { g as getRectByTaro } from "./get-rect-by-taro-D0h6aiDr.js"; import { g as getScrollParent } from "./get-scroll-parent-DB1VRg11.js"; function useWatch(dep, callback, config = { immediate: false }) { const { immediate } = config; const prev = useRef(); const inited = useRef(false); const stop = useRef(false); useEffect(() => { const execute = () => callback(prev.current); if (!stop.current) { if (!inited.current) { inited.current = true; if (immediate) { execute(); } } else { execute(); } prev.current = dep; } }, [dep]); return () => { stop.current = true; }; } const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { position: "top", zIndex: 900 }); const classPrefix = "nut-sticky"; const Sticky = (props) => { const _a = Object.assign(Object.assign({}, defaultProps), props), { position, zIndex, threshold, style, children, container, className, onChange } = _a, rest = __rest(_a, ["position", "zIndex", "threshold", "style", "children", "container", "className", "onChange"]); const stickyRef = useRef(null); const rootRef = useRef(null); const [rootRect, setRootRect] = useState({}); const [fixed, setFixed] = useState(false); const [transform, setTransform] = useState(0); useWatch(fixed, () => { onChange && onChange(fixed); }); const rootStyle = useMemo(() => { var _a2, _b; if (!fixed) { return { height: "", width: "" }; } const style2 = { height: (_a2 = rootRect.height) !== null && _a2 !== void 0 ? _a2 : "", width: (_b = rootRect.width) !== null && _b !== void 0 ? _b : "" }; return style2; }, [fixed, rootRect.height, rootRect.width]); const stickyStyle = useMemo(() => { var _a2, _b; if (!fixed) { return { height: "", width: "", [position]: "" }; } const style2 = { height: (_a2 = rootRect.height) !== null && _a2 !== void 0 ? _a2 : "", width: (_b = rootRect.width) !== null && _b !== void 0 ? _b : "", transform: `translate3d(0, ${transform}px, 0)`, [position]: threshold, zIndex }; return style2; }, [ fixed, rootRect.height, rootRect.width, transform, position, threshold, zIndex ]); const handleScroll = (scrollTop) => __awaiter(void 0, void 0, void 0, function* () { const curRootRect = yield getRectByTaro(rootRef.current); const stickyRect = yield getRectByTaro(stickyRef.current); if (!curRootRect || !stickyRect) { console.warn("getRectByTaro获取失败", { stickyRect, curRootRect }); return; } setRootRect(curRootRect); if (position === "top") { if (container) { const containerRect = yield getRectByTaro(container.current); const difference = containerRect.bottom - threshold - curRootRect.height; const curTransform = difference < 0 ? difference : 0; setTransform(curTransform); const curFixed = threshold > curRootRect.top && containerRect.bottom > 0; setFixed(curFixed); } else { setFixed(threshold > curRootRect.top); } } else { const windowHeight = getWindowInfo().windowHeight; setFixed(windowHeight - threshold < curRootRect.bottom); } }); const getElement = useCallback(() => { return getScrollParent(rootRef.current); }, []); useEffect(() => { if (getEnv() === "WEB" && getElement() !== window) { window.addEventListener("touchmove", handleScroll, true); window.addEventListener("scroll", handleScroll, true); return () => { window.removeEventListener("touchmove", handleScroll); window.removeEventListener("scroll", handleScroll); }; } }, []); usePageScroll((res) => { if (getEnv() !== "WEB") { handleScroll(res.scrollTop); } }); return React__default.createElement( "div", Object.assign({ ref: rootRef, style: rootStyle, className: classNames(classPrefix, className) }, rest), React__default.createElement("div", { className: classNames("nut-sticky-box", { "nut-sticky-fixed": fixed }), ref: stickyRef, style: stickyStyle }, children) ); }; Sticky.displayName = "NutSticky"; export { Sticky as S };