-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RangeControl: Fix number input change interaction #22084
Changes from 1 commit
1e38b31
1069650
b58e9cb
1383dba
60e3f80
400e621
ff4b356
f30ac77
55bc26e
9647605
7d09603
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
|
||
import { noop } from 'lodash'; | ||
ItsJonQ marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { ENTER } from '@wordpress/keycodes'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { useControlledState } from '../utils/hooks'; | ||
import { InputNumber } from './styles/range-control-styles'; | ||
|
||
export default function InputField( { | ||
label, | ||
onBlur = noop, | ||
onChange = noop, | ||
onReset = noop, | ||
onKeyDown = noop, | ||
value: valueProp, | ||
...props | ||
} ) { | ||
/** | ||
* This component stores an internal (input) value state, derived from | ||
* the incoming value prop. | ||
* | ||
* This allows for the <input /> to be updated independently before the | ||
* value is applied and propagated. This independent updating action is | ||
* necessary to accommodate individual keystroke values that may not | ||
* be considered "valid" (e.g. within the min - max range). | ||
*/ | ||
const [ value, setValue ] = useControlledState( valueProp ); | ||
|
||
const handleOnReset = ( event ) => { | ||
onReset( event ); | ||
setValue( '' ); | ||
}; | ||
|
||
const handleOnSubmit = ( event ) => { | ||
const nextValue = parseFloat( event.target.value ); | ||
|
||
if ( isNaN( nextValue ) ) { | ||
handleOnReset(); | ||
return; | ||
} | ||
|
||
// Only propagate the event if the value is valid. | ||
if ( event.target.checkValidity && ! event.target.checkValidity() ) { | ||
// Otherwise... reset to initial value | ||
setValue( valueProp ); | ||
return; | ||
} | ||
onChange( event ); | ||
}; | ||
|
||
const handleOnBlur = ( event ) => { | ||
onBlur( event ); | ||
handleOnSubmit( event ); | ||
}; | ||
|
||
const handleOnChange = ( event ) => { | ||
setValue( event.target.value ); | ||
|
||
/** | ||
* Prevent submitting if changes are invalid. | ||
* This only applies to values being entered via KEY_DOWN. | ||
* | ||
* Pressing the up/down arrows of the HTML input also triggers a | ||
* change event. However, those values will be (pre)validated by the | ||
* HTML input. | ||
*/ | ||
if ( event.target.checkValidity && ! event.target.checkValidity() ) { | ||
return; | ||
} | ||
|
||
handleOnSubmit( event ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand "submit" in this context to mean "propagate a value which is valid", I'd worry about the specific word "submit", since it typically carries a very different meaning when considering an input of a form (i.e. the form submission). At least, that was my first impression seeing this. A word like "commit" or "persist" might be less prone to confusion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you @aduth ! That makes sense. I think |
||
}; | ||
|
||
const handleOnKeyDown = ( event ) => { | ||
const { keyCode } = event; | ||
onKeyDown( event ); | ||
|
||
if ( keyCode === ENTER ) { | ||
event.preventDefault(); | ||
handleOnSubmit( event ); | ||
} | ||
}; | ||
|
||
return ( | ||
<InputNumber | ||
aria-label={ label } | ||
className="components-range-control__number" | ||
inputMode="decimal" | ||
onBlur={ handleOnBlur } | ||
onChange={ handleOnChange } | ||
onKeyDown={ handleOnKeyDown } | ||
type="number" | ||
value={ value } | ||
{ ...props } | ||
/> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the prop needed for? Could we include documentation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still wondering about this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! Thanks for following up. It's the value to be used if the "Reset" button is clicked.
This was a prop that existed previously, but I guess didn't have docs. I'll add some.