From 264f0bff5bb3e1a758ee2e3974665f2245a23da0 Mon Sep 17 00:00:00 2001 From: Vadim Kalushko Date: Fri, 26 Dec 2025 02:41:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=82=D0=B8=D0=BF=D0=B8=D0=B7=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20HOC=20withSuffix=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20NumberInput?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/chatty-kids-jog.md | 8 +++ packages/amount-input/src/Component.tsx | 2 +- packages/with-suffix/package.json | 1 + packages/with-suffix/src/Component.test.tsx | 21 +++++++ packages/with-suffix/src/Component.tsx | 63 ++++++++++++--------- packages/with-suffix/tsconfig.build.json | 3 + packages/with-suffix/tsconfig.json | 3 + 7 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 .changeset/chatty-kids-jog.md diff --git a/.changeset/chatty-kids-jog.md b/.changeset/chatty-kids-jog.md new file mode 100644 index 0000000000..95d5f9621f --- /dev/null +++ b/.changeset/chatty-kids-jog.md @@ -0,0 +1,8 @@ +--- +'@alfalab/core-components-with-suffix': minor +'@alfalab/core-components': minor +--- + +##### withSuffix + +- Обобщена типизация `withSuffix` для принятия как `Input`, так и `NumberInput` компонентов diff --git a/packages/amount-input/src/Component.tsx b/packages/amount-input/src/Component.tsx index 1b27dddef5..653b1e443b 100644 --- a/packages/amount-input/src/Component.tsx +++ b/packages/amount-input/src/Component.tsx @@ -311,7 +311,7 @@ export const AmountInput = forwardRef( onKeyDown?.(event); }; - const handleFocus: withSuffixProps['onFocus'] = (e) => { + const handleFocus: withSuffixProps['onFocus'] = (e) => { setIsFocused(true); onFocus?.(e); diff --git a/packages/with-suffix/package.json b/packages/with-suffix/package.json index e18283bf39..9fc6600bdf 100644 --- a/packages/with-suffix/package.json +++ b/packages/with-suffix/package.json @@ -11,6 +11,7 @@ "module": "./esm/index.js", "dependencies": { "@alfalab/core-components-input": "^16.0.3", + "@alfalab/core-components-number-input": "^3.0.4", "@alfalab/core-components-portal": "^4.0.2", "classnames": "^2.5.1", "react-merge-refs": "^1.1.0", diff --git a/packages/with-suffix/src/Component.test.tsx b/packages/with-suffix/src/Component.test.tsx index e674a736c9..19424cd667 100644 --- a/packages/with-suffix/src/Component.test.tsx +++ b/packages/with-suffix/src/Component.test.tsx @@ -1,11 +1,13 @@ import React from 'react'; import { render } from '@testing-library/react'; import { Input } from '@alfalab/core-components-input'; +import { NumberInput } from '@alfalab/core-components-number-input'; import userEvent from '@testing-library/user-event'; import { withSuffix } from './index'; const SuffixInput = withSuffix(Input); +const NumberSuffixInput = withSuffix(NumberInput); describe('withSuffix', () => { Object.defineProperty(window, 'matchMedia', { @@ -71,4 +73,23 @@ describe('withSuffix', () => { expect(unmount).not.toThrow(); }); + + describe('NumberInput', () => { + it('should render suffix with NumberInput', async () => { + const suffix = ' мес'; + const { container } = render(); + + await new Promise((resolve) => requestAnimationFrame(resolve)); + + expect(container.querySelector('.suffixVisible')).toBeInTheDocument(); + }); + + it('should forward ref to html input with NumberInput', () => { + const inputRef = jest.fn(); + const dataTestId = 'number-test-id'; + render(); + + expect(inputRef.mock.calls[0][0].tagName).toBe('INPUT'); + }); + }); }); diff --git a/packages/with-suffix/src/Component.tsx b/packages/with-suffix/src/Component.tsx index 0c904e3662..9604d07110 100644 --- a/packages/with-suffix/src/Component.tsx +++ b/packages/with-suffix/src/Component.tsx @@ -1,4 +1,5 @@ import React, { + type ChangeEvent, type FC, forwardRef, Fragment, @@ -11,12 +12,16 @@ import mergeRefs from 'react-merge-refs'; import cn from 'classnames'; import { type InputProps } from '@alfalab/core-components-input'; +import { type NumberInputProps } from '@alfalab/core-components-number-input'; import { Portal } from '@alfalab/core-components-portal'; import styles from './index.module.css'; -// eslint-disable-next-line @typescript-eslint/naming-convention -export type withSuffixProps = InputProps & { +type InputRef = RefAttributes; + +type BaseInputProps = InputProps | NumberInputProps; + +type SuffixExtraProps = { /** * Дополнительный закрепленный текст справа от основного значения. * Например: value='85' suffix=' мес' -> 85 мес @@ -29,8 +34,11 @@ export type withSuffixProps = InputProps & { suffixContainerClassName?: string; }; -export const withSuffix = (Input: FC>) => - forwardRef( +// eslint-disable-next-line @typescript-eslint/naming-convention +export type withSuffixProps

= P & SuffixExtraProps; + +export const withSuffix =

(Input: FC

) => + forwardRef>( ( { value, @@ -53,11 +61,12 @@ export const withSuffix = (Input: FC['onChange']>( - (event, payload) => { - if (onChange) { - onChange(event, payload); - } + const handleInputChange = useCallback( + ( + event: ChangeEvent, + payload: { value: string } & { value: number | null }, + ) => { + onChange?.(event, payload); if (uncontrolled) { setStateValue(payload.value); @@ -66,15 +75,13 @@ export const withSuffix = (Input: FC['onClear']>( + const handleClear = useCallback['onClear']>( (event) => { if (uncontrolled) { setStateValue(''); } - if (onClear) { - onClear(event); - } + onClear?.(event); }, [onClear, uncontrolled], ); @@ -89,22 +96,24 @@ export const withSuffix = (Input: FC - +