mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-15 01:23:53 -07:00
New: Replace react-tether with react-popper (#789)
This commit is contained in:
parent
6ea7f97b16
commit
cf40df7606
39 changed files with 981 additions and 970 deletions
|
@ -1,7 +1,3 @@
|
|||
.tether {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.menu {
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,31 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import TetherComponent from 'react-tether';
|
||||
import { Manager, Popper, Reference } from 'react-popper';
|
||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||
import { align } from 'Helpers/Props';
|
||||
import Portal from 'Components/Portal';
|
||||
import styles from './Menu.css';
|
||||
|
||||
const baseTetherOptions = {
|
||||
skipMoveElement: true,
|
||||
constraints: [
|
||||
{
|
||||
to: 'window',
|
||||
attachment: 'together',
|
||||
pin: true
|
||||
const sharedPopperOptions = {
|
||||
modifiers: {
|
||||
preventOverflow: {
|
||||
padding: 0
|
||||
},
|
||||
flip: {
|
||||
padding: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const tetherOptions = {
|
||||
const popperOptions = {
|
||||
[align.RIGHT]: {
|
||||
...baseTetherOptions,
|
||||
attachment: 'top right',
|
||||
targetAttachment: 'bottom right'
|
||||
...sharedPopperOptions,
|
||||
placement: 'bottom-end'
|
||||
},
|
||||
|
||||
[align.LEFT]: {
|
||||
...baseTetherOptions,
|
||||
attachment: 'top left',
|
||||
targetAttachment: 'bottom left'
|
||||
...sharedPopperOptions,
|
||||
placement: 'bottom-start'
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -38,6 +37,9 @@ class Menu extends Component {
|
|||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._scheduleUpdate = null;
|
||||
this._menuButtonId = getUniqueElememtId();
|
||||
|
||||
this.state = {
|
||||
isMenuOpen: false,
|
||||
maxHeight: 0
|
||||
|
@ -48,6 +50,12 @@ class Menu extends Component {
|
|||
this.setMaxHeight();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this._scheduleUpdate) {
|
||||
this._scheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._removeListener();
|
||||
}
|
||||
|
@ -60,22 +68,26 @@ class Menu extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
const menu = ReactDOM.findDOMNode(this.refs.menu);
|
||||
const menuButton = document.getElementById(this._menuButtonId);
|
||||
|
||||
if (!menu) {
|
||||
if (!menuButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { bottom } = menu.getBoundingClientRect();
|
||||
const { bottom } = menuButton.getBoundingClientRect();
|
||||
const maxHeight = window.innerHeight - bottom;
|
||||
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
setMaxHeight() {
|
||||
this.setState({
|
||||
maxHeight: this.getMaxHeight()
|
||||
});
|
||||
const maxHeight = this.getMaxHeight();
|
||||
|
||||
if (maxHeight !== this.state.maxHeight) {
|
||||
this.setState({
|
||||
maxHeight
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_addListener() {
|
||||
|
@ -99,14 +111,13 @@ class Menu extends Component {
|
|||
// Listeners
|
||||
|
||||
onWindowClick = (event) => {
|
||||
const menu = ReactDOM.findDOMNode(this.refs.menu);
|
||||
const menuContent = ReactDOM.findDOMNode(this.refs.menuContent);
|
||||
const menuButton = document.getElementById(this._menuButtonId);
|
||||
|
||||
if (!menu) {
|
||||
if (!menuButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!menu.contains(event.target) || menuContent.contains(event.target)) && this.state.isMenuOpen) {
|
||||
if (!menuButton.contains(event.target) && this.state.isMenuOpen) {
|
||||
this.setState({ isMenuOpen: false });
|
||||
this._removeListener();
|
||||
}
|
||||
|
@ -116,8 +127,10 @@ class Menu extends Component {
|
|||
this.setMaxHeight();
|
||||
}
|
||||
|
||||
onWindowScroll = () => {
|
||||
this.setMaxHeight();
|
||||
onWindowScroll = (event) => {
|
||||
if (this.state.isMenuOpen) {
|
||||
this.setMaxHeight();
|
||||
}
|
||||
}
|
||||
|
||||
onMenuButtonPress = () => {
|
||||
|
@ -158,35 +171,40 @@ class Menu extends Component {
|
|||
}
|
||||
);
|
||||
|
||||
const content = React.cloneElement(
|
||||
childrenArray[1],
|
||||
{
|
||||
ref: 'menuContent',
|
||||
alignMenu,
|
||||
maxHeight,
|
||||
isOpen: isMenuOpen
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<TetherComponent
|
||||
classes={{
|
||||
element: styles.tether
|
||||
}}
|
||||
{...tetherOptions[alignMenu]}
|
||||
>
|
||||
<div
|
||||
ref="menu"
|
||||
className={className}
|
||||
>
|
||||
{button}
|
||||
</div>
|
||||
<Manager>
|
||||
<Reference>
|
||||
{({ ref }) => (
|
||||
<div
|
||||
ref={ref}
|
||||
id={this._menuButtonId}
|
||||
className={className}
|
||||
>
|
||||
{button}
|
||||
</div>
|
||||
)}
|
||||
</Reference>
|
||||
|
||||
{
|
||||
isMenuOpen &&
|
||||
content
|
||||
}
|
||||
</TetherComponent>
|
||||
<Portal>
|
||||
<Popper {...popperOptions[alignMenu]}>
|
||||
{({ ref, style, scheduleUpdate }) => {
|
||||
this._scheduleUpdate = scheduleUpdate;
|
||||
|
||||
return React.cloneElement(
|
||||
childrenArray[1],
|
||||
{
|
||||
forwardedRef: ref,
|
||||
style: {
|
||||
...style,
|
||||
maxHeight
|
||||
},
|
||||
isOpen: isMenuOpen
|
||||
}
|
||||
);
|
||||
}}
|
||||
</Popper>
|
||||
</Portal>
|
||||
</Manager>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
.menuContent {
|
||||
z-index: $popperZIndex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: $toolbarMenuItemBackgroundColor;
|
||||
|
|
|
@ -10,30 +10,37 @@ class MenuContent extends Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
forwardedRef,
|
||||
className,
|
||||
children,
|
||||
maxHeight
|
||||
style,
|
||||
isOpen
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={forwardedRef}
|
||||
className={className}
|
||||
style={{
|
||||
maxHeight: maxHeight ? `${maxHeight}px` : undefined
|
||||
}}
|
||||
style={style}
|
||||
>
|
||||
<Scroller className={styles.scroller}>
|
||||
{children}
|
||||
</Scroller>
|
||||
{
|
||||
isOpen ?
|
||||
<Scroller className={styles.scroller}>
|
||||
{children}
|
||||
</Scroller> :
|
||||
null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MenuContent.propTypes = {
|
||||
forwardedRef: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node.isRequired,
|
||||
maxHeight: PropTypes.number
|
||||
style: PropTypes.object,
|
||||
isOpen: PropTypes.bool
|
||||
};
|
||||
|
||||
MenuContent.defaultProps = {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.separator {
|
||||
overflow: hidden;
|
||||
min-height: 1px;
|
||||
height: 1px;
|
||||
background-color: $themeDarkColor;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue