2019-08-13 11:44:04 +00:00
|
|
|
import React, { memo } from 'react'
|
2019-06-10 12:28:54 +00:00
|
|
|
import styled, { css } from 'styled-components'
|
|
|
|
import PropTypes from 'prop-types'
|
2019-08-13 12:04:56 +00:00
|
|
|
import CustomScrollbarsVirtualList from '../scrollbar/custom-scrollbars-virtual-list'
|
2019-08-13 11:21:38 +00:00
|
|
|
import DropDownItem from '../drop-down-item'
|
2019-12-17 14:27:06 +00:00
|
|
|
import Backdrop from '../backdrop'
|
2019-08-13 11:21:38 +00:00
|
|
|
import { FixedSizeList } from "react-window"
|
2019-06-10 12:28:54 +00:00
|
|
|
|
|
|
|
const StyledDropdown = styled.div`
|
2019-08-07 09:36:28 +00:00
|
|
|
font-family: 'Open Sans',sans-serif,Arial;
|
2019-06-18 14:07:57 +00:00
|
|
|
font-style: normal;
|
|
|
|
font-weight: 600;
|
|
|
|
font-size: 13px;
|
|
|
|
|
2019-08-09 07:57:12 +00:00
|
|
|
${props => props.maxHeight && `
|
2019-08-13 11:21:38 +00:00
|
|
|
max-height: ${props.maxHeight}px;
|
2019-08-09 07:57:12 +00:00
|
|
|
overflow-y: auto;
|
|
|
|
`}
|
|
|
|
|
2019-06-10 12:28:54 +00:00
|
|
|
position: absolute;
|
2019-07-18 07:43:17 +00:00
|
|
|
${props => props.manualWidth && `width: ${props.manualWidth};`}
|
2019-07-19 09:11:37 +00:00
|
|
|
${props => (props.directionY === 'top' && css`bottom: ${props => props.manualY ? props.manualY : '100%'};`)}
|
|
|
|
${props => (props.directionY === 'bottom' && css`top: ${props => props.manualY ? props.manualY : '100%'};`)}
|
2019-08-15 11:08:46 +00:00
|
|
|
${props => (props.directionX === 'right' && css`right: ${props => props.manualX ? props.manualX : '0px'};`)}
|
|
|
|
${props => (props.directionX === 'left' && css`left: ${props => props.manualX ? props.manualX : '0px'};`)}
|
2019-11-25 12:49:38 +00:00
|
|
|
z-index: 150;
|
2019-07-04 11:43:55 +00:00
|
|
|
margin-top: ${props => (props.isUserPreview ? '6px' : '0px')};
|
|
|
|
margin-right: ${props => (props.isUserPreview ? '6px' : '0px')};
|
2019-12-17 14:27:06 +00:00
|
|
|
display: ${props => (props.open ? 'block' : 'none')};
|
2019-07-04 11:43:55 +00:00
|
|
|
background: #FFFFFF;
|
2019-06-18 14:07:57 +00:00
|
|
|
border-radius: 6px;
|
|
|
|
-moz-border-radius: 6px;
|
|
|
|
-webkit-border-radius: 6px;
|
|
|
|
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.13);
|
|
|
|
-moz-box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.13);
|
|
|
|
-webkit-box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.13);
|
2019-06-10 12:28:54 +00:00
|
|
|
`;
|
|
|
|
|
2019-07-04 11:43:55 +00:00
|
|
|
const Arrow = styled.div`
|
|
|
|
position: absolute;
|
|
|
|
top: -6px;
|
2019-07-19 09:11:37 +00:00
|
|
|
${props => (props.directionX === 'right' && css`right: 16px;`)}
|
|
|
|
${props => (props.directionX === 'left' && css`left: 16px;`)}
|
2019-07-04 11:43:55 +00:00
|
|
|
width: 24px;
|
|
|
|
height: 6px;
|
|
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9.27954 1.12012C10.8122 -0.295972 13.1759 -0.295971 14.7086 1.12012L18.8406 4.93793C19.5796 5.62078 20.5489 6 21.5551 6H24H0H2.43299C3.4392 6 4.40845 5.62077 5.1475 4.93793L9.27954 1.12012Z' fill='%23206FA4'/%3E%3C/svg%3E");
|
2019-07-18 14:21:43 +00:00
|
|
|
`;
|
|
|
|
|
2019-09-10 07:37:58 +00:00
|
|
|
// eslint-disable-next-line react/display-name
|
2019-08-13 11:21:38 +00:00
|
|
|
const Row = memo(({ data, index, style }) => {
|
|
|
|
const option = data[index];
|
|
|
|
|
2019-07-31 11:45:39 +00:00
|
|
|
return (
|
2019-08-13 11:21:38 +00:00
|
|
|
<DropDownItem
|
|
|
|
{...option.props}
|
|
|
|
style={style} />
|
2019-07-31 11:45:39 +00:00
|
|
|
);
|
2019-07-24 17:43:18 +00:00
|
|
|
});
|
2019-06-24 13:18:47 +00:00
|
|
|
|
2019-09-09 13:45:07 +00:00
|
|
|
Row.propTypes = {
|
|
|
|
data: PropTypes.any,
|
|
|
|
index: PropTypes.number,
|
|
|
|
style: PropTypes.object
|
|
|
|
};
|
|
|
|
|
2019-08-13 11:21:38 +00:00
|
|
|
class DropDown extends React.PureComponent {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
2019-12-23 13:14:46 +00:00
|
|
|
width: this.dropDownRef ? this.dropDownRef.current.offsetWidth : 240,
|
2019-11-19 10:35:42 +00:00
|
|
|
directionX: props.directionX,
|
|
|
|
directionY: props.directionY
|
2019-08-13 11:21:38 +00:00
|
|
|
};
|
2019-12-17 14:27:06 +00:00
|
|
|
|
2019-11-19 10:35:42 +00:00
|
|
|
this.dropDownRef = React.createRef();
|
2019-08-13 11:21:38 +00:00
|
|
|
}
|
|
|
|
|
2019-12-17 14:27:06 +00:00
|
|
|
componentDidMount() {
|
2019-11-19 10:35:42 +00:00
|
|
|
this.checkPosition();
|
2019-09-09 13:45:07 +00:00
|
|
|
}
|
2019-08-13 11:21:38 +00:00
|
|
|
|
2019-12-23 13:14:46 +00:00
|
|
|
componentDidUpdate(prevProps) {
|
2019-12-17 14:27:06 +00:00
|
|
|
if (this.props.open !== prevProps.open) {
|
2019-11-19 10:35:42 +00:00
|
|
|
this.checkPosition();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-17 14:27:06 +00:00
|
|
|
toggleDropDown = () => {
|
|
|
|
this.props.clickOutsideAction && this.props.clickOutsideAction(!this.props.open);
|
|
|
|
}
|
|
|
|
|
2019-11-19 10:35:42 +00:00
|
|
|
checkPosition = () => {
|
2019-12-17 14:27:06 +00:00
|
|
|
if (!this.dropDownRef.current) return;
|
|
|
|
|
|
|
|
const rects = this.dropDownRef.current.getBoundingClientRect();
|
|
|
|
const container = { width: window.innerWidth, height: window.innerHeight };
|
|
|
|
|
|
|
|
const left = rects.left < 0;
|
|
|
|
const right = rects.right > container.width;
|
|
|
|
|
|
|
|
let newDirection = {};
|
|
|
|
|
|
|
|
newDirection.directionX = left ? 'left' : right ? 'right' : this.props.directionX;
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
directionX: newDirection.directionX,
|
|
|
|
width: rects.width
|
|
|
|
});
|
2019-09-09 13:45:07 +00:00
|
|
|
}
|
2019-08-13 11:21:38 +00:00
|
|
|
|
|
|
|
render() {
|
2019-12-17 14:27:06 +00:00
|
|
|
const { maxHeight, withArrow, withBackdrop, children, open } = this.props;
|
2019-12-23 13:14:46 +00:00
|
|
|
const { directionX, directionY, width } = this.state;
|
2019-12-18 11:05:13 +00:00
|
|
|
const isTablet = window.innerWidth <= 1024; //TODO: Make some better
|
2019-12-27 07:28:24 +00:00
|
|
|
const itemHeight = isTablet ? 36 : 32;
|
2019-12-18 11:05:13 +00:00
|
|
|
const fullHeight = children && children.length * itemHeight;
|
2019-11-05 13:56:30 +00:00
|
|
|
const calculatedHeight = ((fullHeight > 0) && (fullHeight < maxHeight)) ? fullHeight : maxHeight;
|
2019-11-05 13:42:17 +00:00
|
|
|
const dropDownMaxHeightProp = maxHeight ? { height: calculatedHeight + 'px' } : {};
|
2019-08-13 11:21:38 +00:00
|
|
|
//console.log("DropDown render");
|
|
|
|
return (
|
2019-12-17 14:27:06 +00:00
|
|
|
<>
|
2019-12-18 11:05:13 +00:00
|
|
|
{(withBackdrop && open && isTablet) && <Backdrop visible zIndex={149} onClick={this.toggleDropDown} />}
|
2019-12-17 14:27:06 +00:00
|
|
|
<StyledDropdown
|
|
|
|
ref={this.dropDownRef}
|
|
|
|
{...this.props}
|
|
|
|
directionX={directionX}
|
|
|
|
directionY={directionY}
|
|
|
|
{...dropDownMaxHeightProp}
|
|
|
|
>
|
|
|
|
|
|
|
|
{withArrow && <Arrow directionX={directionX} />}
|
|
|
|
{maxHeight
|
|
|
|
? <FixedSizeList
|
|
|
|
height={calculatedHeight}
|
2019-12-23 13:14:46 +00:00
|
|
|
width={width}
|
2019-12-18 11:05:13 +00:00
|
|
|
itemSize={itemHeight}
|
2019-12-17 14:27:06 +00:00
|
|
|
itemCount={children.length}
|
|
|
|
itemData={children}
|
|
|
|
outerElementType={CustomScrollbarsVirtualList}
|
|
|
|
>
|
|
|
|
{Row}
|
|
|
|
</FixedSizeList>
|
|
|
|
: children}
|
|
|
|
</StyledDropdown>
|
|
|
|
</>
|
2019-08-13 11:21:38 +00:00
|
|
|
);
|
|
|
|
}
|
2019-09-09 13:45:07 +00:00
|
|
|
}
|
2019-08-13 11:21:38 +00:00
|
|
|
|
2019-06-28 11:37:43 +00:00
|
|
|
DropDown.propTypes = {
|
2019-09-09 13:45:07 +00:00
|
|
|
children: PropTypes.any,
|
2019-12-17 14:27:06 +00:00
|
|
|
className: PropTypes.string,
|
2019-07-31 11:45:39 +00:00
|
|
|
directionX: PropTypes.oneOf(['left', 'right']),
|
|
|
|
directionY: PropTypes.oneOf(['bottom', 'top']),
|
2019-12-17 14:27:06 +00:00
|
|
|
id: PropTypes.string,
|
|
|
|
open: PropTypes.bool,
|
2019-07-31 11:45:39 +00:00
|
|
|
manualWidth: PropTypes.string,
|
2019-08-15 11:08:46 +00:00
|
|
|
manualX: PropTypes.string,
|
2019-12-17 14:27:06 +00:00
|
|
|
manualY: PropTypes.string,
|
2019-11-27 13:08:22 +00:00
|
|
|
maxHeight: PropTypes.number,
|
2019-12-17 14:27:06 +00:00
|
|
|
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
|
|
withArrow: PropTypes.bool,
|
|
|
|
withBackdrop: PropTypes.bool,
|
|
|
|
clickOutsideAction: PropTypes.func
|
2019-06-28 11:37:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
DropDown.defaultProps = {
|
2019-07-31 11:45:39 +00:00
|
|
|
directionX: 'left',
|
|
|
|
directionY: 'bottom',
|
2019-12-17 14:27:06 +00:00
|
|
|
withArrow: false,
|
2019-12-27 08:49:31 +00:00
|
|
|
withBackdrop: true
|
2019-06-28 11:37:43 +00:00
|
|
|
};
|
|
|
|
|
2019-06-10 12:28:54 +00:00
|
|
|
export default DropDown
|