@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.
- package/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/dist/index.d.mts +122 -34
- package/dist/index.d.ts +122 -34
- package/dist/index.js +263 -225
- package/dist/index.mjs +279 -240
- package/package.json +2 -2
- package/src/index.ts +47 -0
- package/src/lib/AsyncAutocomplete.stories.tsx +21 -36
- package/src/lib/AsyncAutocomplete.test.tsx +17 -53
- package/src/lib/AsyncAutocomplete.tsx +23 -20
- package/src/lib/Autocomplete.stories.tsx +20 -33
- package/src/lib/Autocomplete.test.tsx +7 -37
- package/src/lib/Autocomplete.tsx +16 -15
- package/src/lib/Checkbox.stories.tsx +50 -43
- package/src/lib/Checkbox.test.tsx +14 -46
- package/src/lib/Checkbox.tsx +30 -15
- package/src/lib/CodesAutocomplete.stories.tsx +21 -35
- package/src/lib/CodesAutocomplete.test.tsx +20 -54
- package/src/lib/CodesAutocomplete.tsx +23 -20
- package/src/lib/ControlledForm.stories.tsx +1 -0
- package/src/lib/ControlledForm.tsx +8 -4
- package/src/lib/Datepicker.stories.tsx +19 -32
- package/src/lib/Datepicker.test.tsx +3 -35
- package/src/lib/Datepicker.tsx +18 -10
- package/src/lib/Input.stories.tsx +32 -33
- package/src/lib/Input.test.tsx +71 -7
- package/src/lib/Input.tsx +44 -24
- package/src/lib/OrganizationAutocomplete.stories.tsx +30 -35
- package/src/lib/OrganizationAutocomplete.test.tsx +23 -57
- package/src/lib/OrganizationAutocomplete.tsx +24 -23
- package/src/lib/ProviderAutocomplete.stories.tsx +20 -35
- package/src/lib/ProviderAutocomplete.test.tsx +29 -63
- package/src/lib/ProviderAutocomplete.tsx +22 -20
- package/src/lib/RadioGroup.stories.tsx +41 -36
- package/src/lib/RadioGroup.test.tsx +3 -35
- package/src/lib/RadioGroup.tsx +33 -25
- package/src/lib/Select.stories.tsx +78 -45
- package/src/lib/Select.test.tsx +8 -36
- package/src/lib/Select.tsx +44 -25
- package/src/lib/TextField.stories.tsx +26 -34
- package/src/lib/TextField.test.tsx +71 -5
- package/src/lib/TextField.tsx +55 -37
- package/src/lib/Types.tsx +2489 -0
- package/src/lib/UtilComponents.tsx +52 -0
- package/docs/propDefinitions.tsx +0 -31
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { OrganizationAutocomplete, OrgAutocompleteProps } from '@availity/mui-autocomplete';
|
|
2
|
-
import {
|
|
2
|
+
import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
|
|
3
|
+
import { ControllerProps, DeprecatedRulesProps } from './Types';
|
|
3
4
|
|
|
4
|
-
export type ControlledOrgAutocompleteProps = Omit<OrgAutocompleteProps,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
export type ControlledOrgAutocompleteProps = Omit<OrgAutocompleteProps,
|
|
6
|
+
'onBlur' | 'onChange' | 'value' | 'name'
|
|
7
|
+
> & Pick<RegisterOptions<FieldValues, string>,
|
|
8
|
+
'onBlur' | 'onChange' | 'value'
|
|
9
|
+
> & ControllerProps
|
|
10
|
+
//TODO v1 - remove deprecated props
|
|
11
|
+
& Omit<DeprecatedRulesProps, 'max' | 'maxLength' | 'min' | 'minLength'
|
|
12
|
+
>;
|
|
10
13
|
|
|
11
14
|
export const ControlledOrganizationAutocomplete = ({
|
|
12
15
|
name,
|
|
@@ -16,18 +19,16 @@ export const ControlledOrganizationAutocomplete = ({
|
|
|
16
19
|
onChange,
|
|
17
20
|
pattern,
|
|
18
21
|
required,
|
|
22
|
+
rules = {},
|
|
19
23
|
shouldUnregister,
|
|
20
24
|
validate,
|
|
21
25
|
value,
|
|
22
26
|
FieldProps,
|
|
23
27
|
...rest
|
|
24
28
|
}: ControlledOrgAutocompleteProps) => {
|
|
25
|
-
const { control, getFieldState } = useFormContext();
|
|
26
|
-
const errorMessage = getFieldState(name).error?.message;
|
|
27
29
|
return (
|
|
28
30
|
<Controller
|
|
29
31
|
name={name}
|
|
30
|
-
control={control}
|
|
31
32
|
defaultValue={defaultValue}
|
|
32
33
|
rules={{
|
|
33
34
|
deps,
|
|
@@ -38,25 +39,25 @@ export const ControlledOrganizationAutocomplete = ({
|
|
|
38
39
|
shouldUnregister,
|
|
39
40
|
validate,
|
|
40
41
|
value,
|
|
42
|
+
...rules,
|
|
41
43
|
}}
|
|
42
44
|
shouldUnregister={shouldUnregister}
|
|
43
|
-
render={({ field: { onChange, value, onBlur } }) => (
|
|
45
|
+
render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
|
|
44
46
|
<OrganizationAutocomplete
|
|
45
47
|
{...rest}
|
|
46
48
|
FieldProps={{
|
|
47
49
|
...FieldProps,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
),
|
|
50
|
+
error: !!error,
|
|
51
|
+
helperText: error?.message ? (
|
|
52
|
+
<>
|
|
53
|
+
{error.message}
|
|
54
|
+
<br />
|
|
55
|
+
{FieldProps?.helperText}
|
|
56
|
+
</>
|
|
57
|
+
) : (
|
|
58
|
+
FieldProps?.helperText
|
|
59
|
+
),
|
|
60
|
+
inputRef:ref
|
|
60
61
|
}}
|
|
61
62
|
onChange={(event, value, reason) => {
|
|
62
63
|
if (reason === 'clear') {
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { ControlledProviderAutocomplete } from './ProviderAutocomplete';
|
|
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 {
|
|
8
|
+
import { AllControllerPropertiesCategorized, ProviderAutocompletePropsCategorized } from './Types';
|
|
9
|
+
import { FormProvider, useForm } from '..';
|
|
11
10
|
|
|
12
11
|
const meta: Meta<typeof ControlledProviderAutocomplete> = {
|
|
13
12
|
title: 'Form Components/Controlled Form/Autocomplete/ControlledProviderAutocomplete',
|
|
14
13
|
component: ControlledProviderAutocomplete,
|
|
15
14
|
tags: ['autodocs'],
|
|
16
|
-
argTypes:
|
|
15
|
+
argTypes: {...AllControllerPropertiesCategorized, ...ProviderAutocompletePropsCategorized}
|
|
17
16
|
};
|
|
18
17
|
|
|
19
18
|
export default meta;
|
|
@@ -28,39 +27,25 @@ const client = new QueryClient({
|
|
|
28
27
|
|
|
29
28
|
export const _ControlledProviderAutoComplete: StoryObj<typeof ControlledProviderAutocomplete> = {
|
|
30
29
|
render: (args) => {
|
|
31
|
-
const
|
|
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
|
-
<
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
34
|
+
<FormProvider {...methods}>
|
|
35
|
+
<form onSubmit={methods.handleSubmit((data) => data)}>
|
|
36
|
+
<ControlledProviderAutocomplete {...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
|
},
|
|
@@ -74,6 +59,6 @@ export const _ControlledProviderAutoComplete: StoryObj<typeof ControlledProvider
|
|
|
74
59
|
},
|
|
75
60
|
limit: 10,
|
|
76
61
|
customerId: '1234',
|
|
77
|
-
required:
|
|
62
|
+
rules: { required:'This is required.' },
|
|
78
63
|
},
|
|
79
64
|
};
|
|
@@ -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 { ControlledProviderAutocomplete } from './ProviderAutocomplete';
|
|
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,21 +31,19 @@ describe('ControlledProviderAutocomplete', () => {
|
|
|
61
31
|
test('should loadOptions successfully', async () => {
|
|
62
32
|
const screen = render(
|
|
63
33
|
<QueryClientProvider client={client}>
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<SubmittedValues />
|
|
78
|
-
</ControlledForm>
|
|
34
|
+
<TestForm UseFormOptions={{values: { controlledAutocomplete: null }}} onSubmit={onSubmit}>
|
|
35
|
+
<ControlledProviderAutocomplete
|
|
36
|
+
name="controlledProviderAutocomplete"
|
|
37
|
+
FieldProps={{
|
|
38
|
+
label: 'Provider Select',
|
|
39
|
+
helperText: 'Select a Provider from the list',
|
|
40
|
+
placeholder: 'Select...',
|
|
41
|
+
fullWidth: false,
|
|
42
|
+
}}
|
|
43
|
+
limit={10}
|
|
44
|
+
customerId="1234"
|
|
45
|
+
/>
|
|
46
|
+
</TestForm>
|
|
79
47
|
</QueryClientProvider>
|
|
80
48
|
);
|
|
81
49
|
|
|
@@ -87,23 +55,21 @@ describe('ControlledProviderAutocomplete', () => {
|
|
|
87
55
|
});
|
|
88
56
|
|
|
89
57
|
test('should set the value and submit the form data', async () => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<SubmittedValues />
|
|
106
|
-
</ControlledForm>
|
|
58
|
+
const screen = render(
|
|
59
|
+
<QueryClientProvider client={client}>
|
|
60
|
+
<TestForm UseFormOptions={{values: { controlledAutocomplete: null }}} onSubmit={onSubmit}>
|
|
61
|
+
<ControlledProviderAutocomplete
|
|
62
|
+
name="controlledProviderAutocomplete"
|
|
63
|
+
FieldProps={{
|
|
64
|
+
label: 'Provider Select',
|
|
65
|
+
helperText: 'Select a Provider from the list',
|
|
66
|
+
placeholder: 'Select...',
|
|
67
|
+
fullWidth: false,
|
|
68
|
+
}}
|
|
69
|
+
limit={10}
|
|
70
|
+
customerId="1234"
|
|
71
|
+
/>
|
|
72
|
+
</TestForm>
|
|
107
73
|
</QueryClientProvider>
|
|
108
74
|
);
|
|
109
75
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { ProviderAutocomplete, ProviderAutocompleteProps } from '@availity/mui-autocomplete';
|
|
2
|
-
import {
|
|
2
|
+
import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
|
|
3
|
+
import { ControllerProps, DeprecatedRulesProps } from './Types';
|
|
3
4
|
|
|
4
|
-
export type ControlledProviderAutocompleteProps = Omit<ProviderAutocompleteProps,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
export type ControlledProviderAutocompleteProps = Omit<ProviderAutocompleteProps,
|
|
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 ControlledProviderAutocomplete = ({
|
|
9
14
|
name,
|
|
@@ -17,18 +22,16 @@ export const ControlledProviderAutocomplete = ({
|
|
|
17
22
|
onChange,
|
|
18
23
|
pattern,
|
|
19
24
|
required,
|
|
25
|
+
rules = {},
|
|
20
26
|
shouldUnregister,
|
|
21
27
|
validate,
|
|
22
28
|
value,
|
|
23
29
|
FieldProps,
|
|
24
30
|
...rest
|
|
25
31
|
}: ControlledProviderAutocompleteProps) => {
|
|
26
|
-
const { control, getFieldState } = useFormContext();
|
|
27
|
-
const errorMessage = getFieldState(name).error?.message;
|
|
28
32
|
return (
|
|
29
33
|
<Controller
|
|
30
34
|
name={name}
|
|
31
|
-
control={control}
|
|
32
35
|
defaultValue={defaultValue}
|
|
33
36
|
rules={{
|
|
34
37
|
deps,
|
|
@@ -43,25 +46,24 @@ export const ControlledProviderAutocomplete = ({
|
|
|
43
46
|
shouldUnregister,
|
|
44
47
|
validate,
|
|
45
48
|
value,
|
|
49
|
+
...rules,
|
|
46
50
|
}}
|
|
47
51
|
shouldUnregister={shouldUnregister}
|
|
48
|
-
render={({ field: { onChange, value, onBlur } }) => (
|
|
52
|
+
render={({ field: { onChange, value, onBlur }, fieldState: { error } }) => (
|
|
49
53
|
<ProviderAutocomplete
|
|
50
54
|
{...rest}
|
|
51
55
|
FieldProps={{
|
|
52
56
|
...FieldProps,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
FieldProps?.helperText
|
|
64
|
-
),
|
|
57
|
+
error: !!error,
|
|
58
|
+
helperText: error?.message ? (
|
|
59
|
+
<>
|
|
60
|
+
{error.message}
|
|
61
|
+
<br />
|
|
62
|
+
{FieldProps?.helperText}
|
|
63
|
+
</>
|
|
64
|
+
) : (
|
|
65
|
+
FieldProps?.helperText
|
|
66
|
+
),
|
|
65
67
|
}}
|
|
66
68
|
onChange={(event, value, reason) => {
|
|
67
69
|
if (reason === 'clear') {
|
|
@@ -1,59 +1,64 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { ControlledRadioGroup, ControlledRadioGroupProps } from './RadioGroup';
|
|
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 { FormControlLabel, Radio } from '@availity/mui-form-utils';
|
|
9
7
|
import { Grid } from '@availity/mui-layout';
|
|
8
|
+
import { AllControllerPropertiesCategorized, RadioGroupPropsCategorized } from './Types';
|
|
9
|
+
import { FormProvider, useForm } from '..';
|
|
10
10
|
|
|
11
11
|
const meta: Meta<typeof ControlledRadioGroup> = {
|
|
12
12
|
title: 'Form Components/Controlled Form/ControlledRadioGroup',
|
|
13
13
|
component: ControlledRadioGroup,
|
|
14
14
|
tags: ['autodocs'],
|
|
15
|
+
argTypes: {
|
|
16
|
+
...AllControllerPropertiesCategorized,
|
|
17
|
+
...RadioGroupPropsCategorized,
|
|
18
|
+
required: {
|
|
19
|
+
table: { category: 'Input Props'}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
parameters: {
|
|
23
|
+
controls: {
|
|
24
|
+
exclude: [
|
|
25
|
+
'max',
|
|
26
|
+
'maxLength',
|
|
27
|
+
'min',
|
|
28
|
+
'minLength',
|
|
29
|
+
'pattern',
|
|
30
|
+
'validate'
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
15
34
|
};
|
|
16
35
|
|
|
17
36
|
export default meta;
|
|
18
37
|
|
|
19
38
|
export const _ControlledRadioGroup: StoryObj<typeof ControlledRadioGroup> = {
|
|
20
39
|
render: (args: ControlledRadioGroupProps) => {
|
|
21
|
-
const
|
|
22
|
-
const {
|
|
23
|
-
getValues,
|
|
24
|
-
formState: { isSubmitSuccessful },
|
|
25
|
-
} = useFormContext();
|
|
26
|
-
|
|
27
|
-
return isSubmitSuccessful ? (
|
|
28
|
-
<Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
|
|
29
|
-
<Typography variant="h2">Submitted Values</Typography>
|
|
30
|
-
<pre>{JSON.stringify(getValues(), null, 2)}</pre>
|
|
31
|
-
</Paper>
|
|
32
|
-
) : null;
|
|
33
|
-
};
|
|
40
|
+
const methods = useForm();
|
|
34
41
|
|
|
35
|
-
const Actions = () => {
|
|
36
|
-
const {
|
|
37
|
-
reset,
|
|
38
|
-
formState: { isSubmitSuccessful },
|
|
39
|
-
} = useFormContext();
|
|
40
|
-
return (
|
|
41
|
-
<Grid container direction="row" justifyContent="space-between" marginTop={1}>
|
|
42
|
-
<Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
|
|
43
|
-
<Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
|
|
44
|
-
</Grid>
|
|
45
|
-
);
|
|
46
|
-
};
|
|
47
42
|
return (
|
|
48
|
-
<
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
<FormProvider {...methods}>
|
|
44
|
+
<form onSubmit={methods.handleSubmit((data) => data)}>
|
|
45
|
+
<ControlledRadioGroup {...args}>
|
|
46
|
+
<FormControlLabel control={<Radio />} label="N/A" value="N/A" />
|
|
47
|
+
<FormControlLabel control={<Radio />} label="Yes" value="Yes" />
|
|
48
|
+
<FormControlLabel control={<Radio />} label="No" value="No" />
|
|
49
|
+
</ControlledRadioGroup>
|
|
50
|
+
<Grid container direction="row" justifyContent="space-between" marginTop={1}>
|
|
51
|
+
<Button disabled={!methods?.formState?.isSubmitSuccessful} children="Reset" color="secondary" onClick={() => methods.reset()} />
|
|
52
|
+
<Button type="submit" disabled={methods?.formState?.isSubmitSuccessful} children="Submit" />
|
|
53
|
+
</Grid>
|
|
54
|
+
{ methods?.formState?.isSubmitSuccessful ? (
|
|
55
|
+
<Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
|
|
56
|
+
<Typography variant="h2">Submitted Values</Typography>
|
|
57
|
+
<pre data-testid="result">{JSON.stringify(methods.getValues(), null, 2)}</pre>
|
|
58
|
+
</Paper>
|
|
59
|
+
) : null }
|
|
60
|
+
</form>
|
|
61
|
+
</FormProvider>
|
|
57
62
|
);
|
|
58
63
|
},
|
|
59
64
|
args: {
|
|
@@ -1,52 +1,20 @@
|
|
|
1
1
|
import { render, fireEvent, waitFor } from '@testing-library/react';
|
|
2
2
|
import { FormControlLabel, Radio } 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 { ControlledRadioGroup } from './RadioGroup';
|
|
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('ControlledRadioGroup', () => {
|
|
39
9
|
test('should set the value and submit the form data', async () => {
|
|
40
10
|
const screen = render(
|
|
41
|
-
<
|
|
11
|
+
<TestForm UseFormOptions={{values: { controlledRadioGroup: undefined }}} onSubmit={onSubmit}>
|
|
42
12
|
<ControlledRadioGroup name="controlledRadioGroup" label="Radio Group" value="N/A">
|
|
43
13
|
<FormControlLabel control={<Radio />} label="N/A" value="N/A" />
|
|
44
14
|
<FormControlLabel control={<Radio />} label="Yes" value="Yes" />
|
|
45
15
|
<FormControlLabel control={<Radio />} label="No" value="No" />
|
|
46
16
|
</ControlledRadioGroup>
|
|
47
|
-
|
|
48
|
-
<SubmittedValues />
|
|
49
|
-
</ControlledForm>
|
|
17
|
+
</TestForm>
|
|
50
18
|
);
|
|
51
19
|
|
|
52
20
|
const option1 = screen.getByDisplayValue('Yes');
|
package/src/lib/RadioGroup.tsx
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
import { RadioGroup, RadioGroupProps } from '@availity/mui-form-utils';
|
|
2
|
-
import {
|
|
2
|
+
import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
|
|
3
3
|
import { FormControl, FormLabel, FormHelperText } from '@availity/mui-form-utils';
|
|
4
|
+
import { ControllerProps, DeprecatedRulesProps } from './Types';
|
|
4
5
|
|
|
5
|
-
export type ControlledRadioGroupProps =
|
|
6
|
+
export type ControlledRadioGroupProps = {
|
|
6
7
|
name: string;
|
|
7
8
|
label: string;
|
|
8
9
|
helperText?: string;
|
|
9
|
-
} & Omit<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
} & Omit <RadioGroupProps,
|
|
11
|
+
'onBlur' | 'onChange' | 'value' | 'name'
|
|
12
|
+
> & Pick<RegisterOptions<FieldValues, string>,
|
|
13
|
+
'onBlur' | 'onChange' | 'value'
|
|
14
|
+
> & ControllerProps
|
|
15
|
+
//TODO v1 - remove deprecated props
|
|
16
|
+
& Omit<DeprecatedRulesProps,
|
|
17
|
+
'max'
|
|
18
|
+
| 'maxLength'
|
|
19
|
+
| 'min'
|
|
20
|
+
| 'minLength'
|
|
21
|
+
| 'pattern'
|
|
22
|
+
| 'required'
|
|
23
|
+
| 'validate'
|
|
24
|
+
> & {
|
|
25
|
+
/** If `true`, will add `aria-required` to `input`.
|
|
26
|
+
*
|
|
27
|
+
* @deprecated There has been a collision of properties. The boolean value
|
|
28
|
+
* to mark the input as required will remain in future versions, but the
|
|
29
|
+
* required object for `react-hook-form` has been moved to the `rules` prop.
|
|
30
|
+
*/
|
|
31
|
+
required?: boolean | RegisterOptions['required'];
|
|
32
|
+
};
|
|
23
33
|
|
|
24
34
|
export const ControlledRadioGroup = ({
|
|
25
35
|
name,
|
|
@@ -30,27 +40,25 @@ export const ControlledRadioGroup = ({
|
|
|
30
40
|
onBlur,
|
|
31
41
|
onChange,
|
|
32
42
|
required,
|
|
43
|
+
rules = {},
|
|
33
44
|
shouldUnregister,
|
|
34
45
|
value,
|
|
35
46
|
...rest
|
|
36
47
|
}: ControlledRadioGroupProps) => {
|
|
37
|
-
const { control, getFieldState } = useFormContext();
|
|
38
|
-
const errorMessage = getFieldState(name).error?.message;
|
|
39
48
|
return (
|
|
40
49
|
<Controller
|
|
41
|
-
control={control}
|
|
42
50
|
name={name}
|
|
43
51
|
defaultValue={defaultValue}
|
|
44
|
-
rules={{ deps, onBlur, onChange, required, shouldUnregister, value }}
|
|
52
|
+
rules={{ deps, onBlur, onChange, required: typeof required === 'boolean' ? undefined : required, shouldUnregister, value, ...rules }}
|
|
45
53
|
shouldUnregister={shouldUnregister}
|
|
46
|
-
render={({ field }) => (
|
|
47
|
-
<FormControl error={!!
|
|
48
|
-
<FormLabel
|
|
54
|
+
render={({ field: {disabled, ...field}, fieldState: { error } }) => (
|
|
55
|
+
<FormControl error={!!error} disabled={disabled} required={!!required}>
|
|
56
|
+
<FormLabel>{label}</FormLabel>
|
|
49
57
|
<RadioGroup {...field} {...rest} />
|
|
50
58
|
<FormHelperText>
|
|
51
|
-
{
|
|
59
|
+
{error?.message ? (
|
|
52
60
|
<>
|
|
53
|
-
{
|
|
61
|
+
{error.message}
|
|
54
62
|
<br />
|
|
55
63
|
{helperText}
|
|
56
64
|
</>
|