import * as React from "react" ; import { Observable } from "babylonjs/Misc/observable" ; import { PropertyChangedEvent } from "./propertyChangedEvent" ; import { GlobalState } from "../globalState" ; interface IFloatLineComponentProps { label : string ; target : any ; propertyName : string ; onChange ? : ( newValue : number ) => void ; isInteger ? : boolean ; onPropertyChangedObservable ? : Observable < PropertyChangedEvent > ; additionalClass ? : string ; step ? : string ; digits ? : number ; globalState : GlobalState ; min ? : number ; max ? : number ; smallUI ? : boolean ; onEnter ? : ( newValue : number ) => void ; } export class FloatLineComponent extends React . Component < IFloatLineComponentProps , { value : string ; } > { private _localChange = false ; private _store : number ; private _regExp : RegExp ; private _onFocus = false ; constructor ( props ) { super ( props ) ; let currentValue = this . props . target [ this . props . propertyName ] ; this . state = { value : currentValue ? ( this . props . isInteger ? currentValue . toFixed ( 0 ) : currentValue . toFixed ( this . props . digits || 4 ) ) : "0" } ; this . _store = currentValue ; let rexp = "(.*\\." ; let numDigits = this . props . digits || 4 ; while ( numDigits -- ) { rexp += "." ; } rexp += ").+" ; this . _regExp = new RegExp ( rexp ) ; } shouldComponentUpdate ( nextProps , nextState ) { if ( this . _localChange ) { this . _localChange = false ; return true ; } const newValue = nextProps . target [ nextProps . propertyName ] ; const newValueString = newValue ? ( this . props . isInteger ? newValue . toFixed ( 0 ) : newValue . toFixed ( this . props . digits || 4 ) ) : "0" ; if ( newValueString !== nextState . value ) { nextState . value = newValueString ; return true ; } return false ; } componentWillUnmount ( ) { if ( this . _onFocus ) { if ( this . props . onEnter ) { this . props . onEnter ( this . _store ) ; } } } raiseOnPropertyChanged ( newValue , previousValue ) { if ( this . props . onChange ) { this . props . onChange ( newValue ) ; } if ( ! this . props . onPropertyChangedObservable ) { return ; } this . props . onPropertyChangedObservable . notifyObservers ( { object : this . props . target , property : this . props . propertyName , value : newValue , initialValue : previousValue , } ) ; } updateValue ( valueString ) { if ( /[^0-9\.\-]/g . test ( valueString ) ) { return ; } valueString = valueString . replace ( this . _regExp , "$1" ) ; let valueAsNumber ; if ( this . props . isInteger ) { valueAsNumber = parseInt ( valueString ) ; } else { valueAsNumber = parseFloat ( valueString ) ; } this . _localChange = true ; this . setState ( { value : valueString } ) ; if ( isNaN ( valueAsNumber ) ) { return ; } if ( this . props . max != undefined && valueAsNumber > this . props . max ) { valueAsNumber = this . props . max ; } if ( this . props . min != undefined && valueAsNumber < this . props . min ) { valueAsNumber = this . props . min ; } this . props . target [ this . props . propertyName ] = valueAsNumber ; this . raiseOnPropertyChanged ( valueAsNumber , this . _store ) ; this . _store = valueAsNumber ; } render ( ) { let className = this . props . smallUI ? "short" : "value" ; return ( < > { < div className = { this . props . additionalClass ? this . props . additionalClass + " floatLine" : "floatLine" } > < div className = "label" title = { this . props . label } > { this . props . label } < /div> < div className = { className } > < input type = "number" step = { this . props . step || "0.01" } className = "numeric-input" onBlur = { ( evt ) => { this . _onFocus = false ; this . props . globalState . blockKeyboardEvents = false ; if ( this . props . onEnter ) { this . props . onEnter ( this . _store ) ; } } } onKeyDown = { ( evt ) => { if ( evt . keyCode !== 13 ) { return ; } if ( this . props . onEnter ) { this . props . onEnter ( this . _store ) ; } } } onFocus = { ( ) => { this . props . globalState . blockKeyboardEvents = true ; this . _onFocus = true ; } } value = { this . state . value } onChange = { ( evt ) => this . updateValue ( evt . target . value ) } /> < /div> < /div>} < />); } }