mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(input): isClearable & add test cases to input (#2796)
* feat(input): add @nextui-org/use-safe-layout-effect * fix(input): use useSafeLayoutEffect to handle react-hook-form case * feat(input): add isClearable test case * feat(input): add react-hook-form to dev dependencies for storybook * feat(input): add WithReactHookForm to input storybook * feat(changeset): fixes isClearable function in input * chore(changeset): update changeset message * refactor(input): revise input test
This commit is contained in:
parent
1cc5215ce6
commit
3552353203
5
.changeset/gold-dolphins-fail.md
Normal file
5
.changeset/gold-dolphins-fail.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@nextui-org/input": patch
|
||||
---
|
||||
|
||||
Fixes the isClearable function in the input component (#2791)
|
||||
@ -1,5 +1,6 @@
|
||||
import * as React from "react";
|
||||
import {render} from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import {Input} from "../src";
|
||||
|
||||
@ -116,4 +117,32 @@ describe("Input", () => {
|
||||
|
||||
expect(ref.current?.value)?.toBe(value);
|
||||
});
|
||||
|
||||
it("should clear the value and onClear is triggered", async () => {
|
||||
const onClear = jest.fn();
|
||||
|
||||
const ref = React.createRef<HTMLInputElement>();
|
||||
|
||||
const {getByRole} = render(
|
||||
<Input
|
||||
ref={ref}
|
||||
isClearable
|
||||
defaultValue="junior@nextui.org"
|
||||
label="test input"
|
||||
onClear={onClear}
|
||||
/>,
|
||||
);
|
||||
|
||||
const clearButton = getByRole("button");
|
||||
|
||||
expect(clearButton).not.toBeNull();
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
await user.click(clearButton);
|
||||
|
||||
expect(ref.current?.value)?.toBe("");
|
||||
|
||||
expect(onClear).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"@nextui-org/react-utils": "workspace:*",
|
||||
"@nextui-org/shared-icons": "workspace:*",
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"@nextui-org/use-safe-layout-effect": "workspace:*",
|
||||
"@react-aria/focus": "^3.16.2",
|
||||
"@react-aria/interactions": "^3.21.1",
|
||||
"@react-aria/textfield": "^3.14.3",
|
||||
@ -57,7 +58,8 @@
|
||||
"@nextui-org/system": "workspace:*",
|
||||
"clean-package": "2.2.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
"react-dom": "^18.0.0",
|
||||
"react-hook-form": "^7.51.3"
|
||||
},
|
||||
"clean-package": "../../../clean-package.config.json"
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import type {InputVariantProps, SlotsToClasses, InputSlots} from "@nextui-org/th
|
||||
import type {AriaTextFieldOptions} from "@react-aria/textfield";
|
||||
|
||||
import {HTMLNextUIProps, mapPropsVariants, PropGetter} from "@nextui-org/system";
|
||||
import {useSafeLayoutEffect} from "@nextui-org/use-safe-layout-effect";
|
||||
import {AriaTextFieldProps} from "@react-types/textfield";
|
||||
import {useFocusRing} from "@react-aria/focus";
|
||||
import {input} from "@nextui-org/theme";
|
||||
@ -143,6 +144,15 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
|
||||
domRef.current?.focus();
|
||||
}, [setInputValue, onClear]);
|
||||
|
||||
// if we use `react-hook-form`, it will set the input value using the ref in register
|
||||
// i.e. setting ref.current.value to something which is uncontrolled
|
||||
// hence, sync the state with `ref.current.value`
|
||||
useSafeLayoutEffect(() => {
|
||||
if (!domRef.current) return;
|
||||
|
||||
setInputValue(domRef.current.value);
|
||||
}, [domRef.current]);
|
||||
|
||||
const {
|
||||
labelProps,
|
||||
inputProps,
|
||||
@ -156,7 +166,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
|
||||
...originalProps,
|
||||
validationBehavior: "native",
|
||||
autoCapitalize: originalProps.autoCapitalize as AutoCapitalize,
|
||||
value: domRef?.current?.value ?? inputValue,
|
||||
value: inputValue,
|
||||
"aria-label": safeAriaLabel(
|
||||
originalProps?.["aria-label"],
|
||||
originalProps?.label,
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
CloseFilledIcon,
|
||||
} from "@nextui-org/shared-icons";
|
||||
import {button} from "@nextui-org/theme";
|
||||
import {useForm} from "react-hook-form";
|
||||
|
||||
import {Input, InputProps, useInput} from "../src";
|
||||
|
||||
@ -474,6 +475,38 @@ const CustomWithHooksTemplate = (args: InputProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const WithReactHookFormTemplate = (args: InputProps) => {
|
||||
const {
|
||||
register,
|
||||
formState: {errors},
|
||||
handleSubmit,
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
withDefaultValue: "wkw",
|
||||
withoutDefaultValue: "",
|
||||
requiredField: "",
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = (data: any) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(data);
|
||||
alert("Submitted value: " + JSON.stringify(data));
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="flex flex-col gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Input isClearable label="With default value" {...register("withDefaultValue")} />
|
||||
<Input {...args} label="Without default value" {...register("withoutDefaultValue")} />
|
||||
<Input {...args} label="Required" {...register("requiredField", {required: true})} />
|
||||
{errors.requiredField && <span className="text-danger">This field is required</span>}
|
||||
<button className={button({class: "w-fit"})} type="submit">
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
render: MirrorTemplate,
|
||||
|
||||
@ -706,3 +739,11 @@ export const CustomWithHooks = {
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const WithReactHookForm = {
|
||||
render: WithReactHookFormTemplate,
|
||||
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
};
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@ -1523,6 +1523,9 @@ importers:
|
||||
'@nextui-org/shared-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../utilities/shared-utils
|
||||
'@nextui-org/use-safe-layout-effect':
|
||||
specifier: workspace:*
|
||||
version: link:../../hooks/use-safe-layout-effect
|
||||
'@react-aria/focus':
|
||||
specifier: ^3.16.2
|
||||
version: 3.16.2(react@18.2.0)
|
||||
@ -1563,6 +1566,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
react-hook-form:
|
||||
specifier: ^7.51.3
|
||||
version: 7.51.3(react@18.2.0)
|
||||
|
||||
packages/components/kbd:
|
||||
dependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user