MyCrypto/common/components/ui/DropdownShell.tsx
William O'Beirne a043334685 Node Refactor (#1603)
* Initial work on refactoring node definitions to reduce number of places theyre defined, amount of copy pasting.

* Use makeAutoNodeNAme instead of manually appending _auto

* Add getNetVersion to list of unsupported methods

* PR feedback

* Rework web template node selector to be a network selector. Refactor some types to help with that. Better handle removing custom nodes.

* Remove color dropdown.

* Fix selecting custom networks. Show notification if change network intent fails.

* Use selectors for current node / network instead of intuiting from nodeSelection

* Add id key to all networks, simplify add and remove custom node and network functions.

* Fix a lot of uses of network.name to use network.id instead.

* Dont allow network chainid conflicts

* Fix web3 network by chainid

* Add testnet badge to network selector

* Change nomenclature from change(Node|Network)(Intent)? to change(Node|Network)(Requested|Succeeded)

* tscheck

* Better code for chainid collision

* Remove console logs

* Fix tests

* Network selector becomes self contained component used both by web header and electron nav.

* Dont select node again

* Additional title text

* tscheck

* Custom node behavior in Electron

* Close panel too

* Convert node label data into selector function

* tscheck

* Parens & space
2018-05-29 09:51:42 -05:00

91 lines
2.1 KiB
TypeScript

import React, { Component } from 'react';
import classnames from 'classnames';
interface Props {
ariaLabel: string;
disabled?: boolean;
size?: string;
color?: string;
renderLabel(): any;
renderOptions(): any;
}
interface State {
expanded: boolean;
}
export default class DropdownComponent extends Component<Props, State> {
public static defaultProps = {
color: 'default',
size: 'sm'
};
public state: State = {
expanded: false
};
private dropdown: HTMLElement | null;
public componentDidMount() {
document.addEventListener('click', this.clickOffHandler);
}
public componentWillUnmount() {
document.removeEventListener('click', this.clickOffHandler);
}
public render() {
const { ariaLabel, color, disabled, size, renderOptions, renderLabel } = this.props;
const { expanded } = this.state;
const toggleClasses = classnames(['dropdown-toggle', 'btn', `btn-${color}`, `btn-${size}`]);
return (
<span
className={`dropdown ${expanded || disabled ? 'open' : ''}`}
ref={el => (this.dropdown = el)}
>
<a
tabIndex={0}
aria-haspopup="true"
aria-expanded={expanded}
aria-label={ariaLabel}
className={toggleClasses}
onClick={this.toggle}
>
{renderLabel()}
{!disabled && <i className="caret" />}
</a>
{expanded && !disabled && renderOptions()}
</span>
);
}
public toggle = () => {
this.setState({ expanded: !this.state.expanded });
};
public open = () => {
this.setState({ expanded: true });
};
public close = () => {
this.setState({ expanded: false });
};
private clickOffHandler = (ev: MouseEvent) => {
// Only calculate if dropdown is open & we have the ref
if (!this.state.expanded || !this.dropdown) {
return;
}
// If it's an element that's not inside of the dropdown, close it up
if (
this.dropdown !== ev.target &&
ev.target instanceof HTMLElement &&
!this.dropdown.contains(ev.target)
) {
this.setState({ expanded: false });
}
};
}