diff --git a/frontend/src/AddSeries/ImportSeries/Import/SelectSeries/ImportSeriesSelectSeries.js b/frontend/src/AddSeries/ImportSeries/Import/SelectSeries/ImportSeriesSelectSeries.js index 8e21dcb05..d67a6bf2e 100644 --- a/frontend/src/AddSeries/ImportSeries/Import/SelectSeries/ImportSeriesSelectSeries.js +++ b/frontend/src/AddSeries/ImportSeries/Import/SelectSeries/ImportSeriesSelectSeries.js @@ -34,6 +34,8 @@ class ImportSeriesSelectSeries extends Component { super(props, context); this._seriesLookupTimeout = null; + this._buttonRef = {}; + this._contentRef = {}; this.state = { term: props.id, @@ -44,14 +46,6 @@ class ImportSeriesSelectSeries extends Component { // // Control - _setButtonRef = (ref) => { - this._buttonRef = ref; - } - - _setContentRef = (ref) => { - this._contentRef = ref; - } - _addListener() { window.addEventListener('click', this.onWindowClick); } @@ -64,14 +58,18 @@ class ImportSeriesSelectSeries extends Component { // Listeners onWindowClick = (event) => { - const button = ReactDOM.findDOMNode(this._buttonRef); - const content = ReactDOM.findDOMNode(this._contentRef); + const button = ReactDOM.findDOMNode(this._buttonRef.current); + const content = ReactDOM.findDOMNode(this._contentRef.current); - if (!button) { + if (!button || !content) { return; } - if (!button.contains(event.target) && content && !content.contains(event.target) && this.state.isOpen) { + if ( + !button.contains(event.target) && + !content.contains(event.target) && + this.state.isOpen + ) { this.setState({ isOpen: false }); this._removeListener(); } @@ -134,124 +132,145 @@ class ImportSeriesSelectSeries extends Component { element: styles.tether }} {...tetherOptions} - > - - { - isLookingUpSeries && isQueued && !isPopulated && - - } + renderTarget={ + (ref) => { + this._buttonRef = ref; - { - isPopulated && selectedSeries && isExistingSeries && - - } + return ( +
+ + { + isLookingUpSeries && isQueued && !isPopulated ? + : + null + } - { - isPopulated && selectedSeries && - - } + { + isPopulated && selectedSeries && isExistingSeries ? + : + null + } - { - isPopulated && !selectedSeries && -
- + { + isPopulated && selectedSeries ? + : + null + } + + { + isPopulated && !selectedSeries ? +
+ No match found! -
- } +
: + null + } - { - !isFetching && !!error && -
- + { + !isFetching && !!error ? +
+ Search failed, please try again later. +
: + null + } + +
+ +
+
+ ); } + } + renderElement={ + (ref) => { + this._contentRef = ref; -
- -
- + if (!this.state.isOpen) { + return; + } - { - this.state.isOpen && -
-
-
-
- + return ( +
+
+
+
+ +
+ + + + + +
- - - - - -
- -
- { - items.map((item) => { - return ( - - ); - }) - } +
+ { + items.map((item) => { + return ( + + ); + }) + } +
-
+ ); + } } - + /> ); } } diff --git a/frontend/src/Components/Form/EnhancedSelectInput.js b/frontend/src/Components/Form/EnhancedSelectInput.js index a127feaed..74a0d53f8 100644 --- a/frontend/src/Components/Form/EnhancedSelectInput.js +++ b/frontend/src/Components/Form/EnhancedSelectInput.js @@ -87,6 +87,9 @@ class EnhancedSelectInput extends Component { constructor(props, context) { super(props, context); + this._buttonRef = {}; + this._optionsRef = {}; + this.state = { isOpen: false, selectedIndex: getSelectedIndex(props), @@ -106,14 +109,6 @@ class EnhancedSelectInput extends Component { // // Control - _setButtonRef = (ref) => { - this._buttonRef = ref; - } - - _setOptionsRef = (ref) => { - this._optionsRef = ref; - } - _addListener() { window.addEventListener('click', this.onWindowClick); } @@ -126,8 +121,8 @@ class EnhancedSelectInput extends Component { // Listeners onWindowClick = (event) => { - const button = ReactDOM.findDOMNode(this._buttonRef); - const options = ReactDOM.findDOMNode(this._optionsRef); + const button = ReactDOM.findDOMNode(this._buttonRef.current); + const options = ReactDOM.findDOMNode(this._optionsRef.current); if (!button || this.state.isMobile) { return; @@ -276,75 +271,91 @@ class EnhancedSelectInput extends Component { element: styles.tether }} {...tetherOptions} - > - - - - {selectedOption ? selectedOption.value : null} - + renderTarget={ + (ref) => { + this._buttonRef = ref; -
- -
- -
+ return ( + +
+ + + {selectedOption ? selectedOption.value : null} + - { - isOpen && !isMobile && -
-
- { - values.map((v, index) => { - return ( - - {v.value} - - ); - }) - } -
-
+
+ +
+ +
+
+ ); + } } - + renderElement={ + (ref) => { + this._optionsRef = ref; + + if (!isOpen || isMobile) { + return; + } + + return ( +
+
+ { + values.map((v, index) => { + return ( + + {v.value} + + ); + }) + } +
+
+ ); + } + } + /> { isMobile && diff --git a/frontend/src/Components/Menu/Menu.js b/frontend/src/Components/Menu/Menu.js index da778bb7a..946b7e0ec 100644 --- a/frontend/src/Components/Menu/Menu.js +++ b/frontend/src/Components/Menu/Menu.js @@ -38,6 +38,9 @@ class Menu extends Component { constructor(props, context) { super(props, context); + this._menuRef = {}; + this._menuContentRef = {}; + this.state = { isMenuOpen: false, maxHeight: 0 @@ -60,7 +63,7 @@ class Menu extends Component { return; } - const menu = ReactDOM.findDOMNode(this.refs.menu); + const menu = ReactDOM.findDOMNode(this._menuRef.current); if (!menu) { return; @@ -73,9 +76,13 @@ class Menu extends Component { } setMaxHeight() { - this.setState({ - maxHeight: this.getMaxHeight() - }); + const maxHeight = this.getMaxHeight(); + + if (maxHeight !== this.state.maxHeight) { + this.setState({ + maxHeight + }); + } } _addListener() { @@ -99,10 +106,10 @@ class Menu extends Component { // Listeners onWindowClick = (event) => { - const menu = ReactDOM.findDOMNode(this.refs.menu); - const menuContent = ReactDOM.findDOMNode(this.refs.menuContent); + const menu = ReactDOM.findDOMNode(this._menuRef.current); + const menuContent = ReactDOM.findDOMNode(this._menuContentRef.current); - if (!menu) { + if (!menu || !menuContent) { return; } @@ -116,7 +123,17 @@ class Menu extends Component { this.setMaxHeight(); } - onWindowScroll = () => { + onWindowScroll = (event) => { + if (!this._menuContentRef.current) { + return; + } + + const menuContent = ReactDOM.findDOMNode(this._menuContentRef.current); + + if (menuContent && menuContent.contains(event.target)) { + return; + } + this.setMaxHeight(); } @@ -158,35 +175,46 @@ class Menu extends Component { } ); - const content = React.cloneElement( - childrenArray[1], - { - ref: 'menuContent', - alignMenu, - maxHeight, - isOpen: isMenuOpen - } - ); - return ( -
- {button} -
+ renderTarget={ + (ref) => { + this._menuRef = ref; - { - isMenuOpen && - content + return ( +
+ {button} +
+ ); + } } -
+ renderElement={ + (ref) => { + this._menuContentRef = ref; + + if (!isMenuOpen) { + return null; + } + + return React.cloneElement( + childrenArray[1], + { + ref, + alignMenu, + maxHeight, + isOpen: isMenuOpen + } + ); + } + } + /> ); } } diff --git a/frontend/src/Components/Tooltip/Popover.js b/frontend/src/Components/Tooltip/Popover.js index c958fce1b..567815654 100644 --- a/frontend/src/Components/Tooltip/Popover.js +++ b/frontend/src/Components/Tooltip/Popover.js @@ -105,42 +105,53 @@ class Popover extends Component { element: styles.tether }} {...tetherOptions[position]} - > - - {anchor} - - - { - this.state.isOpen && -
( + -
-
+ {anchor} + + ) + } + renderElement={ + (ref) => { + if (!this.state.isOpen) { + return null; + } -
- {title} -
+ return ( +
+
+
-
- {body} +
+ {title} +
+ +
+ {body} +
-
+ ); + } } - + /> ); } } diff --git a/frontend/src/Components/Tooltip/Tooltip.js b/frontend/src/Components/Tooltip/Tooltip.js index 43caf87e8..40293081c 100644 --- a/frontend/src/Components/Tooltip/Tooltip.js +++ b/frontend/src/Components/Tooltip/Tooltip.js @@ -105,44 +105,55 @@ class Tooltip extends Component { element: styles.tether }} {...tetherOptions[position]} - > - - {anchor} - - - { - this.state.isOpen && -
( + + {anchor} + + ) + } + renderElement={ + (ref) => { + if (!this.state.isOpen) { + return; + } + + return (
+ > +
-
- {tooltip} +
+ {tooltip} +
-
+ ); + } } - + /> ); } } diff --git a/package.json b/package.json index 2af318098..bfe56581d 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "react-router-dom": "4.3.1", "react-slider": "0.11.2", "react-tabs": "3.0.0", - "react-tether": "1.0.1", + "react-tether": "2.0.0", "react-text-truncate": "0.14.0", "react-virtualized": "9.21.0", "redux": "4.0.1", diff --git a/yarn.lock b/yarn.lock index 0116c2e18..cbb53cf77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6940,13 +6940,13 @@ react-tabs@3.0.0: classnames "^2.2.0" prop-types "^15.5.0" -react-tether@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/react-tether/-/react-tether-1.0.1.tgz#6e5173764d4f9b8bef6d1b20ff51972909674942" - integrity sha512-OsgGk2hmsIpnpMl1Uq9aYKopG4V7bDuz2msNYPaRosF0CBbpa1YVF9P1qJ8MRsf1Zj/oK/I2uH++S+ffqxL98A== +react-tether@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-tether/-/react-tether-2.0.0.tgz#84928b9636f1fe0a6874d1e450e7822e87f8cb07" + integrity sha512-iJnqTQV42Pf7w4xrg3g1gxSxbBCXleDt8AzlSoAqRINqB+mhcJUeegpB8SFMJ/nKT7lSfMkx3GvUfYY+9sPBGw== dependencies: - prop-types "^15.5.8" - tether "^1.4.3" + prop-types "^15.6.2" + tether "^1.4.5" react-text-truncate@0.14.0: version "0.14.0" @@ -8243,7 +8243,7 @@ terser@^3.16.1: source-map "~0.6.1" source-map-support "~0.5.9" -tether@^1.4.3: +tether@^1.4.5: version "1.4.5" resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.5.tgz#8efd7b35572767ba502259ba9b1cc167fcf6f2c1" integrity sha512-fysT1Gug2wbRi7a6waeu39yVDwiNtvwj5m9eRD+qZDSHKNghLo6KqP/U3yM2ap6TNUL2skjXGJaJJTJqoC31vw==