-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathSelectionOverlay.js
127 lines (117 loc) · 3.19 KB
/
SelectionOverlay.js
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import Portal from 'react-overlays/Portal';
import SelectionList from './SelectionList';
import Popper, { OVERLAY_MODIFIERS } from '../Popper';
import css from './Selection.css';
const SelectionOverlay = ({
controlRef,
listContainerRef,
getMenuProps,
id,
isOpen,
listMaxHeight,
onChangeFilterValue,
optionAlignment,
popper,
renderFilterInput,
renderOptions,
usePortal,
width,
...props
}) => {
const filterRef = useRef(null);
const getPortalElement = useRef(() => document.getElementById('OverlayContainer')).current;
useEffect(() => {
// if the overlay is open and focus is outside of it, move focus to the filter.
if (
isOpen &&
listContainerRef.current?.matches(':not(:focus-within)')
) {
filterRef.current?.focus();
}
// if overlay is closing and focus is within the overlay, move focus to the Selection control.
if (!isOpen &&
listContainerRef.current?.matches(':focus-within')
) {
onChangeFilterValue('');
controlRef.current?.focus();
}
}, [isOpen, onChangeFilterValue, controlRef, listContainerRef]);
const atSmallMedia = window.matchMedia('(max-width: 640px)').matches;
const selectList = (
<SelectionList
renderOptions={renderOptions}
listMaxHeight={listMaxHeight}
optionAlignment={optionAlignment}
getMenuProps={getMenuProps}
isOpen={isOpen}
{...props}
/>
);
if (atSmallMedia) {
return (
<div>
{isOpen &&
<Portal container={getPortalElement()}>
<div
role="presentation"
className={css.selectionMobileBackdrop}
onClick={() => { controlRef.current?.focus() }}
>
<div
className={css.selectionListRoot}
style={{ width: '85vw' }}
id={`sl-container-${id}`}
ref={listContainerRef}
>
{renderFilterInput(filterRef)}
{isOpen && selectList}
</div>
</div>
</Portal>
}
</div>
);
}
const popperProps = {
portal: (isOpen && usePortal) ? getPortalElement() : undefined,
modifiers: OVERLAY_MODIFIERS,
...popper
}
return (
<Popper
isOpen={isOpen}
anchorRef={controlRef}
hideIfClosed
{...popperProps}
>
<div
className={css.selectionListRoot}
style={{ width }}
id={`sl-container-${id}`}
ref={listContainerRef}
>
{renderFilterInput(filterRef)}
{selectList}
</div>
</Popper>
);
};
SelectionOverlay.propTypes = {
controlRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
emptyMessage: PropTypes.node,
getMenuProps: PropTypes.func,
id: PropTypes.string,
isOpen: PropTypes.bool,
listContainerRef: PropTypes.object,
listMaxHeight: PropTypes.string,
onChangeFilterValue: PropTypes.func,
optionAlignment: PropTypes.string,
popper: PropTypes.object,
renderFilterInput: PropTypes.func,
renderOptions: PropTypes.func,
usePortal: PropTypes.bool,
width: PropTypes.number,
}
export default SelectionOverlay;