-
Notifications
You must be signed in to change notification settings - Fork 15
/
useModal.ts
110 lines (98 loc) · 3.14 KB
/
useModal.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/
import { useState } from 'react';
import { useUIDSeed } from 'react-uid';
import { composeEventHandlers, KEY_CODES } from '@zendeskgarden/container-utilities';
import { useFocusJail } from '@zendeskgarden/container-focusjail';
export interface IUseModalProps {
onClose?: (event: KeyboardEvent | MouseEvent) => void;
modalRef: React.RefObject<HTMLElement>;
id?: string;
focusOnMount?: boolean;
environment?: Document;
}
export interface IUseModalReturnValue {
getBackdropProps: <T>(options?: T) => T & React.HTMLProps<any>;
getModalProps: <T>(options?: T) => T & React.HTMLProps<any>;
getTitleProps: <T>(options?: T) => T & React.HTMLProps<any>;
getContentProps: <T>(options?: T) => T & React.HTMLProps<any>;
getCloseProps: <T>(options?: T) => T & React.HTMLProps<any>;
closeModal?: (event: any) => void;
}
export function useModal(
{ onClose, modalRef, id: _id, focusOnMount, environment }: IUseModalProps = {} as any
): IUseModalReturnValue {
const seed = useUIDSeed();
const [idPrefix] = useState(_id || seed(`modal_${PACKAGE_VERSION}`));
const titleId = `${idPrefix}--title`;
const contentId = `${idPrefix}--content`;
const closeModal = (event: KeyboardEvent | MouseEvent) => {
onClose && onClose(event);
};
const getBackdropProps = ({ onClick, ...other } = {} as any) => {
return {
onClick: composeEventHandlers(onClick, (event: MouseEvent) => {
closeModal(event);
}),
'data-garden-container-id': 'containers.modal',
'data-garden-container-version': PACKAGE_VERSION,
...other
};
};
const getModalProps = ({ role = 'dialog', onClick, onKeyDown, ...other } = {} as any) => {
return {
role,
tabIndex: -1,
'aria-modal': true,
'aria-labelledby': titleId,
'aria-describedby': contentId,
onClick: composeEventHandlers(onClick, (event: MouseEvent) => {
/**
* Don't want to trigger the backdrop close event
* if click originates within the Modal
*/
event.stopPropagation();
}),
onKeyDown: composeEventHandlers(onKeyDown, (event: KeyboardEvent) => {
if (event.keyCode === KEY_CODES.ESCAPE) {
closeModal(event);
}
}),
...other
};
};
const getTitleProps = ({ id = titleId, ...other } = {} as any) => {
return {
id,
...other
};
};
const getContentProps = ({ id = contentId, ...other } = {} as any) => {
return {
id,
...other
};
};
const getCloseProps = ({ onClick, ...other } = {} as any) => {
return {
'aria-label': 'Close modal',
onClick: composeEventHandlers(onClick, (event: MouseEvent) => {
closeModal(event);
}),
...other
};
};
const { getContainerProps } = useFocusJail({ containerRef: modalRef, focusOnMount, environment });
return {
getBackdropProps,
getModalProps: props => getContainerProps(getModalProps(props)),
getTitleProps,
getContentProps,
getCloseProps,
closeModal
};
}