@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
138 lines (137 loc) • 4.71 kB
JavaScript
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
};