@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
62 lines (61 loc) • 1.85 kB
JavaScript
import { useLayoutEffect, useRef, useState } from "react";
const REPOP_ANIMATION = [[{
opacity: 0,
scale: .97
}, {
opacity: 1,
scale: 1
}], {
duration: 200,
easing: "cubic-bezier(0.33, 1, 0.68, 1)"
}];
const centerOf = (el) => {
const rect = el.getBoundingClientRect();
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
};
const prefersReducedMotion = () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const useRepopOnFarTriggerSwitch = (store, options) => {
const enabled = options?.enabled ?? true;
const threshold = options?.threshold ?? 280;
const activeTrigger = store.useState?.("activeTriggerElement") ?? store.state.activeTriggerElement ?? null;
const open = store.useState?.("open") ?? Boolean(store.state.open);
const popupElement = store.useState?.("popupElement") ?? store.state.popupElement ?? null;
const lastRef = useRef({
center: null,
el: null
});
const [repop, setRepop] = useState(false);
useLayoutEffect(() => {
if (!open || !enabled) {
lastRef.current = {
center: null,
el: null
};
setRepop(false);
return;
}
const last = lastRef.current;
if (activeTrigger === last.el) return;
const center = activeTrigger ? centerOf(activeTrigger) : null;
const far = Boolean(last.el && last.center && center && Math.hypot(center.x - last.center.x, center.y - last.center.y) > threshold);
lastRef.current = {
center,
el: activeTrigger
};
setRepop(far);
if (far && popupElement && !prefersReducedMotion()) popupElement.animate?.(...REPOP_ANIMATION);
}, [
activeTrigger,
enabled,
open,
popupElement,
threshold
]);
return repop;
};
//#endregion
export { useRepopOnFarTriggerSwitch };
//# sourceMappingURL=useRepopOnFarTriggerSwitch.mjs.map