William O'Beirne c0cd668c64 Custom Nodes (#322)
* Layed out components for custom nodes.

* Outline of custom nodes. Still missing various features and error handling.

* Persist custom nodes to local storage.

* Make custom nodes removable.

* Add latest block functions, call it when switching nodes.

* Initialize correct node, move node utils into utils file.

* Fix names

* Send headers along with rpc requests.

* Remove custom network options for now.

* PR feedback.

* One last log.

* Fix tests.

* Headers in batch too.

* Switch to node when you add it.

* Reduce hackery.

* Clean up linter and tsc.

* Fix latest block hex conversion.

* Unit tests.

* Fix missing property.

* Fix Modal title typing.
2017-11-18 14:33:53 -06:00

109 lines
2.8 KiB
TypeScript

import closeIcon from 'assets/images/icon-x.svg';
import React, { Component } from 'react';
import './Modal.scss';
export interface IButton {
text: string | React.ReactElement<string>;
type?:
| 'default'
| 'primary'
| 'success'
| 'info'
| 'warning'
| 'danger'
| 'link';
disabled?: boolean;
onClick?(): void;
}
interface Props {
isOpen?: boolean;
title: string | React.ReactElement<any>;
disableButtons?: boolean;
children: any;
buttons: IButton[];
handleClose(): void;
}
export default class Modal extends Component<Props, {}> {
public componentDidMount() {
this.updateBodyClass();
document.addEventListener('keydown', this.escapeListner);
}
public componentDidUpdate() {
this.updateBodyClass();
}
public updateBodyClass() {
document.body.classList.toggle('no-scroll', !!this.props.isOpen);
}
public componentWillUnmount() {
document.removeEventListener('keydown', this.escapeListner);
document.body.classList.remove('no-scroll');
}
public render() {
const { isOpen, title, children, buttons, handleClose } = this.props;
const hasButtons = buttons && buttons.length;
return (
<div>
<div className={`Modalshade ${isOpen ? 'is-open' : ''}`} />
<div className={`Modal ${isOpen ? 'is-open' : ''}`}>
<div className="Modal-header">
<h2 className="Modal-header-title">{title}</h2>
<button className="Modal-header-close" onClick={handleClose}>
<img className="Modal-header-close-icon" src={closeIcon} />
</button>
</div>
<div className="Modal-content">{isOpen && children}</div>
{hasButtons && (
<div className="Modal-footer">{this.renderButtons()}</div>
)}
</div>
</div>
);
}
private escapeListner = (ev: KeyboardEvent) => {
// Don't trigger if they hit escape while on an input
if (ev.target) {
if (
(ev.target as HTMLElement).tagName === 'INPUT' ||
(ev.target as HTMLElement).tagName === 'SELECT' ||
(ev.target as HTMLElement).tagName === 'TEXTAREA' ||
(ev.target as HTMLElement).isContentEditable
) {
return;
}
}
if (ev.key === 'Escape' || ev.keyCode === 27) {
this.props.handleClose();
}
};
private renderButtons = () => {
const { disableButtons, buttons } = this.props;
return buttons.map((btn, idx) => {
let btnClass = 'Modal-footer-btn btn';
if (btn.type) {
btnClass += ` btn-${btn.type}`;
}
return (
<button
className={btnClass}
onClick={btn.onClick}
key={idx}
disabled={disableButtons || btn.disabled}
>
{btn.text}
</button>
);
});
};
}