Skip to content

Commit

Permalink
fix: text input and date input to be fixed (#3944)
Browse files Browse the repository at this point in the history
* fix: date input not working properly

* fix: text input and date input to be fixed

* fix: add on change value

* ci: fix unit testing

* fix: unit testing
  • Loading branch information
matthprost authored Jul 12, 2024
1 parent 4483ab9 commit d571c5e
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 36 deletions.
6 changes: 6 additions & 0 deletions .changeset/hot-llamas-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ultraviolet/form": patch
---

- Minor fixes to `<TextInputV2 />` component
- Fixed issue with `<DateInput />` component preventing the input to be edited
16 changes: 16 additions & 0 deletions .changeset/shy-parrots-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@ultraviolet/ui": patch
---

Fix `<TextInputV2 />` prop `onChange` will now take function with event.

```tsx
// Before
onChange={value => value}

// After
onChangeValue={value => value}
onChange={event => event.target.value}
```

This will also fix `<DateInput />` issues such as editing the input value.
11 changes: 4 additions & 7 deletions packages/form/src/components/TextInputFieldV2/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TextInputV2 } from '@ultraviolet/ui'
import type { ComponentProps } from 'react'
import type { FieldPath, FieldValues, Path, PathValue } from 'react-hook-form'
import type { FieldPath, FieldValues } from 'react-hook-form'
import { useController } from 'react-hook-form'
import { useErrors } from '../../providers'
import type { BaseFieldProps } from '../../types'
Expand All @@ -10,10 +10,7 @@ type TextInputFieldProps<
TFieldValues extends FieldValues,
TFieldName extends FieldPath<TFieldValues>,
> = BaseFieldProps<TFieldValues, TFieldName> &
Omit<
ComponentProps<typeof TextInputV2>,
'value' | 'error' | 'name' | 'onChange'
> & {
Omit<ComponentProps<typeof TextInputV2>, 'value' | 'error' | 'name'> & {
regex?: (RegExp | RegExp[])[]
}

Expand Down Expand Up @@ -116,7 +113,7 @@ export const TextInputField = <
}}
onChange={event => {
field.onChange(event)
onChange?.(event as PathValue<TFieldValues, Path<TFieldValues>>)
onChange?.(event)
}}
onFocus={event => {
onFocus?.(event)
Expand All @@ -128,7 +125,7 @@ export const TextInputField = <
tabIndex={tabIndex}
tooltip={tooltip}
type={type}
value={field.value}
value={field.value === undefined ? '' : field.value}
id={id}
prefix={prefix}
suffix={suffix}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ const locales = [

export const Localized = (props: ComponentProps<typeof DateInput>) =>
locales.map(({ label, locale }) => (
<DateInput {...props} onChange={() => {}} label={label} locale={locale} />
<DateInput
{...props}
key={label}
onChange={() => {}}
label={label}
locale={locale}
/>
))

Localized.args = Template.args
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Stack } from '../../Stack'
export const Size: StoryFn<typeof DateInput> = args => (
<Stack gap="2">
{(['small', 'medium', 'large'] as const).map(size => (
<DateInput {...args} label={size} size={size} />
<DateInput {...args} key={size} label={size} size={size} />
))}
</Stack>
)
2 changes: 1 addition & 1 deletion packages/ui/src/components/DateInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ export const DateInput = ({
id={localId}
label={label}
labelDescription={labelDescription}
value={valueFormat || ''}
value={valueFormat}
disabled={disabled}
size={size}
suffix={
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/SearchInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ export const SearchInput = forwardRef(
label={label}
placeholder={placeholder}
loading={loading}
onChange={onSearchCallback}
onChange={event => onSearchCallback(event.target.value)}
clearable
disabled={disabled}
className={className}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export const SearchBarDropdown = ({
return (
<StyledInput
value={searchInput}
onChange={event => handleChange(event)}
onChange={event => handleChange(event.target.value)}
placeholder={placeholder}
onFocus={() => setSearchBarActive(true)}
onBlur={() => setSearchBarActive(false)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { StoryFn } from '@storybook/react'
import { useState } from 'react'
import { TextInputV2 } from '..'
import { Stack } from '../../Stack'
import { Text } from '../../Text'

export const ControlledVSUncontrolled: StoryFn<typeof TextInputV2> = props => {
const [value, setValue] = useState('content')

return (
<Stack direction="column" gap={2}>
<TextInputV2 label="Uncontrolled" defaultValue="content" {...props} />
<Stack gap={1}>
<TextInputV2
label="Controlled"
value={value}
onChange={event => setValue(event.target.value)}
{...props}
/>
<Text as="p" variant="body" sentiment="neutral">
We can get the value from the input, which is:{' '}
<Text as="span" variant="body" sentiment="neutral" italic>
{value}
</Text>
</Text>
</Stack>
</Stack>
)
}

ControlledVSUncontrolled.parameters = {
docs: {
description: {
story:
'The component can be controlled or uncontrolled.\n\n The difference is that in the controlled version, the `value` and `onChange` is passed as a prop and the component does not manage its own state.\n\n In the uncontrolled version, the component manages its own state. For more information check [React documentation](https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components).',
},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ export const Examples: StoryFn<typeof TextInputV2> = args => {
label="With prefix"
prefix="https://"
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
/>
<TextInputV2
{...args}
label="Text input with random hook"
prefix="https://"
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
onRandomize={() => setValue(randomName())}
/>
<TextInputV2
{...args}
label="Password input with random hook"
prefix="https://"
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
onRandomize={() => setValue(randomName())}
type="password"
/>
Expand All @@ -41,7 +41,7 @@ export const Examples: StoryFn<typeof TextInputV2> = args => {
prefix="https://"
suffix=".com"
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
onRandomize={() => setValue(randomName())}
success="Field has been updated!"
loading
Expand All @@ -53,7 +53,7 @@ export const Examples: StoryFn<typeof TextInputV2> = args => {
disabled
helper="Notice to fill the field"
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
onRandomize={() => setValue(randomName())}
loading
/>
Expand All @@ -69,7 +69,7 @@ export const Examples: StoryFn<typeof TextInputV2> = args => {
</Text>
}
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
onRandomize={() => setValue(randomName())}
loading
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const OnRandomize: StoryFn<typeof TextInputV2> = ({ ...args }) => {
<TextInputV2
{...args}
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
onRandomize={() => {
setValue(`randomValue-${Math.round(Math.random() * 1000)}`)
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ export const Size: StoryFn<typeof TextInputV2> = args => {
).map(size => (
<TextInputV2
{...args}
key={size}
label={size}
size={size}
value={value}
onChange={setValue}
onChange={event => setValue(event.target.value)}
placeholder="Placeholder"
/>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { TextInputV2 } from '..'
export const Template: StoryFn<typeof TextInputV2> = ({ ...args }) => {
const [value, setValue] = useState<string | undefined>(args.value)

return <TextInputV2 {...args} value={value} onChange={setValue} />
return (
<TextInputV2
{...args}
value={value}
onChange={event => setValue(event.target.value)}
/>
)
}

Template.args = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export { ReadOnly } from './ReadOnly.stories'
export { Loading } from './Loading.stories'
export { Success } from './Success.stories'
export { Error } from './Error.stories'
export { ControlledVSUncontrolled } from './ControlledVSUncontrolled.stories'
export { Examples } from './Examples.stories'
17 changes: 13 additions & 4 deletions packages/ui/src/components/TextInputV2/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,22 @@ describe('TextInputV2', () => {

test('should control the value', () => {
const onChange = vi.fn()
const onChangeValue = vi.fn()

renderWithTheme(
<TextInputV2 label="Test" value="test" onChange={onChange} />,
<TextInputV2
label="Test"
value="test"
onChange={onChange}
onChangeValue={onChangeValue}
/>,
)

const textarea = screen.getByLabelText<HTMLInputElement>('Test')
expect(textarea.value).toBe('test')
// userEvent.type do not work here at the moment
fireEvent.change(textarea, { target: { value: 'another value' } })
expect(onChange).toHaveBeenCalledWith('another value')
expect(onChange).toHaveBeenCalled()
expect(onChangeValue).toHaveBeenCalledWith('another value')
})

test('should be clearable', async () => {
Expand All @@ -35,7 +41,10 @@ describe('TextInputV2', () => {
expect(textarea.value).toBe('test')
const clearableButton = screen.getByLabelText('clear value')
await userEvent.click(clearableButton)
expect(onChange).toHaveBeenCalledWith('')
expect(onChange).toHaveBeenCalledWith({
target: { value: '' },
currentTarget: { value: '' },
})
})

test('should render correctly when input is disabled', () =>
Expand Down
Loading

0 comments on commit d571c5e

Please sign in to comment.