mirror of
https://github.com/HSLdevcom/digitransit-ui
synced 2025-09-20 20:32:47 +02:00
146 lines
3.6 KiB
JavaScript
146 lines
3.6 KiB
JavaScript
import PropTypes from 'prop-types';
|
|
import React, { useRef, useLayoutEffect, useState } from 'react';
|
|
import MapBottomsheetContext from './map/MapBottomsheetContext';
|
|
import MobileFooter from './MobileFooter';
|
|
|
|
function slowlyScrollTo(el, to = 0, duration = 1000) {
|
|
const element = el;
|
|
const start = element.scrollTop;
|
|
const change = to - start;
|
|
const increment = 20;
|
|
let currentTime = 0;
|
|
|
|
const animateScroll = () => {
|
|
currentTime += increment;
|
|
|
|
const val = Math.easeInOutQuad(currentTime, start, change, duration);
|
|
|
|
element.scrollTop = val;
|
|
|
|
if (currentTime < duration) {
|
|
setTimeout(animateScroll, increment);
|
|
}
|
|
};
|
|
|
|
animateScroll();
|
|
}
|
|
|
|
Math.easeInOutQuad = function (a, b, c, d) {
|
|
let t = a;
|
|
t /= d / 2;
|
|
if (t < 1) {
|
|
return (c / 2) * t * t + b;
|
|
}
|
|
t -= 1;
|
|
return (-c / 2) * (t * (t - 2) - 1) + b;
|
|
};
|
|
|
|
export default function MobileView({
|
|
header,
|
|
map,
|
|
content,
|
|
settingsDrawer,
|
|
selectFromMapHeader,
|
|
expandMap,
|
|
searchBox,
|
|
}) {
|
|
if (settingsDrawer && settingsDrawer.props.open) {
|
|
return <div className="mobile">{settingsDrawer}</div>;
|
|
}
|
|
const scrollRef = useRef(null);
|
|
const topBarHeight = 64;
|
|
// pass these to map according to bottom sheet placement
|
|
const [bottomsheetState, changeBottomsheetState] = useState({
|
|
context: { mapBottomPadding: 0, buttonBottomPadding: 0 },
|
|
});
|
|
|
|
useLayoutEffect(() => {
|
|
if (map) {
|
|
const paddingHeight = (window.innerHeight - topBarHeight) * 0.9; // height of .drawer-padding, defined as 90% of map height
|
|
const newSheetPosition = paddingHeight / 2;
|
|
scrollRef.current.scrollTop = newSheetPosition;
|
|
changeBottomsheetState({
|
|
context: {
|
|
mapBottomPadding: newSheetPosition,
|
|
buttonBottomPadding: newSheetPosition,
|
|
},
|
|
});
|
|
}
|
|
}, [header]);
|
|
|
|
useLayoutEffect(() => {
|
|
if (map && expandMap) {
|
|
const newSheetPosition = 0;
|
|
slowlyScrollTo(scrollRef.current);
|
|
changeBottomsheetState({
|
|
context: {
|
|
mapBottomPadding: newSheetPosition,
|
|
buttonBottomPadding: newSheetPosition,
|
|
},
|
|
});
|
|
}
|
|
}, [expandMap]);
|
|
|
|
const onScroll = e => {
|
|
if (map) {
|
|
if (e.target.className === 'drawer-container') {
|
|
const scroll = e.target.scrollTop;
|
|
changeBottomsheetState({
|
|
context: { ...bottomsheetState.context, buttonBottomPadding: scroll },
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="mobile">
|
|
{selectFromMapHeader}
|
|
{searchBox && <>{searchBox}</>}
|
|
{map ? (
|
|
<>
|
|
<MapBottomsheetContext.Provider value={bottomsheetState.context}>
|
|
{map}
|
|
</MapBottomsheetContext.Provider>
|
|
<div
|
|
className="drawer-container"
|
|
onScroll={onScroll}
|
|
ref={scrollRef}
|
|
role="main"
|
|
>
|
|
<div className="drawer-padding" />
|
|
<div className="drawer-content">
|
|
<div className="drag-line" />
|
|
<div className="content-container">
|
|
{header}
|
|
{content}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<div role="main" className="mobile-main-container">
|
|
<div className="mobile-main-content-container">
|
|
{header}
|
|
{content}
|
|
</div>
|
|
|
|
<MobileFooter />
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
MobileView.propTypes = {
|
|
header: PropTypes.node,
|
|
map: PropTypes.any,
|
|
content: PropTypes.node,
|
|
settingsDrawer: PropTypes.node,
|
|
selectFromMapHeader: PropTypes.node,
|
|
searchBox: PropTypes.node,
|
|
expandMap: PropTypes.number,
|
|
};
|
|
|
|
MobileView.contextTypes = {
|
|
config: PropTypes.object.isRequired,
|
|
};
|