import React, { MouseEventHandler } from 'react';
import clsx from 'clsx';
import { AccountSwitcher } from 'app/components/accounts';
import styles from './loggedInPanel.scss';
export default class LoggedInPanel extends React.Component<
{
username: string;
},
{
isAccountSwitcherActive: boolean;
}
> {
state = {
isAccountSwitcherActive: false,
};
_isMounted: boolean = false;
el: HTMLElement | null;
componentDidMount() {
if (window.document) {
// @ts-ignore
window.document.addEventListener('click', this.onBodyClick);
}
this._isMounted = true;
}
componentWillUnmount() {
if (window.document) {
// @ts-ignore
window.document.removeEventListener('click', this.onBodyClick);
}
this._isMounted = false;
}
render() {
const { username } = this.props;
const { isAccountSwitcherActive } = this.state;
return (
(this.el = el)} className={clsx(styles.loggedInPanel)}>
);
}
toggleAccountSwitcher = () =>
this._isMounted &&
this.setState({
isAccountSwitcherActive: !this.state.isAccountSwitcherActive,
});
onToggleAccountSwitcher = () => {
this.toggleAccountSwitcher();
};
onExpandAccountSwitcher = (event: React.MouseEvent) => {
event.preventDefault();
this.toggleAccountSwitcher();
};
onBodyClick = createOnOutsideComponentClickHandler(
() => this.el,
() => this.state.isAccountSwitcherActive && this._isMounted,
() => this.toggleAccountSwitcher(),
);
}
/**
* Creates an event handling function to handle clicks outside the component
*
* The handler will check if current click was outside container el and if so
* and component isActive, it will call the callback
*
* @param {Function} getEl - the function, that returns reference to container el
* @param {Function} isActive - whether the component is active and callback may be called
* @param {Function} callback - the callback to call, when there was a click outside el
*
* @returns {Function}
*/
function createOnOutsideComponentClickHandler(
getEl: () => HTMLElement | null,
isActive: () => boolean,
callback: () => void,
): MouseEventHandler {
// TODO: we have the same logic in LangMenu
// Probably we should decouple this into some helper function
// TODO: the name of function may be better...
return event => {
const el = getEl();
if (isActive() && el) {
if (!el.contains(event.target as HTMLElement) && el !== event.target) {
event.preventDefault();
// add a small delay for the case someone have alredy called toggle
setTimeout(() => isActive() && callback(), 0);
}
}
};
}