added hook for handle flip side
This commit is contained in:
parent
3569bdc8d3
commit
9e29510711
@ -1,4 +1,4 @@
|
|||||||
import { useState, useMemo, useCallback, useEffect } from "react";
|
import { useState, useMemo, useCallback, useEffect,useLayoutEffect } from "react";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
options:
|
options:
|
||||||
@ -239,3 +239,75 @@ export function useGridCore({
|
|||||||
serverMode,
|
serverMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function useDropdownPosition(btnRef, menuRef, isOpen, level = 0) {
|
||||||
|
const [style, setStyle] = useState({});
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!isOpen || !btnRef.current || !menuRef.current) return;
|
||||||
|
|
||||||
|
const updatePosition = () => {
|
||||||
|
const btn = btnRef.current.getBoundingClientRect();
|
||||||
|
const menu = menuRef.current;
|
||||||
|
|
||||||
|
const menuHeight = menu.offsetHeight;
|
||||||
|
const menuWidth = menu.offsetWidth;
|
||||||
|
|
||||||
|
const vh = window.innerHeight;
|
||||||
|
const vw = window.innerWidth;
|
||||||
|
|
||||||
|
const spaceBelow = vh - btn.bottom;
|
||||||
|
const spaceAbove = btn.top;
|
||||||
|
|
||||||
|
// ------------ AUTO FLIP (top/bottom) ------------
|
||||||
|
const openUp = menuHeight > spaceBelow && spaceAbove > spaceBelow;
|
||||||
|
let top = openUp ? btn.top - menuHeight : btn.bottom;
|
||||||
|
|
||||||
|
if (top < 8) top = 8;
|
||||||
|
if (top + menuHeight > vh - 8) top = vh - menuHeight - 8;
|
||||||
|
|
||||||
|
// ------------ AUTO FLIP (left/right) ------------
|
||||||
|
let left = btn.left;
|
||||||
|
|
||||||
|
if (level === 0) {
|
||||||
|
// Main menu
|
||||||
|
if (left + menuWidth > vw - 8) left = vw - menuWidth - 8;
|
||||||
|
} else {
|
||||||
|
// Nested menu opens to right
|
||||||
|
left = btn.right;
|
||||||
|
if (left + menuWidth > vw - 8) {
|
||||||
|
left = btn.left - menuWidth; // flip to left if overflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle({
|
||||||
|
position: "fixed",
|
||||||
|
top,
|
||||||
|
left,
|
||||||
|
zIndex: 99999,
|
||||||
|
maxHeight: vh - 16,
|
||||||
|
overflowY: "auto",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// RUN AFTER MENU RENDERS
|
||||||
|
requestAnimationFrame(updatePosition);
|
||||||
|
|
||||||
|
// RUN AGAIN after potential layout changes
|
||||||
|
setTimeout(updatePosition, 50);
|
||||||
|
|
||||||
|
window.addEventListener("resize", updatePosition);
|
||||||
|
return () => window.removeEventListener("resize", updatePosition);
|
||||||
|
}, [isOpen, level]);
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user