@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
76 lines (73 loc) • 2.13 kB
JavaScript
"use client";
import { jsx } from 'react/jsx-runtime';
import { useControlledState, useDebounce, useUnmount } from '@nex-ui/hooks';
import { useRef, useId, useCallback, useMemo, useEffect } from 'react';
import { PopperProvider } from './PopperContext.mjs';
import { PopperManager } from './PopperManager.mjs';
const popperManager = new PopperManager();
const Popper = (props)=>{
const { children, onOpenChange, open: openProp, openDelay = 100, closeDelay = 100, defaultOpen = false } = props;
const referenceRef = useRef(null);
const popperRootRef = useRef(null);
const id = useId();
const [open, setOpen] = useControlledState(openProp, defaultOpen, onOpenChange);
const debouncedOpenPopper = useDebounce(()=>{
if (!open) setOpen(true);
}, {
wait: openDelay
});
const debouncedClosePopper = useDebounce(()=>{
if (open) setOpen(false);
}, {
wait: closeDelay
});
const handleOpen = useCallback(()=>{
debouncedClosePopper.cancel();
debouncedOpenPopper();
popperManager.flush(id);
}, [
debouncedClosePopper,
debouncedOpenPopper,
id
]);
const handleClose = useCallback(()=>{
debouncedOpenPopper.cancel();
debouncedClosePopper();
}, [
debouncedClosePopper,
debouncedOpenPopper
]);
useUnmount(()=>{
debouncedClosePopper.cancel();
debouncedOpenPopper.cancel();
});
const ctx = useMemo(()=>({
open,
setOpen,
referenceRef,
popperRootRef,
handleOpen,
handleClose
}), [
handleClose,
handleOpen,
open,
setOpen
]);
useEffect(()=>{
if (open) {
popperManager.register(id, debouncedClosePopper.flush);
return ()=>popperManager.unregister(id);
}
}, [
debouncedClosePopper.flush,
id,
open
]);
return /*#__PURE__*/ jsx(PopperProvider, {
value: ctx,
children: children
});
};
Popper.displayName = 'Popper';
export { Popper };