@@ -7,9 +7,9 @@ import {debounce, isNumeric, isEmpty} from "./Utils";
77/** 
88 * Default constants 
99 */ 
10+ const  defaultSpeed  =  2.5 ; 
11+ const  defaultAccelerationDelay  =  1000 ; 
1012const  defaultColor  =  "#3E525F" ; 
11- const  defaultLongPressDelay  =  750 ; 
12- const  defaultLongPressSpeed  =  5 ; 
1313const  defaultTypingTime  =  500 ; 
1414
1515/** 
@@ -27,6 +27,7 @@ class InputSpinner extends Component {
2727		// Timers 
2828		this . increaseTimer  =  null ; 
2929		this . decreaseTimer  =  null ; 
30+ 		this . holdTime  =  null ; 
3031
3132		let  spinnerStep  =  this . parseNum ( this . props . step ) ; 
3233		if  ( ! this . typeDecimal ( )  &&  spinnerStep  <  1 )  { 
@@ -151,23 +152,31 @@ class InputSpinner extends Component {
151152		this . decreaseTimer  =  null ; 
152153	} 
153154
155+ 	/** 
156+ 	 * Clear on change timers 
157+ 	 * @private  
158+ 	 */ 
159+ 	_clearOnChangeTimers ( )  { 
160+ 		this . _clearMaxTimer ( ) ; 
161+ 		this . _clearMinTimer ( ) ; 
162+ 	} 
163+ 
154164	/** 
155165	 * Clear all timers 
156166	 * @private  
157167	 */ 
158- 	clearTimers ( )  { 
168+ 	_clearTimers ( )  { 
169+ 		this . _clearOnChangeTimers ( ) ; 
159170		this . _clearIncreaseTimer ( ) ; 
160171		this . _clearDecreaseTimer ( ) ; 
161- 		this . _clearMaxTimer ( ) ; 
162- 		this . _clearMinTimer ( ) ; 
163172	} 
164173
165174	/** 
166175	 * On value change 
167176	 * @param  value 
168177	 */ 
169178	async  onChange ( value )  { 
170- 		this . clearTimers ( ) ; 
179+ 		this . _clearOnChangeTimers ( ) ; 
171180
172181		let  num  =  value ; 
173182		let  parsedNum  =  value ; 
@@ -188,23 +197,34 @@ class InputSpinner extends Component {
188197		num  =  parsedNum  =  this . parseNum ( String ( num ) . replace ( / ^ 0 + / ,  "" ) )  ||  0 ; 
189198		if  ( ! this . minReached ( num ) )  { 
190199			if  ( this . maxReached ( num ) )  { 
191- 				parsedNum  =  this . state . max ; 
192- 				if  ( ! isEmpty ( value ) )  { 
193- 					this . maxTimer  =  this . _debounceSetMax ( ) ; 
194- 				} 
195- 				if  ( this . props . onMax )  { 
196- 					this . props . onMax ( this . state . max ) ; 
200+ 				if  ( this . maxReached ( num ) )  { 
201+ 					parsedNum  =  this . state . max ; 
202+ 					if  ( ! isEmpty ( value ) )  { 
203+ 						this . maxTimer  =  this . _debounceSetMax ( ) ; 
204+ 					} 
205+ 					if  ( this . props . onMax )  { 
206+ 						this . props . onMax ( this . state . max ) ; 
207+ 					} 
197208				} 
198209			} 
199210		}  else  { 
200- 			parsedNum   =   this . state . min ; 
201- 			if   ( ! isEmpty ( value ) )   { 
211+ 			if   ( ! isEmpty ( value )   &&   ! this . isEmptied ( ) )   { 
212+ 				 parsedNum   =   this . state . min ; 
202213				this . minTimer  =  this . _debounceSetMin ( ) ; 
214+ 			}  else  if  ( this . isEmptied ( ) )  { 
215+ 				parsedNum  =  null ; 
216+ 			}  else  { 
217+ 				parsedNum  =  this . state . min ; 
203218			} 
204219			if  ( this . props . onMin )  { 
205- 				this . props . onMin ( this . state . min ) ; 
220+ 				this . props . onMin ( parsedNum ) ; 
206221			} 
207222		} 
223+ 
224+ 		if  ( isEmpty ( value )  &&  this . isEmptied ( ) )  { 
225+ 			parsedNum  =  value ; 
226+ 		} 
227+ 
208228		if  ( current_value  !==  num  &&  this . props . onChange )  { 
209229			const  res  =  await  this . props . onChange ( parsedNum ) ; 
210230			if  ( ! isEmpty ( value ) )  { 
@@ -222,6 +242,15 @@ class InputSpinner extends Component {
222242		} 
223243	} 
224244
245+ 	/** 
246+ 	 * On buttons press out 
247+ 	 * @param  e 
248+ 	 */ 
249+ 	onPressOut ( e )  { 
250+ 		this . _clearTimers ( ) ; 
251+ 		this . _resetHoldTime ( ) ; 
252+ 	} 
253+ 
225254	/** 
226255	 * On Button Press 
227256	 * @param  buttonDirection 
@@ -342,8 +371,6 @@ class InputSpinner extends Component {
342371			return  "" ; 
343372		}  else  { 
344373			return  String ( this . state . min ) ; 
345- 		}  else   { 
346- 			return  this . props . placeholder ; 
347374		} 
348375	} 
349376
@@ -374,11 +401,56 @@ class InputSpinner extends Component {
374401	} 
375402
376403	/** 
377- 	 * Get time to wait before increase/decrease on long press 
404+ 	 * Update holding time 
405+ 	 * @private  
406+ 	 */ 
407+ 	_startHoldTime ( )  { 
408+ 		this . holdTime  =  new  Date ( ) . getTime ( ) ; 
409+ 	} 
410+ 
411+ 	/** 
412+ 	 * Get the holding time 
413+ 	 * @private  
414+ 	 */ 
415+ 	_getHoldTime ( )  { 
416+ 		if  ( isEmpty ( this . holdTime ) )  { 
417+ 			return  0 ; 
418+ 		} 
419+ 		let  now  =  new  Date ( ) . getTime ( ) ; 
420+ 		return  now  -  this . holdTime ; 
421+ 	} 
422+ 
423+ 	/** 
424+ 	 * Reset holding time 
425+ 	 * @private  
426+ 	 */ 
427+ 	_resetHoldTime ( )  { 
428+ 		this . holdTime  =  null ; 
429+ 	} 
430+ 
431+ 	/** 
432+ 	 * Find the interval between changing values after a button has been held for a certain amount of time 
378433	 * @returns  {number } 
434+ 	 * @author  Tom Hardern <https://gist.github.com/taeh98/f709451457400818094d802cd33694d5> 
435+ 	 * @private  
379436	 */ 
380- 	getLongPressWaitingTime ( )  { 
381- 		return  1000  /  ( this . withinRange ( this . props . onLongPressSpeed ,  1 ,  10 )  *  2 ) ; 
437+ 	_getHoldChangeInterval ( )  { 
438+ 		const  MIN_HOLD_CHANGE_INTERVAL  =  10 ;  // the minimum time interval between increases or decreases in value when holding a button 
439+ 		const  HOLD_CHANGE_ACCELERATION_FACTOR  =  this . props . acceleration ;  // a factor that controls how fast the speed of the change in value will accelerate while a button is held 
440+ 		const  HOLD_CHANGE_ACCELERATION_DELAY  =  this . props . accelerationDelay ;  // how long to wait after a button is being held before the acceleration of it speed going through values starts 
441+ 		const  TIME_HOLDING_BUTTON_FOR_MIN_CHANGE_INTERVAL  = 
442+ 			( Math . exp ( MIN_HOLD_CHANGE_INTERVAL  /  - 1 )  + 
443+ 				HOLD_CHANGE_ACCELERATION_DELAY )  / 
444+ 			HOLD_CHANGE_ACCELERATION_FACTOR ; 
445+ 		const  HOLD_TIME  =  this . _getHoldTime ( ) ;  // time on hold in ms 
446+ 
447+ 		return  HOLD_TIME  >=  TIME_HOLDING_BUTTON_FOR_MIN_CHANGE_INTERVAL 
448+ 			? MIN_HOLD_CHANGE_INTERVAL  // if the button has been held for long enough, return the minimum interval 
449+ 			: - 1  * 
450+ 					Math . log ( 
451+ 						HOLD_CHANGE_ACCELERATION_FACTOR  *  HOLD_TIME  - 
452+ 							HOLD_CHANGE_ACCELERATION_DELAY , 
453+ 					) ;  // otherwise calculate with a logarithm => an exponential increase in speed 
382454	} 
383455
384456	/** 
@@ -401,9 +473,10 @@ class InputSpinner extends Component {
401473			} 
402474		} 
403475
404- 		let  wait  =  this . getLongPressWaitingTime ( ) ; 
476+ 		let  wait  =  this . _getHoldChangeInterval ( ) ; 
405477		if  ( this . increaseTimer  ===  null )  { 
406- 			wait  =  this . props . onLongPressDelay ; 
478+ 			this . _startHoldTime ( ) ; 
479+ 			wait  =  this . props . accelerationDelay ; 
407480		}  else  { 
408481			if  ( this . props . onLongPress )  { 
409482				await  this . props . onLongPress ( num ) ; 
@@ -434,9 +507,10 @@ class InputSpinner extends Component {
434507			} 
435508		} 
436509
437- 		let  wait  =  this . getLongPressWaitingTime ( ) ; 
510+ 		let  wait  =  this . _getHoldChangeInterval ( ) ; 
438511		if  ( this . decreaseTimer  ===  null )  { 
439- 			wait  =  this . props . onLongPressDelay ; 
512+ 			this . _startHoldTime ( ) ; 
513+ 			wait  =  this . props . accelerationDelay ; 
440514		}  else  { 
441515			if  ( this . props . onLongPress )  { 
442516				await  this . props . onLongPress ( num ) ; 
@@ -892,7 +966,7 @@ class InputSpinner extends Component {
892966				disabled = { this . _isDisabledButtonLeft ( ) } 
893967				style = { buttonStyle } 
894968				onPressIn = { this . decrease . bind ( this ) } 
895- 				onPressOut = { this . clearTimers . bind ( this ) } 
969+ 				onPressOut = { this . onPressOut . bind ( this ) } 
896970				{ ...this . props . leftButtonProps } > 
897971				{ this . _renderLeftButtonElement ( ) } 
898972			</ TouchableHighlight > 
@@ -928,7 +1002,7 @@ class InputSpinner extends Component {
9281002				disabled = { this . _isDisabledButtonRight ( ) } 
9291003				style = { buttonStyle } 
9301004				onPressIn = { this . increase . bind ( this ) } 
931- 				onPressOut = { this . clearTimers . bind ( this ) } 
1005+ 				onPressOut = { this . onPressOut . bind ( this ) } 
9321006				{ ...this . props . rightButtonProps } > 
9331007				{ this . _renderRightButtonElement ( ) } 
9341008			</ TouchableHighlight > 
0 commit comments