diff --git a/lib/src/number-input/NumberInput.test.js b/lib/src/number-input/NumberInput.test.js
index dd337b081..ace5a0d58 100644
--- a/lib/src/number-input/NumberInput.test.js
+++ b/lib/src/number-input/NumberInput.test.js
@@ -49,7 +49,7 @@ describe("Number input component tests", () => {
await userEvent.click(increment);
expect(number.value).toBe("");
});
-
+
test("Number input is read only and cannot be incremented or decremented using the arrow keys", () => {
const { getByLabelText } = render();
const number = getByLabelText("Number label");
@@ -68,7 +68,9 @@ describe("Number input component tests", () => {
test("Number input is not optional: required field, displays error if not filled in", () => {
const onBlur = jest.fn();
const onChange = jest.fn();
- const { getByLabelText } = render();
+ const { getByLabelText } = render(
+
+ );
const number = getByLabelText("Number input label");
userEvent.type(number, "1");
userEvent.clear(number);
@@ -381,6 +383,90 @@ describe("Number input component tests", () => {
expect(number.value).toBe("5");
});
+ test("Value is unchanged when using the scroll wheel in mouse in a disabled input", () => {
+ const { getByLabelText } = render(
+
+ );
+ const number = getByLabelText("Number input label");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("10");
+ });
+
+ test("Value is unchanged when using the arrows in keyboard in a disabled input", () => {
+ const { getByLabelText } = render(
+
+ );
+ const number = getByLabelText("Number input label");
+ fireEvent.keyDown(number, { keyCode: 38 });
+ expect(number.value).toBe("10");
+ fireEvent.keyDown(number, { keyCode: 40 });
+ expect(number.value).toBe("10");
+ fireEvent.keyDown(number, { keyCode: 38 });
+ expect(number.value).toBe("10");
+ fireEvent.keyDown(number, { keyCode: 40 });
+ expect(number.value).toBe("10");
+ });
+
+ test("Value is unchanged when using the scroll wheel in mouse in a read-only input", () => {
+ const { getByLabelText } = render(
+
+ );
+ const number = getByLabelText("Number input label");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("10");
+ });
+
+ test("Value is unchanged when using the arrows in keyboard in a read-only input", () => {
+ const { getByLabelText } = render(
+
+ );
+ const number = getByLabelText("Number input label");
+ fireEvent.keyDown(number, { keyCode: 38 });
+ expect(number.value).toBe("10");
+ fireEvent.keyDown(number, { keyCode: 40 });
+ expect(number.value).toBe("10");
+ fireEvent.keyDown(number, { keyCode: 38 });
+ expect(number.value).toBe("10");
+ fireEvent.keyDown(number, { keyCode: 40 });
+ expect(number.value).toBe("10");
+ });
+
+ test("Increment and decrement the value with min, max and step using the scroll wheel in mouse", () => {
+ const { getByLabelText } = render();
+ const number = getByLabelText("Number input label");
+ userEvent.type(number, "1");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("5");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("15");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("20");
+ fireEvent.wheel(number, { deltaY: -100 });
+ expect(number.value).toBe("20");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("15");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("10");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("5");
+ fireEvent.wheel(number, { deltaY: 100 });
+ expect(number.value).toBe("5");
+ });
+
test("Number has correct accessibility attributes", () => {
const { getByLabelText, getAllByRole } = render();
const number = getByLabelText("Number input label");
diff --git a/lib/src/number-input/NumberInput.tsx b/lib/src/number-input/NumberInput.tsx
index af4122fe0..91057a2d1 100644
--- a/lib/src/number-input/NumberInput.tsx
+++ b/lib/src/number-input/NumberInput.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useEffect } from "react";
import styled from "styled-components";
import DxcTextInput from "../text-input/TextInput";
import NumberInputPropsType, { RefType } from "./types";
@@ -38,33 +38,49 @@ const DxcNumberInput = React.forwardRef(
tabIndex,
},
ref
- ) => (
-
-
-
-
-
- )
+ ) => {
+ const numberInputRef = React.useRef(null);
+
+ useEffect(() => {
+ const input = numberInputRef.current?.getElementsByTagName("input")[0] as HTMLInputElement;
+ const preventDefault = (event: WheelEvent) => {
+ event.preventDefault();
+ };
+
+ input?.addEventListener("wheel", preventDefault, { passive: false });
+ return () => {
+ input?.removeEventListener("wheel", preventDefault);
+ };
+ }, []);
+
+ return (
+
+
+
+
+
+ );
+ }
);
const NumberInputContainer = styled.div`
diff --git a/lib/src/text-input/TextInput.test.js b/lib/src/text-input/TextInput.test.js
index e3588c084..4c8988903 100644
--- a/lib/src/text-input/TextInput.test.js
+++ b/lib/src/text-input/TextInput.test.js
@@ -462,6 +462,17 @@ describe("TextInput component tests", () => {
const options = getAllByRole("option");
expect(options[0].getAttribute("aria-selected")).toBeNull();
});
+
+ test("Mouse wheel interaction does not affect the text value", () => {
+ const { getByRole } = render(
+
+ );
+ const input = getByRole("textbox");
+ fireEvent.wheel(input, { deltaY: -100 });
+ expect(input.value).toBe("Example text");
+ fireEvent.wheel(input, { deltaY: 100 });
+ expect(input.value).toBe("Example text");
+ });
});
describe("TextInput component synchronous autosuggest tests", () => {
diff --git a/lib/src/text-input/TextInput.tsx b/lib/src/text-input/TextInput.tsx
index d5009480d..58b429782 100644
--- a/lib/src/text-input/TextInput.tsx
+++ b/lib/src/text-input/TextInput.tsx
@@ -168,6 +168,43 @@ const DxcTextInput = React.forwardRef(
else onChange?.({ value: formattedValue });
};
+ const decrementNumber = (currentValue = value ?? innerValue) => {
+ if (!disabled && !readOnly) {
+ const numberValue = Number(currentValue);
+ const steppedValue = Math.round((numberValue - numberInputContext?.stepNumber + Number.EPSILON) * 100) / 100;
+
+ if (currentValue !== "") {
+ if (numberValue < numberInputContext?.minNumber || steppedValue < numberInputContext?.minNumber)
+ changeValue(numberValue);
+ else if (numberValue > numberInputContext?.maxNumber) changeValue(numberInputContext?.maxNumber);
+ else if (numberValue === numberInputContext?.minNumber) changeValue(numberInputContext?.minNumber);
+ else changeValue(steppedValue);
+ } else {
+ if (numberInputContext?.minNumber >= 0) changeValue(numberInputContext?.minNumber);
+ else if (numberInputContext?.maxNumber < 0) changeValue(numberInputContext?.maxNumber);
+ else changeValue(-numberInputContext.stepNumber);
+ }
+ }
+ };
+ const incrementNumber = (currentValue = value ?? innerValue) => {
+ if (!disabled && !readOnly) {
+ const numberValue = Number(currentValue);
+ const steppedValue = Math.round((numberValue + numberInputContext?.stepNumber + Number.EPSILON) * 100) / 100;
+
+ if (currentValue !== "") {
+ if (numberValue > numberInputContext?.maxNumber || steppedValue > numberInputContext?.maxNumber)
+ changeValue(numberValue);
+ else if (numberValue < numberInputContext?.minNumber) changeValue(numberInputContext?.minNumber);
+ else if (numberValue === numberInputContext?.maxNumber) changeValue(numberInputContext?.maxNumber);
+ else changeValue(steppedValue);
+ } else {
+ if (numberInputContext?.minNumber > 0) changeValue(numberInputContext?.minNumber);
+ else if (numberInputContext?.maxNumber <= 0) changeValue(numberInputContext?.maxNumber);
+ else changeValue(numberInputContext.stepNumber);
+ }
+ }
+ };
+
const handleInputContainerOnClick = () => {
document.activeElement !== actionRef.current && inputRef.current.focus();
};
@@ -248,12 +285,10 @@ const DxcTextInput = React.forwardRef(
break;
}
};
- const handleWheel = useCallback((event: WheelEvent) => {
- if (document.activeElement === inputRef.current) {
- event.preventDefault();
+ const handleNumberInputWheel = (event: React.WheelEvent) => {
+ if (document.activeElement === inputRef.current)
event.deltaY < 0 ? incrementNumber(inputRef.current.value) : decrementNumber(inputRef.current.value);
- }
- }, []);
+ };
const handleClearActionOnClick = () => {
changeValue("");
@@ -276,38 +311,6 @@ const DxcTextInput = React.forwardRef(
inputRef?.current?.setAttribute("step", step);
inputRef?.current?.setAttribute("type", type);
};
- const decrementNumber = (currentValue = value ?? innerValue) => {
- const numberValue = Number(currentValue);
- const steppedValue = Math.round((numberValue - numberInputContext?.stepNumber + Number.EPSILON) * 100) / 100;
-
- if (currentValue !== "") {
- if (numberValue < numberInputContext?.minNumber || steppedValue < numberInputContext?.minNumber)
- changeValue(numberValue);
- else if (numberValue > numberInputContext?.maxNumber) changeValue(numberInputContext?.maxNumber);
- else if (numberValue === numberInputContext?.minNumber) changeValue(numberInputContext?.minNumber);
- else changeValue(steppedValue);
- } else {
- if (numberInputContext?.minNumber >= 0) changeValue(numberInputContext?.minNumber);
- else if (numberInputContext?.maxNumber < 0) changeValue(numberInputContext?.maxNumber);
- else changeValue(-numberInputContext.stepNumber);
- }
- };
- const incrementNumber = (currentValue = value ?? innerValue) => {
- const numberValue = Number(currentValue);
- const steppedValue = Math.round((numberValue + numberInputContext?.stepNumber + Number.EPSILON) * 100) / 100;
-
- if (currentValue !== "") {
- if (numberValue > numberInputContext?.maxNumber || steppedValue > numberInputContext?.maxNumber)
- changeValue(numberValue);
- else if (numberValue < numberInputContext?.minNumber) changeValue(numberInputContext?.minNumber);
- else if (numberValue === numberInputContext?.maxNumber) changeValue(numberInputContext?.maxNumber);
- else changeValue(steppedValue);
- } else {
- if (numberInputContext?.minNumber > 0) changeValue(numberInputContext?.minNumber);
- else if (numberInputContext?.maxNumber <= 0) changeValue(numberInputContext?.maxNumber);
- else changeValue(numberInputContext.stepNumber);
- }
- };
useEffect(() => {
if (typeof suggestions === "function") {
@@ -348,16 +351,6 @@ const DxcTextInput = React.forwardRef(
);
}, [value, innerValue, suggestions, numberInputContext]);
- useEffect(() => {
- const input = inputRef.current;
-
- input.addEventListener('wheel', handleWheel, { passive: false });
-
- return () => {
- input.removeEventListener('wheel', handleWheel);
- };
- }, [handleWheel]);
-
return (
@@ -428,6 +421,7 @@ const DxcTextInput = React.forwardRef(
onMouseDown={(event) => {
event.stopPropagation();
}}
+ onWheel={numberInputContext?.typeNumber === "number" ? handleNumberInputWheel : undefined}
disabled={disabled}
readOnly={readOnly}
ref={inputRef}