diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/instant/src/components/asset_amount_input.tsx | 15 | ||||
-rw-r--r-- | packages/instant/src/components/scaling_amount_input.tsx | 8 | ||||
-rw-r--r-- | packages/instant/src/components/scaling_input.tsx | 73 |
3 files changed, 57 insertions, 39 deletions
diff --git a/packages/instant/src/components/asset_amount_input.tsx b/packages/instant/src/components/asset_amount_input.tsx index 0b22c889c..beb21a4cf 100644 --- a/packages/instant/src/components/asset_amount_input.tsx +++ b/packages/instant/src/components/asset_amount_input.tsx @@ -41,8 +41,9 @@ export class AssetAmountInput extends React.Component<AssetAmountInputProps, Ass {...rest} startWidthCh={3.5} endWidthCh={5} - fontSizePx={this.state.currentFontSizePx} + maxFontSizePx={this.props.startingFontSizePx} onChange={this._handleChange} + onFontSizeChange={this._handleFontSizeChange} /> </Container> <Container display="inline-block" marginLeft="10px"> @@ -57,12 +58,12 @@ export class AssetAmountInput extends React.Component<AssetAmountInputProps, Ass </Container> ); } - private readonly _handleChange = (value?: BigNumber, fontSize?: number): void => { + private readonly _handleChange = (value?: BigNumber): void => { this.props.onChange(value, this.props.asset); - if (!_.isUndefined(fontSize)) { - this.setState({ - currentFontSizePx: fontSize, - }); - } + }; + private readonly _handleFontSizeChange = (fontSizePx: number): void => { + this.setState({ + currentFontSizePx: fontSizePx, + }); }; } diff --git a/packages/instant/src/components/scaling_amount_input.tsx b/packages/instant/src/components/scaling_amount_input.tsx index a0b7b74af..83375af00 100644 --- a/packages/instant/src/components/scaling_amount_input.tsx +++ b/packages/instant/src/components/scaling_amount_input.tsx @@ -9,12 +9,13 @@ import { ScalingInput } from './scaling_input'; import { Container, Text } from './ui'; export interface ScalingAmountInputProps { - fontSizePx: number; + maxFontSizePx: number; startWidthCh: number; endWidthCh: number; fontColor?: ColorOption; value?: BigNumber; onChange: (value?: BigNumber, fontSize?: number) => void; + onFontSizeChange: (fontSizePx: number) => void; } export class ScalingAmountInput extends React.Component<ScalingAmountInputProps> { @@ -23,12 +24,13 @@ export class ScalingAmountInput extends React.Component<ScalingAmountInputProps> onFontSizeChange: util.boundNoop, }; public render(): React.ReactNode { - const { startWidthCh, endWidthCh, fontColor, fontSizePx, value } = this.props; + const { startWidthCh, endWidthCh, fontColor, maxFontSizePx, value, onFontSizeChange } = this.props; return ( <ScalingInput startWidthCh={startWidthCh} endWidthCh={endWidthCh} - fontSizePx={fontSizePx} + maxFontSizePx={maxFontSizePx} + onFontSizeChange={onFontSizeChange} fontColor={fontColor} onChange={this._handleChange} value={!_.isUndefined(value) ? value.toString() : ''} diff --git a/packages/instant/src/components/scaling_input.tsx b/packages/instant/src/components/scaling_input.tsx index a2c4ba342..7824c10f9 100644 --- a/packages/instant/src/components/scaling_input.tsx +++ b/packages/instant/src/components/scaling_input.tsx @@ -17,21 +17,29 @@ export enum ScalingInputPhase { export interface ScalingInputProps { startWidthCh: number; endWidthCh: number; - fontSizePx: number; + maxFontSizePx: number; value?: string; - onChange: (event: React.ChangeEvent<HTMLInputElement>, fontSize: number) => void; + onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; + onFontSizeChange: (fontSizePx: number) => void; fontColor?: ColorOption; placeholder?: string; + maxLength?: number; } -export interface ScalingInputProps { +export interface ScalingInputState { fixedWidthInPxIfExists?: number; } -export class ScalingInput extends React.Component<ScalingInputProps> { +export interface ScalingInputSnapshot { + inputWidthPx: number; +} +// This is a magic number that was determined experimentally. +const percentageToReduceByPerCharacter = 0.15; +export class ScalingInput extends React.Component<ScalingInputProps, ScalingInputState> { public static defaultProps = { onChange: util.boundNoop, onFontSizeChange: util.boundNoop, + maxLength: 10, }; public state = { fixedWidthInPxIfExists: undefined, @@ -50,13 +58,35 @@ export class ScalingInput extends React.Component<ScalingInputProps> { const { value, startWidthCh, endWidthCh } = props; return ScalingInput.getPhase(startWidthCh, endWidthCh, value); } - public componentDidUpdate(prevProps: ScalingInputProps): void { + public static calculateFontSize(props: ScalingInputProps): number { + const { startWidthCh, endWidthCh, value, maxFontSizePx } = props; + const phase = ScalingInput.getPhase(startWidthCh, endWidthCh, value); + if (_.isUndefined(value) || phase !== ScalingInputPhase.End) { + return maxFontSizePx; + } + const charactersOverMax = value.length - endWidthCh; + const scalingFactor = (1 - percentageToReduceByPerCharacter) ** charactersOverMax; + const fontSize = scalingFactor * maxFontSizePx; + return fontSize; + } + public getSnapshotBeforeUpdate(): ScalingInputSnapshot { + return { + inputWidthPx: this._getInputWidthInPx(), + }; + } + public componentDidUpdate( + prevProps: ScalingInputProps, + prevState: ScalingInputState, + snapshot: ScalingInputSnapshot, + ): void { const prevPhase = ScalingInput.getPhaseFromProps(prevProps); const curPhase = ScalingInput.getPhaseFromProps(this.props); + const prevFontSize = ScalingInput.calculateFontSize(prevProps); + const curFontSize = ScalingInput.calculateFontSize(this.props); // if we went from anything else to end, fix to the current width as it shouldn't change as we grow if (prevPhase !== ScalingInputPhase.End && curPhase === ScalingInputPhase.End) { this.setState({ - fixedWidthInPxIfExists: this._getInputWidthInPx(), + fixedWidthInPxIfExists: snapshot.inputWidthPx, }); } // if we end from end to to anything else, un-fix the width @@ -65,19 +95,24 @@ export class ScalingInput extends React.Component<ScalingInputProps> { fixedWidthInPxIfExists: undefined, }); } + // If font size has changed, notify. + if (prevFontSize !== curFontSize) { + this.props.onFontSizeChange(curFontSize); + } } public render(): React.ReactNode { - const { fontColor, onChange, placeholder, value } = this.props; + const { fontColor, onChange, placeholder, value, maxLength } = this.props; const phase = ScalingInput.getPhaseFromProps(this.props); return ( <Input ref={this._inputRef as any} fontColor={fontColor} - onChange={this._handleChange} + onChange={onChange} value={value} placeholder={placeholder} - fontSize={`${this.props.fontSizePx}px`} + fontSize={`${ScalingInput.calculateFontSize(this.props)}px`} width={this._calculateWidth()} + maxLength={maxLength} /> ); } @@ -108,24 +143,4 @@ export class ScalingInput extends React.Component<ScalingInputProps> { } return (ref as any).getBoundingClientRect().width; }; - private readonly _calculateNextFontSize = ( - currentFontSizePx: number, - value: string, - startWidthCh: number, - endWidthCh: number, - ): number => { - const phase = ScalingInput.getPhase(startWidthCh, endWidthCh, value); - if (_.isUndefined(value) || phase !== ScalingInputPhase.End) { - return currentFontSizePx; - } - const charactersOverMax = value.length - endWidthCh; - const pixelsToReduceFontSizeBy = charactersOverMax * 5; - const fontSize = currentFontSizePx - pixelsToReduceFontSizeBy; - return fontSize; - }; - private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const value = event.target.value; - const { fontSizePx, startWidthCh, endWidthCh } = this.props; - this.props.onChange(event, this._calculateNextFontSize(fontSizePx, value, startWidthCh, endWidthCh)); - }; } |