1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | import {DOMAttributes, FocusableElement, FocusEvents} from '@react-types/shared';
|
19 | import {FocusEvent, useCallback} from 'react';
|
20 | import {getOwnerDocument} from '@react-aria/utils';
|
21 | import {useSyntheticBlurEvent} from './utils';
|
22 |
|
23 | export interface FocusProps<Target = FocusableElement> extends FocusEvents<Target> {
|
24 |
|
25 | isDisabled?: boolean
|
26 | }
|
27 |
|
28 | export interface FocusResult<Target = FocusableElement> {
|
29 |
|
30 | focusProps: DOMAttributes<Target>
|
31 | }
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | export function useFocus<Target extends FocusableElement = FocusableElement>(props: FocusProps<Target>): FocusResult<Target> {
|
38 | let {
|
39 | isDisabled,
|
40 | onFocus: onFocusProp,
|
41 | onBlur: onBlurProp,
|
42 | onFocusChange
|
43 | } = props;
|
44 |
|
45 | const onBlur: FocusProps<Target>['onBlur'] = useCallback((e: FocusEvent<Target>) => {
|
46 | if (e.target === e.currentTarget) {
|
47 | if (onBlurProp) {
|
48 | onBlurProp(e);
|
49 | }
|
50 |
|
51 | if (onFocusChange) {
|
52 | onFocusChange(false);
|
53 | }
|
54 |
|
55 | return true;
|
56 | }
|
57 | }, [onBlurProp, onFocusChange]);
|
58 |
|
59 |
|
60 | const onSyntheticFocus = useSyntheticBlurEvent<Target>(onBlur);
|
61 |
|
62 | const onFocus: FocusProps<Target>['onFocus'] = useCallback((e: FocusEvent<Target>) => {
|
63 |
|
64 |
|
65 |
|
66 | const ownerDocument = getOwnerDocument(e.target);
|
67 |
|
68 | if (e.target === e.currentTarget && ownerDocument.activeElement === e.target) {
|
69 | if (onFocusProp) {
|
70 | onFocusProp(e);
|
71 | }
|
72 |
|
73 | if (onFocusChange) {
|
74 | onFocusChange(true);
|
75 | }
|
76 |
|
77 | onSyntheticFocus(e);
|
78 | }
|
79 | }, [onFocusChange, onFocusProp, onSyntheticFocus]);
|
80 |
|
81 | return {
|
82 | focusProps: {
|
83 | onFocus: (!isDisabled && (onFocusProp || onFocusChange || onBlurProp)) ? onFocus : undefined,
|
84 | onBlur: (!isDisabled && (onBlurProp || onFocusChange)) ? onBlur : undefined
|
85 | }
|
86 | };
|
87 | }
|