( props: AriaSubmenuTriggerProps, state: SubmenuTriggerState, ref: RefObject<FocusableElement | null> )
| 92 | * @param ref - Ref to the submenu trigger element. |
| 93 | */ |
| 94 | export function useSubmenuTrigger<T>( |
| 95 | props: AriaSubmenuTriggerProps, |
| 96 | state: SubmenuTriggerState, |
| 97 | ref: RefObject<FocusableElement | null> |
| 98 | ): SubmenuTriggerAria<T> { |
| 99 | let { |
| 100 | parentMenuRef, |
| 101 | submenuRef, |
| 102 | type = 'menu', |
| 103 | isDisabled, |
| 104 | delay = 200, |
| 105 | shouldUseVirtualFocus |
| 106 | } = props; |
| 107 | let submenuTriggerId = useId(); |
| 108 | let overlayId = useId(); |
| 109 | let {direction} = useLocale(); |
| 110 | let openTimeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined); |
| 111 | let cancelOpenTimeout = useCallback(() => { |
| 112 | if (openTimeout.current) { |
| 113 | clearTimeout(openTimeout.current); |
| 114 | openTimeout.current = undefined; |
| 115 | } |
| 116 | }, [openTimeout]); |
| 117 | |
| 118 | let onSubmenuOpen = useCallback( |
| 119 | (focusStrategy?: FocusStrategy) => { |
| 120 | cancelOpenTimeout(); |
| 121 | state.open(focusStrategy); |
| 122 | }, |
| 123 | [state, cancelOpenTimeout] |
| 124 | ); |
| 125 | |
| 126 | let onSubmenuClose = useCallback(() => { |
| 127 | cancelOpenTimeout(); |
| 128 | state.close(); |
| 129 | }, [state, cancelOpenTimeout]); |
| 130 | |
| 131 | useLayoutEffect(() => { |
| 132 | return () => { |
| 133 | cancelOpenTimeout(); |
| 134 | }; |
| 135 | }, [cancelOpenTimeout]); |
| 136 | |
| 137 | let submenuKeyDown = (e: KeyboardEvent) => { |
| 138 | // If focus is not within the menu, assume virtual focus is being used. |
| 139 | // This means some other input element is also within the popover, so we shouldn't close the menu. |
| 140 | if (!isFocusWithin(e.currentTarget)) { |
| 141 | return; |
| 142 | } |
| 143 | |
| 144 | switch (e.key) { |
| 145 | case 'ArrowLeft': |
| 146 | if (direction === 'ltr' && nodeContains(e.currentTarget, getEventTarget(e) as Element)) { |
| 147 | e.preventDefault(); |
| 148 | e.stopPropagation(); |
| 149 | onSubmenuClose(); |
| 150 | if (!shouldUseVirtualFocus && ref.current) { |
| 151 | focusWithoutScrolling(ref.current); |
no test coverage detected