Skip to content

Commit 8b927ab

Browse files
committed
fix(form): better blur error cases for useNumberField
1 parent 8fa3f58 commit 8b927ab

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

packages/form/src/text-field/__tests__/useNumberField.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,37 @@ describe("useNumberField", () => {
162162
fireEvent.blur(field);
163163
expect(field.value).toBe("100");
164164
});
165+
166+
it("should set the value to the min or defaultValue on blur if there is no value in the text field", () => {
167+
const { getByRole, rerender } = render(<NumberField defaultValue={1} />);
168+
const field = getByRole("spinbutton") as HTMLInputElement;
169+
expect(field.value).toBe("1");
170+
171+
fireEvent.focus(field);
172+
fireEvent.blur(field);
173+
expect(field.value).toBe("1");
174+
175+
userEvent.type(field, "00");
176+
expect(field.value).toBe("100");
177+
178+
userEvent.clear(field);
179+
fireEvent.blur(field);
180+
expect(field.value).toBe("1");
181+
182+
rerender(<NumberField min={0} defaultValue={1} />);
183+
expect(field.value).toBe("1");
184+
185+
fireEvent.focus(field);
186+
fireEvent.blur(field);
187+
expect(field.value).toBe("1");
188+
189+
userEvent.type(field, "00");
190+
expect(field.value).toBe("100");
191+
192+
userEvent.clear(field);
193+
fireEvent.blur(field);
194+
expect(field.value).toBe("0");
195+
});
165196
});
166197

167198
describe("number change behavior", () => {

packages/form/src/text-field/useNumberField.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,18 @@ export function useNumberField({
262262
return;
263263
}
264264

265+
let value = input.valueAsNumber;
266+
if (input.value === "" && typeof initial.current === "number") {
267+
value = min ?? initial.current;
268+
}
269+
265270
// can't have both rangeUnderflow and rangeOverflow at the same time, so
266-
// it's "safe" to alwaays provide both
267-
const value = withinRange(input.valueAsNumber, min, max);
268-
setNumber(value);
269-
input.value = `${value}`;
271+
// it's "safe" to always provide both
272+
value = withinRange(value, min, max);
273+
if (!Number.isNaN(value)) {
274+
setNumber(value);
275+
input.value = `${value}`;
276+
}
270277
},
271278
[onBlur, fixOnBlur, min, max]
272279
);

0 commit comments

Comments
 (0)