Skip to content

Commit

Permalink
feat: support mouse wheel
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Petrov committed Oct 28, 2023
1 parent 86a93fe commit b18ad09
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ online example: https://input-number.vercel.app/
<td></td>
<td>Specifies the inputmode of input</td>
</tr>
<tr>
<td>wheel</td>
<td>Boolean</td>
<td>true</td>
<td>Allows changing value with mouse wheel</td>
</tr>
</tbody>
</table>

Expand All @@ -246,6 +252,10 @@ online example: https://input-number.vercel.app/
* With the <kbd>Shift</kbd> key (<kbd>Shift+⬆</kbd>, <kbd>Shift+⬇</kbd>), the input value will be changed by `10 * step`
* With the <kbd>Ctrl</kbd> or <kbd>⌘</kbd> key (<kbd>Ctrl+⬆</kbd> or <kbd>⌘+⬆</kbd> or <kbd>Ctrl+⬇</kbd> or <kbd>⌘+⬇</kbd> ), the input value will be changed by `0.1 * step`

## Mouse Wheel
* When you scroll up or down, the input value will be increased or decreased by `step`
* Scrolling with the <kbd>Shift</kbd> key, the input value will be changed by `10 * step`

## Test Case

```
Expand Down
13 changes: 13 additions & 0 deletions src/InputNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface InputNumberProps<T extends ValueType = ValueType>
upHandler?: React.ReactNode;
downHandler?: React.ReactNode;
keyboard?: boolean;
wheel?: boolean;

/** Parse display value to validate number */
parser?: (displayValue: string | undefined) => T;
Expand Down Expand Up @@ -127,6 +128,7 @@ const InternalInputNumber = React.forwardRef(
upHandler,
downHandler,
keyboard,
wheel,
controls = true,

classNames,
Expand Down Expand Up @@ -517,6 +519,16 @@ const InternalInputNumber = React.forwardRef(
shiftKeyRef.current = false;
};

const onWheel = (event) => {
if (wheel === false) {
return;
}
// moving mouse wheel rises wheel event with deltaY < 0
// scroll value grows from top to bottom, as screen Y coordinate
onInternalStep(event.deltaY < 0);
event.preventDefault();
};

// >>> Focus & Blur
const onBlur = () => {
if (changeOnBlur) {
Expand Down Expand Up @@ -575,6 +587,7 @@ const InternalInputNumber = React.forwardRef(
onBlur={onBlur}
onKeyDown={onKeyDown}
onKeyUp={onKeyUp}
onWheel={onWheel}
onCompositionStart={onCompositionStart}
onCompositionEnd={onCompositionEnd}
onBeforeInput={onBeforeInput}
Expand Down
71 changes: 71 additions & 0 deletions tests/wheel.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import KeyCode from 'rc-util/lib/KeyCode';
import InputNumber from '../src';
import { fireEvent, render } from './util/wrapper';

describe('InputNumber.Wheel', () => {
it('wheel up', () => {
const onChange = jest.fn();
const { container } = render(<InputNumber onChange={onChange} />);
fireEvent.wheel(container.querySelector('input'), {deltaY: -1});
expect(onChange).toHaveBeenCalledWith(1);
});

it('wheel up with pressing shift key', () => {
const onChange = jest.fn();
const { container } = render(<InputNumber onChange={onChange} step={0.01} value={1.2} />);
fireEvent.keyDown(container.querySelector('input'), {
which: KeyCode.SHIFT,
key: 'Shift',
keyCode: KeyCode.SHIFT,
shiftKey: true,
});
fireEvent.wheel(container.querySelector('input'), {deltaY: -1});
expect(onChange).toHaveBeenCalledWith(1.3);
});

it('wheel down', () => {
const onChange = jest.fn();
const { container } = render(<InputNumber onChange={onChange} />);
fireEvent.wheel(container.querySelector('input'), {deltaY: 1});
expect(onChange).toHaveBeenCalledWith(-1);
});

it('wheel down with pressing shift key', () => {
const onChange = jest.fn();
const { container } = render(<InputNumber onChange={onChange} step={0.01} value={1.2} />);
fireEvent.keyDown(container.querySelector('input'), {
which: KeyCode.SHIFT,
key: 'Shift',
keyCode: KeyCode.SHIFT,
shiftKey: true,
});
fireEvent.wheel(container.querySelector('input'), {deltaY: 1});
expect(onChange).toHaveBeenCalledWith(1.1);
});

it('disabled wheel', () => {
const onChange = jest.fn();
const { container } = render(<InputNumber wheel={false} onChange={onChange} />);

fireEvent.wheel(container.querySelector('input'), {deltaY: -1});
expect(onChange).not.toHaveBeenCalled();

fireEvent.wheel(container.querySelector('input'), {deltaY: 1});
expect(onChange).not.toHaveBeenCalled();
});

it('wheel is limited to range', () => {
const onChange = jest.fn();
const { container } = render(<InputNumber onChange={onChange} min={-3} max={3} />);
fireEvent.keyDown(container.querySelector('input'), {
which: KeyCode.SHIFT,
key: 'Shift',
keyCode: KeyCode.SHIFT,
shiftKey: true,
});
fireEvent.wheel(container.querySelector('input'), {deltaY: -1});
expect(onChange).toHaveBeenCalledWith(3);
fireEvent.wheel(container.querySelector('input'), {deltaY: 1});
expect(onChange).toHaveBeenCalledWith(-3);
});
});

0 comments on commit b18ad09

Please sign in to comment.