'use client'; import * as React from 'react'; import { useMergedRefs, slot } from '@fluentui/react-utilities'; import { useModalAttributes } from '@fluentui/react-tabster'; import { usePopoverContext_unstable } from '../../popoverContext'; import { useMotionForwardedRef } from '@fluentui/react-motion'; /** * Create the state required to render PopoverSurface. * * The returned state can be modified with hooks such as usePopoverSurfaceStyles_unstable, * before being passed to renderPopoverSurface_unstable. * * @param props - props from this instance of PopoverSurface * @param ref - reference to root HTMLDivElement of PopoverSurface */ export const usePopoverSurface_unstable = (props, ref)=>{ const size = usePopoverContext_unstable((context)=>context.size); const appearance = usePopoverContext_unstable((context)=>context.appearance); const motionForwardedRef = useMotionForwardedRef(); const state = usePopoverSurfaceBase_unstable(props, useMergedRefs(ref, motionForwardedRef)); return { appearance, size, ...state }; }; /** * Base hook that builds PopoverSurface state for behavior and structure only. * * @internal * @param props - User provided props to the PopoverSurface component. * @param ref - User provided ref to be passed to the PopoverSurface component. */ export const usePopoverSurfaceBase_unstable = (props, ref)=>{ const contentRef = usePopoverContext_unstable((context)=>context.contentRef); const openOnHover = usePopoverContext_unstable((context)=>context.openOnHover); const setOpen = usePopoverContext_unstable((context)=>context.setOpen); const mountNode = usePopoverContext_unstable((context)=>context.mountNode); const arrowRef = usePopoverContext_unstable((context)=>context.arrowRef); const withArrow = usePopoverContext_unstable((context)=>context.withArrow); const trapFocus = usePopoverContext_unstable((context)=>context.trapFocus); const inertTrapFocus = usePopoverContext_unstable((context)=>context.inertTrapFocus); const inline = usePopoverContext_unstable((context)=>context.inline); const { modalAttributes } = useModalAttributes({ trapFocus, legacyTrapFocus: !inertTrapFocus, alwaysFocusable: !trapFocus }); const state = { inline, withArrow, arrowRef, mountNode, components: { root: 'div' }, root: slot.always({ ref: useMergedRefs(ref, contentRef), role: trapFocus ? 'dialog' : 'group', 'aria-modal': trapFocus ? true : undefined, ...modalAttributes, ...props }, { elementType: 'div' }) }; const { onMouseEnter: onMouseEnterOriginal, onMouseLeave: onMouseLeaveOriginal, onKeyDown: onKeyDownOriginal } = state.root; state.root.onMouseEnter = (e)=>{ if (openOnHover) { setOpen(e, true); } onMouseEnterOriginal === null || onMouseEnterOriginal === void 0 ? void 0 : onMouseEnterOriginal(e); }; state.root.onMouseLeave = (e)=>{ if (openOnHover) { setOpen(e, false); } onMouseLeaveOriginal === null || onMouseLeaveOriginal === void 0 ? void 0 : onMouseLeaveOriginal(e); }; state.root.onKeyDown = (e)=>{ var _contentRef_current; // only close if the event happened inside the current popover // If using a stack of inline popovers, the user should call `stopPropagation` to avoid dismissing the entire stack if (e.key === 'Escape' && ((_contentRef_current = contentRef.current) === null || _contentRef_current === void 0 ? void 0 : _contentRef_current.contains(e.target))) { e.preventDefault(); setOpen(e, false); } onKeyDownOriginal === null || onKeyDownOriginal === void 0 ? void 0 : onKeyDownOriginal(e); }; return state; };