AutoSizeInput: Allow to be controlled by value (#92997)

This commit is contained in:
Ivan Ortega Alba 2024-09-05 19:50:40 +02:00 committed by GitHub
parent d5ebaa0ef9
commit 35ba8fbad1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 3 deletions

View File

@ -35,6 +35,8 @@ const meta: Meta = {
suffixVisible: '',
invalid: false,
loading: false,
value: '',
defaultValue: '',
},
argTypes: {
prefixVisible: {
@ -80,6 +82,8 @@ export const Simple: StoryFn = (args) => {
type={args.type}
placeholder={args.placeholder}
minWidth={args.minWidth}
value={args.value}
defaultValue={args.defaultValue}
/>
);
};
@ -88,6 +92,8 @@ Simple.args = {
before: false,
after: false,
placeholder: 'Enter your name here...',
value: '',
defaultValue: '',
};
export default meta;

View File

@ -1,4 +1,5 @@
import { screen, render, fireEvent, waitFor } from '@testing-library/react';
import { useEffect, useState } from 'react';
import { measureText } from '../../utils/measureText';
@ -117,4 +118,30 @@ describe('AutoSizeInput', () => {
expect(getComputedStyle(screen.getByTestId('input-wrapper')).width).toBe('32px');
});
it('should update the input value if the value prop changes', () => {
// Wrapper component to control the `value` prop
const Wrapper = () => {
const [value, setValue] = useState('Initial');
// Simulate prop change after render
useEffect(() => {
setTimeout(() => setValue('Updated'), 100); // Update `value` after 100ms
}, []);
return <AutoSizeInput value={value} />;
};
render(<Wrapper />);
const input: HTMLInputElement = screen.getByTestId('autosize-input');
// Check initial value
expect(input.value).toBe('Initial');
// Wait for the value to update
return waitFor(() => {
expect(input.value).toBe('Updated');
});
});
});

View File

@ -15,13 +15,32 @@ export interface Props extends InputProps {
}
export const AutoSizeInput = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
const { defaultValue = '', minWidth = 10, maxWidth, onCommitChange, onKeyDown, onBlur, ...restProps } = props;
const [value, setValue] = React.useState(defaultValue);
const {
defaultValue = '',
minWidth = 10,
maxWidth,
onCommitChange,
onKeyDown,
onBlur,
value: controlledValue,
...restProps
} = props;
// Initialize internal state
const [value, setValue] = React.useState(controlledValue ?? defaultValue);
const [inputWidth, setInputWidth] = React.useState(minWidth);
// Update internal state when controlled `value` prop changes
useEffect(() => {
if (controlledValue !== undefined) {
setValue(controlledValue);
}
}, [controlledValue]);
// Update input width when `value`, `minWidth`, or `maxWidth` change
useEffect(() => {
setInputWidth(getWidthFor(value.toString(), minWidth, maxWidth));
}, [value, maxWidth, minWidth]);
}, [value, minWidth, maxWidth]);
return (
<Input