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.

121 lines (119 loc) 4.15 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.NavigationMenuContent = void 0; var React = _interopRequireWildcard(require("react")); var ReactDOM = _interopRequireWildcard(require("react-dom")); var _inertValue = require("@base-ui-components/utils/inertValue"); var _floatingUiReact = require("../../floating-ui-react"); var _utils = require("../../floating-ui-react/utils"); var _NavigationMenuRootContext = require("../root/NavigationMenuRootContext"); var _NavigationMenuItemContext = require("../item/NavigationMenuItemContext"); var _useTransitionStatus = require("../../utils/useTransitionStatus"); var _useOpenChangeComplete = require("../../utils/useOpenChangeComplete"); var _stateAttributesMapping = require("../../utils/stateAttributesMapping"); var _CompositeRoot = require("../../composite/root/CompositeRoot"); var _popupStateMapping = require("../../utils/popupStateMapping"); var _jsxRuntime = require("react/jsx-runtime"); const stateAttributesMapping = { ..._popupStateMapping.popupStateMapping, ..._stateAttributesMapping.transitionStatusMapping, activationDirection(value) { if (!value) { return null; } return { 'data-activation-direction': value }; } }; /** * A container for the content of the navigation menu item that is moved into the popup * when the item is active. * Renders a `<div>` element. * * Documentation: [Base UI Navigation Menu](https://base-ui.com/react/components/navigation-menu) */ const NavigationMenuContent = exports.NavigationMenuContent = /*#__PURE__*/React.forwardRef(function NavigationMenuContent(componentProps, forwardedRef) { const { className, render, ...elementProps } = componentProps; const { mounted: popupMounted, viewportElement, value, activationDirection, currentContentRef, viewportTargetElement } = (0, _NavigationMenuRootContext.useNavigationMenuRootContext)(); const itemValue = (0, _NavigationMenuItemContext.useNavigationMenuItemContext)(); const nodeId = (0, _NavigationMenuRootContext.useNavigationMenuTreeContext)(); const open = popupMounted && value === itemValue; const ref = React.useRef(null); const [focusInside, setFocusInside] = React.useState(false); const { mounted, setMounted, transitionStatus } = (0, _useTransitionStatus.useTransitionStatus)(open); (0, _useOpenChangeComplete.useOpenChangeComplete)({ ref, open, onComplete() { if (!open) { setMounted(false); } } }); const state = React.useMemo(() => ({ open, transitionStatus, activationDirection }), [open, transitionStatus, activationDirection]); const handleCurrentContentRef = React.useCallback(node => { if (node) { currentContentRef.current = node; } }, [currentContentRef]); const commonProps = { onFocus() { setFocusInside(true); }, onBlur(event) { if (!(0, _utils.contains)(event.currentTarget, event.relatedTarget)) { setFocusInside(false); } } }; const defaultProps = !open && mounted ? { style: { position: 'absolute', top: 0, left: 0 }, inert: (0, _inertValue.inertValue)(!focusInside), ...commonProps } : commonProps; const portalContainer = viewportTargetElement || viewportElement; const shouldRender = portalContainer !== null && mounted; if (!portalContainer || !shouldRender) { return null; } return /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingUiReact.FloatingNode, { id: nodeId, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CompositeRoot.CompositeRoot, { render: render, className: className, state: state, refs: [forwardedRef, ref, handleCurrentContentRef], props: [defaultProps, elementProps], stateAttributesMapping: stateAttributesMapping }) }), portalContainer); }); if (process.env.NODE_ENV !== "production") NavigationMenuContent.displayName = "NavigationMenuContent";