Web: Components: added portals to drop-down
This commit is contained in:
parent
500deafd58
commit
1fe11360a8
@ -17,7 +17,6 @@ class AdvancedSelector extends React.Component {
|
||||
super(props);
|
||||
|
||||
this.ref = React.createRef();
|
||||
|
||||
this.state = {
|
||||
displayType: this.getTypeByWidth(),
|
||||
};
|
||||
@ -92,9 +91,10 @@ class AdvancedSelector extends React.Component {
|
||||
//console.log(`AdvancedSelector render() isOpen=${isOpen} displayType=${displayType}`);
|
||||
|
||||
return (
|
||||
<div ref={this.ref} id={id} className={className} style={style}>
|
||||
<div id={id} className={className} style={style}>
|
||||
{displayType === "dropdown" ? (
|
||||
<DropDown
|
||||
forwardedRef={this.ref}
|
||||
open={isOpen}
|
||||
className="dropdown-container"
|
||||
clickOutsideAction={this.onClose}
|
||||
|
@ -61,6 +61,7 @@ class HideFilter extends React.Component {
|
||||
|
||||
<div className="dropdown-style" ref={this.dropDownRef}>
|
||||
<DropDown
|
||||
forwardedRef={this.ref}
|
||||
className="drop-down hide-filter-drop-down"
|
||||
clickOutsideAction={this.handleClickOutside}
|
||||
manualY="8px"
|
||||
|
@ -95,8 +95,9 @@ class ComboBox extends React.Component {
|
||||
const dropDownMaxHeightProp = dropDownMaxHeight
|
||||
? { maxHeight: dropDownMaxHeight }
|
||||
: {};
|
||||
const dropDownManualWidthProp = scaledOptions
|
||||
? { manualWidth: "100%" }
|
||||
|
||||
const dropDownManualWidthProp = this.ref.current
|
||||
? { manualWidth: this.ref.current.clientWidth + "px" }
|
||||
: {};
|
||||
|
||||
const optionsLength = options.length
|
||||
@ -140,6 +141,7 @@ class ComboBox extends React.Component {
|
||||
directionY={directionY}
|
||||
manualY="102%"
|
||||
open={isOpen}
|
||||
forwardedRef={this.ref}
|
||||
clickOutsideAction={this.handleClickOutside}
|
||||
{...dropDownMaxHeightProp}
|
||||
{...dropDownManualWidthProp}
|
||||
@ -175,7 +177,7 @@ ComboBox.propTypes = {
|
||||
/** X direction selection */
|
||||
directionX: PropTypes.oneOf(["left", "right"]),
|
||||
/** Y direction selection */
|
||||
directionY: PropTypes.oneOf(["bottom", "top"]),
|
||||
directionY: PropTypes.oneOf(["bottom", "top", "both"]),
|
||||
/** Component Display Type */
|
||||
displayType: PropTypes.oneOf(["default", "toggle"]),
|
||||
/** Height of Dropdown */
|
||||
|
@ -196,6 +196,7 @@ class ContextMenuButton extends React.Component {
|
||||
directionX={directionX}
|
||||
directionY={directionY}
|
||||
open={isOpen}
|
||||
forwardedRef={this.ref}
|
||||
clickOutsideAction={this.clickOutsideAction}
|
||||
columnCount={columnCount}
|
||||
withBackdrop={!!isMobile}
|
||||
|
@ -347,6 +347,7 @@ class DatePicker extends Component {
|
||||
displayType === "dropdown" ? (
|
||||
<DropDownStyle>
|
||||
<DropDown
|
||||
forwardedRef={this.ref}
|
||||
className="drop-down"
|
||||
open={isOpen}
|
||||
clickOutsideAction={this.onClose}
|
||||
|
@ -3,6 +3,8 @@ import PropTypes from "prop-types";
|
||||
import { VariableSizeList } from "react-window";
|
||||
import onClickOutside from "react-onclickoutside";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import Portal from "../portal";
|
||||
import DomHelpers from "../utils/domHelpers";
|
||||
|
||||
import CustomScrollbarsVirtualList from "../scrollbar/custom-scrollbars-virtual-list";
|
||||
import DropDownItem from "../drop-down-item";
|
||||
@ -36,7 +38,6 @@ class DropDown extends React.PureComponent {
|
||||
directionX: props.directionX,
|
||||
directionY: props.directionY,
|
||||
};
|
||||
|
||||
this.dropDownRef = React.createRef();
|
||||
}
|
||||
|
||||
@ -49,6 +50,7 @@ class DropDown extends React.PureComponent {
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.disableOnClickOutside();
|
||||
this.unbindDocumentResizeListener();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@ -56,6 +58,7 @@ class DropDown extends React.PureComponent {
|
||||
if (this.props.open) {
|
||||
this.props.enableOnClickOutside();
|
||||
this.checkPosition();
|
||||
this.bindDocumentResizeListener();
|
||||
} else {
|
||||
this.props.disableOnClickOutside();
|
||||
}
|
||||
@ -72,26 +75,62 @@ class DropDown extends React.PureComponent {
|
||||
this.props.clickOutsideAction(e, !this.props.open);
|
||||
};
|
||||
|
||||
checkPosition = () => {
|
||||
if (!this.dropDownRef.current) return;
|
||||
bindDocumentResizeListener() {
|
||||
if (!this.documentResizeListener) {
|
||||
this.documentResizeListener = (e) => {
|
||||
if (this.props.open) {
|
||||
this.checkPosition();
|
||||
}
|
||||
};
|
||||
|
||||
const rects = this.dropDownRef.current.getBoundingClientRect();
|
||||
const container = { width: window.innerWidth, height: window.innerHeight };
|
||||
const left = rects.left < 0 && rects.width < container.width;
|
||||
const right =
|
||||
rects.width &&
|
||||
rects.left < 250 &&
|
||||
rects.left > rects.width &&
|
||||
rects.width < container.width;
|
||||
const top = rects.bottom > container.height && rects.top > rects.height;
|
||||
const bottom = rects.top < 0;
|
||||
const x = left ? "left" : right ? "right" : this.state.directionX;
|
||||
const y = bottom ? "bottom" : top ? "top" : this.state.directionY;
|
||||
window.addEventListener("resize", this.documentResizeListener);
|
||||
}
|
||||
}
|
||||
|
||||
unbindDocumentResizeListener() {
|
||||
if (this.documentResizeListener) {
|
||||
window.removeEventListener("resize", this.documentResizeListener);
|
||||
this.documentResizeListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
checkPosition = () => {
|
||||
const parent = this.props.forwardedRef;
|
||||
const rects = parent.current.getBoundingClientRect();
|
||||
|
||||
let dropDownHeight = this.dropDownRef.current.offsetParent
|
||||
? this.dropDownRef.current.offsetHeight
|
||||
: DomHelpers.getHiddenElementOuterHeight(this.dropDownRef.current);
|
||||
|
||||
let left = rects.left;
|
||||
let bottom = rects.bottom;
|
||||
|
||||
const viewport = DomHelpers.getViewport();
|
||||
const dropDownRects = this.dropDownRef.current.getBoundingClientRect();
|
||||
|
||||
if (
|
||||
this.props.directionY === "top" ||
|
||||
(this.props.directionY === "both" &&
|
||||
rects.top + dropDownHeight > viewport.height)
|
||||
) {
|
||||
bottom -= parent.current.clientHeight + dropDownHeight;
|
||||
}
|
||||
|
||||
if (this.props.right) {
|
||||
this.dropDownRef.current.style.right = this.props.right;
|
||||
} else if (this.props.directionX === "right") {
|
||||
this.dropDownRef.current.style.left =
|
||||
rects.right - this.dropDownRef.current.clientWidth + "px";
|
||||
} else {
|
||||
this.dropDownRef.current.style.left = left + "px";
|
||||
}
|
||||
|
||||
this.dropDownRef.current.style.top = this.props.top || bottom + "px";
|
||||
|
||||
this.setState({
|
||||
directionX: x,
|
||||
directionY: y,
|
||||
width: rects.width,
|
||||
directionX: this.props.directionX,
|
||||
directionY: this.props.directionY,
|
||||
width: dropDownRects.width,
|
||||
});
|
||||
};
|
||||
|
||||
@ -123,7 +162,7 @@ class DropDown extends React.PureComponent {
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
renderDropDown() {
|
||||
const { maxHeight, children, showDisabledItems } = this.props;
|
||||
const { directionX, directionY, width } = this.state;
|
||||
let cleanChildren;
|
||||
@ -169,6 +208,10 @@ class DropDown extends React.PureComponent {
|
||||
</StyledDropdown>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const element = this.renderDropDown();
|
||||
return <Portal element={element} appendTo={this.props.appendTo} />;
|
||||
}
|
||||
}
|
||||
|
||||
const EnhancedComponent = onClickOutside(DropDown);
|
||||
@ -211,7 +254,7 @@ DropDownContainer.propTypes = {
|
||||
/** Sets the opening direction relative to the parent */
|
||||
directionX: PropTypes.oneOf(["left", "right"]), //TODO: make more informative
|
||||
/** Sets the opening direction relative to the parent */
|
||||
directionY: PropTypes.oneOf(["bottom", "top"]),
|
||||
directionY: PropTypes.oneOf(["bottom", "top", "both"]),
|
||||
/** Accepts id */
|
||||
id: PropTypes.string,
|
||||
/** Required if you need to specify the exact width of the component, for example 100% */
|
||||
@ -232,6 +275,7 @@ DropDownContainer.propTypes = {
|
||||
columnCount: PropTypes.number,
|
||||
/** Display disabled items or not */
|
||||
showDisabledItems: PropTypes.bool,
|
||||
forwardedRef: PropTypes.shape({ current: PropTypes.any }),
|
||||
};
|
||||
|
||||
DropDownContainer.defaultProps = {
|
||||
|
@ -138,6 +138,7 @@ class GroupButton extends React.Component {
|
||||
</Caret>
|
||||
</StyledDropdownToggle>
|
||||
<DropDown
|
||||
forwardedRef={this.ref}
|
||||
{...dropDownMaxHeightProp}
|
||||
{...offsetSelectDropDown}
|
||||
manualY="72px"
|
||||
|
@ -107,6 +107,7 @@ class LinkWithDropdown extends React.Component {
|
||||
className="fixed-max-width"
|
||||
open={this.state.isOpen}
|
||||
withArrow={false}
|
||||
forwardedRef={this.ref}
|
||||
clickOutsideAction={this.onClose}
|
||||
{...rest}
|
||||
>
|
||||
|
@ -75,6 +75,9 @@ class MainButton extends React.PureComponent {
|
||||
|
||||
render() {
|
||||
//console.log("MainButton render");
|
||||
const dropDownManualWidthProp = this.ref.current
|
||||
? { manualWidth: this.ref.current.clientWidth + "px" }
|
||||
: {};
|
||||
return (
|
||||
<GroupMainButton {...this.props} ref={this.ref}>
|
||||
<StyledMainButton {...this.props} onClick={this.onMainButtonClick}>
|
||||
@ -84,8 +87,10 @@ class MainButton extends React.PureComponent {
|
||||
</StyledMainButton>
|
||||
{this.props.isDropdown ? (
|
||||
<StyledDropDown
|
||||
forwardedRef={this.ref}
|
||||
open={this.state.isOpen}
|
||||
clickOutsideAction={this.handleClick}
|
||||
{...dropDownManualWidthProp}
|
||||
{...this.props}
|
||||
onClick={this.onDropDownClick}
|
||||
/>
|
||||
|
@ -114,7 +114,7 @@ Paging.propTypes = {
|
||||
/** Items per page combo box items */
|
||||
countItems: PropTypes.array,
|
||||
/** Indicates opening direction of combo box */
|
||||
openDirection: PropTypes.oneOf(["bottom", "top"]),
|
||||
openDirection: PropTypes.oneOf(["bottom", "top", "both"]),
|
||||
/** Accepts class */
|
||||
className: PropTypes.string,
|
||||
/** Accepts id */
|
||||
|
@ -52,7 +52,7 @@ const ProgressBar = (props) => {
|
||||
</div>
|
||||
<div className="progress-bar_field" />
|
||||
{dropDownContent && (
|
||||
<DropDown open={isOpen} clickOutsideAction={onClose}>
|
||||
<DropDown open={isOpen} clickOutsideAction={onClose} forwardedRef={ref}>
|
||||
<div className="progress-bar_drop-down">{dropDownContent}</div>
|
||||
</DropDown>
|
||||
)}
|
||||
|
@ -194,7 +194,7 @@ const Base = {
|
||||
},
|
||||
|
||||
dropDown: {
|
||||
width: "100%",
|
||||
// width: "100%",
|
||||
top: "100%",
|
||||
},
|
||||
|
||||
|
@ -179,7 +179,7 @@ const Dark = {
|
||||
},
|
||||
|
||||
dropDown: {
|
||||
width: "100%",
|
||||
// width: "100%",
|
||||
top: "100%",
|
||||
},
|
||||
|
||||
|
@ -465,6 +465,7 @@ class SharingPanelComponent extends React.Component {
|
||||
/>
|
||||
|
||||
<DropDown
|
||||
forwardedRef={this.ref}
|
||||
directionX="right"
|
||||
className="sharing_panel-drop-down"
|
||||
open={showActionPanel}
|
||||
@ -475,12 +476,12 @@ class SharingPanelComponent extends React.Component {
|
||||
label={t("LinkText")}
|
||||
onClick={this.onShowUsersPanel}
|
||||
/>
|
||||
{!isEncrypted && (
|
||||
<DropDownItem
|
||||
label={t("AddGroupsForSharingButton")}
|
||||
onClick={this.onShowGroupsPanel}
|
||||
/>
|
||||
)}
|
||||
{!isEncrypted && (
|
||||
<DropDownItem
|
||||
label={t("AddGroupsForSharingButton")}
|
||||
onClick={this.onShowGroupsPanel}
|
||||
/>
|
||||
)}
|
||||
</DropDown>
|
||||
</div>
|
||||
|
||||
|
@ -157,7 +157,7 @@ const SectionPagingContent = ({
|
||||
disableHover={isMobile}
|
||||
previousAction={onPrevClick}
|
||||
nextAction={onNextClick}
|
||||
openDirection="top"
|
||||
openDirection="both"
|
||||
selectedPageItem={selectedPageItem} //FILTER CURRENT PAGE
|
||||
selectedCountItem={selectedCountItem} //FILTER PAGE COUNT
|
||||
showCountItem={showCountItem}
|
||||
|
@ -5,6 +5,7 @@ import DropDown from "@appserver/components/drop-down";
|
||||
|
||||
import styled, { css } from "styled-components";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import { isDesktop, isTablet } from "react-device-detect";
|
||||
|
||||
const commonStyle = css`
|
||||
font-family: "Open Sans", sans-serif, Arial;
|
||||
@ -82,14 +83,20 @@ class ProfileMenu extends React.Component {
|
||||
email,
|
||||
clickOutsideAction,
|
||||
open,
|
||||
forwardedRef,
|
||||
} = this.props;
|
||||
const right = isTablet ? "6px" : "12px";
|
||||
const top = "66px";
|
||||
|
||||
return (
|
||||
<DropDown
|
||||
className={className}
|
||||
directionX="right"
|
||||
right={right}
|
||||
top={top}
|
||||
open={open}
|
||||
clickOutsideAction={clickOutsideAction}
|
||||
forwardedRef={forwardedRef}
|
||||
>
|
||||
<StyledProfileMenu>
|
||||
<MenuContainer>
|
||||
|
Loading…
Reference in New Issue
Block a user