115 lines
2.7 KiB
JavaScript
115 lines
2.7 KiB
JavaScript
import { useState, useRef } from 'react';
|
|
|
|
import { Button, IconButton } from '@mui/material';
|
|
import MenuIcon from '@mui/icons-material/Menu';
|
|
import CloseIcon from '@mui/icons-material/Close';
|
|
|
|
import './SwipeableDrawer.css';
|
|
|
|
function SwipeableDrawer({children, anchor="right", hidden=true, className, ...props}) {
|
|
const [ open, setOpen ] = useState(!hidden);
|
|
|
|
const [ distance, setDistance ] = useState(0);
|
|
const [ origin, setOrigin ] = useState(0);
|
|
const [ inTouch, setInTouch ] = useState(false);
|
|
|
|
const swipeTargetRef = useRef(null);
|
|
|
|
function onTouchStart(e) {
|
|
setInTouch(true);
|
|
setOrigin(e.targetTouches[0].clientX);
|
|
}
|
|
function onTouchMove(e) {
|
|
setDistance(e.targetTouches[0].clientX - origin);
|
|
}
|
|
function onTouchEnd(e) {
|
|
let threshhold = 100;
|
|
if (swipeTargetRef.current) {
|
|
threshhold = swipeTargetRef.current.getBoundingClientRect().width * 0.5;
|
|
}
|
|
|
|
if (anchor == "right") {
|
|
if (distance < -threshhold) {
|
|
setOpen(true);
|
|
}
|
|
if (distance > threshhold) {
|
|
setOpen(false);
|
|
}
|
|
}
|
|
|
|
if (anchor == "left") {
|
|
if (distance > threshhold) {
|
|
setOpen(true);
|
|
}
|
|
if (distance < -threshhold) {
|
|
setOpen(false);
|
|
}
|
|
}
|
|
|
|
setOrigin(0);
|
|
setDistance(0);
|
|
setInTouch(false);
|
|
}
|
|
|
|
const dragStyle = {};
|
|
if (inTouch) {
|
|
dragStyle.transition = "none";
|
|
|
|
if (open) {
|
|
dragStyle.transform = `translateX(${distance}px)`;
|
|
} else {
|
|
if (anchor == "right") dragStyle.transform = `translateX(calc(30vw + ${distance}px))`;
|
|
if (anchor == "left") dragStyle.transform = `translateX(calc(-30vw + ${distance}px))`;
|
|
}
|
|
}
|
|
|
|
const drawerClosedClass = open ? "" : `drawerStyle-${anchor}-closed`;
|
|
|
|
return (<>
|
|
<div
|
|
ref={swipeTargetRef}
|
|
className={`swipeTargetStyle swipeTargetStyle-${anchor}`}
|
|
onTouchStart={onTouchStart}
|
|
onTouchMove={onTouchMove}
|
|
onTouchEnd={onTouchEnd}>
|
|
<IconButton
|
|
size="large"
|
|
variant="contained"
|
|
style={{
|
|
visible: open,
|
|
padding: "2rem",
|
|
position: "absolute",
|
|
right: anchor == "right" ? 0 : "auto",
|
|
left: anchor == "left" ? 0 : "auto",
|
|
top: 0
|
|
}}
|
|
onClick={() => setOpen(true)} >
|
|
<MenuIcon />
|
|
</IconButton>
|
|
</div>
|
|
<div
|
|
className={`drawerStyle drawerStyle-${anchor} ${drawerClosedClass} ${className}`}
|
|
style={dragStyle}
|
|
onTouchStart={onTouchStart}
|
|
onTouchMove={onTouchMove}
|
|
onTouchEnd={onTouchEnd}>
|
|
<IconButton
|
|
size="large"
|
|
variant="contained"
|
|
style={{
|
|
visible: open,
|
|
padding: "2rem",
|
|
position: "absolute",
|
|
right: anchor == "left" ? 0 : "auto",
|
|
left: anchor == "right" ? 0 : "auto",
|
|
top: 0
|
|
}}
|
|
onClick={() => setOpen(false)} >
|
|
<CloseIcon />
|
|
</IconButton>
|
|
{children}
|
|
</div>
|
|
</>);
|
|
}
|
|
|
|
export default SwipeableDrawer; |