diff --git a/src/components/views/elements/AddressSelector.js b/src/components/views/elements/AddressSelector.tsx similarity index 70% rename from src/components/views/elements/AddressSelector.js rename to src/components/views/elements/AddressSelector.tsx index b7c9124438..c55f6f22d2 100644 --- a/src/components/views/elements/AddressSelector.js +++ b/src/components/views/elements/AddressSelector.tsx @@ -15,30 +15,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; +import React, { createRef } from 'react'; import * as sdk from '../../../index'; import classNames from 'classnames'; -import { UserAddressType } from '../../../UserAddress'; import { replaceableComponent } from "../../../utils/replaceableComponent"; +interface IProps { + onSelected: (index: number) => void; + + // List of the addresses to display + addressList; // FIXME: UserAddressType should be an interface + // Whether to show the address on the address tiles + showAddress?: boolean; + truncateAt: number; + selected?: number; + + // Element to put as a header on top of the list + header?: JSX.Element; +} + +interface IState { + selected: number; + hover: boolean; +} + @replaceableComponent("views.elements.AddressSelector") -export default class AddressSelector extends React.Component { - static propTypes = { - onSelected: PropTypes.func.isRequired, +export default class AddressSelector extends React.Component { + private scrollElement = createRef(); + private addressListElement = createRef(); - // List of the addresses to display - addressList: PropTypes.arrayOf(UserAddressType).isRequired, - // Whether to show the address on the address tiles - showAddress: PropTypes.bool, - truncateAt: PropTypes.number.isRequired, - selected: PropTypes.number, - - // Element to put as a header on top of the list - header: PropTypes.node, - }; - - constructor(props) { + constructor(props: IProps) { super(props); this.state = { @@ -48,10 +54,10 @@ export default class AddressSelector extends React.Component { } // TODO: [REACT-WARNING] Replace with appropriate lifecycle event - UNSAFE_componentWillReceiveProps(props) { // eslint-disable-line camelcase + UNSAFE_componentWillReceiveProps(props: IProps) { // eslint-disable-line // Make sure the selected item isn't outside the list bounds const selected = this.state.selected; - const maxSelected = this._maxSelected(props.addressList); + const maxSelected = this.maxSelected(props.addressList); if (selected > maxSelected) { this.setState({ selected: maxSelected }); } @@ -60,13 +66,13 @@ export default class AddressSelector extends React.Component { componentDidUpdate() { // As the user scrolls with the arrow keys keep the selected item // at the top of the window. - if (this.scrollElement && this.props.addressList.length > 0 && !this.state.hover) { - const elementHeight = this.addressListElement.getBoundingClientRect().height; - this.scrollElement.scrollTop = (this.state.selected * elementHeight) - elementHeight; + if (this.scrollElement.current && this.props.addressList.length > 0 && !this.state.hover) { + const elementHeight = this.addressListElement.current.getBoundingClientRect().height; + this.scrollElement.current.scrollTop = (this.state.selected * elementHeight) - elementHeight; } } - moveSelectionTop = () => { + public moveSelectionTop = (): void => { if (this.state.selected > 0) { this.setState({ selected: 0, @@ -75,7 +81,7 @@ export default class AddressSelector extends React.Component { } }; - moveSelectionUp = () => { + public moveSelectionUp = (): void => { if (this.state.selected > 0) { this.setState({ selected: this.state.selected - 1, @@ -84,8 +90,8 @@ export default class AddressSelector extends React.Component { } }; - moveSelectionDown = () => { - if (this.state.selected < this._maxSelected(this.props.addressList)) { + public moveSelectionDown = (): void => { + if (this.state.selected < this.maxSelected(this.props.addressList)) { this.setState({ selected: this.state.selected + 1, hover: false, @@ -93,26 +99,26 @@ export default class AddressSelector extends React.Component { } }; - chooseSelection = () => { + public chooseSelection = (): void => { this.selectAddress(this.state.selected); }; - onClick = index => { + private onClick = (index: number): void => { this.selectAddress(index); }; - onMouseEnter = index => { + private onMouseEnter = (index: number): void => { this.setState({ selected: index, hover: true, }); }; - onMouseLeave = () => { + private onMouseLeave = (): void => { this.setState({ hover: false }); }; - selectAddress = index => { + private selectAddress = (index: number): void => { // Only try to select an address if one exists if (this.props.addressList.length !== 0) { this.props.onSelected(index); @@ -120,9 +126,9 @@ export default class AddressSelector extends React.Component { } }; - createAddressListTiles() { + private createAddressListTiles(): JSX.Element[] { const AddressTile = sdk.getComponent("elements.AddressTile"); - const maxSelected = this._maxSelected(this.props.addressList); + const maxSelected = this.maxSelected(this.props.addressList); const addressList = []; // Only create the address elements if there are address @@ -143,7 +149,7 @@ export default class AddressSelector extends React.Component { onMouseEnter={this.onMouseEnter.bind(this, i)} onMouseLeave={this.onMouseLeave} key={this.props.addressList[i].addressType + "/" + this.props.addressList[i].address} - ref={(ref) => { this.addressListElement = ref; }} + ref={this.addressListElement} > (this.props.truncateAt - 1) ? (this.props.truncateAt - 1) : listSize; return maxSelected; @@ -172,7 +178,7 @@ export default class AddressSelector extends React.Component { }); return ( -
{this.scrollElement = ref;}}> +
{ this.props.header } { this.createAddressListTiles() }