UNPKG

fanyucomponents

Version:

一款以 純邏輯為核心、無樣式綁定 的 React 元件套件

68 lines (67 loc) 2.54 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useLayoutEffect, useRef, useState } from "react"; export const Collapse = ({ as, state: show, style, children, ...rest }) => { const Tag = as !== null && as !== void 0 ? as : "div"; const innerRef = useRef(null); const [collapsed, setCollapsed] = useState(show); const transitionTimerRef = useRef(null); const resizeObserverRef = useRef(null); useLayoutEffect(() => { const el = innerRef.current; if (!el) return; // 清理函数 const cleanup = () => { if (transitionTimerRef.current) { clearTimeout(transitionTimerRef.current); } if (resizeObserverRef.current) { resizeObserverRef.current.disconnect(); } }; // 處理過度結束 const onTransitionEnd = (e) => { if (e.propertyName === "height" && show) { el.style.height = "auto"; // 添加防抖重置以防内容变化 resizeObserverRef.current = new ResizeObserver(() => { el.style.height = "auto"; }); resizeObserverRef.current.observe(el); } }; // 備用(防止 transitionend 未觸發) const startFallbackTimer = () => { transitionTimerRef.current = setTimeout(() => { if (show) { el.style.height = "auto"; } }, parseInt(el.style.transitionDuration || "500")); // 匹配 CSS 过渡时间 }; if (show) { setCollapsed(true); el.style.height = "0px"; // 強制重繪,讓上面設定生效 void el.offsetHeight; el.style.height = `${el.scrollHeight}px`; } else { el.style.height = `${el.scrollHeight}px`; // 強制重繪,讓上面設定生效 void el.offsetHeight; el.style.height = "0px"; } el.addEventListener("transitionend", onTransitionEnd); startFallbackTimer(); return () => { cleanup(); el.removeEventListener("transitionend", onTransitionEnd); }; }, [show]); return (_jsx(Tag, { ref: innerRef, style: { overflow: "hidden", maxHeight: !collapsed && !show ? "0px" : undefined, ...style, }, ...rest, children: children })); }; Collapse.displayName = "Collapse";