Skip to content

Commit 83c7a17

Browse files
authored
fix(TextInput): inputRef (#648)
1 parent e091ed4 commit 83c7a17

File tree

7 files changed

+53
-14
lines changed

7 files changed

+53
-14
lines changed

.changeset/sixty-carpets-drop.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cube-dev/ui-kit': patch
3+
---
4+
5+
Fix inputRef for text inputs.

src/components/fields/Input/Input.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type CubeInput = typeof TextInput & {
1515
};
1616

1717
export const Input: CubeInput = Object.assign(
18-
forwardRef(function Input(props, ref: ForwardedRef<HTMLInputElement>) {
18+
forwardRef(function Input(props, ref: ForwardedRef<HTMLElement>) {
1919
return <TextInput ref={ref} {...props} />;
2020
}),
2121
{

src/components/fields/NumberInput/NumberInput.tsx

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { forwardRef, RefObject, useRef } from 'react';
1+
import { ForwardedRef, forwardRef, RefObject, useRef } from 'react';
22
import { useLocale, useNumberField, AriaNumberFieldProps } from 'react-aria';
33
import { useNumberFieldState } from 'react-stately';
44

@@ -36,7 +36,10 @@ const StepperContainer = tasty({
3636
},
3737
});
3838

39-
function NumberInput(props: WithNullableValue<CubeNumberInputProps>, ref) {
39+
function NumberInput(
40+
props: WithNullableValue<CubeNumberInputProps>,
41+
ref: ForwardedRef<HTMLElement>,
42+
) {
4043
props = castNullableNumberValue(props);
4144
props = useProviderProps(props);
4245
props = useFieldProps(props);
@@ -53,9 +56,9 @@ function NumberInput(props: WithNullableValue<CubeNumberInputProps>, ref) {
5356
let showStepper = !hideStepper;
5457
let { locale } = useLocale();
5558
let state = useNumberFieldState({ ...props, locale });
56-
let defaultInputRef = useRef(null);
59+
let localInputRef = useRef<HTMLInputElement>(null);
5760

58-
inputRef = inputRef || defaultInputRef;
61+
inputRef = inputRef ?? localInputRef;
5962

6063
let {
6164
groupProps,
@@ -113,7 +116,7 @@ function NumberInput(props: WithNullableValue<CubeNumberInputProps>, ref) {
113116
}
114117

115118
/**
116-
* NumberFields allow users to enter a number, and increment or decrement the value using stepper buttons.
119+
* NumberFields allow users to enter a number and increment or decrement the value using stepper buttons.
117120
*/
118121
const _NumberInput = forwardRef(NumberInput);
119122

src/components/fields/PasswordInput/PasswordInput.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { forwardRef, useCallback, useRef, useState } from 'react';
1+
import { ForwardedRef, forwardRef, useCallback, useRef, useState } from 'react';
22
import { useTextField } from 'react-aria';
33

44
import { CubeTextInputBaseProps, TextInputBase } from '../TextInput';
@@ -14,7 +14,10 @@ import { EyeIcon, EyeInvisibleIcon } from '../../../icons';
1414
export interface CubePasswordInputProps
1515
extends WithNullableValue<CubeTextInputBaseProps> {}
1616

17-
function PasswordInput(props: CubePasswordInputProps, ref) {
17+
function PasswordInput(
18+
props: CubePasswordInputProps,
19+
ref: ForwardedRef<HTMLElement>,
20+
) {
1821
props = castNullableStringValue(props);
1922
props = useProviderProps(props);
2023
props = useFieldProps(props, {
@@ -26,7 +29,8 @@ function PasswordInput(props: CubePasswordInputProps, ref) {
2629
});
2730

2831
let [type, setType] = useState('password');
29-
let inputRef = useRef(null);
32+
let localInputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
33+
let inputRef = props.inputRef ?? localInputRef;
3034
let { labelProps, inputProps } = useTextField(
3135
{
3236
...props,

src/components/fields/TextArea/TextArea.tsx

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { forwardRef, useEffect, useLayoutEffect, useRef } from 'react';
1+
import {
2+
ForwardedRef,
3+
forwardRef,
4+
useEffect,
5+
useLayoutEffect,
6+
useRef,
7+
} from 'react';
28
import { useControlledState } from '@react-stately/utils';
39
import { useTextField } from 'react-aria';
410

@@ -22,7 +28,10 @@ export interface CubeTextAreaProps extends CubeTextInputBaseProps {
2228
rows?: number;
2329
}
2430

25-
function TextArea(props: WithNullableValue<CubeTextAreaProps>, ref) {
31+
function TextArea(
32+
props: WithNullableValue<CubeTextAreaProps>,
33+
ref: ForwardedRef<HTMLElement>,
34+
) {
2635
props = castNullableStringValue(props);
2736
props = useProviderProps(props);
2837
props = useFieldProps(props, {
@@ -51,7 +60,8 @@ function TextArea(props: WithNullableValue<CubeTextAreaProps>, ref) {
5160
props.defaultValue,
5261
() => {},
5362
);
54-
let inputRef = useRef<HTMLTextAreaElement>(null);
63+
let localInputRef = useRef<HTMLTextAreaElement>(null);
64+
let inputRef = props.inputRef ?? localInputRef;
5565

5666
let { labelProps, inputProps } = useTextField(
5767
{

src/components/fields/TextInput/TextInput.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export { useTextField };
1616

1717
export const TextInput = forwardRef(function TextInput(
1818
props: CubeTextInputProps,
19-
ref: ForwardedRef<HTMLInputElement>,
19+
ref: ForwardedRef<HTMLElement>,
2020
) {
2121
props = castNullableStringValue(props);
2222
props = useProviderProps(props);
@@ -28,7 +28,9 @@ export const TextInput = forwardRef(function TextInput(
2828
}),
2929
});
3030

31-
let inputRef = useRef(null);
31+
let localInputRef = useRef<HTMLTextAreaElement | HTMLInputElement>(null);
32+
let inputRef = props.inputRef ?? localInputRef;
33+
3234
let { labelProps, inputProps } = useTextField(props, inputRef);
3335

3436
return (

src/components/fields/TextInput/text-input.test.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { createRef } from 'react';
2+
13
import { renderWithForm, userEvent, render, act } from '../../../test';
24
import { Field, TextInput } from '../../../index';
35

@@ -41,4 +43,17 @@ describe('<TextInput />', () => {
4143
expect(input).toHaveValue('Hello, World!');
4244
expect(formInstance.getFieldValue('test')).toEqual('Hello, World!');
4345
});
46+
47+
it('should correctly assign the inputRef to the input element', () => {
48+
const inputRef = createRef<HTMLInputElement>();
49+
50+
const { getByRole } = render(
51+
<TextInput label="test" inputRef={inputRef} />,
52+
);
53+
54+
const input = getByRole('textbox');
55+
56+
// Check if the ref is assigned to the input element
57+
expect(inputRef.current).toBe(input);
58+
});
4459
});

0 commit comments

Comments
 (0)