-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
[base-ui][NumberInput] Implement numberInputReducer
#38723
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
Conversation
Netlify deploy previewhttps://deploy-preview-38723--material-ui.netlify.app/ Bundle size report |
ebdfda6
to
e155ab0
Compare
@michaldudak Regarding managing the controlled/uncontrolled state, if a component is using |
/** | ||
* The dirty `value` of the `input` element when it is in focus. | ||
*/ | ||
inputValue?: string; |
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.
I'm leaning towards calling this inputValue
again, it's easier to associate with onInputChange
Even though this is just internal for now, I think we also need to provide the option to have inputValue
as a controlled state
Right. |
This comment was marked as outdated.
This comment was marked as outdated.
49fc3e7
to
aa450a6
Compare
aa450a6
to
7efefe1
Compare
7efefe1
to
7a6ce95
Compare
@michaldudak I've updated this ~ in the end I decided to not pass any events into this at all to keep it simpler (I was only using very few properties on the events anyway) It's also much clearer what each action is going to do:
|
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.
Looking good in general. I've got a couple of remarks but I like the direction!
) { | ||
const { getInputValueAsString } = context; | ||
|
||
const parsedValue = getInputValueAsString(inputValue); |
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.
Nit: technically, a "parsed" value would be a number, while here it's just a string representing the value.
BTW, do you intend developers to provide their own implementation of getInputValueAsString
? What would be the use case?
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 I haven't fully thought out the terminology yet (including getInputValueAsString
), so let me rename parsedValue
to numberValueAsString
for now to be 100% literal 😄
The use case would be if a user wanted to accept something like $50
in the input, we would expose getInputValueAsString
as a prop (with a better name) to accept a custom function to remove the $
.
It would also require something like formatNewValueToDisplayValue()
to add back the $
when the value is updated.
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.
Do you think we need such a two-step process? Wouldn't it be enough if developers could override just the parsing function (that gets whatever string there is in the input and returns a number)?
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.
@michaldudak I will benchmark possible alternatives, but with a currency/money input component in mind as a use-case (has currency symbol, decimals, thousands separator), I know this "parse + format" approach will work from redux-form
antd has a very similar api for their InputNumber
component, though their example feels a bit weird when you use it: https://codesandbox.io/s/antd-number-input-formatter-and-parser-n74kgs?file=/src/index.js
state: State, | ||
context: NumberInputActionContext, | ||
applyMultiplier: boolean, | ||
direction: StepDirection, |
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.
If we used 1 | -1
as direction, we could get rid of some code without sacrificing readability IMO (using an enum would also work).
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.
How about '+' | '-'
😬
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.
This still requires some logic other than simple multiplication, but if you feel 1 | -1
is not expressive enough, let's leave it.
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.
OK I've reverted this bit – it's just that having a number as direction just made me stop and think all the time 😅
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.
I like it! Feels like the domain-specific action names look better than event-specific ones. I'm considering refactoring the existing ones in Select and Menu.
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.
I like it! Feels like the domain-specific action names look better than event-specific ones. I'm considering refactoring the existing ones in Select and Menu.
Part of #38514
This PR adds a
numberInputReducer
function that would be used to determine the internalvalue
andinputValue
of theuseNumberInput
hook. (I plan to integrate this withuseNumberInput
anduseControllableReducer
in a separate PR)Action types:
clamp
: apply the clamp function toinputValue
inputChange
: updateinputValue
increment
,decrement
: step the value up or down based onstep
,multiplier
incrementToMax
,decrementToMin
: directly set the value tomax
ormin
if they are setThe logic is mostly extracted from
useNumberInput
with one notable change – thevalue
can be set to an empty string when the input is completely cleared. Previously it was justundefined
but it shouldn't be used as it would change the controlled/uncontrolled state (#38513)