diff --git a/.changeset/chilly-ways-dance.md b/.changeset/chilly-ways-dance.md
new file mode 100644
index 0000000..ec83d44
--- /dev/null
+++ b/.changeset/chilly-ways-dance.md
@@ -0,0 +1,5 @@
+---
+"@openfun/cunningham-react": minor
+---
+
+add RHF examples
diff --git a/packages/react/.eslintrc.cjs b/packages/react/.eslintrc.cjs
index 2cbf790..7dcbfa9 100644
--- a/packages/react/.eslintrc.cjs
+++ b/packages/react/.eslintrc.cjs
@@ -17,6 +17,8 @@ module.exports = {
"**/*.stories.tsx",
"**/*.spec.tsx",
"src/tests/*",
+ "**/stories-utils.tsx",
+ "**/reactHookFormUtils.tsx"
],
},
],
diff --git a/packages/react/src/components/Forms/Checkbox/index.stories.tsx b/packages/react/src/components/Forms/Checkbox/index.stories.tsx
index 9170e1c..41ffd1f 100644
--- a/packages/react/src/components/Forms/Checkbox/index.stories.tsx
+++ b/packages/react/src/components/Forms/Checkbox/index.stories.tsx
@@ -3,13 +3,13 @@ import { yupResolver } from "@hookform/resolvers/yup";
import { Meta, StoryFn } from "@storybook/react";
import { useForm } from "react-hook-form";
import * as Yup from "yup";
-import { Checkbox, CheckboxGroup } from ":/components/Forms/Checkbox/index";
-import { Button } from ":/components/Button";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
-} from ":/tests/reactHookFormUtils";
+} from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
+import { Checkbox, CheckboxGroup } from ":/components/Forms/Checkbox/index";
+import { Button } from ":/components/Button";
export default {
title: "Components/Forms/Checkbox",
diff --git a/packages/react/src/components/Forms/DatePicker/index.stories.tsx b/packages/react/src/components/Forms/DatePicker/index.stories.tsx
index d06accf..5520852 100644
--- a/packages/react/src/components/Forms/DatePicker/index.stories.tsx
+++ b/packages/react/src/components/Forms/DatePicker/index.stories.tsx
@@ -1,9 +1,14 @@
import { Meta, StoryFn } from "@storybook/react";
import React, { useState } from "react";
+import * as Yup from "yup";
+import { FormProvider, useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
import { CunninghamProvider } from ":/components/Provider";
import { Button } from ":/components/Button";
import { DateRangePicker } from ":/components/Forms/DatePicker/DateRangePicker";
import { DatePicker } from ":/components/Forms/DatePicker/DatePicker";
+import { onSubmit } from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
+import { RhfDatePicker } from ":/components/Forms/DatePicker/stories-utils";
export default {
title: "Components/Forms/DatePicker",
@@ -135,6 +140,38 @@ export const Controlled = () => {
);
};
+export const ReactHookForm = () => {
+ const methods = useForm({
+ defaultValues: {
+ date: "",
+ },
+ resolver: yupResolver(
+ Yup.object().shape({
+ date: Yup.string().required(),
+ }),
+ ),
+ });
+
+ return (
+
+
+
+
+
+ );
+};
+
export const RangeDefault = () => {
return (
diff --git a/packages/react/src/components/Forms/DatePicker/stories-utils.tsx b/packages/react/src/components/Forms/DatePicker/stories-utils.tsx
new file mode 100644
index 0000000..580aab3
--- /dev/null
+++ b/packages/react/src/components/Forms/DatePicker/stories-utils.tsx
@@ -0,0 +1,27 @@
+import { Controller, useFormContext } from "react-hook-form";
+import React from "react";
+import {
+ DatePicker,
+ DatePickerProps,
+} from ":/components/Forms/DatePicker/DatePicker";
+
+export const RhfDatePicker = (props: DatePickerProps & { name: string }) => {
+ const { control } = useFormContext();
+ return (
+
{
+ return (
+
+ );
+ }}
+ />
+ );
+};
diff --git a/packages/react/src/components/Forms/Examples/ReactHookForm/Login.stories.tsx b/packages/react/src/components/Forms/Examples/ReactHookForm/Login.stories.tsx
index 8aae6e2..7d40f60 100644
--- a/packages/react/src/components/Forms/Examples/ReactHookForm/Login.stories.tsx
+++ b/packages/react/src/components/Forms/Examples/ReactHookForm/Login.stories.tsx
@@ -10,10 +10,10 @@ import {
getFieldState,
getFieldErrorMessage,
onSubmit,
-} from ":/tests/reactHookFormUtils";
+} from "./reactHookFormUtils";
export default {
- title: "Components/Forms/Reac-Hook-Form",
+ title: "Components/Forms/Examples/React-Hook-Form",
} as Meta;
interface LoginStoryFormValues {
diff --git a/packages/react/src/components/Forms/Examples/ReactHookForm/Sports.stories.tsx b/packages/react/src/components/Forms/Examples/ReactHookForm/Sports.stories.tsx
index 383a49a..f978833 100644
--- a/packages/react/src/components/Forms/Examples/ReactHookForm/Sports.stories.tsx
+++ b/packages/react/src/components/Forms/Examples/ReactHookForm/Sports.stories.tsx
@@ -1,218 +1,153 @@
import { yupResolver } from "@hookform/resolvers/yup";
import { Meta } from "@storybook/react";
import React from "react";
-import { useForm, Controller, ControllerRenderProps } from "react-hook-form";
+import { useForm, FormProvider } from "react-hook-form";
import * as Yup from "yup";
import { Input } from ":/components/Forms/Input";
import { Button } from ":/components/Button";
-import { Select } from ":/components/Forms/Select";
import { CunninghamProvider } from ":/components/Provider";
import { Radio, RadioGroup } from ":/components/Forms/Radio";
+import { RhfSelect } from ":/components/Forms/Select/stories-utils";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
-} from ":/tests/reactHookFormUtils";
+} from "./reactHookFormUtils";
export default {
- title: "Components/Forms/Reac-Hook-Form",
+ title: "Components/Forms/Examples/React-Hook-Form",
} as Meta;
-enum GenderEnum {
- MALE = "male",
- FEMALE = "female",
- OTHER = "other",
-}
-enum CompetitionEnum {
- ATHLETICS = "Athletics",
- SWIMMING = "Swimming",
- MARATHON = "Marathon",
-}
-enum RewardEnum {
- BRONZE = "bronze",
- SILVER = "silver",
- GOLD = "gold",
- FLOCON = "flocon",
- OURSON = "ourson",
- CHAMOIS = "chamois",
-}
-
interface SportsStoryFormValues {
firstName: string;
lastName: string;
- gender: GenderEnum;
- competition: CompetitionEnum;
- rewards: RewardEnum[];
+ gender: string;
+ competition: string;
+ rewards: string[];
}
const sportsSchema = Yup.object().shape({
firstName: Yup.string().required(),
lastName: Yup.string().required(),
- gender: Yup.string().required(),
- competition: Yup.string()
- .defined()
- .required()
- .oneOf(Object.values(CompetitionEnum)),
- rewards: Yup.array().of(Yup.string().defined()).defined(),
+ gender: Yup.string().required(),
+ competition: Yup.string().defined().required(),
+ rewards: Yup.array().of(Yup.string().defined()).defined(),
});
export const Sports = () => {
- const { register, handleSubmit, formState, control } =
- useForm({
- defaultValues: {
- firstName: "",
- lastName: "",
- rewards: [],
- },
- mode: "onChange",
- reValidateMode: "onChange",
- resolver: yupResolver(sportsSchema),
- });
-
- const renderCompetitionSelect = ({
- field,
- }: {
- field: ControllerRenderProps;
- }) => {
- return (
-
- );
- };
-
- const renderRewardsMultiSelect = ({
- field,
- }: {
- field: ControllerRenderProps;
- }) => {
- return (
-
- );
- };
+ const methods = useForm({
+ defaultValues: {
+ firstName: "",
+ lastName: "",
+ rewards: [],
+ },
+ mode: "onChange",
+ reValidateMode: "onChange",
+ resolver: yupResolver(sportsSchema),
+ });
return (
-
+
+
+
+
);
};
diff --git a/packages/react/src/tests/reactHookFormUtils.tsx b/packages/react/src/components/Forms/Examples/ReactHookForm/reactHookFormUtils.tsx
similarity index 100%
rename from packages/react/src/tests/reactHookFormUtils.tsx
rename to packages/react/src/components/Forms/Examples/ReactHookForm/reactHookFormUtils.tsx
diff --git a/packages/react/src/components/Forms/Input/index.stories.tsx b/packages/react/src/components/Forms/Input/index.stories.tsx
index 78a07bc..96d2fdc 100644
--- a/packages/react/src/components/Forms/Input/index.stories.tsx
+++ b/packages/react/src/components/Forms/Input/index.stories.tsx
@@ -3,13 +3,13 @@ import { Meta } from "@storybook/react";
import { useForm } from "react-hook-form";
import * as Yup from "yup";
import React, { useRef } from "react";
-import { Input } from ":/components/Forms/Input/index";
-import { Button } from ":/components/Button";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
-} from ":/tests/reactHookFormUtils";
+} from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
+import { Input } from ":/components/Forms/Input/index";
+import { Button } from ":/components/Button";
export default {
title: "Components/Forms/Input",
@@ -175,47 +175,6 @@ export const WithRef = () => {
);
};
-export const ReactHookForm = () => {
- interface InputExampleFormValues {
- email: string;
- }
-
- const inputExampleSchema = Yup.object().shape({
- email: Yup.string().email().required(),
- });
- const { register, handleSubmit, formState } = useForm(
- {
- defaultValues: {
- email: "",
- },
- mode: "onChange",
- reValidateMode: "onChange",
- resolver: yupResolver(inputExampleSchema),
- },
- );
-
- return (
-
- );
-};
-
export const FormExample = () => {
return (
@@ -268,3 +227,44 @@ export const FormExample = () => {
);
};
+
+export const ReactHookForm = () => {
+ interface InputExampleFormValues {
+ email: string;
+ }
+
+ const inputExampleSchema = Yup.object().shape({
+ email: Yup.string().email().required(),
+ });
+ const { register, handleSubmit, formState } = useForm(
+ {
+ defaultValues: {
+ email: "",
+ },
+ mode: "onChange",
+ reValidateMode: "onChange",
+ resolver: yupResolver(inputExampleSchema),
+ },
+ );
+
+ return (
+
+ );
+};
diff --git a/packages/react/src/components/Forms/Radio/index.stories.tsx b/packages/react/src/components/Forms/Radio/index.stories.tsx
index 83b8818..1f04b48 100644
--- a/packages/react/src/components/Forms/Radio/index.stories.tsx
+++ b/packages/react/src/components/Forms/Radio/index.stories.tsx
@@ -3,13 +3,13 @@ import { useForm } from "react-hook-form";
import * as Yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { Meta, StoryFn } from "@storybook/react";
-import { Radio, RadioGroup } from ":/components/Forms/Radio/index";
-import { Button } from ":/components/Button";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
-} from ":/tests/reactHookFormUtils";
+} from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
+import { Radio, RadioGroup } from ":/components/Forms/Radio/index";
+import { Button } from ":/components/Button";
export default {
title: "Components/Forms/Radio",
diff --git a/packages/react/src/components/Forms/Select/mono.stories.tsx b/packages/react/src/components/Forms/Select/mono.stories.tsx
index 40dd5ec..8a3ba96 100644
--- a/packages/react/src/components/Forms/Select/mono.stories.tsx
+++ b/packages/react/src/components/Forms/Select/mono.stories.tsx
@@ -1,17 +1,14 @@
import { Meta, StoryFn } from "@storybook/react";
import React, { useState } from "react";
-import { useForm, Controller, ControllerRenderProps } from "react-hook-form";
+import { useForm, FormProvider } from "react-hook-form";
import * as Yup from "yup";
import { faker } from "@faker-js/faker";
import { yupResolver } from "@hookform/resolvers/yup";
+import { onSubmit } from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
import { Select } from ":/components/Forms/Select";
import { Button } from ":/components/Button";
import { CunninghamProvider } from ":/components/Provider";
-import {
- getFieldState,
- getFieldErrorMessage,
- onSubmit,
-} from ":/tests/reactHookFormUtils";
+import { RhfSelect } from ":/components/Forms/Select/stories-utils";
export default {
title: "Components/Forms/Select/Mono",
@@ -164,87 +161,6 @@ export const SearchableControlled = () => {
);
};
-export const ReactHookForm = () => {
- enum CitiesOptionEnum {
- NONE = "",
- DIJON = "dijon",
- PARIS = "paris",
- TOKYO = "tokyo",
- }
-
- interface SelectExampleFormValues {
- joTown: CitiesOptionEnum;
- }
-
- const selectExampleSchema = Yup.object().shape({
- joTown: Yup.string()
- .required()
- .oneOf([CitiesOptionEnum.PARIS], "That's not the right town!"),
- });
-
- const { handleSubmit, formState, control } = useForm(
- {
- defaultValues: {
- joTown: CitiesOptionEnum.NONE,
- },
- mode: "onChange",
- reValidateMode: "onChange",
- resolver: yupResolver(selectExampleSchema),
- },
- );
-
- const renderSelect = ({
- field,
- }: {
- field: ControllerRenderProps;
- }) => {
- return (
- <>
- Where will the 2024 Olympics take place?
-
- >
- );
- };
-
- return (
-
-
-
- );
-};
-
export const FullWidth = {
render: Template,
@@ -405,3 +321,69 @@ export const FormExample = () => {
);
};
+
+export const ReactHookForm = () => {
+ enum CitiesOptionEnum {
+ NONE = "",
+ DIJON = "dijon",
+ PARIS = "paris",
+ TOKYO = "tokyo",
+ }
+
+ interface SelectExampleFormValues {
+ joTown: CitiesOptionEnum;
+ }
+
+ const selectExampleSchema = Yup.object().shape({
+ joTown: Yup.string()
+ .required()
+ .oneOf([CitiesOptionEnum.PARIS], "That's not the right town!"),
+ });
+
+ const methods = useForm({
+ defaultValues: {
+ joTown: CitiesOptionEnum.NONE,
+ },
+ mode: "onChange",
+ reValidateMode: "onChange",
+ resolver: yupResolver(selectExampleSchema),
+ });
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/packages/react/src/components/Forms/Select/multi.stories.tsx b/packages/react/src/components/Forms/Select/multi.stories.tsx
index c1f3a5d..2570574 100644
--- a/packages/react/src/components/Forms/Select/multi.stories.tsx
+++ b/packages/react/src/components/Forms/Select/multi.stories.tsx
@@ -1,17 +1,14 @@
import React, { useState } from "react";
-import { useForm, Controller, ControllerRenderProps } from "react-hook-form";
+import { useForm, FormProvider } from "react-hook-form";
import * as Yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { Meta, StoryFn } from "@storybook/react";
import { faker } from "@faker-js/faker";
+import { onSubmit } from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
import { Select } from ":/components/Forms/Select";
import { CunninghamProvider } from ":/components/Provider";
import { Button } from ":/components/Button";
-import {
- getFieldState,
- getFieldErrorMessage,
- onSubmit,
-} from ":/tests/reactHookFormUtils";
+import { RhfSelect } from ":/components/Forms/Select/stories-utils";
export default {
title: "Components/Forms/Select/Multi",
@@ -216,103 +213,6 @@ export const Error = {
},
};
-export const ReactHookForm = () => {
- enum CitiesOptionEnum {
- NONE = "",
- DIJON = "dijon",
- PARIS = "paris",
- TOKYO = "tokyo",
- VANNES = "vannes",
- }
-
- interface SelectExampleFormValues {
- capitalCity: CitiesOptionEnum[];
- }
-
- const selectExampleSchema = Yup.object().shape({
- capitalCity: Yup.array()
- .required()
- .test({
- test: (cityList) =>
- cityList.every((city) =>
- [CitiesOptionEnum.PARIS, CitiesOptionEnum.TOKYO].includes(city),
- ),
- message: "Wrong answer!",
- }),
- });
-
- const { handleSubmit, formState, control } = useForm(
- {
- defaultValues: {
- capitalCity: [],
- },
- mode: "onChange",
- reValidateMode: "onChange",
- resolver: yupResolver(selectExampleSchema),
- },
- );
-
- const renderSelect = ({
- field,
- }: {
- field: ControllerRenderProps;
- }) => {
- return (
- <>
- Which are the capital of the country ?
-
- >
- );
- };
-
- return (
-
-
-
- );
-};
-
export const FormExample = () => {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
@@ -409,3 +309,81 @@ export const FormExample = () => {
);
};
+
+export const ReactHookForm = () => {
+ enum CitiesOptionEnum {
+ NONE = "",
+ DIJON = "dijon",
+ PARIS = "paris",
+ TOKYO = "tokyo",
+ VANNES = "vannes",
+ }
+
+ interface SelectExampleFormValues {
+ capitalCity: CitiesOptionEnum[];
+ }
+
+ const selectExampleSchema = Yup.object().shape({
+ capitalCity: Yup.array()
+ .required()
+ .test({
+ test: (cityList) =>
+ cityList.every((city) =>
+ [CitiesOptionEnum.PARIS, CitiesOptionEnum.TOKYO].includes(city),
+ ),
+ message: "Wrong answer!",
+ }),
+ });
+
+ const methods = useForm({
+ defaultValues: {
+ capitalCity: [],
+ },
+ mode: "onChange",
+ reValidateMode: "onChange",
+ resolver: yupResolver(selectExampleSchema),
+ });
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/packages/react/src/components/Forms/Select/stories-utils.tsx b/packages/react/src/components/Forms/Select/stories-utils.tsx
new file mode 100644
index 0000000..b8928de
--- /dev/null
+++ b/packages/react/src/components/Forms/Select/stories-utils.tsx
@@ -0,0 +1,26 @@
+import { Controller, useFormContext } from "react-hook-form";
+import React from "react";
+import { Select } from ":/components/Forms/Select/index";
+import { SelectProps } from ":/components/Forms/Select/mono";
+
+export const RhfSelect = (props: SelectProps & { name: string }) => {
+ const { control } = useFormContext();
+ return (
+ {
+ return (
+
+ );
+ }}
+ />
+ );
+};
diff --git a/packages/react/src/components/Forms/Switch/index.stories.tsx b/packages/react/src/components/Forms/Switch/index.stories.tsx
index e2376ce..db31e98 100644
--- a/packages/react/src/components/Forms/Switch/index.stories.tsx
+++ b/packages/react/src/components/Forms/Switch/index.stories.tsx
@@ -3,13 +3,13 @@ import { Meta } from "@storybook/react";
import { useForm } from "react-hook-form";
import * as Yup from "yup";
import React from "react";
-import { Switch } from ":/components/Forms/Switch/index";
-import { Button } from ":/components/Button";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
-} from ":/tests/reactHookFormUtils";
+} from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
+import { Switch } from ":/components/Forms/Switch/index";
+import { Button } from ":/components/Button";
export default {
title: "Components/Forms/Switch",
@@ -130,49 +130,6 @@ export const Controlled = {
},
};
-export const ReactHookForm = () => {
- interface SwitchExampleFormValues {
- terms: boolean;
- }
-
- const switchExampleSchema = Yup.object().shape({
- terms: Yup.boolean()
- .required()
- .oneOf([true], "You have to accept the terms of use"),
- });
-
- const { register, handleSubmit, formState } =
- useForm({
- defaultValues: {
- terms: false,
- },
- mode: "onChange",
- reValidateMode: "onChange",
- resolver: yupResolver(switchExampleSchema),
- });
-
- return (
-
- );
-};
-
export const FormExample = {
render: () => {
return (
@@ -240,3 +197,46 @@ export const FormExampleRight = {
);
},
};
+
+export const ReactHookForm = () => {
+ interface SwitchExampleFormValues {
+ terms: boolean;
+ }
+
+ const switchExampleSchema = Yup.object().shape({
+ terms: Yup.boolean()
+ .required()
+ .oneOf([true], "You have to accept the terms of use"),
+ });
+
+ const { register, handleSubmit, formState } =
+ useForm({
+ defaultValues: {
+ terms: false,
+ },
+ mode: "onChange",
+ reValidateMode: "onChange",
+ resolver: yupResolver(switchExampleSchema),
+ });
+
+ return (
+
+ );
+};