@availity/mui-controlled-form 0.2.5 → 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 +14 -0
  2. package/README.md +2 -2
  3. package/dist/index.d.mts +122 -34
  4. package/dist/index.d.ts +122 -34
  5. package/dist/index.js +263 -225
  6. package/dist/index.mjs +279 -240
  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 +23 -20
  12. package/src/lib/Autocomplete.stories.tsx +20 -33
  13. package/src/lib/Autocomplete.test.tsx +7 -37
  14. package/src/lib/Autocomplete.tsx +16 -15
  15. package/src/lib/Checkbox.stories.tsx +50 -43
  16. package/src/lib/Checkbox.test.tsx +14 -46
  17. package/src/lib/Checkbox.tsx +30 -15
  18. package/src/lib/CodesAutocomplete.stories.tsx +21 -35
  19. package/src/lib/CodesAutocomplete.test.tsx +20 -54
  20. package/src/lib/CodesAutocomplete.tsx +23 -20
  21. package/src/lib/ControlledForm.stories.tsx +1 -0
  22. package/src/lib/ControlledForm.tsx +8 -4
  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 -10
  26. package/src/lib/Input.stories.tsx +32 -33
  27. package/src/lib/Input.test.tsx +71 -7
  28. package/src/lib/Input.tsx +44 -24
  29. package/src/lib/OrganizationAutocomplete.stories.tsx +30 -35
  30. package/src/lib/OrganizationAutocomplete.test.tsx +23 -57
  31. package/src/lib/OrganizationAutocomplete.tsx +24 -23
  32. package/src/lib/ProviderAutocomplete.stories.tsx +20 -35
  33. package/src/lib/ProviderAutocomplete.test.tsx +29 -63
  34. package/src/lib/ProviderAutocomplete.tsx +22 -20
  35. package/src/lib/RadioGroup.stories.tsx +41 -36
  36. package/src/lib/RadioGroup.test.tsx +3 -35
  37. package/src/lib/RadioGroup.tsx +33 -25
  38. package/src/lib/Select.stories.tsx +78 -45
  39. package/src/lib/Select.test.tsx +8 -36
  40. package/src/lib/Select.tsx +44 -25
  41. package/src/lib/TextField.stories.tsx +26 -34
  42. package/src/lib/TextField.test.tsx +71 -5
  43. package/src/lib/TextField.tsx +55 -37
  44. package/src/lib/Types.tsx +2489 -0
  45. package/src/lib/UtilComponents.tsx +52 -0
  46. package/docs/propDefinitions.tsx +0 -31
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@availity/mui-controlled-form",
3
- "version": "0.2.5",
4
- "description": "Availity MUI ControlledForm Component - part of the @availity/element design system",
3
+ "version": "0.3.0",
4
+ "description": "Availity MUI/react-hook-form controlled form components - part of the @availity/element design system",
5
5
  "keywords": [
6
6
  "react",
7
7
  "typescript",
package/src/index.ts CHANGED
@@ -10,3 +10,50 @@ export * from './lib/ProviderAutocomplete';
10
10
  export * from './lib/RadioGroup';
11
11
  export * from './lib/Select';
12
12
  export * from './lib/TextField';
13
+
14
+ export {
15
+ FormProvider,
16
+ /** Custom react-hook-form hook to manage the entire form.
17
+ *
18
+ * ```tsx
19
+ * function App() {
20
+ * const { handleSubmit, methods, formState: { isSubmitting } } = useForm();
21
+ * const schema = yup.object({
22
+ * textField: yup
23
+ * .string(),
24
+ * requiredTextField: yup
25
+ * .string()
26
+ * .required('This field is required.'),
27
+ * });
28
+ *
29
+ * type FormInputsType = yup.InferType<typeof schema>;
30
+ *
31
+ * const onSubmit: SubmitHandler<FormInputsType> = (data) => console.log(data)
32
+ *
33
+ * const defaultValues = {
34
+ * textField: "",
35
+ * requiredTextField: ""
36
+ * }
37
+ *
38
+ * return (
39
+ * <FormProvider {...methods}>
40
+ * <form onSubmit={methods.handleSubmit(onSubmit)}>
41
+ * <TextField name="textField" />
42
+ * <TextField name="requiredTextField" />
43
+ * <LoadingButton loading={isSubmitting}>Submit</LoadingButton>
44
+ * </form>
45
+ * </FormProvider>
46
+ * );
47
+ * }
48
+ * ```
49
+ */
50
+ useForm,
51
+ useFormContext
52
+ } from 'react-hook-form';
53
+
54
+ export type {
55
+ SubmitHandler,
56
+ /** 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) */
57
+ UseFormProps,
58
+ UseFormReturn,
59
+ } from 'react-hook-form';
@@ -1,20 +1,19 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { ControlledAsyncAutocomplete } from './AsyncAutocomplete';
3
- import { ControlledForm } from './ControlledForm';
4
3
  import { Button } from '@availity/mui-button';
5
- import { useFormContext } from 'react-hook-form';
4
+ import { FormProvider, useForm } from 'react-hook-form';
6
5
  import { Paper } from '@availity/mui-paper';
7
6
  import { Typography } from '@availity/mui-typography';
8
7
  import { Grid } from '@availity/mui-layout';
9
8
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
9
  import AvApi, { ApiConfig } from '@availity/api-axios';
11
- import { missingRHFprops } from '../../docs/propDefinitions';
10
+ import { AllControllerPropertiesCategorized, AsyncAutocompletePropsCategorized } from './Types';
12
11
 
13
12
  const meta: Meta<typeof ControlledAsyncAutocomplete> = {
14
13
  title: 'Form Components/Controlled Form/Autocomplete/ControlledAsyncAutocomplete',
15
14
  component: ControlledAsyncAutocomplete,
16
15
  tags: ['autodocs'],
17
- argTypes: missingRHFprops,
16
+ argTypes: {...AllControllerPropertiesCategorized, ...AsyncAutocompletePropsCategorized}
18
17
  };
19
18
 
20
19
  export default meta;
@@ -65,49 +64,35 @@ const client = new QueryClient({
65
64
 
66
65
  export const _ControlledAsyncAutoComplete: StoryObj<typeof ControlledAsyncAutocomplete> = {
67
66
  render: (args) => {
68
- const SubmittedValues = () => {
69
- const {
70
- getValues,
71
- formState: { isSubmitSuccessful },
72
- } = useFormContext();
67
+ const methods = useForm();
73
68
 
74
- return isSubmitSuccessful ? (
75
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
76
- <Typography variant="h2">Submitted Values</Typography>
77
- <pre>{JSON.stringify(getValues(), null, 2)}</pre>
78
- </Paper>
79
- ) : null;
80
- };
81
-
82
- const Actions = () => {
83
- const {
84
- reset,
85
- formState: { isSubmitSuccessful },
86
- } = useFormContext();
87
- return (
88
- <Grid container direction="row" justifyContent="space-between" marginTop={1}>
89
- <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
90
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
91
- </Grid>
92
- );
93
- };
94
69
  return (
95
70
  <QueryClientProvider client={client}>
96
- <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={(data) => data}>
97
- <ControlledAsyncAutocomplete {...args} />
98
- <Actions />
99
- <SubmittedValues />
100
- </ControlledForm>
71
+ <FormProvider {...methods}>
72
+ <form onSubmit={methods.handleSubmit((data) => data)}>
73
+ <ControlledAsyncAutocomplete {...args} />
74
+ <Grid container direction="row" justifyContent="space-between" marginTop={1}>
75
+ <Button disabled={!methods?.formState?.isSubmitSuccessful} children="Reset" color="secondary" onClick={() => methods.reset()} />
76
+ <Button type="submit" disabled={methods?.formState?.isSubmitSuccessful} children="Submit" />
77
+ </Grid>
78
+ { methods?.formState?.isSubmitSuccessful ? (
79
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
80
+ <Typography variant="h2">Submitted Values</Typography>
81
+ <pre data-testid="result">{JSON.stringify(methods.getValues(), null, 2)}</pre>
82
+ </Paper>
83
+ ) : null }
84
+ </form>
85
+ </FormProvider>
101
86
  </QueryClientProvider>
102
87
  );
103
88
  },
104
89
  args: {
105
90
  name: 'controlledAsyncAutocomplete',
106
- FieldProps: { label: 'Async Select', helperText: 'Helper Text', fullWidth: false },
91
+ FieldProps: { label: 'Async Select', helperText: 'Helper Text', fullWidth: false, required: true },
107
92
  getOptionLabel: (val: Option) => val.label,
108
93
  loadOptions,
109
94
  limit: 10,
110
95
  queryKey: 'example',
111
- required: 'This is required.',
96
+ rules: { required:'This is required.' },
112
97
  },
113
98
  };
@@ -1,15 +1,10 @@
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
  import AvApi, { ApiConfig } from '@availity/api-axios';
9
4
  // eslint-disable-next-line @nx/enforce-module-boundaries
10
5
  import { server } from '@availity/mock/src/lib/server';
11
- import { ControlledForm } from './ControlledForm';
12
6
  import { ControlledAsyncAutocomplete } from './AsyncAutocomplete';
7
+ import { TestForm } from './UtilComponents';
13
8
 
14
9
  const api = new AvApi({ name: 'example' } as ApiConfig);
15
10
 
@@ -47,33 +42,6 @@ const loadOptions = async (offset: number, limit: number) => {
47
42
  };
48
43
  };
49
44
 
50
- const SubmittedValues = () => {
51
- const {
52
- getValues,
53
- formState: { isSubmitSuccessful },
54
- } = useFormContext();
55
-
56
- return isSubmitSuccessful ? (
57
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
58
- <Typography variant="h2">Submitted Values</Typography>
59
- <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
60
- </Paper>
61
- ) : null;
62
- };
63
-
64
- const Actions = () => {
65
- const {
66
- reset,
67
- formState: { isSubmitSuccessful },
68
- } = useFormContext();
69
- return (
70
- <Grid container direction="row" justifyContent="space-between">
71
- <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
72
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
73
- </Grid>
74
- );
75
- };
76
-
77
45
  const onSubmit = jest.fn();
78
46
 
79
47
  describe('ControlledAsyncAutocomplete', () => {
@@ -98,20 +66,18 @@ describe('ControlledAsyncAutocomplete', () => {
98
66
  });
99
67
 
100
68
  test('should loadOptions successfully', async () => {
101
- const screen = render(
102
- <QueryClientProvider client={client}>
103
- <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={(data) => data}>
104
- <ControlledAsyncAutocomplete
105
- name="controlledAsyncAutocomplete"
106
- FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
107
- getOptionLabel={(val: Option) => val.label}
108
- loadOptions={loadOptions}
109
- limit={10}
110
- queryKey="example"
111
- />
112
- <Actions />
113
- <SubmittedValues />
114
- </ControlledForm>
69
+ const screen = render(
70
+ <QueryClientProvider client={client}>
71
+ <TestForm UseFormOptions={{values: { controlledAutocomplete: undefined }}} onSubmit={onSubmit}>
72
+ <ControlledAsyncAutocomplete
73
+ name="controlledAsyncAutocomplete"
74
+ FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
75
+ getOptionLabel={(val: Option) => val.label}
76
+ loadOptions={loadOptions}
77
+ limit={10}
78
+ queryKey="example"
79
+ />
80
+ </TestForm>
115
81
  </QueryClientProvider>
116
82
  );
117
83
 
@@ -125,7 +91,7 @@ describe('ControlledAsyncAutocomplete', () => {
125
91
  test('should set the value and submit the form data', async () => {
126
92
  const screen = render(
127
93
  <QueryClientProvider client={client}>
128
- <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={onSubmit}>
94
+ <TestForm UseFormOptions={{values: { controlledAutocomplete: undefined }}} onSubmit={onSubmit}>
129
95
  <ControlledAsyncAutocomplete
130
96
  name="controlledAsyncAutocomplete"
131
97
  FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
@@ -134,11 +100,9 @@ describe('ControlledAsyncAutocomplete', () => {
134
100
  limit={10}
135
101
  queryKey="example"
136
102
  />
137
- <Actions />
138
- <SubmittedValues />
139
- </ControlledForm>
140
- </QueryClientProvider>
141
- );
103
+ </TestForm>
104
+ </QueryClientProvider>
105
+ );
142
106
 
143
107
  const dropdown = screen.getByRole('combobox');
144
108
  fireEvent.click(dropdown);
@@ -1,6 +1,7 @@
1
1
  import { AsyncAutocomplete, AsyncAutocompleteProps } from '@availity/mui-autocomplete';
2
- import { useFormContext, RegisterOptions, FieldValues, Controller, ControllerProps } from 'react-hook-form';
2
+ import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
3
3
  import { ChipTypeMap } from '@mui/material/Chip';
4
+ import { ControllerProps, DeprecatedRulesProps } from './Types';
4
5
 
5
6
  export type ControlledAsyncAutocompleteProps<
6
7
  Option,
@@ -8,9 +9,13 @@ export type ControlledAsyncAutocompleteProps<
8
9
  DisableClearable extends boolean | undefined,
9
10
  FreeSolo extends boolean | undefined,
10
11
  ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
11
- > = Omit<AsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>, 'name'> &
12
- Omit<RegisterOptions<FieldValues, string>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'> &
13
- Pick<ControllerProps, 'defaultValue' | 'shouldUnregister' | 'name'>;
12
+ > = Omit<AsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>,
13
+ 'onBlur' | 'onChange' | 'value' | 'name'
14
+ > & Pick<RegisterOptions<FieldValues, string>,
15
+ 'onBlur' | 'onChange' | 'value'
16
+ > & ControllerProps
17
+ //TODO v1 - remove deprecated props
18
+ & DeprecatedRulesProps;
14
19
 
15
20
  export const ControlledAsyncAutocomplete = <
16
21
  Option,
@@ -29,18 +34,16 @@ export const ControlledAsyncAutocomplete = <
29
34
  onChange,
30
35
  pattern,
31
36
  required,
37
+ rules = {},
32
38
  shouldUnregister,
33
39
  validate,
34
40
  value,
35
41
  FieldProps,
36
42
  ...rest
37
43
  }: ControlledAsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>) => {
38
- const { control, getFieldState } = useFormContext();
39
- const errorMessage = getFieldState(name).error?.message;
40
44
  return (
41
45
  <Controller
42
46
  name={name}
43
- control={control}
44
47
  defaultValue={rest.defaultValue}
45
48
  rules={{
46
49
  deps,
@@ -55,25 +58,25 @@ export const ControlledAsyncAutocomplete = <
55
58
  shouldUnregister,
56
59
  validate,
57
60
  value,
61
+ ...rules,
58
62
  }}
59
63
  shouldUnregister={shouldUnregister}
60
- render={({ field: { onChange, value, onBlur } }) => (
64
+ render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
61
65
  <AsyncAutocomplete
62
66
  {...rest}
63
67
  FieldProps={{
64
68
  ...FieldProps,
65
- required: typeof required === 'object' ? required.value : !!required,
66
- error: !!errorMessage,
67
- helperText:
68
- errorMessage && typeof errorMessage === 'string' ? (
69
- <>
70
- {errorMessage}
71
- <br />
72
- {FieldProps?.helperText}
73
- </>
74
- ) : (
75
- FieldProps?.helperText
76
- ),
69
+ error: !!error,
70
+ helperText: error?.message ? (
71
+ <>
72
+ {error.message}
73
+ <br />
74
+ {FieldProps?.helperText}
75
+ </>
76
+ ) : (
77
+ FieldProps?.helperText
78
+ ),
79
+ inputRef:ref
77
80
  }}
78
81
  onChange={(event, value, reason) => {
79
82
  if (reason === 'clear') {
@@ -1,60 +1,47 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { ControlledAutocomplete } from './Autocomplete';
3
- import { ControlledForm } from './ControlledForm';
4
3
  import { Button } from '@availity/mui-button';
5
- import { useFormContext } from 'react-hook-form';
4
+ import { FormProvider, useForm } from '..';
6
5
  import { Paper } from '@availity/mui-paper';
7
6
  import { Typography } from '@availity/mui-typography';
8
7
  import { Grid } from '@availity/mui-layout';
8
+ import { AllControllerPropertiesCategorized, AutocompletePropsCategorized } from './Types';
9
9
 
10
10
  const meta: Meta<typeof ControlledAutocomplete> = {
11
11
  title: 'Form Components/Controlled Form/Autocomplete/ControlledAutocomplete',
12
12
  component: ControlledAutocomplete,
13
13
  tags: ['autodocs'],
14
+ argTypes: {...AllControllerPropertiesCategorized, ...AutocompletePropsCategorized}
14
15
  };
15
16
 
16
17
  export default meta;
17
18
 
18
19
  export const _ControlledAutoComplete: StoryObj<typeof ControlledAutocomplete> = {
19
20
  render: (args) => {
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={{ controlledAutocomplete: undefined }} onSubmit={(data) => data}>
48
- <ControlledAutocomplete {...args} />
49
- <Actions />
50
- <SubmittedValues />
51
- </ControlledForm>
24
+ <FormProvider {...methods}>
25
+ <form onSubmit={methods.handleSubmit((data) => data)}>
26
+ <ControlledAutocomplete {...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: {
55
42
  name: 'controlledAutocomplete',
56
43
  options: ['Option 1', 'Option 2'],
57
- required: 'This is required.',
44
+ rules: { required: 'This is required.' },
58
45
  FieldProps: { label: 'Autocomplete Label' },
59
46
  },
60
47
  };
@@ -1,11 +1,6 @@
1
1
  import { fireEvent, render, 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
- import { ControlledForm } from './ControlledForm';
8
2
  import { ControlledAutocomplete } from './Autocomplete';
3
+ import { TestForm } from './UtilComponents';
9
4
 
10
5
  const onSubmit = jest.fn();
11
6
 
@@ -17,38 +12,13 @@ describe('ControlledAsyncAutocomplete', () => {
17
12
  });
18
13
 
19
14
  test('should set the value and submit the form', async () => {
20
- const SubmittedValues = () => {
21
- const {
22
- getValues,
23
- formState: { isSubmitSuccessful },
24
- } = useFormContext();
25
-
26
- return isSubmitSuccessful ? (
27
- <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
28
- <Typography variant="h2">Submitted Values</Typography>
29
- <pre data-testid="result">{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">
41
- <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
42
- <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
43
- </Grid>
44
- );
45
- };
46
15
  const screen = render(
47
- <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={onSubmit}>
48
- <ControlledAutocomplete name="controlledAutocomplete" options={['Option 1', 'Option 2']} />
49
- <Actions />
50
- <SubmittedValues />
51
- </ControlledForm>
16
+ <TestForm UseFormOptions={{values: { controlledAutocomplete: null}}} onSubmit={onSubmit}>
17
+ <ControlledAutocomplete
18
+ name="controlledAutocomplete"
19
+ options={['Option 1', 'Option 2']}
20
+ />
21
+ </TestForm>
52
22
  );
53
23
 
54
24
  const dropdown = screen.getByRole('combobox');
@@ -1,6 +1,7 @@
1
1
  import { Autocomplete, AutocompleteProps } from '@availity/mui-autocomplete';
2
- import { useFormContext, RegisterOptions, FieldValues, Controller, ControllerProps } from 'react-hook-form';
2
+ import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
3
3
  import { ChipTypeMap } from '@mui/material/Chip';
4
+ import { ControllerProps, DeprecatedRulesProps } from './Types';
4
5
 
5
6
  export type ControlledAutocompleteProps<
6
7
  T,
@@ -9,11 +10,13 @@ export type ControlledAutocompleteProps<
9
10
  FreeSolo extends boolean | undefined,
10
11
  ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
11
12
  > = Omit<
12
- AutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>,
13
- 'onChange' | 'onBlur' | 'value' | 'name'
14
- > &
15
- Omit<RegisterOptions<FieldValues, string>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'> &
16
- Pick<ControllerProps, 'defaultValue' | 'shouldUnregister' | 'name'>;
13
+ AutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>,
14
+ 'onBlur' | 'onChange' | 'value' | 'name'
15
+ > & Pick<RegisterOptions<FieldValues, string>,
16
+ 'onBlur' | 'onChange' | 'value'
17
+ > & ControllerProps
18
+ //TODO v1 - remove deprecated props
19
+ & DeprecatedRulesProps;
17
20
 
18
21
  export const ControlledAutocomplete = <
19
22
  T,
@@ -25,6 +28,7 @@ export const ControlledAutocomplete = <
25
28
  name,
26
29
  FieldProps,
27
30
  defaultValue,
31
+ rules = {},
28
32
  deps,
29
33
  max,
30
34
  maxLength,
@@ -39,11 +43,8 @@ export const ControlledAutocomplete = <
39
43
  value,
40
44
  ...rest
41
45
  }: ControlledAutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>) => {
42
- const { control, getFieldState } = useFormContext();
43
- const errorMessage = getFieldState(name).error?.message;
44
46
  return (
45
47
  <Controller
46
- control={control}
47
48
  name={name}
48
49
  defaultValue={defaultValue}
49
50
  rules={{
@@ -59,25 +60,25 @@ export const ControlledAutocomplete = <
59
60
  shouldUnregister,
60
61
  validate,
61
62
  value,
63
+ ...rules,
62
64
  }}
63
65
  shouldUnregister={shouldUnregister}
64
- render={({ field: { onChange, value, onBlur } }) => (
66
+ render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
65
67
  <Autocomplete
66
68
  {...rest}
67
69
  FieldProps={{
68
70
  ...FieldProps,
69
- required: typeof required === 'object' ? required.value : !!required,
70
- error: !!errorMessage,
71
- helperText:
72
- errorMessage && typeof errorMessage === 'string' ? (
71
+ error: !!error,
72
+ helperText: error?.message ? (
73
73
  <>
74
- {errorMessage}
74
+ {error.message}
75
75
  <br />
76
76
  {FieldProps?.helperText}
77
77
  </>
78
78
  ) : (
79
79
  FieldProps?.helperText
80
80
  ),
81
+ inputRef: ref
81
82
  }}
82
83
  onChange={(event, value, reason) => {
83
84
  if (reason === 'clear') {