11import type { ComputedRef } from 'vue-demi'
2- import { computed } from 'vue-demi'
2+ import { computed , ref } from 'vue-demi'
33import type { MaybeElementRef } from '../unrefElement'
44import { unrefElement } from '../unrefElement'
55import { useActiveElement } from '../useActiveElement'
66import type { ConfigurableWindow } from '../_configurable'
7+ import { defaultWindow } from '../_configurable'
8+ import { useEventListener } from '../useEventListener'
79
810export interface UseFocusWithinReturn {
911 /**
@@ -12,6 +14,9 @@ export interface UseFocusWithinReturn {
1214 focused : ComputedRef < boolean >
1315}
1416
17+ const EVENT_FOCUS_IN = 'focusin'
18+ const EVENT_FOCUS_OUT = 'focusout'
19+
1520/**
1621 * Track if focus is contained within the target element
1722 *
@@ -20,9 +25,18 @@ export interface UseFocusWithinReturn {
2025 * @param options Focus within options
2126 */
2227export function useFocusWithin ( target : MaybeElementRef , options : ConfigurableWindow = { } ) : UseFocusWithinReturn {
23- const activeElement = useActiveElement ( options )
28+ const { window = defaultWindow } = options
2429 const targetElement = computed ( ( ) => unrefElement ( target ) )
25- const focused = computed ( ( ) => ( targetElement . value && activeElement . value ) ? targetElement . value . contains ( activeElement . value ) : false )
30+ const _focused = ref ( false )
31+ const focused = computed ( ( ) => _focused . value )
32+ const activeElement = useActiveElement ( options )
33+
34+ if ( ! window || ! activeElement . value ) {
35+ return { focused }
36+ }
37+
38+ useEventListener ( targetElement , EVENT_FOCUS_IN , ( ) => _focused . value = true )
39+ useEventListener ( targetElement , EVENT_FOCUS_OUT , ( ) => _focused . value = false )
2640
2741 return { focused }
2842}
0 commit comments