diff --git a/ui/src/shared/components/OptIn.js b/ui/src/shared/components/OptIn.tsx similarity index 64% rename from ui/src/shared/components/OptIn.js rename to ui/src/shared/components/OptIn.tsx index 2160648e7e..50c40ec140 100644 --- a/ui/src/shared/components/OptIn.js +++ b/ui/src/shared/components/OptIn.tsx @@ -1,14 +1,42 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' +import React, {Component, ChangeEvent, KeyboardEvent, MouseEvent} from 'react' import classnames from 'classnames' import uuid from 'uuid' -import ClickOutsideInput from 'shared/components/ClickOutsideInput' +import ClickOutsideInput from 'src/shared/components/ClickOutsideInput' import {ErrorHandling} from 'src/shared/decorators/errors' +interface Props { + min: string + fixedPlaceholder: string + fixedValue: string + customPlaceholder: string + customValue: string + onSetValue: (value: string) => void + type: string | number +} + +interface State { + fixedValue: string + customValue: string + useCustomValue: boolean +} + @ErrorHandling -class OptIn extends Component { +export default class OptIn extends Component { + public static defaultProps: Partial = { + fixedValue: '', + customPlaceholder: 'Custom Value', + fixedPlaceholder: 'auto', + customValue: '', + } + + private id: string + private isCustomValueInputFocused: boolean + private grooveKnobContainer: HTMLElement + private grooveKnob: HTMLElement + private customValueInput: HTMLInputElement + constructor(props) { super(props) @@ -24,84 +52,7 @@ class OptIn extends Component { this.isCustomValueInputFocused = false } - useFixedValue = () => { - this.setState({useCustomValue: false, customValue: ''}, () => - this.setValue() - ) - } - - useCustomValue = () => { - this.setState({useCustomValue: true}, () => this.setValue()) - } - - handleClickToggle = () => { - const useCustomValueNext = !this.state.useCustomValue - if (useCustomValueNext) { - this.useCustomValue() - this.customValueInput.focus() - } else { - this.useFixedValue() - } - } - - handleFocusCustomValueInput = () => { - this.isCustomValueInputFocused = true - this.useCustomValue() - } - - handleChangeCustomValue = e => { - this.setCustomValue(e.target.value) - } - - handleKeyDownCustomValueInput = e => { - if (e.key === 'Enter' || e.key === 'Tab') { - if (e.key === 'Enter') { - this.customValueInput.blur() - } - this.considerResetCustomValue() - } - } - - handleClickOutsideInput = e => { - if ( - e.target.id !== this.grooveKnob.id && - e.target.id !== this.grooveKnobContainer.id && - this.isCustomValueInputFocused - ) { - this.considerResetCustomValue() - } - } - - considerResetCustomValue = () => { - const customValue = this.customValueInput.value.trim() - - this.setState({customValue}) - - if (customValue === '') { - this.useFixedValue() - } - - this.isCustomValueInputFocused = false - } - - setCustomValue = value => { - this.setState({customValue: value}, this.setValue) - } - - setValue = () => { - const {onSetValue} = this.props - const {useCustomValue, fixedValue, customValue} = this.state - - if (useCustomValue) { - onSetValue(customValue) - } else { - onSetValue(fixedValue) - } - } - - handleInputRef = el => (this.customValueInput = el) - - render() { + public render() { const {fixedPlaceholder, customPlaceholder, type, min} = this.props const {useCustomValue, customValue} = this.state @@ -143,25 +94,86 @@ class OptIn extends Component { ) } + + private useFixedValue = (): void => { + this.setState({useCustomValue: false, customValue: ''}, () => + this.setValue() + ) + } + + private useCustomValue = (): void => { + this.setState({useCustomValue: true}, () => this.setValue()) + } + + private handleClickToggle = (): void => { + const useCustomValueNext = !this.state.useCustomValue + if (useCustomValueNext) { + this.useCustomValue() + this.customValueInput.focus() + } else { + this.useFixedValue() + } + } + + private handleFocusCustomValueInput = (): void => { + this.isCustomValueInputFocused = true + this.useCustomValue() + } + + private handleChangeCustomValue = ( + e: ChangeEvent + ): void => { + this.setCustomValue(e.target.value) + } + + private handleKeyDownCustomValueInput = ( + e: KeyboardEvent + ): void => { + if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Enter') { + this.customValueInput.blur() + } + this.considerResetCustomValue() + } + } + + private handleClickOutsideInput = (e: MouseEvent): void => { + if ( + e.currentTarget.id !== this.grooveKnob.id && + e.currentTarget.id !== this.grooveKnobContainer.id && + this.isCustomValueInputFocused + ) { + this.considerResetCustomValue() + } + } + + private considerResetCustomValue = (): void => { + const customValue = this.customValueInput.value.trim() + + this.setState({customValue}) + + if (customValue === '') { + this.useFixedValue() + } + + this.isCustomValueInputFocused = false + } + + private setCustomValue = (value): void => { + this.setState({customValue: value}, this.setValue) + } + + private setValue = (): void => { + const {onSetValue} = this.props + const {useCustomValue, fixedValue, customValue} = this.state + + if (useCustomValue) { + onSetValue(customValue) + } else { + onSetValue(fixedValue) + } + } + + private handleInputRef = (el: HTMLInputElement) => + (this.customValueInput = el) } - -OptIn.defaultProps = { - fixedValue: '', - customPlaceholder: 'Custom Value', - fixedPlaceholder: 'auto', - customValue: '', -} - -const {func, oneOf, string} = PropTypes - -OptIn.propTypes = { - min: string, - fixedPlaceholder: string, - fixedValue: string, - customPlaceholder: string, - customValue: string, - onSetValue: func.isRequired, - type: oneOf(['text', 'number']), -} - -export default OptIn