-
Notifications
You must be signed in to change notification settings - Fork 331
/
Copy pathdrawer.tsx
92 lines (82 loc) · 2.32 KB
/
drawer.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
import React, { MouseEvent, useEffect, useState } from 'react'
import { withScale } from '../use-scale'
import usePortal from '../utils/use-portal'
import useBodyScroll from '../utils/use-body-scroll'
import useKeyboard, { KeyCode } from '../use-keyboard'
import { createPortal } from 'react-dom'
import Backdrop from '../shared/backdrop'
import { DrawerPlacement } from './helper'
import DrawerWrapper from './drawer-wrapper'
interface Props {
visible?: boolean
keyboard?: boolean
disableBackdropClick?: boolean
onClose?: () => void
onContentClick?: (event: MouseEvent<HTMLElement>) => void
wrapClassName?: string
placement?: DrawerPlacement
}
const defaultProps = {
wrapClassName: '',
keyboard: true,
disableBackdropClick: false,
placement: 'right' as DrawerPlacement,
}
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
export type DrawerProps = Props & NativeAttrs
const DrawerComponent: React.FC<React.PropsWithChildren<DrawerProps>> = ({
visible: customVisible,
keyboard,
disableBackdropClick,
onClose,
onContentClick,
wrapClassName,
children,
...props
}: React.PropsWithChildren<DrawerProps> & typeof defaultProps) => {
const portal = usePortal('drawer')
const [visible, setVisible] = useState<boolean>(false)
const [, setBodyHidden] = useBodyScroll(null, { delayReset: 300 })
const closeDrawer = () => {
onClose && onClose()
setVisible(false)
setBodyHidden(false)
}
useEffect(() => {
if (typeof customVisible === 'undefined') return
setVisible(customVisible)
setBodyHidden(customVisible)
}, [customVisible])
const { bindings } = useKeyboard(
() => {
keyboard && closeDrawer()
},
KeyCode.Escape,
{
disableGlobalEvent: true,
},
)
const closeFromBackdrop = () => {
if (disableBackdropClick) return
closeDrawer()
}
if (!portal) return null
return createPortal(
<Backdrop
onClick={closeFromBackdrop}
onContentClick={onContentClick}
visible={visible}
width="100%"
{...bindings}
>
<DrawerWrapper visible={visible} className={wrapClassName} {...props}>
{children}
</DrawerWrapper>
</Backdrop>,
portal,
)
}
DrawerComponent.defaultProps = defaultProps
DrawerComponent.displayName = 'GeistDrawer'
const Drawer = withScale(DrawerComponent)
export default Drawer