diff options
-rw-r--r-- | packages/instant/src/components/amount_input.tsx | 10 | ||||
-rw-r--r-- | packages/instant/src/components/scaling_input.tsx | 82 |
2 files changed, 88 insertions, 4 deletions
diff --git a/packages/instant/src/components/amount_input.tsx b/packages/instant/src/components/amount_input.tsx index c89fb05ad..f6f562be8 100644 --- a/packages/instant/src/components/amount_input.tsx +++ b/packages/instant/src/components/amount_input.tsx @@ -5,7 +5,8 @@ import * as React from 'react'; import { ColorOption } from '../style/theme'; import { util } from '../util/util'; -import { Container, Input } from './ui'; +import { ScalingInput } from './scaling_input'; +import { Container, Text } from './ui'; export interface AmountInputProps { fontColor?: ColorOption; @@ -22,13 +23,14 @@ export class AmountInput extends React.Component<AmountInputProps> { const { fontColor, fontSize, value } = this.props; return ( <Container borderBottom="1px solid rgba(255,255,255,0.3)" display="inline-block"> - <Input + <ScalingInput + startWidthCh={3.5} + endWidthCh={6} + startFontSizePx={45} fontColor={fontColor} - fontSize={fontSize} onChange={this._handleChange} value={!_.isUndefined(value) ? value.toString() : ''} placeholder="0.00" - width="2.2em" /> </Container> ); diff --git a/packages/instant/src/components/scaling_input.tsx b/packages/instant/src/components/scaling_input.tsx new file mode 100644 index 000000000..ea0a925d2 --- /dev/null +++ b/packages/instant/src/components/scaling_input.tsx @@ -0,0 +1,82 @@ +import { BigNumber } from '@0x/utils'; +import * as _ from 'lodash'; +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; + +import { ColorOption } from '../style/theme'; +import { util } from '../util/util'; + +import { Container, Input } from './ui'; + +export enum ScalingInputPhase { + Start, + Scaling, + End, +} + +export interface ScalingInputProps { + startWidthCh: number; + endWidthCh: number; + startFontSizePx: number; + value?: string; + onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; + fontColor?: ColorOption; + placeholder?: string; +} +// Magic value obtained via trial-and-error +const scalingRateToMaintainSameWidth = 0.1; +export class ScalingInput extends React.Component<ScalingInputProps> { + public static defaultProps = { + onChange: util.boundNoop, + }; + public render(): React.ReactNode { + const { fontColor, onChange, placeholder, value } = this.props; + const phase = this._getPhase(); + return ( + <Input + fontColor={fontColor} + onChange={onChange} + value={value} + placeholder={placeholder} + fontSize={this._calculateFontSize(phase)} + width={this._calculateWidth(phase)} + /> + ); + } + private readonly _calculateFontSize = (phase: ScalingInputPhase): string => { + const { value, endWidthCh, startFontSizePx } = this.props; + if (_.isUndefined(value) || phase !== ScalingInputPhase.End) { + return `${startFontSizePx}px`; + } + const charactersOverMax = value.length - endWidthCh; + const pixelsToReduceFontSizeBy = charactersOverMax * 2; + const newFontSizePx = startFontSizePx - pixelsToReduceFontSizeBy; + return `${newFontSizePx}px`; + }; + private readonly _calculateWidth = (phase: ScalingInputPhase): string => { + const { value, startWidthCh, endWidthCh } = this.props; + if (_.isUndefined(value)) { + return `${startWidthCh}ch`; + } + switch (phase) { + case ScalingInputPhase.Start: + return `${startWidthCh}ch`; + case ScalingInputPhase.Scaling: + return `${value.length}ch`; + case ScalingInputPhase.End: + return `${endWidthCh}ch`; + default: + return `${startWidthCh}ch`; + } + }; + private readonly _getPhase = (): ScalingInputPhase => { + const { value, startWidthCh, endWidthCh } = this.props; + if (_.isUndefined(value) || value.length <= this.props.startWidthCh) { + return ScalingInputPhase.Start; + } + if (value.length > startWidthCh && value.length <= endWidthCh) { + return ScalingInputPhase.Scaling; + } + return ScalingInputPhase.End; + }; +} |