From 4c8378551e7e466ddcd93cf57374ea7351cf316f Mon Sep 17 00:00:00 2001 From: Artem Kulikov Date: Fri, 7 Feb 2025 06:12:05 +0300 Subject: [PATCH] feat: add a new parameter for onStep & update api-docs (#701) --- docs/api.md | 14 ++++++++++++- docs/demo/on-step.tsx | 46 +++++++++++++++++++++++++++++++++++++++++++ docs/example.md | 4 ++++ src/InputNumber.tsx | 9 +++++---- src/StepHandler.tsx | 6 +++--- tests/click.test.tsx | 21 +++++++++++--------- 6 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 docs/demo/on-step.tsx diff --git a/docs/api.md b/docs/api.md index 9dae0301..25d2bf5e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -80,7 +80,13 @@ nav: readOnly Boolean false - Specifies that an InputNumber is read only + Specifies that an InputNumber is read only + + + changeOnWheel + Boolean + false + Specifies that the value is set using the mouse wheel controls @@ -136,6 +142,12 @@ nav: Called when an element gets focus + + onStep + (value: T, info: { offset: ValueType; type: 'up' | 'down', emitter: 'handler' | 'keydown' | 'wheel' }) => void + + Called when the user clicks the arrows on the keyboard or interface and when the mouse wheel is spun. + style Object diff --git a/docs/demo/on-step.tsx b/docs/demo/on-step.tsx new file mode 100644 index 00000000..1cfd6371 --- /dev/null +++ b/docs/demo/on-step.tsx @@ -0,0 +1,46 @@ +/* eslint no-console:0 */ +import InputNumber from '@rc-component/input-number'; +import React, { useState } from 'react'; +import '../../assets/index.less'; + +export default () => { + const [emitter, setEmitter] = useState('interface buttons (up)'); + const [value, setValue] = React.useState(0); + + const onChange = (val: number) => { + console.warn('onChange:', val, typeof val); + setValue(val); + }; + + const onStep = (_: number, info: { offset: number; type: 'up' | 'down', emitter: 'handler' | 'keyboard' | 'wheel' }) => { + if (info.emitter === 'handler') { + setEmitter(`interface buttons (${info.type})`); + } + + if (info.emitter === 'keyboard') { + setEmitter(`keyboard (${info.type})`); + } + + if (info.emitter === 'wheel') { + setEmitter(`mouse wheel (${info.type})`); + } + }; + + return ( +
+

onStep callback

+ + +
Triggered by: {emitter}
+
+ ); +}; diff --git a/docs/example.md b/docs/example.md index 8252ae2d..7743a757 100644 --- a/docs/example.md +++ b/docs/example.md @@ -41,6 +41,10 @@ nav: +## on-step + + + ## wheel diff --git a/src/InputNumber.tsx b/src/InputNumber.tsx index 07e3ac0e..969e97e2 100644 --- a/src/InputNumber.tsx +++ b/src/InputNumber.tsx @@ -99,7 +99,7 @@ export interface InputNumberProps onChange?: (value: T | null) => void; onPressEnter?: React.KeyboardEventHandler; - onStep?: (value: T, info: { offset: ValueType; type: 'up' | 'down' }) => void; + onStep?: (value: T, info: { offset: ValueType; type: 'up' | 'down', emitter: 'handler' | 'keyboard' | 'wheel' }) => void; /** * Trigger change onBlur event. @@ -432,7 +432,7 @@ const InternalInputNumber = React.forwardRef( }; // ============================= Step ============================= - const onInternalStep = (up: boolean) => { + const onInternalStep = (up: boolean, emitter: 'handler' | 'keyboard' | 'wheel') => { // Ignore step since out of range if ((up && upDisabled) || (!up && downDisabled)) { return; @@ -454,6 +454,7 @@ const InternalInputNumber = React.forwardRef( onStep?.(getDecimalValue(stringMode, updatedValue), { offset: shiftKeyRef.current ? getDecupleSteps(step) : step, type: up ? 'up' : 'down', + emitter, }); inputRef.current?.focus(); @@ -511,7 +512,7 @@ const InternalInputNumber = React.forwardRef( // Do step if (!compositionRef.current && ['Up', 'ArrowUp', 'Down', 'ArrowDown'].includes(key)) { - onInternalStep(key === 'Up' || key === 'ArrowUp'); + onInternalStep(key === 'Up' || key === 'ArrowUp', 'keyboard'); event.preventDefault(); } }; @@ -526,7 +527,7 @@ const InternalInputNumber = React.forwardRef( const onWheel = (event) => { // moving mouse wheel rises wheel event with deltaY < 0 // scroll value grows from top to bottom, as screen Y coordinate - onInternalStep(event.deltaY < 0); + onInternalStep(event.deltaY < 0, 'wheel'); event.preventDefault(); }; const input = inputRef.current; diff --git a/src/StepHandler.tsx b/src/StepHandler.tsx index 2d6da10c..4051d189 100644 --- a/src/StepHandler.tsx +++ b/src/StepHandler.tsx @@ -20,7 +20,7 @@ export interface StepHandlerProps { downNode?: React.ReactNode; upDisabled?: boolean; downDisabled?: boolean; - onStep: (up: boolean) => void; + onStep: (up: boolean, emitter: 'handler' | 'keyboard' | 'wheel') => void; } export default function StepHandler({ @@ -48,11 +48,11 @@ export default function StepHandler({ e.preventDefault(); onStopStep(); - onStepRef.current(up); + onStepRef.current(up, 'handler'); // Loop step for interval function loopStep() { - onStepRef.current(up); + onStepRef.current(up, 'handler'); stepTimeoutRef.current = setTimeout(loopStep, STEP_INTERVAL); } diff --git a/tests/click.test.tsx b/tests/click.test.tsx index d70af273..27297222 100644 --- a/tests/click.test.tsx +++ b/tests/click.test.tsx @@ -23,6 +23,7 @@ describe('InputNumber.Click', () => { selector: string, changedValue: string | number, stepType: 'up' | 'down', + emitter: 'handler' | 'keyboard' | 'wheel', ) { it(name, () => { const onChange = jest.fn(); @@ -36,27 +37,27 @@ describe('InputNumber.Click', () => { fireEvent.click(container.querySelector(selector)); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(changedValue); - expect(onStep).toHaveBeenCalledWith(changedValue, { offset: 1, type: stepType }); + expect(onStep).toHaveBeenCalledWith(changedValue, { offset: 1, type: stepType, emitter }); unmount(); }); } describe('basic work', () => { - testInputNumber('up button', { defaultValue: 10 }, '.rc-input-number-handler-up', 11, 'up'); + testInputNumber('up button', { defaultValue: 10 }, '.rc-input-number-handler-up', 11, 'up', 'handler'); - testInputNumber('down button', { value: 10 }, '.rc-input-number-handler-down', 9, 'down'); + testInputNumber('down button', { value: 10 }, '.rc-input-number-handler-down', 9, 'down', 'handler'); }); describe('empty input', () => { - testInputNumber('up button', {}, '.rc-input-number-handler-up', 1, 'up'); + testInputNumber('up button', {}, '.rc-input-number-handler-up', 1, 'up', 'handler'); - testInputNumber('down button', {}, '.rc-input-number-handler-down', -1, 'down'); + testInputNumber('down button', {}, '.rc-input-number-handler-down', -1, 'down', 'handler'); }); describe('empty with min & max', () => { - testInputNumber('up button', { min: 6, max: 10 }, '.rc-input-number-handler-up', 6, 'up'); + testInputNumber('up button', { min: 6, max: 10 }, '.rc-input-number-handler-up', 6, 'up', 'handler'); - testInputNumber('down button', { min: 6, max: 10 }, '.rc-input-number-handler-down', 6, 'down'); + testInputNumber('down button', { min: 6, max: 10 }, '.rc-input-number-handler-down', 6, 'down', 'handler'); }); describe('null with min & max', () => { @@ -66,6 +67,7 @@ describe('InputNumber.Click', () => { '.rc-input-number-handler-up', 6, 'up', + 'handler', ); testInputNumber( @@ -74,6 +76,7 @@ describe('InputNumber.Click', () => { '.rc-input-number-handler-down', 6, 'down', + 'handler', ); }); @@ -183,7 +186,7 @@ describe('InputNumber.Click', () => { }); expect(onChange).toHaveBeenCalledWith(1.1); - expect(onStep).toHaveBeenCalledWith(1.1, { offset: '0.1', type: 'down' }); + expect(onStep).toHaveBeenCalledWith(1.1, { offset: '0.1', type: 'down', emitter: 'keyboard' }); }); it('click up button with pressing shift key', () => { @@ -201,6 +204,6 @@ describe('InputNumber.Click', () => { keyCode: KeyCode.UP, }); expect(onChange).toHaveBeenCalledWith(1.3); - expect(onStep).toHaveBeenCalledWith(1.3, { offset: '0.1', type: 'up' }); + expect(onStep).toHaveBeenCalledWith(1.3, { offset: '0.1', type: 'up', emitter: 'keyboard' }); }); });