diff options
author | fragosti <francesco.agosti93@gmail.com> | 2018-10-23 07:45:48 +0800 |
---|---|---|
committer | fragosti <francesco.agosti93@gmail.com> | 2018-10-23 07:45:48 +0800 |
commit | 921492e8186697e477c27d76bd7eb58ce2454765 (patch) | |
tree | 7b30f9a4f5d40cafc4bbc60c7b1e02ae64de52d4 /packages/instant/src/components/scaling_input.tsx | |
parent | 77a4d7e2b76a1808c37ed9f0a97cbd3b34a0ebe9 (diff) | |
download | dexon-sol-tools-921492e8186697e477c27d76bd7eb58ce2454765.tar.gz dexon-sol-tools-921492e8186697e477c27d76bd7eb58ce2454765.tar.zst dexon-sol-tools-921492e8186697e477c27d76bd7eb58ce2454765.zip |
feature: reduce font size by a percentage instead of a constant
Diffstat (limited to 'packages/instant/src/components/scaling_input.tsx')
-rw-r--r-- | packages/instant/src/components/scaling_input.tsx | 73 |
1 files changed, 44 insertions, 29 deletions
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)); - }; } |