-
Notifications
You must be signed in to change notification settings - Fork 11.7k
/
TimePickerCalendar.tsx
122 lines (111 loc) · 3.47 KB
/
TimePickerCalendar.tsx
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
import { css } from '@emotion/css';
import { useDialog } from '@react-aria/dialog';
import { FocusScope } from '@react-aria/focus';
import { OverlayContainer, useOverlay } from '@react-aria/overlays';
import React, { FormEvent, memo } from 'react';
import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useTheme2 } from '../../../themes';
import { getModalStyles } from '../../Modal/getModalStyles';
import { Body } from './CalendarBody';
import { Footer } from './CalendarFooter';
import { Header } from './CalendarHeader';
export const getStyles = (theme: GrafanaTheme2, isReversed = false) => {
return {
container: css`
top: 0px;
position: absolute;
${isReversed ? 'left' : 'right'}: 544px;
box-shadow: ${theme.shadows.z3};
background-color: ${theme.colors.background.primary};
z-index: -1;
border: 1px solid ${theme.colors.border.weak};
border-radius: 2px 0 0 2px;
&:after {
display: block;
background-color: ${theme.colors.background.primary};
width: 19px;
height: 100%;
content: ${!isReversed ? ' ' : ''};
position: absolute;
top: 0;
right: -19px;
border-left: 1px solid ${theme.colors.border.weak};
}
`,
modal: css`
box-shadow: ${theme.shadows.z3};
left: 50%;
position: fixed;
top: 50%;
transform: translate(-50%, -50%);
z-index: ${theme.zIndex.modal};
`,
content: css`
margin: 0 auto;
width: 268px;
`,
};
};
export interface TimePickerCalendarProps {
isOpen: boolean;
from: DateTime;
to: DateTime;
onClose: () => void;
onApply: (e: FormEvent<HTMLButtonElement>) => void;
onChange: (from: DateTime, to: DateTime) => void;
isFullscreen: boolean;
timeZone?: TimeZone;
isReversed?: boolean;
}
const stopPropagation = (event: React.MouseEvent<HTMLDivElement>) => event.stopPropagation();
function TimePickerCalendar(props: TimePickerCalendarProps) {
const theme = useTheme2();
const { modalBackdrop } = getModalStyles(theme);
const styles = getStyles(theme, props.isReversed);
const { isOpen, isFullscreen, onClose } = props;
const ref = React.createRef<HTMLElement>();
const { dialogProps } = useDialog(
{
'aria-label': selectors.components.TimePicker.calendar.label,
},
ref
);
const { overlayProps } = useOverlay(
{
isDismissable: true,
isOpen,
onClose,
},
ref
);
if (!isOpen) {
return null;
}
if (isFullscreen) {
return (
<FocusScope contain restoreFocus autoFocus>
<section className={styles.container} onClick={stopPropagation} ref={ref} {...overlayProps} {...dialogProps}>
<Header {...props} />
<Body {...props} />
</section>
</FocusScope>
);
}
return (
<OverlayContainer>
<div className={modalBackdrop} onClick={stopPropagation} />
<FocusScope contain autoFocus restoreFocus>
<section className={styles.modal} onClick={stopPropagation} ref={ref} {...overlayProps} {...dialogProps}>
<div className={styles.content} aria-label={selectors.components.TimePicker.calendar.label}>
<Header {...props} />
<Body {...props} />
<Footer {...props} />
</div>
</section>
</FocusScope>
</OverlayContainer>
);
}
export default memo(TimePickerCalendar);
TimePickerCalendar.displayName = 'TimePickerCalendar';