UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

101 lines (100 loc) 3.31 kB
"use client"; const require_use_did_update = require("../use-did-update/use-did-update.cjs"); const require_use_merged_ref = require("../use-merged-ref/use-merged-ref.cjs"); let react = require("react"); let react_dom = require("react-dom"); //#region packages/@mantine/hooks/src/use-collapse/use-collapse.ts function getAutoHeightDuration(height) { if (!height || typeof height === "string") return 0; const constant = height / 36; return Math.round((4 + 15 * constant ** .25 + constant / 5) * 10); } function getElementHeight(elementRef) { return elementRef.current ? elementRef.current.scrollHeight : "auto"; } function useCollapse({ transitionDuration, transitionTimingFunction = "ease", onTransitionEnd, onTransitionStart, expanded, keepMounted }) { const collapsedStyles = { height: 0, overflow: "hidden", ...keepMounted ? {} : { display: "none" } }; const onTransitionStartEvent = (0, react.useEffectEvent)(() => onTransitionStart?.()); const elementRef = (0, react.useRef)(null); const [styles, setStylesRaw] = (0, react.useState)(expanded ? {} : collapsedStyles); const [state, setState] = (0, react.useState)(expanded ? "entered" : "exited"); const setStyles = (newStyles) => { (0, react_dom.flushSync)(() => setStylesRaw(newStyles)); }; const mergeStyles = (newStyles) => { setStyles((oldStyles) => ({ ...oldStyles, ...newStyles })); }; const getTransitionStyles = (height) => { const duration = transitionDuration || getAutoHeightDuration(height); return { transition: `height ${duration}ms ${transitionTimingFunction}, opacity ${duration}ms ${transitionTimingFunction}` }; }; require_use_did_update.useDidUpdate(() => { if (transitionDuration !== 0) onTransitionStartEvent(); if (expanded) window.requestAnimationFrame(() => { (0, react_dom.flushSync)(() => setState("entering")); mergeStyles({ willChange: "height", display: "block", overflow: "hidden" }); window.requestAnimationFrame(() => { const height = getElementHeight(elementRef); mergeStyles({ ...getTransitionStyles(height), height }); }); }); else window.requestAnimationFrame(() => { (0, react_dom.flushSync)(() => setState("exiting")); const height = getElementHeight(elementRef); mergeStyles({ ...getTransitionStyles(height), willChange: "height", height }); window.requestAnimationFrame(() => mergeStyles({ height: 0, overflow: "hidden" })); }); }, [expanded]); const handleTransitionEnd = (event) => { if (event.target !== elementRef.current || event.propertyName !== "height") return; if (expanded) { const height = getElementHeight(elementRef); if (height === styles.height) setStyles({}); else mergeStyles({ height }); setState("entered"); onTransitionEnd?.(); } else if (styles.height === 0) { setStyles(collapsedStyles); setState("exited"); onTransitionEnd?.(); } }; return { state, getCollapseProps: (input) => ({ "aria-hidden": !expanded, inert: !expanded, ref: require_use_merged_ref.mergeRefs(elementRef, input?.ref), onTransitionEnd: handleTransitionEnd, style: { boxSizing: "border-box", ...input?.style, ...styles } }) }; } //#endregion exports.useCollapse = useCollapse; //# sourceMappingURL=use-collapse.cjs.map