@blocknote/react
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
48 lines (42 loc) • 1.76 kB
text/typescript
import { useRef } from "react";
// This hook is used to stop Mantine Menu.Dropdown components from extending
// beyond the viewport. It does this by dynamically setting the max height of
// the dropdown. To use it, set the ref on a Menu.Dropdown's parent div, and
// call updateMaxHeight() in the Menu's `onOpen` listener. Unfortunately, this
// may mean you have to create an additional parent div, but you cannot set the
// ref on the Menu or Menu.Dropdown components directly so this is a necessary
// workaround.
export function usePreventMenuOverflow() {
const ref = useRef<HTMLDivElement>(null);
return {
ref: ref,
updateMaxHeight: () => {
// Seems a small delay is necessary to get the correct DOM rect - likely
// because the menu is not yet fully rendered when the `onOpen` event is
// fired.
setTimeout(() => {
if (!ref.current) {
return;
}
if (ref.current.childElementCount > 0) {
// Reset any previously set max-height
(ref.current.firstElementChild as HTMLDivElement).style.maxHeight =
"none";
// Get the menu DOM rect
const domRect =
ref.current.firstElementChild!.getBoundingClientRect();
// Set the menu max height, based on the element position. Checking if
// the top of the menu is above the viewport (position < 0) is a quick
// way to check if the placement is "top" or "bottom".
(
ref.current.firstElementChild as HTMLDivElement
).style.maxHeight = `${Math.min(
domRect.top >= 0
? window.innerHeight - domRect.top - 20
: domRect.bottom - 20
)}px`;
}
}, 10);
},
};
}