@availity/mui-controlled-form 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +2 -2
  3. package/dist/index.d.mts +122 -26
  4. package/dist/index.d.ts +122 -26
  5. package/dist/index.js +174 -132
  6. package/dist/index.mjs +174 -131
  7. package/package.json +2 -2
  8. package/src/index.ts +47 -0
  9. package/src/lib/AsyncAutocomplete.stories.tsx +21 -36
  10. package/src/lib/AsyncAutocomplete.test.tsx +17 -53
  11. package/src/lib/AsyncAutocomplete.tsx +13 -6
  12. package/src/lib/Autocomplete.stories.tsx +20 -33
  13. package/src/lib/Autocomplete.test.tsx +7 -37
  14. package/src/lib/Autocomplete.tsx +21 -16
  15. package/src/lib/Checkbox.stories.tsx +48 -46
  16. package/src/lib/Checkbox.test.tsx +14 -46
  17. package/src/lib/Checkbox.tsx +19 -16
  18. package/src/lib/CodesAutocomplete.stories.tsx +21 -35
  19. package/src/lib/CodesAutocomplete.test.tsx +20 -54
  20. package/src/lib/CodesAutocomplete.tsx +13 -6
  21. package/src/lib/ControlledForm.stories.tsx +1 -0
  22. package/src/lib/ControlledForm.tsx +7 -3
  23. package/src/lib/Datepicker.stories.tsx +19 -32
  24. package/src/lib/Datepicker.test.tsx +3 -35
  25. package/src/lib/Datepicker.tsx +18 -8
  26. package/src/lib/Input.stories.tsx +32 -38
  27. package/src/lib/Input.test.tsx +71 -7
  28. package/src/lib/Input.tsx +30 -15
  29. package/src/lib/OrganizationAutocomplete.stories.tsx +30 -35
  30. package/src/lib/OrganizationAutocomplete.test.tsx +23 -57
  31. package/src/lib/OrganizationAutocomplete.tsx +14 -9
  32. package/src/lib/ProviderAutocomplete.stories.tsx +20 -35
  33. package/src/lib/ProviderAutocomplete.test.tsx +29 -63
  34. package/src/lib/ProviderAutocomplete.tsx +11 -5
  35. package/src/lib/RadioGroup.stories.tsx +41 -36
  36. package/src/lib/RadioGroup.test.tsx +3 -35
  37. package/src/lib/RadioGroup.tsx +31 -20
  38. package/src/lib/Select.stories.tsx +66 -93
  39. package/src/lib/Select.test.tsx +8 -36
  40. package/src/lib/Select.tsx +30 -15
  41. package/src/lib/TextField.stories.tsx +26 -39
  42. package/src/lib/TextField.test.tsx +71 -5
  43. package/src/lib/TextField.tsx +32 -17
  44. package/src/lib/Types.tsx +2489 -0
  45. package/src/lib/UtilComponents.tsx +52 -0
  46. package/docs/propDefinitions.tsx +0 -31
@@ -1,57 +1,25 @@
1
1
  import { render, fireEvent, waitFor } from '@testing-library/react';
2
2
  import { FormControl, FormLabel, FormControlLabel, FormGroup } from '@availity/mui-form-utils';
3
- import { useFormContext } from 'react-hook-form';
4
- import { Paper } from '@availity/mui-paper';
5
- import { Typography } from '@availity/mui-typography';
6
- import { Grid } from '@availity/mui-layout';
7
- import { Button } from '@availity/mui-button';
8
- import { ControlledForm } from './ControlledForm';
9
3
  import { ControlledCheckbox } from './Checkbox';
10
-
11
- const SubmittedValues = () => {
12
- const {
13
- getValues,
14
- formState: { isSubmitSuccessful },
15
- } = useFormContext();
16
-
17
- return isSubmitSuccessful ? (
18
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
19
- <Typography variant="h2">Submitted Values</Typography>
20
- <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
21
- </Paper>
22
- ) : null;
23
- };
24
-
25
- const Actions = () => {
26
- const {
27
- formState: { isSubmitSuccessful },
28
- } = useFormContext();
29
- return (
30
- <Grid container direction="row" justifyContent="space-between">
31
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
32
- </Grid>
33
- );
34
- };
4
+ import { TestForm } from './UtilComponents';
35
5
 
36
6
  const onSubmit = jest.fn();
37
7
 
38
8
  describe('ControlledCheckbox', () => {
39
9
  test('should set the value and submit the form data', async () => {
40
- const screen = render(
41
- <ControlledForm onSubmit={onSubmit} values={{ controlledCheckbox: undefined }}>
42
- <FormControl>
43
- <FormLabel id="radio-group" component="div">
44
- Radio Group
45
- </FormLabel>
46
- <FormGroup>
47
- <FormControlLabel label="Option 1" control={<ControlledCheckbox name="option1" />} />
48
- <FormControlLabel label="Option 2" control={<ControlledCheckbox name="option2" />} />
49
- <FormControlLabel label="Option 3" control={<ControlledCheckbox name="option3" />} />
50
- </FormGroup>
51
- </FormControl>
52
- <Actions />
53
- <SubmittedValues />
54
- </ControlledForm>
10
+ const screen = render(
11
+ <TestForm onSubmit={onSubmit} UseFormOptions={{values: { option1: undefined, option2: undefined, option3: undefined }}}>
12
+ <FormControl>
13
+ <FormLabel id="radio-group" component="div">
14
+ Radio Group
15
+ </FormLabel>
16
+ <FormGroup>
17
+ <FormControlLabel label="Option 1" control={<ControlledCheckbox name="option1" />} />
18
+ <FormControlLabel label="Option 2" control={<ControlledCheckbox name="option2" />} />
19
+ <FormControlLabel label="Option 3" control={<ControlledCheckbox name="option3" />} />
20
+ </FormGroup>
21
+ </FormControl>
22
+ </TestForm>
55
23
  );
56
24
 
57
25
  const option1 = screen.getByText('Option 1');
@@ -1,21 +1,20 @@
1
1
  import { Checkbox, CheckboxProps } from '@availity/mui-checkbox';
2
- import { RegisterOptions, FieldValues, Controller, ControllerProps } from 'react-hook-form';
2
+ import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
3
+ import { ControllerProps, DeprecatedRulesProps } from './Types';
3
4
 
4
- export type ControlledCheckboxProps = CheckboxProps &
5
- Omit<
6
- RegisterOptions<FieldValues, string>,
7
- | 'required'
8
- | 'disabled'
9
- | 'valueAsNumber'
10
- | 'valueAsDate'
11
- | 'setValueAs'
12
- | 'max'
13
- | 'maxLength'
14
- | 'min'
15
- | 'minLength'
16
- | 'pattern'
17
- > &
18
- Pick<ControllerProps, 'defaultValue' | 'shouldUnregister' | 'name'>;
5
+ export type ControlledCheckboxProps = Omit<CheckboxProps,
6
+ 'disabled' | 'onBlur' | 'onChange' | 'value' | 'name'
7
+ > & Pick<RegisterOptions<FieldValues, string>,
8
+ 'disabled' | 'onBlur' | 'onChange' | 'value'
9
+ > & ControllerProps
10
+ //TODO v1 - remove deprecated props
11
+ & Omit<DeprecatedRulesProps,
12
+ | 'required'
13
+ | 'max'
14
+ | 'maxLength'
15
+ | 'min'
16
+ | 'minLength'
17
+ | 'pattern'>;
19
18
 
20
19
  export const ControlledCheckbox = ({
21
20
  name,
@@ -24,8 +23,10 @@ export const ControlledCheckbox = ({
24
23
  onBlur,
25
24
  value,
26
25
  defaultValue = false,
26
+ rules = {},
27
27
  shouldUnregister,
28
28
  deps,
29
+ validate,
29
30
  ...rest
30
31
  }: ControlledCheckboxProps) => {
31
32
  return (
@@ -39,6 +40,8 @@ export const ControlledCheckbox = ({
39
40
  value,
40
41
  shouldUnregister,
41
42
  deps,
43
+ validate,
44
+ ...rules,
42
45
  }}
43
46
  shouldUnregister={shouldUnregister}
44
47
  render={({ field }) => (
@@ -1,19 +1,18 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { ControlledCodesAutocomplete } from './CodesAutocomplete';
3
- import { ControlledForm } from './ControlledForm';
4
3
  import { Button } from '@availity/mui-button';
5
- import { useFormContext } from 'react-hook-form';
6
4
  import { Paper } from '@availity/mui-paper';
7
5
  import { Typography } from '@availity/mui-typography';
8
6
  import { Grid } from '@availity/mui-layout';
9
7
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
- import { missingRHFprops } from '../../docs/propDefinitions';
8
+ import { AllControllerPropertiesCategorized, CodesAutocompletePropsCategorized } from './Types';
9
+ import { FormProvider, useForm } from '..';
11
10
 
12
11
  const meta: Meta<typeof ControlledCodesAutocomplete> = {
13
12
  title: 'Form Components/Controlled Form/Autocomplete/ControlledCodesAutocomplete',
14
13
  component: ControlledCodesAutocomplete,
15
14
  tags: ['autodocs'],
16
- argTypes: missingRHFprops,
15
+ argTypes: {...AllControllerPropertiesCategorized, ...CodesAutocompletePropsCategorized}
17
16
  };
18
17
 
19
18
  export default meta;
@@ -28,39 +27,25 @@ const client = new QueryClient({
28
27
 
29
28
  export const _ControlledCodesAutoComplete: StoryObj<typeof ControlledCodesAutocomplete> = {
30
29
  render: (args) => {
31
- const SubmittedValues = () => {
32
- const {
33
- getValues,
34
- formState: { isSubmitSuccessful },
35
- } = useFormContext();
30
+ const methods = useForm();
36
31
 
37
- return isSubmitSuccessful ? (
38
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
39
- <Typography variant="h2">Submitted Values</Typography>
40
- <pre>{JSON.stringify(getValues(), null, 2)}</pre>
41
- </Paper>
42
- ) : null;
43
- };
44
-
45
- const Actions = () => {
46
- const {
47
- reset,
48
- formState: { isSubmitSuccessful },
49
- } = useFormContext();
50
- return (
51
- <Grid container direction="row" justifyContent="space-between" marginTop={1}>
52
- <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
53
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
54
- </Grid>
55
- );
56
- };
57
32
  return (
58
33
  <QueryClientProvider client={client}>
59
- <ControlledForm values={{}} onSubmit={(data) => data}>
60
- <ControlledCodesAutocomplete {...args} />
61
- <Actions />
62
- <SubmittedValues />
63
- </ControlledForm>
34
+ <FormProvider {...methods}>
35
+ <form onSubmit={methods.handleSubmit((data) => data)}>
36
+ <ControlledCodesAutocomplete {...args} />
37
+ <Grid container direction="row" justifyContent="space-between" marginTop={1}>
38
+ <Button disabled={!methods?.formState?.isSubmitSuccessful} children="Reset" color="secondary" onClick={() => methods.reset()} />
39
+ <Button type="submit" disabled={methods?.formState?.isSubmitSuccessful} children="Submit" />
40
+ </Grid>
41
+ { methods?.formState?.isSubmitSuccessful ? (
42
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
43
+ <Typography variant="h2">Submitted Values</Typography>
44
+ <pre data-testid="result">{JSON.stringify(methods.getValues(), null, 2)}</pre>
45
+ </Paper>
46
+ ) : null }
47
+ </form>
48
+ </FormProvider>
64
49
  </QueryClientProvider>
65
50
  );
66
51
  },
@@ -72,8 +57,9 @@ export const _ControlledCodesAutoComplete: StoryObj<typeof ControlledCodesAutoco
72
57
  helperText: 'Select a code from the list',
73
58
  placeholder: 'Select...',
74
59
  fullWidth: false,
60
+ required: true
75
61
  },
76
62
  limit: 15,
77
- required: 'This is required.',
63
+ rules: { required:'This is required.' },
78
64
  },
79
65
  };
@@ -1,39 +1,9 @@
1
1
  import { fireEvent, render, waitFor } from '@testing-library/react';
2
2
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
- import { Paper } from '@availity/mui-paper';
4
- import { Typography } from '@availity/mui-typography';
5
- import { useFormContext } from 'react-hook-form';
6
- import { Grid } from '@availity/mui-layout';
7
- import { Button } from '@availity/mui-button';
8
3
  // eslint-disable-next-line @nx/enforce-module-boundaries
9
4
  import { server } from '@availity/mock/src/lib/server';
10
- import { ControlledForm } from './ControlledForm';
11
5
  import { ControlledCodesAutocomplete } from './CodesAutocomplete';
12
-
13
- const SubmittedValues = () => {
14
- const {
15
- getValues,
16
- formState: { isSubmitSuccessful },
17
- } = useFormContext();
18
-
19
- return isSubmitSuccessful ? (
20
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
21
- <Typography variant="h2">Submitted Values</Typography>
22
- <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
23
- </Paper>
24
- ) : null;
25
- };
26
-
27
- const Actions = () => {
28
- const {
29
- formState: { isSubmitSuccessful },
30
- } = useFormContext();
31
- return (
32
- <Grid container direction="row" justifyContent="space-between">
33
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
34
- </Grid>
35
- );
36
- };
6
+ import { TestForm } from './UtilComponents';
37
7
 
38
8
  const onSubmit = jest.fn();
39
9
 
@@ -61,7 +31,7 @@ describe('ControlledAsyncAutocomplete', () => {
61
31
  test('should loadOptions successfully', async () => {
62
32
  const screen = render(
63
33
  <QueryClientProvider client={client}>
64
- <ControlledForm values={{}} onSubmit={onSubmit}>
34
+ <TestForm onSubmit={onSubmit}>
65
35
  <ControlledCodesAutocomplete
66
36
  name="controlledCodesAutocomplete"
67
37
  list="ABC"
@@ -73,11 +43,9 @@ describe('ControlledAsyncAutocomplete', () => {
73
43
  }}
74
44
  limit={15}
75
45
  />
76
- <Actions />
77
- <SubmittedValues />
78
- </ControlledForm>
79
- </QueryClientProvider>
80
- );
46
+ </TestForm>
47
+ </QueryClientProvider>
48
+ );
81
49
 
82
50
  const dropdown = screen.getByRole('combobox');
83
51
  fireEvent.click(dropdown);
@@ -87,23 +55,21 @@ describe('ControlledAsyncAutocomplete', () => {
87
55
  });
88
56
 
89
57
  test('should set the value and submit the form data', async () => {
90
- const screen = render(
91
- <QueryClientProvider client={client}>
92
- <ControlledForm values={{}} onSubmit={onSubmit}>
93
- <ControlledCodesAutocomplete
94
- name="controlledCodesAutocomplete"
95
- list="ABC"
96
- FieldProps={{
97
- label: 'Code Select',
98
- helperText: 'Select a code from the list',
99
- placeholder: 'Select...',
100
- fullWidth: false,
101
- }}
102
- limit={15}
103
- />
104
- <Actions />
105
- <SubmittedValues />
106
- </ControlledForm>
58
+ const screen = render(
59
+ <QueryClientProvider client={client}>
60
+ <TestForm onSubmit={onSubmit}>
61
+ <ControlledCodesAutocomplete
62
+ name="controlledCodesAutocomplete"
63
+ list="ABC"
64
+ FieldProps={{
65
+ label: 'Code Select',
66
+ helperText: 'Select a code from the list',
67
+ placeholder: 'Select...',
68
+ fullWidth: false,
69
+ }}
70
+ limit={15}
71
+ />
72
+ </TestForm>
107
73
  </QueryClientProvider>
108
74
  );
109
75
 
@@ -1,9 +1,14 @@
1
1
  import { CodesAutocomplete, CodesAutocompleteProps } from '@availity/mui-autocomplete';
2
- import { Controller, RegisterOptions, ControllerProps, FieldValues } from 'react-hook-form';
2
+ import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
3
+ import { ControllerProps, DeprecatedRulesProps } from './Types';
3
4
 
4
- export type ControlledCodesAutocompleteProps = Omit<CodesAutocompleteProps, 'name'> &
5
- Omit<RegisterOptions<FieldValues, string>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'> &
6
- Pick<ControllerProps, 'defaultValue' | 'shouldUnregister' | 'name'>;
5
+ export type ControlledCodesAutocompleteProps = Omit<CodesAutocompleteProps,
6
+ 'onBlur' | 'onChange' | 'value' | 'name'
7
+ > & Pick<RegisterOptions<FieldValues, string>,
8
+ 'onBlur' | 'onChange' | 'value'
9
+ > & ControllerProps
10
+ //TODO v1 - remove deprecated props
11
+ & DeprecatedRulesProps;
7
12
 
8
13
  export const ControlledCodesAutocomplete = ({
9
14
  name,
@@ -15,6 +20,7 @@ export const ControlledCodesAutocomplete = ({
15
20
  onChange,
16
21
  pattern,
17
22
  required,
23
+ rules = {},
18
24
  shouldUnregister,
19
25
  validate,
20
26
  value,
@@ -36,14 +42,14 @@ export const ControlledCodesAutocomplete = ({
36
42
  shouldUnregister,
37
43
  validate,
38
44
  value,
45
+ ...rules,
39
46
  }}
40
47
  shouldUnregister={shouldUnregister}
41
- render={({ field: { onChange, value, onBlur }, fieldState: { error } }) => (
48
+ render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
42
49
  <CodesAutocomplete
43
50
  {...rest}
44
51
  FieldProps={{
45
52
  ...FieldProps,
46
- required: typeof required === 'object' ? required.value : !!required,
47
53
  error: !!error,
48
54
  helperText: error?.message ? (
49
55
  <>
@@ -54,6 +60,7 @@ export const ControlledCodesAutocomplete = ({
54
60
  ) : (
55
61
  FieldProps?.helperText
56
62
  ),
63
+ inputRef:ref
57
64
  }}
58
65
  onChange={(event, value, reason) => {
59
66
  if (reason === 'clear') {
@@ -11,6 +11,7 @@ import { ControlledTextField } from './TextField';
11
11
  import * as yup from 'yup';
12
12
  import { yupResolver } from '@hookform/resolvers/yup';
13
13
 
14
+ /** Deprecated. Use `FormProvider` and `useForm` directly. */
14
15
  const meta: Meta<typeof ControlledForm> = {
15
16
  title: 'Form Components/Controlled Form/ControlledForm',
16
17
  component: ControlledForm,
@@ -1,6 +1,7 @@
1
1
  import { FormHTMLAttributes } from 'react';
2
- import { useForm, SubmitHandler, FormProvider, Resolver } from 'react-hook-form';
2
+ import { useForm, SubmitHandler, FormProvider, Resolver, UseFormProps } from 'react-hook-form';
3
3
 
4
+ /** @deprecated Use `UseFormProps` directly with `useForm` and `FormProvider` */
4
5
  export type ControlledFormProps = {
5
6
  /** This function will receive the form data if form validation is successful. */
6
7
  onSubmit: SubmitHandler<any>;
@@ -13,6 +14,8 @@ export type ControlledFormProps = {
13
14
  * found here: https://github.com/react-hook-form/resolvers#quickstart
14
15
  */
15
16
  validationResolver?: (schema: unknown) => Resolver;
17
+ /** Additional react-hook-form `useForm` options, like `defaultValues` and validation `mode`. For more information see the [react-hook-form useForm docs](https://react-hook-form.com/docs/useform) */
18
+ additionalUseFormOptions?: Omit<UseFormProps, 'values' | 'resolver'>;
16
19
  } & FormHTMLAttributes<HTMLFormElement>;
17
20
 
18
21
  type UseFormOptions = {
@@ -20,8 +23,9 @@ type UseFormOptions = {
20
23
  resolver?: Resolver;
21
24
  };
22
25
 
23
- export const ControlledForm = ({ onSubmit, values, schema, validationResolver, ...rest }: ControlledFormProps) => {
24
- const useFormOptions: UseFormOptions = { values };
26
+ /** @deprecated Use `FormProvider` and `useForm` directly. */
27
+ export const ControlledForm = ({ onSubmit, values, schema, validationResolver, additionalUseFormOptions = {mode: 'onBlur'}, ...rest }: ControlledFormProps) => {
28
+ const useFormOptions: UseFormOptions = { values, ...additionalUseFormOptions };
25
29
  if (schema && validationResolver) {
26
30
  useFormOptions.resolver = validationResolver(schema);
27
31
  }
@@ -1,54 +1,41 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { ControlledDatepicker, ControlledDatepickerProps } from './Datepicker';
3
- import { ControlledForm } from './ControlledForm';
4
3
  import { Button } from '@availity/mui-button';
5
- import { useFormContext } from 'react-hook-form';
6
4
  import { Paper } from '@availity/mui-paper';
7
5
  import { Typography } from '@availity/mui-typography';
8
6
  import { Grid } from '@availity/mui-layout';
7
+ import { AllControllerPropertiesCategorized, DatepickerPropsCategorized } from './Types';
8
+ import { FormProvider, useForm } from '..';
9
9
 
10
10
  const meta: Meta<typeof ControlledDatepicker> = {
11
11
  title: 'Form Components/Controlled Form/ControlledDatepicker',
12
12
  component: ControlledDatepicker,
13
13
  tags: ['autodocs'],
14
+ argTypes: {...AllControllerPropertiesCategorized, ...DatepickerPropsCategorized}
14
15
  };
15
16
 
16
17
  export default meta;
17
18
 
18
19
  export const _ControlledInput: StoryObj<typeof ControlledDatepicker> = {
19
20
  render: (args: ControlledDatepickerProps) => {
20
- const SubmittedValues = () => {
21
- const {
22
- getValues,
23
- formState: { isSubmitSuccessful },
24
- } = useFormContext();
21
+ const methods = useForm();
25
22
 
26
- return isSubmitSuccessful ? (
27
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
28
- <Typography variant="h2">Submitted Values</Typography>
29
- <pre>{JSON.stringify(getValues(), null, 2)}</pre>
30
- </Paper>
31
- ) : null;
32
- };
33
-
34
- const Actions = () => {
35
- const {
36
- reset,
37
- formState: { isSubmitSuccessful },
38
- } = useFormContext();
39
- return (
40
- <Grid container direction="row" justifyContent="space-between" marginTop={1}>
41
- <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
42
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
43
- </Grid>
44
- );
45
- };
46
23
  return (
47
- <ControlledForm values={{ controlledInput: undefined }} onSubmit={(data) => data}>
48
- <ControlledDatepicker {...args} />
49
- <Actions />
50
- <SubmittedValues />
51
- </ControlledForm>
24
+ <FormProvider {...methods}>
25
+ <form onSubmit={methods.handleSubmit((data) => data)}>
26
+ <ControlledDatepicker {...args} />
27
+ <Grid container direction="row" justifyContent="space-between" marginTop={1}>
28
+ <Button disabled={!methods?.formState?.isSubmitSuccessful} children="Reset" color="secondary" onClick={() => methods.reset()} />
29
+ <Button type="submit" disabled={methods?.formState?.isSubmitSuccessful} children="Submit" />
30
+ </Grid>
31
+ { methods?.formState?.isSubmitSuccessful ? (
32
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
33
+ <Typography variant="h2">Submitted Values</Typography>
34
+ <pre data-testid="result">{JSON.stringify(methods.getValues(), null, 2)}</pre>
35
+ </Paper>
36
+ ) : null }
37
+ </form>
38
+ </FormProvider>
52
39
  );
53
40
  },
54
41
  args: {
@@ -1,38 +1,8 @@
1
1
  import { render, fireEvent, waitFor } from '@testing-library/react';
2
- import { useFormContext } from 'react-hook-form';
3
- import { Paper } from '@availity/mui-paper';
4
- import { Typography } from '@availity/mui-typography';
5
- import { Grid } from '@availity/mui-layout';
6
- import { Button } from '@availity/mui-button';
7
2
  import { ThemeProvider } from '@availity/theme-provider';
8
3
  import dayjs from 'dayjs';
9
- import { ControlledForm } from './ControlledForm';
10
4
  import { ControlledDatepicker } from './Datepicker';
11
-
12
- const SubmittedValues = () => {
13
- const {
14
- getValues,
15
- formState: { isSubmitSuccessful },
16
- } = useFormContext();
17
-
18
- return isSubmitSuccessful ? (
19
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
20
- <Typography variant="h2">Submitted Values</Typography>
21
- <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
22
- </Paper>
23
- ) : null;
24
- };
25
-
26
- const Actions = () => {
27
- const {
28
- formState: { isSubmitSuccessful },
29
- } = useFormContext();
30
- return (
31
- <Grid container direction="row" justifyContent="space-between">
32
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
33
- </Grid>
34
- );
35
- };
5
+ import { TestForm } from './UtilComponents';
36
6
 
37
7
  const onSubmit = jest.fn();
38
8
 
@@ -40,7 +10,7 @@ describe('Datepicker', () => {
40
10
  test('should render successfully and submit selection', async () => {
41
11
  const screen = render(
42
12
  <ThemeProvider>
43
- <ControlledForm values={{ controlledDatepicker: undefined }} onSubmit={onSubmit}>
13
+ <TestForm UseFormOptions={{values: { controlledDatepicker: null}}} onSubmit={onSubmit}>
44
14
  <ControlledDatepicker
45
15
  name="controlledDatepicker"
46
16
  FieldProps={{
@@ -50,9 +20,7 @@ describe('Datepicker', () => {
50
20
  label: 'Date',
51
21
  }}
52
22
  />
53
- <Actions />
54
- <SubmittedValues />
55
- </ControlledForm>
23
+ </TestForm>
56
24
  </ThemeProvider>
57
25
  );
58
26
  expect(screen.getAllByText('Date')).toBeTruthy();
@@ -1,9 +1,14 @@
1
1
  import { Datepicker, DatepickerProps } from '@availity/mui-datepicker';
2
- import { RegisterOptions, FieldValues, Controller, ControllerProps } from 'react-hook-form';
2
+ import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
3
+ import { ControllerProps, DeprecatedRulesProps } from './Types';
3
4
 
4
- export type ControlledDatepickerProps = DatepickerProps &
5
- Omit<RegisterOptions<FieldValues, string>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'> &
6
- Pick<ControllerProps, 'defaultValue' | 'shouldUnregister' | 'name'>;
5
+ export type ControlledDatepickerProps = Omit<DatepickerProps,
6
+ 'onBlur' | 'onChange' | 'value' | 'name'
7
+ > & Pick<RegisterOptions<FieldValues, string>,
8
+ 'onBlur' | 'onChange' | 'value'
9
+ > & ControllerProps
10
+ //TODO v1 - remove deprecated props
11
+ & DeprecatedRulesProps;
7
12
 
8
13
  export const ControlledDatepicker = ({
9
14
  name,
@@ -17,6 +22,7 @@ export const ControlledDatepicker = ({
17
22
  onChange,
18
23
  pattern,
19
24
  required,
25
+ rules = {},
20
26
  shouldUnregister,
21
27
  validate,
22
28
  value,
@@ -40,24 +46,28 @@ export const ControlledDatepicker = ({
40
46
  shouldUnregister,
41
47
  validate,
42
48
  value,
49
+ ...rules,
43
50
  }}
44
51
  shouldUnregister={shouldUnregister}
45
- render={({ field: { onChange, value }, fieldState: { error } }) => (
52
+ render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
46
53
  <Datepicker
47
54
  {...rest}
48
55
  FieldProps={{
49
56
  ...FieldProps,
50
- required: typeof required === 'object' ? required.value : !!required,
51
57
  error: !!error,
52
- helperText: error?.message ? (
58
+ helperText: error ? (
53
59
  <>
54
- {error?.message}
60
+ {error.message}
55
61
  <br />
56
62
  {FieldProps?.helperText}
57
63
  </>
58
64
  ) : (
59
65
  FieldProps?.helperText
60
66
  ),
67
+ inputRef: ref,
68
+ inputProps: {
69
+ onBlur: onBlur
70
+ },
61
71
  }}
62
72
  onChange={onChange}
63
73
  value={value || null}