@@ -36,6 +36,7 @@ type CurrencyInputState = {
3636 disableSelectionHandling : boolean ,
3737 maskedValue : string ,
3838 value : number | string , // TODO: should be string? should also have a separate float field for 'pennies'
39+ previousProps ?: Readonly < CurrencyInputProps > , // Track previous props to detect changes
3940} ;
4041
4142type SelectionSnapshot = {
@@ -124,22 +125,23 @@ class CurrencyInput extends React.Component<CurrencyInputProps, CurrencyInputSta
124125 * General function used to cleanup and define the final props used for rendering
125126 * @returns CurrencyInputState
126127 */
127- static prepareProps ( {
128- onChangeEvent,
129- value : propValue ,
130- decimalSeparator,
131- thousandSeparator,
132- precision,
133- inputType,
134- allowNegative,
135- allowEmpty,
136- prefix,
137- suffix,
138- selectAllOnFocus,
139- autoFocus,
140- disableSelectionHandling : propDisableSelectionHandling ,
141- ...customProps
142- } : Readonly < CurrencyInputProps > ) : CurrencyInputState {
128+ static prepareProps ( props : Readonly < CurrencyInputProps > ) : CurrencyInputState {
129+ const {
130+ onChangeEvent,
131+ value : propValue ,
132+ decimalSeparator,
133+ thousandSeparator,
134+ precision,
135+ inputType,
136+ allowNegative,
137+ allowEmpty,
138+ prefix,
139+ suffix,
140+ selectAllOnFocus,
141+ autoFocus,
142+ disableSelectionHandling : propDisableSelectionHandling ,
143+ ...customProps
144+ } = props ;
143145 let initialValue = propValue ;
144146 if ( initialValue === null ) {
145147 initialValue = allowEmpty ? null : '' ;
@@ -166,7 +168,7 @@ class CurrencyInput extends React.Component<CurrencyInputProps, CurrencyInputSta
166168 ) ;
167169
168170 const disableSelectionHandling = propDisableSelectionHandling || inputType === 'number' ;
169- return { maskedValue, value, customProps, disableSelectionHandling } ;
171+ return { maskedValue, value, customProps, disableSelectionHandling, previousProps : props } ;
170172 }
171173
172174 /**
@@ -182,11 +184,57 @@ class CurrencyInput extends React.Component<CurrencyInputProps, CurrencyInputSta
182184 * @see https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
183185 */
184186 static getDerivedStateFromProps ( nextProps : Readonly < CurrencyInputProps > , prevState : Readonly < CurrencyInputState > ) {
185- const props = { ...nextProps } ;
186- if ( nextProps . value !== prevState . value ) {
187- props . value = prevState . value ;
187+ const previousProps = prevState . previousProps || nextProps ; // First call uses the initial props snapshot
188+
189+ // Check if the VALUE prop itself changed (parent is controlling the input)
190+ const valueChanged = nextProps . value !== previousProps . value ;
191+
192+ // Check if allowNegative changed (affects whether negative values are allowed)
193+ const allowNegativeChanged = nextProps . allowNegative !== previousProps . allowNegative ;
194+
195+ // Check if separators or display formatting changed (these require reformatting the current value)
196+ const formatChanged =
197+ nextProps . decimalSeparator !== previousProps . decimalSeparator ||
198+ nextProps . thousandSeparator !== previousProps . thousandSeparator ||
199+ nextProps . precision !== previousProps . precision ||
200+ nextProps . prefix !== previousProps . prefix ||
201+ nextProps . suffix !== previousProps . suffix ||
202+ allowNegativeChanged ;
203+
204+ if ( valueChanged ) {
205+ // Parent changed the value prop - use the new value
206+ const newState = CurrencyInput . prepareProps ( nextProps ) ;
207+ return { ...newState , previousProps : nextProps } ;
188208 }
189- return CurrencyInput . prepareProps ( props ) ;
209+
210+ if ( formatChanged ) {
211+ // Display formatting or allowNegative changed - reformat the current value
212+ // First, determine the value to use. Start with the current state value,
213+ // which may be adjusted below if allowNegative was disabled and value is negative.
214+ let valueToFormat = prevState . value ;
215+
216+ if ( allowNegativeChanged && ! nextProps . allowNegative ) {
217+ // allowNegative was disabled - if current value is negative, make it positive
218+ const parsedValue = typeof prevState . value === 'number'
219+ ? prevState . value
220+ : prevState . value === null
221+ ? 0
222+ : CurrencyInput . stringValueToFloat ( String ( prevState . value ) , nextProps . thousandSeparator , nextProps . decimalSeparator ) ;
223+
224+ if ( parsedValue < 0 ) {
225+ valueToFormat = Math . abs ( parsedValue ) ;
226+ }
227+ }
228+
229+ // Reformat with new formatting and potentially adjusted value
230+ const propsWithCurrentValue = { ...nextProps , value : valueToFormat } ;
231+ const newState = CurrencyInput . prepareProps ( propsWithCurrentValue ) ;
232+ return { ...newState , previousProps : nextProps } ;
233+ }
234+
235+ // Other props changed but value and display formatting didn't
236+ // Just update the previousProps reference and preserve current state
237+ return { ...prevState , previousProps : nextProps } ;
190238 }
191239
192240 /**
0 commit comments