@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.
156 lines (155 loc) • 5.63 kB
JavaScript
;
'use client';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useMenuRoot = useMenuRoot;
var React = _interopRequireWildcard(require("react"));
var _react2 = require("@floating-ui/react");
var _mergeReactProps = require("../../utils/mergeReactProps");
var _useTransitionStatus = require("../../utils/useTransitionStatus");
var _useEventCallback = require("../../utils/useEventCallback");
var _useControlled = require("../../utils/useControlled");
var _constants = require("../../utils/constants");
var _useAfterExitAnimation = require("../../utils/useAfterExitAnimation");
var _useScrollLock = require("../../utils/useScrollLock");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const EMPTY_ARRAY = [];
function useMenuRoot(parameters) {
const {
open: openParam,
defaultOpen,
onOpenChange,
orientation,
direction,
disabled,
nested,
closeParentOnEsc,
loop,
delay,
openOnHover,
onTypingChange,
modal
} = parameters;
const [triggerElement, setTriggerElement] = React.useState(null);
const [positionerElement, setPositionerElementUnwrapped] = React.useState(null);
const popupRef = React.useRef(null);
const positionerRef = React.useRef(null);
const [hoverEnabled, setHoverEnabled] = React.useState(true);
const [activeIndex, setActiveIndex] = React.useState(null);
const [open, setOpenUnwrapped] = (0, _useControlled.useControlled)({
controlled: openParam,
default: defaultOpen,
name: 'useMenuRoot',
state: 'open'
});
const setPositionerElement = React.useCallback(value => {
positionerRef.current = value;
setPositionerElementUnwrapped(value);
}, []);
const allowMouseUpTriggerRef = React.useRef(false);
(0, _useScrollLock.useScrollLock)(modal && open, triggerElement);
const {
mounted,
setMounted,
transitionStatus
} = (0, _useTransitionStatus.useTransitionStatus)(open);
const setOpen = (0, _useEventCallback.useEventCallback)((nextOpen, event) => {
onOpenChange?.(nextOpen, event);
setOpenUnwrapped(nextOpen);
});
(0, _useAfterExitAnimation.useAfterExitAnimation)({
open,
animatedElementRef: popupRef,
onFinished: () => setMounted(false)
});
const floatingRootContext = (0, _react2.useFloatingRootContext)({
elements: {
reference: triggerElement,
floating: positionerElement
},
open,
onOpenChange: setOpen
});
const hover = (0, _react2.useHover)(floatingRootContext, {
enabled: hoverEnabled && openOnHover && !disabled,
handleClose: (0, _react2.safePolygon)({
blockPointerEvents: true
}),
mouseOnly: true,
delay: {
open: delay
}
});
const click = (0, _react2.useClick)(floatingRootContext, {
enabled: !disabled,
event: 'mousedown',
toggle: !nested,
ignoreMouse: nested
});
const dismiss = (0, _react2.useDismiss)(floatingRootContext, {
bubbles: closeParentOnEsc && nested,
outsidePressEvent: 'mousedown'
});
const role = (0, _react2.useRole)(floatingRootContext, {
role: 'menu'
});
const itemDomElements = React.useRef([]);
const itemLabels = React.useRef([]);
const listNavigation = (0, _react2.useListNavigation)(floatingRootContext, {
enabled: !disabled,
listRef: itemDomElements,
activeIndex,
nested,
loop,
orientation,
rtl: direction === 'rtl',
disabledIndices: EMPTY_ARRAY,
onNavigate: setActiveIndex
});
const typeahead = (0, _react2.useTypeahead)(floatingRootContext, {
listRef: itemLabels,
activeIndex,
resetMs: _constants.TYPEAHEAD_RESET_MS,
onMatch: index => {
if (open && index !== activeIndex) {
setActiveIndex(index);
}
},
onTypingChange
});
const {
getReferenceProps,
getFloatingProps,
getItemProps
} = (0, _react2.useInteractions)([hover, click, dismiss, role, listNavigation, typeahead]);
const getTriggerProps = React.useCallback(externalProps => getReferenceProps((0, _mergeReactProps.mergeReactProps)(externalProps, {
onMouseEnter: () => {
setHoverEnabled(true);
}
})), [getReferenceProps]);
const getPopupProps = React.useCallback(externalProps => getFloatingProps((0, _mergeReactProps.mergeReactProps)(externalProps, {
onMouseEnter: () => {
setHoverEnabled(false);
}
})), [getFloatingProps]);
return React.useMemo(() => ({
activeIndex,
allowMouseUpTriggerRef,
floatingRootContext,
getItemProps,
getPopupProps,
getTriggerProps,
itemDomElements,
itemLabels,
mounted,
open,
popupRef,
positionerRef,
setOpen,
setPositionerElement,
setTriggerElement,
transitionStatus
}), [activeIndex, floatingRootContext, getItemProps, getPopupProps, getTriggerProps, itemDomElements, itemLabels, mounted, open, positionerRef, setOpen, transitionStatus, setPositionerElement]);
}