mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
77 lines
2.6 KiB
JavaScript
77 lines
2.6 KiB
JavaScript
import React, { Component } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import withModalsContainer from '../Modal/withModalsContainer';
|
|
import FocusableContext from './FocusableContext';
|
|
|
|
class FocusableProvider extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.contentRef = React.createRef();
|
|
this.modalsContainerDomTreeObserver = new MutationObserver(this.onModalsContainerDomTreeChange);
|
|
this.state = {
|
|
focusable: false
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.onModalsContainerDomTreeChange();
|
|
this.modalsContainerDomTreeObserver.observe(this.props.modalsContainer, {
|
|
childList: true
|
|
});
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.modalsContainerDomTreeObserver.disconnect();
|
|
}
|
|
|
|
shouldComponentUpdate(nextProps, nextState) {
|
|
return nextState.focusable !== this.state.focusable ||
|
|
nextProps.modalsContainer !== this.props.modalsContainer ||
|
|
nextProps.children !== this.props.children;
|
|
}
|
|
|
|
componentDidUpdate(prevProps, prevState) {
|
|
if (prevState.focusable && !this.state.focusable) {
|
|
const focusedElement = this.contentRef.current.querySelector(':focus');
|
|
if (focusedElement !== null) {
|
|
focusedElement.blur();
|
|
}
|
|
}
|
|
|
|
if (prevProps.modalsContainer !== this.props.modalsContainer) {
|
|
this.onModalsContainerDomTreeChange();
|
|
this.modalsContainerDomTreeObserver.disconnect();
|
|
this.modalsContainerDomTreeObserver.observe(this.props.modalsContainer, {
|
|
childList: true
|
|
});
|
|
}
|
|
}
|
|
|
|
onModalsContainerDomTreeChange = () => {
|
|
const focusable = this.props.onModalsContainerDomTreeChange({
|
|
modalsContainerElement: this.props.modalsContainer,
|
|
contentElement: this.contentRef.current
|
|
});
|
|
this.setState({ focusable });
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<FocusableContext.Provider value={this.state.focusable}>
|
|
{React.cloneElement(React.Children.only(this.props.children), { ref: this.contentRef })}
|
|
</FocusableContext.Provider>
|
|
);
|
|
}
|
|
}
|
|
|
|
FocusableProvider.propTypes = {
|
|
modalsContainer: PropTypes.instanceOf(HTMLElement).isRequired,
|
|
onModalsContainerDomTreeChange: PropTypes.func.isRequired
|
|
};
|
|
|
|
const FocusableProviderWithModalsContainer = withModalsContainer(FocusableProvider);
|
|
|
|
FocusableProviderWithModalsContainer.displayName = 'FocusableProviderWithModalsContainer';
|
|
|
|
export default FocusableProviderWithModalsContainer;
|