11import React , { useEffect , useState } from 'react' ;
2- import RCInputNumber from 'rc-input-number ' ;
2+ import { NumberInput } from '@patternfly/react-core ' ;
33import PropTypes from 'prop-types' ;
4- import { translate as __ } from '../../../../common/I18n' ;
4+ import { translate as __ , sprintf } from '../../../../common/I18n' ;
55import { noop } from '../../../../common/helpers' ;
66
77const CounterInput = ( {
@@ -16,37 +16,104 @@ const CounterInput = ({
1616 onChange,
1717 setError,
1818 setWarning,
19+ widthChars,
20+ unit,
21+ handlePlus,
22+ handleMinus,
1923} ) => {
20- const [ innerValue , setInnerValue ] = useState ( value ) ;
24+ const parseValue = v => {
25+ if ( v === '' || v == null ) return v ;
26+ const parsed = Number ( v ) ;
27+ return Number . isNaN ( parsed ) ? v : parsed ;
28+ } ;
29+
30+ const [ innerValue , setInnerValue ] = useState ( ( ) => parseValue ( value ) ) ;
31+
2132 useEffect ( ( ) => {
22- if ( max && innerValue > max ) {
33+ setInnerValue ( parseValue ( value ) ) ;
34+ } , [ value ] ) ;
35+
36+ const getValidated = ( ) => {
37+ if ( max && innerValue > max ) return 'error' ;
38+ if ( recommendedMaxValue && innerValue > recommendedMaxValue )
39+ return 'warning' ;
40+ return 'default' ;
41+ } ;
42+ const validated = getValidated ( ) ;
43+
44+ useEffect ( ( ) => {
45+ if ( validated === 'error' ) {
2346 setWarning ( null ) ;
24- setError ( __ ( 'Specified value is higher than maximum value' ) ) ;
25- } else if ( recommendedMaxValue && innerValue > recommendedMaxValue ) {
47+ setError (
48+ sprintf (
49+ __ ( 'Specified value is higher than maximum value %s%s' ) ,
50+ max ,
51+ unit ? ` ${ unit } ` : ''
52+ )
53+ ) ;
54+ } else if ( validated === 'warning' ) {
2655 setError ( null ) ;
27- setWarning ( __ ( 'Specified value is higher than recommended maximum' ) ) ;
56+ setWarning (
57+ sprintf (
58+ __ ( 'Specified value is higher than recommended maximum %s%s' ) ,
59+ recommendedMaxValue ,
60+ unit ? ` ${ unit } ` : ''
61+ )
62+ ) ;
2863 } else {
2964 setError ( null ) ;
3065 setWarning ( null ) ;
3166 }
32- // eslint-disable-next-line react-hooks/exhaustive-deps
33- } , [ recommendedMaxValue , max , innerValue ] ) ;
67+ } , [ validated , max , recommendedMaxValue , setError , setWarning , unit ] ) ;
68+ const setValue = newValue => {
69+ setInnerValue ( newValue ) ;
70+ onChange ( newValue ) ;
71+ } ;
72+ const handleChange = event => {
73+ const inputValue = event . target . value ;
74+ if ( inputValue === '' ) {
75+ setValue ( '' ) ;
76+ } else {
77+ const parsed = parseInt ( inputValue , 10 ) ;
78+ const clamped = Number . isNaN ( parsed ) ? min : parsed ;
79+ setValue ( min != null ? Math . max ( min , clamped ) : clamped ) ;
80+ }
81+ } ;
82+
83+ const defaultHandlePlus = ( ) => {
84+ if ( handlePlus ) {
85+ handlePlus ( innerValue ) ;
86+ } else {
87+ const newValue = ( innerValue || 0 ) + ( step || 1 ) ;
88+ setValue ( newValue ) ;
89+ }
90+ } ;
3491
35- const handleChange = v => {
36- setInnerValue ( v ) ;
37- onChange ( v ) ;
92+ const defaultHandleMinus = ( ) => {
93+ if ( handleMinus ) {
94+ handleMinus ( innerValue ) ;
95+ } else {
96+ const current = innerValue || 0 ;
97+ if ( min != null && current <= min ) return ;
98+ const newValue = current - ( step || 1 ) ;
99+ setValue ( min != null ? Math . max ( min , newValue ) : newValue ) ;
100+ }
38101 } ;
39102
40103 return (
41- < RCInputNumber
42- value = { innerValue }
43- name = { name }
44- id = { id }
104+ < NumberInput
105+ value = { innerValue ?? 0 }
106+ inputName = { name }
107+ inputProps = { { id , name } }
45108 min = { min }
46- disabled = { disabled }
109+ max = { max }
110+ isDisabled = { disabled }
47111 onChange = { handleChange }
48- step = { step }
49- prefixCls = "foreman-numeric-input"
112+ onPlus = { defaultHandlePlus }
113+ onMinus = { defaultHandleMinus }
114+ validated = { validated }
115+ widthChars = { widthChars }
116+ unit = { unit }
50117 />
51118 ) ;
52119} ;
@@ -60,20 +127,28 @@ CounterInput.propTypes = {
60127 recommendedMaxValue : PropTypes . number ,
61128 /** Set the max value of the numeric input */
62129 max : PropTypes . number ,
63- /** Set the min value of the numeric input */
130+ /** Set the min value of the numeric input, undefined will be defaulted to 0 */
64131 min : PropTypes . number ,
65132 /** Set whether the numeric input will be disabled or not */
66133 disabled : PropTypes . bool ,
67134 /** Set the onChange function of the numeric input */
68135 onChange : PropTypes . func ,
69136 /** Set the default value of the numeric input */
70- value : PropTypes . number ,
137+ value : PropTypes . oneOfType ( [ PropTypes . number , PropTypes . string ] ) ,
71138 /** Set the step, the counter will increase and decrease by */
72139 step : PropTypes . number ,
73140 /** Component passes the validation error to this function */
74141 setError : PropTypes . func ,
75142 /** Component passes the validation warning to this function */
76143 setWarning : PropTypes . func ,
144+ /** Set the width of the numeric input in characters */
145+ widthChars : PropTypes . number ,
146+ /** Set the unit of the numeric input */
147+ unit : PropTypes . string ,
148+ /** Override the default handlePlus function */
149+ handlePlus : PropTypes . func ,
150+ /** Override the default handleMinus function */
151+ handleMinus : PropTypes . func ,
77152} ;
78153
79154CounterInput . defaultProps = {
@@ -83,11 +158,15 @@ CounterInput.defaultProps = {
83158 value : 1 ,
84159 step : 1 ,
85160 min : 1 ,
86- max : null ,
161+ max : undefined ,
87162 recommendedMaxValue : null ,
88163 onChange : noop ,
89164 setError : noop ,
90165 setWarning : noop ,
166+ widthChars : 10 ,
167+ unit : '' ,
168+ handlePlus : null ,
169+ handleMinus : null ,
91170} ;
92171
93172export default CounterInput ;
0 commit comments