UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

72 lines (71 loc) 1.93 kB
'use client'; import * as React from 'react'; import { mergeReactProps } from '../../utils/mergeReactProps.js'; import { useAnchorPositioning } from '../../utils/useAnchorPositioning.js'; import { useMenuRootContext } from '../root/MenuRootContext.js'; export function useMenuPositioner(params) { const { keepMounted, mounted, menuEvents, nodeId, parentNodeId, setOpen } = params; const { open } = useMenuRootContext(); const { positionerStyles, arrowStyles, anchorHidden, arrowRef, arrowUncentered, renderedSide, renderedAlign, positionerContext: floatingContext } = useAnchorPositioning(params); const getPositionerProps = React.useCallback((externalProps = {}) => { const hiddenStyles = {}; if (keepMounted && !open) { hiddenStyles.pointerEvents = 'none'; } return mergeReactProps(externalProps, { role: 'presentation', hidden: !mounted, style: { ...positionerStyles, ...hiddenStyles } }); }, [keepMounted, open, positionerStyles, mounted]); React.useEffect(() => { function onMenuOpened(event) { if (event.nodeId !== nodeId && event.parentNodeId === parentNodeId) { setOpen(false); } } menuEvents.on('opened', onMenuOpened); return () => { menuEvents.off('opened', onMenuOpened); }; }, [menuEvents, nodeId, parentNodeId, setOpen]); React.useEffect(() => { if (open) { menuEvents.emit('opened', { nodeId, parentNodeId }); } }, [menuEvents, open, nodeId, parentNodeId]); return React.useMemo(() => ({ getPositionerProps, arrowRef, arrowUncentered, arrowStyles, side: renderedSide, align: renderedAlign, floatingContext, anchorHidden }), [getPositionerProps, arrowRef, arrowUncentered, arrowStyles, renderedSide, renderedAlign, floatingContext, anchorHidden]); }