@availity/mui-controlled-form 0.3.2 → 1.0.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 +44 -0
- package/dist/index.d.mts +30 -123
- package/dist/index.d.ts +30 -123
- package/dist/index.js +111 -301
- package/dist/index.mjs +90 -279
- package/{introduction.stories.mdx → introduction.mdx} +3 -0
- package/package.json +17 -17
- package/src/index.ts +0 -1
- package/src/lib/AsyncAutocomplete.test.tsx +80 -16
- package/src/lib/AsyncAutocomplete.tsx +9 -25
- package/src/lib/Autocomplete.test.tsx +52 -6
- package/src/lib/Autocomplete.tsx +16 -33
- package/src/lib/Checkbox.tsx +11 -19
- package/src/lib/CodesAutocomplete.test.tsx +90 -17
- package/src/lib/CodesAutocomplete.tsx +6 -21
- package/src/lib/Datepicker.test.tsx +68 -1
- package/src/lib/Datepicker.tsx +6 -25
- package/src/lib/Input.test.tsx +0 -93
- package/src/lib/Input.tsx +5 -33
- package/src/lib/OrganizationAutocomplete.test.tsx +85 -18
- package/src/lib/OrganizationAutocomplete.tsx +6 -18
- package/src/lib/ProviderAutocomplete.test.tsx +99 -26
- package/src/lib/ProviderAutocomplete.tsx +8 -24
- package/src/lib/RadioGroup.tsx +13 -29
- package/src/lib/Select.tsx +5 -33
- package/src/lib/TextField.test.tsx +0 -94
- package/src/lib/TextField.tsx +6 -34
- package/src/lib/Types.tsx +811 -719
- package/src/lib/ControlledForm.stories.tsx +0 -76
- package/src/lib/ControlledForm.test.tsx +0 -77
- package/src/lib/ControlledForm.tsx +0 -39
|
@@ -1,28 +1,18 @@
|
|
|
1
1
|
import { CodesAutocomplete, CodesAutocompleteProps } from '@availity/mui-autocomplete';
|
|
2
2
|
import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
|
|
3
|
-
import { ControllerProps
|
|
3
|
+
import { ControllerProps } from './Types';
|
|
4
4
|
|
|
5
|
-
export type ControlledCodesAutocompleteProps = Omit<CodesAutocompleteProps,
|
|
6
|
-
'onBlur' | 'onChange' | 'value'
|
|
7
|
-
|
|
8
|
-
'onBlur' | 'onChange' | 'value'
|
|
9
|
-
> & ControllerProps
|
|
10
|
-
//TODO v1 - remove deprecated props
|
|
11
|
-
& DeprecatedRulesProps;
|
|
5
|
+
export type ControlledCodesAutocompleteProps = Omit<CodesAutocompleteProps, 'onBlur' | 'onChange' | 'value' | 'name'> &
|
|
6
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
7
|
+
ControllerProps;
|
|
12
8
|
|
|
13
9
|
export const ControlledCodesAutocomplete = ({
|
|
14
10
|
name,
|
|
15
11
|
defaultValue,
|
|
16
|
-
deps,
|
|
17
|
-
max,
|
|
18
|
-
maxLength,
|
|
19
12
|
onBlur,
|
|
20
13
|
onChange,
|
|
21
|
-
pattern,
|
|
22
|
-
required,
|
|
23
14
|
rules = {},
|
|
24
15
|
shouldUnregister,
|
|
25
|
-
validate,
|
|
26
16
|
value,
|
|
27
17
|
FieldProps,
|
|
28
18
|
...rest
|
|
@@ -32,15 +22,9 @@ export const ControlledCodesAutocomplete = ({
|
|
|
32
22
|
name={name}
|
|
33
23
|
defaultValue={defaultValue}
|
|
34
24
|
rules={{
|
|
35
|
-
deps,
|
|
36
|
-
max,
|
|
37
|
-
maxLength,
|
|
38
25
|
onBlur,
|
|
39
26
|
onChange,
|
|
40
|
-
pattern,
|
|
41
|
-
required,
|
|
42
27
|
shouldUnregister,
|
|
43
|
-
validate,
|
|
44
28
|
value,
|
|
45
29
|
...rules,
|
|
46
30
|
}}
|
|
@@ -49,6 +33,7 @@ export const ControlledCodesAutocomplete = ({
|
|
|
49
33
|
<CodesAutocomplete
|
|
50
34
|
{...rest}
|
|
51
35
|
FieldProps={{
|
|
36
|
+
required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
|
|
52
37
|
...FieldProps,
|
|
53
38
|
error: !!error,
|
|
54
39
|
helperText: error?.message ? (
|
|
@@ -60,7 +45,7 @@ export const ControlledCodesAutocomplete = ({
|
|
|
60
45
|
) : (
|
|
61
46
|
FieldProps?.helperText
|
|
62
47
|
),
|
|
63
|
-
inputRef:ref
|
|
48
|
+
inputRef: ref,
|
|
64
49
|
}}
|
|
65
50
|
onChange={(event, value, reason) => {
|
|
66
51
|
if (reason === 'clear') {
|
|
@@ -10,7 +10,7 @@ describe('Datepicker', () => {
|
|
|
10
10
|
test('should render successfully and submit selection', async () => {
|
|
11
11
|
const screen = render(
|
|
12
12
|
<ThemeProvider>
|
|
13
|
-
<TestForm UseFormOptions={{values: { controlledDatepicker: null}}} onSubmit={onSubmit}>
|
|
13
|
+
<TestForm UseFormOptions={{ values: { controlledDatepicker: null } }} onSubmit={onSubmit}>
|
|
14
14
|
<ControlledDatepicker
|
|
15
15
|
name="controlledDatepicker"
|
|
16
16
|
FieldProps={{
|
|
@@ -38,4 +38,71 @@ describe('Datepicker', () => {
|
|
|
38
38
|
expect(dayjs(controlledDatepickerValue).isValid()).toBeTruthy();
|
|
39
39
|
});
|
|
40
40
|
}, 10000);
|
|
41
|
+
|
|
42
|
+
describe('when using rules', () => {
|
|
43
|
+
describe('when required', () => {
|
|
44
|
+
test('should indicate it is required when passing a string', async () => {
|
|
45
|
+
const screen = render(
|
|
46
|
+
<ThemeProvider>
|
|
47
|
+
<TestForm UseFormOptions={{ values: { controlledDatepicker: null } }} onSubmit={onSubmit}>
|
|
48
|
+
<ControlledDatepicker
|
|
49
|
+
name="controlledDatepicker"
|
|
50
|
+
FieldProps={{
|
|
51
|
+
fullWidth: false,
|
|
52
|
+
helperText: 'Help text for the field',
|
|
53
|
+
helpTopicId: '1234',
|
|
54
|
+
label: 'Date',
|
|
55
|
+
}}
|
|
56
|
+
rules={{ required: 'This field is required' }}
|
|
57
|
+
/>
|
|
58
|
+
</TestForm>
|
|
59
|
+
</ThemeProvider>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should indicate it is required when passing an object with true', async () => {
|
|
66
|
+
const screen = render(
|
|
67
|
+
<ThemeProvider>
|
|
68
|
+
<TestForm UseFormOptions={{ values: { controlledDatepicker: null } }} onSubmit={onSubmit}>
|
|
69
|
+
<ControlledDatepicker
|
|
70
|
+
name="controlledDatepicker"
|
|
71
|
+
FieldProps={{
|
|
72
|
+
fullWidth: false,
|
|
73
|
+
helperText: 'Help text for the field',
|
|
74
|
+
helpTopicId: '1234',
|
|
75
|
+
label: 'Date',
|
|
76
|
+
}}
|
|
77
|
+
rules={{ required: { value: true, message: 'This field is required' } }}
|
|
78
|
+
/>
|
|
79
|
+
</TestForm>
|
|
80
|
+
</ThemeProvider>
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('should not indicate it is required when passing an object with false', async () => {
|
|
87
|
+
const screen = render(
|
|
88
|
+
<ThemeProvider>
|
|
89
|
+
<TestForm UseFormOptions={{ values: { controlledDatepicker: null } }} onSubmit={onSubmit}>
|
|
90
|
+
<ControlledDatepicker
|
|
91
|
+
name="controlledDatepicker"
|
|
92
|
+
FieldProps={{
|
|
93
|
+
fullWidth: false,
|
|
94
|
+
helperText: 'Help text for the field',
|
|
95
|
+
helpTopicId: '1234',
|
|
96
|
+
label: 'Date',
|
|
97
|
+
}}
|
|
98
|
+
rules={{ required: { value: false, message: 'This field is required' } }}
|
|
99
|
+
/>
|
|
100
|
+
</TestForm>
|
|
101
|
+
</ThemeProvider>
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
expect(screen.queryByText('*')).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
41
108
|
});
|
package/src/lib/Datepicker.tsx
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
import { Datepicker, DatepickerProps } from '@availity/mui-datepicker';
|
|
2
2
|
import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
|
|
3
|
-
import { ControllerProps
|
|
3
|
+
import { ControllerProps } from './Types';
|
|
4
4
|
|
|
5
|
-
export type ControlledDatepickerProps = Omit<DatepickerProps,
|
|
6
|
-
'onBlur' | 'onChange' | 'value'
|
|
7
|
-
|
|
8
|
-
'onBlur' | 'onChange' | 'value'
|
|
9
|
-
> & ControllerProps
|
|
10
|
-
//TODO v1 - remove deprecated props
|
|
11
|
-
& DeprecatedRulesProps;
|
|
5
|
+
export type ControlledDatepickerProps = Omit<DatepickerProps, 'onBlur' | 'onChange' | 'value' | 'name'> &
|
|
6
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
7
|
+
ControllerProps;
|
|
12
8
|
|
|
13
9
|
export const ControlledDatepicker = ({
|
|
14
10
|
name,
|
|
15
11
|
defaultValue,
|
|
16
|
-
deps,
|
|
17
|
-
max,
|
|
18
|
-
maxLength,
|
|
19
|
-
min,
|
|
20
|
-
minLength,
|
|
21
12
|
onBlur,
|
|
22
13
|
onChange,
|
|
23
|
-
pattern,
|
|
24
|
-
required,
|
|
25
14
|
rules = {},
|
|
26
15
|
shouldUnregister,
|
|
27
|
-
validate,
|
|
28
16
|
value,
|
|
29
17
|
FieldProps,
|
|
30
18
|
...rest
|
|
@@ -34,17 +22,9 @@ export const ControlledDatepicker = ({
|
|
|
34
22
|
name={name}
|
|
35
23
|
defaultValue={defaultValue}
|
|
36
24
|
rules={{
|
|
37
|
-
deps,
|
|
38
|
-
max,
|
|
39
|
-
maxLength,
|
|
40
|
-
min,
|
|
41
|
-
minLength,
|
|
42
25
|
onBlur,
|
|
43
26
|
onChange,
|
|
44
|
-
pattern,
|
|
45
|
-
required,
|
|
46
27
|
shouldUnregister,
|
|
47
|
-
validate,
|
|
48
28
|
value,
|
|
49
29
|
...rules,
|
|
50
30
|
}}
|
|
@@ -53,6 +33,7 @@ export const ControlledDatepicker = ({
|
|
|
53
33
|
<Datepicker
|
|
54
34
|
{...rest}
|
|
55
35
|
FieldProps={{
|
|
36
|
+
required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
|
|
56
37
|
...FieldProps,
|
|
57
38
|
error: !!error,
|
|
58
39
|
helperText: error ? (
|
|
@@ -66,7 +47,7 @@ export const ControlledDatepicker = ({
|
|
|
66
47
|
),
|
|
67
48
|
inputRef: ref,
|
|
68
49
|
inputProps: {
|
|
69
|
-
onBlur: onBlur
|
|
50
|
+
onBlur: onBlur,
|
|
70
51
|
},
|
|
71
52
|
}}
|
|
72
53
|
onChange={onChange}
|
package/src/lib/Input.test.tsx
CHANGED
|
@@ -1,103 +1,10 @@
|
|
|
1
1
|
import { render, fireEvent, waitFor } from '@testing-library/react';
|
|
2
|
-
import { Paper } from '@availity/mui-paper';
|
|
3
|
-
import { Typography } from '@availity/mui-typography';
|
|
4
|
-
import { Grid } from '@availity/mui-layout';
|
|
5
|
-
import { Button } from '@availity/mui-button';
|
|
6
2
|
import { ControlledInput } from './Input';
|
|
7
|
-
import { useFormContext } from '..';
|
|
8
|
-
import { ControlledForm } from './ControlledForm';
|
|
9
3
|
import { TestForm } from './UtilComponents';
|
|
10
4
|
|
|
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
|
-
};
|
|
35
|
-
|
|
36
5
|
const onSubmit = jest.fn();
|
|
37
|
-
const onSubmitDeprecated = jest.fn();
|
|
38
6
|
|
|
39
7
|
describe('ControlledInput', () => {
|
|
40
|
-
test('Deprecation Check: should render the error styling if an error is returned', async () => {
|
|
41
|
-
const screen = render(
|
|
42
|
-
<ControlledForm values={{ controlledInput: undefined }} onSubmit={onSubmitDeprecated}>
|
|
43
|
-
<ControlledInput
|
|
44
|
-
data-testid="controlledInputWrapper"
|
|
45
|
-
name="controlledInput"
|
|
46
|
-
required="This field is required."
|
|
47
|
-
maxLength={{ value: 10, message: 'Too long' }}
|
|
48
|
-
inputProps={{
|
|
49
|
-
'data-testid': 'testInput',
|
|
50
|
-
}}
|
|
51
|
-
/>
|
|
52
|
-
<Actions />
|
|
53
|
-
<SubmittedValues />
|
|
54
|
-
</ControlledForm>
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const input = screen.getByTestId('testInput');
|
|
58
|
-
|
|
59
|
-
fireEvent.change(input, { target: { value: 'This is way too much text' } });
|
|
60
|
-
|
|
61
|
-
fireEvent.click(screen.getByText('Submit'));
|
|
62
|
-
|
|
63
|
-
await waitFor(() => expect(onSubmitDeprecated).toHaveBeenCalledTimes(0));
|
|
64
|
-
|
|
65
|
-
const muiInputBase = screen.getByTestId('controlledInputWrapper');
|
|
66
|
-
|
|
67
|
-
await waitFor(() => expect(muiInputBase.classList).toContain('Mui-error'));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('DeprecatedCheck: should not render the error styling if no error is returned', async () => {
|
|
71
|
-
const screen = render(
|
|
72
|
-
<ControlledForm values={{ controlledInput: undefined }} onSubmit={onSubmitDeprecated}>
|
|
73
|
-
<ControlledInput
|
|
74
|
-
name="controlledInput"
|
|
75
|
-
required="This field is required."
|
|
76
|
-
maxLength={{ value: 10, message: 'Too long' }}
|
|
77
|
-
inputProps={{
|
|
78
|
-
'data-testid': 'testInput',
|
|
79
|
-
}}
|
|
80
|
-
/>
|
|
81
|
-
<Actions />
|
|
82
|
-
<SubmittedValues />
|
|
83
|
-
</ControlledForm>
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const input = screen.getByTestId('testInput');
|
|
87
|
-
|
|
88
|
-
fireEvent.change(input, { target: { value: 'Input Text' } });
|
|
89
|
-
|
|
90
|
-
fireEvent.click(screen.getByText('Submit'));
|
|
91
|
-
|
|
92
|
-
await waitFor(() => expect(onSubmitDeprecated).toHaveBeenCalledTimes(1));
|
|
93
|
-
|
|
94
|
-
const result = screen.getByTestId('result');
|
|
95
|
-
await waitFor(() => {
|
|
96
|
-
const formValues = JSON.parse(result.innerHTML).controlledInput;
|
|
97
|
-
expect(formValues).toBe('Input Text');
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
8
|
test('should render the error styling if an error is returned', async () => {
|
|
102
9
|
const screen = render(
|
|
103
10
|
<TestForm UseFormOptions={{values: { controlledInput: undefined }}} onSubmit={onSubmit}>
|
package/src/lib/Input.tsx
CHANGED
|
@@ -1,39 +1,19 @@
|
|
|
1
1
|
import { Input, InputProps } from '@availity/mui-form-utils';
|
|
2
2
|
import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
|
|
3
|
-
import { ControllerProps
|
|
3
|
+
import { ControllerProps } from './Types';
|
|
4
4
|
|
|
5
|
-
export type ControlledInputProps = Omit<InputProps,
|
|
6
|
-
'onBlur' | 'onChange' | 'value'
|
|
7
|
-
|
|
8
|
-
'onBlur' | 'onChange' | 'value'
|
|
9
|
-
> & ControllerProps
|
|
10
|
-
//TODO v1 - remove deprecated props
|
|
11
|
-
& Omit<DeprecatedRulesProps, 'required'> & {
|
|
12
|
-
/** If `true`, will add `aria-required` to `input`.
|
|
13
|
-
*
|
|
14
|
-
* @deprecated There has been a collision of properties. The boolean value
|
|
15
|
-
* to mark the input as required will remain in future versions, but the
|
|
16
|
-
* required object for `react-hook-form` has been moved to the `rules` prop.
|
|
17
|
-
*/
|
|
18
|
-
required?: boolean | RegisterOptions['required'];
|
|
19
|
-
};
|
|
5
|
+
export type ControlledInputProps = Omit<InputProps, 'onBlur' | 'onChange' | 'value' | 'name'> &
|
|
6
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
7
|
+
ControllerProps;
|
|
20
8
|
|
|
21
9
|
export const ControlledInput = ({
|
|
22
10
|
name,
|
|
23
11
|
defaultValue,
|
|
24
|
-
deps,
|
|
25
12
|
disabled,
|
|
26
|
-
max,
|
|
27
|
-
maxLength,
|
|
28
|
-
min,
|
|
29
|
-
minLength,
|
|
30
13
|
onBlur,
|
|
31
14
|
onChange,
|
|
32
|
-
pattern,
|
|
33
|
-
required,
|
|
34
15
|
rules = {},
|
|
35
16
|
shouldUnregister,
|
|
36
|
-
validate,
|
|
37
17
|
value,
|
|
38
18
|
...rest
|
|
39
19
|
}: ControlledInputProps) => {
|
|
@@ -43,27 +23,19 @@ export const ControlledInput = ({
|
|
|
43
23
|
defaultValue={defaultValue}
|
|
44
24
|
disabled={disabled}
|
|
45
25
|
rules={{
|
|
46
|
-
required: typeof required === 'boolean' ? undefined : required,
|
|
47
|
-
maxLength,
|
|
48
|
-
minLength,
|
|
49
|
-
max,
|
|
50
|
-
min,
|
|
51
|
-
pattern,
|
|
52
|
-
validate,
|
|
53
26
|
onChange,
|
|
54
27
|
onBlur,
|
|
55
28
|
value,
|
|
56
29
|
shouldUnregister,
|
|
57
|
-
deps,
|
|
58
30
|
...rules,
|
|
59
31
|
}}
|
|
60
32
|
shouldUnregister={shouldUnregister}
|
|
61
33
|
render={({ field, fieldState: { error } }) => (
|
|
62
34
|
<Input
|
|
35
|
+
required={typeof rules.required === 'object' ? rules.required.value : !!rules.required}
|
|
63
36
|
{...rest}
|
|
64
37
|
{...field}
|
|
65
38
|
error={!!error}
|
|
66
|
-
required={!!required}
|
|
67
39
|
/>
|
|
68
40
|
)}
|
|
69
41
|
/>
|
|
@@ -32,15 +32,15 @@ describe('ControlledOrganizationAutocomplete', () => {
|
|
|
32
32
|
const screen = render(
|
|
33
33
|
<QueryClientProvider client={client}>
|
|
34
34
|
<TestForm onSubmit={onSubmit}>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
<ControlledOrganizationAutocomplete
|
|
36
|
+
name="controlledOrganizationAutocomplete"
|
|
37
|
+
FieldProps={{
|
|
38
|
+
label: 'Organization Select',
|
|
39
|
+
helperText: 'Select an Organization from the list',
|
|
40
|
+
placeholder: 'Select...',
|
|
41
|
+
fullWidth: false,
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
44
|
</TestForm>
|
|
45
45
|
</QueryClientProvider>
|
|
46
46
|
);
|
|
@@ -56,15 +56,15 @@ describe('ControlledOrganizationAutocomplete', () => {
|
|
|
56
56
|
const screen = render(
|
|
57
57
|
<QueryClientProvider client={client}>
|
|
58
58
|
<TestForm onSubmit={onSubmit}>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
<ControlledOrganizationAutocomplete
|
|
60
|
+
name="controlledOrganizationAutocomplete"
|
|
61
|
+
FieldProps={{
|
|
62
|
+
label: 'Organization Select',
|
|
63
|
+
helperText: 'Select an Organization from the list',
|
|
64
|
+
placeholder: 'Select...',
|
|
65
|
+
fullWidth: false,
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
68
|
</TestForm>
|
|
69
69
|
</QueryClientProvider>
|
|
70
70
|
);
|
|
@@ -88,4 +88,71 @@ describe('ControlledOrganizationAutocomplete', () => {
|
|
|
88
88
|
expect(controlledCodesAutocompleteValue.id).toBeDefined();
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
|
+
|
|
92
|
+
describe('when using rules', () => {
|
|
93
|
+
describe('when required', () => {
|
|
94
|
+
test('should indicate it is required when passing a string', async () => {
|
|
95
|
+
const screen = render(
|
|
96
|
+
<QueryClientProvider client={client}>
|
|
97
|
+
<TestForm onSubmit={onSubmit}>
|
|
98
|
+
<ControlledOrganizationAutocomplete
|
|
99
|
+
name="controlledOrganizationAutocomplete"
|
|
100
|
+
FieldProps={{
|
|
101
|
+
label: 'Organization Select',
|
|
102
|
+
helperText: 'Select an Organization from the list',
|
|
103
|
+
placeholder: 'Select...',
|
|
104
|
+
fullWidth: false,
|
|
105
|
+
}}
|
|
106
|
+
rules={{ required: 'This field is required' }}
|
|
107
|
+
/>
|
|
108
|
+
</TestForm>
|
|
109
|
+
</QueryClientProvider>
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('should indicate it is required when passing an object with true', async () => {
|
|
116
|
+
const screen = render(
|
|
117
|
+
<QueryClientProvider client={client}>
|
|
118
|
+
<TestForm onSubmit={onSubmit}>
|
|
119
|
+
<ControlledOrganizationAutocomplete
|
|
120
|
+
name="controlledOrganizationAutocomplete"
|
|
121
|
+
FieldProps={{
|
|
122
|
+
label: 'Organization Select',
|
|
123
|
+
helperText: 'Select an Organization from the list',
|
|
124
|
+
placeholder: 'Select...',
|
|
125
|
+
fullWidth: false,
|
|
126
|
+
}}
|
|
127
|
+
rules={{ required: { value: true, message: 'This field is required' } }}
|
|
128
|
+
/>
|
|
129
|
+
</TestForm>
|
|
130
|
+
</QueryClientProvider>
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('should not indicate it is required when passing an object with false', async () => {
|
|
137
|
+
const screen = render(
|
|
138
|
+
<QueryClientProvider client={client}>
|
|
139
|
+
<TestForm onSubmit={onSubmit}>
|
|
140
|
+
<ControlledOrganizationAutocomplete
|
|
141
|
+
name="controlledOrganizationAutocomplete"
|
|
142
|
+
FieldProps={{
|
|
143
|
+
label: 'Organization Select',
|
|
144
|
+
helperText: 'Select an Organization from the list',
|
|
145
|
+
placeholder: 'Select...',
|
|
146
|
+
fullWidth: false,
|
|
147
|
+
}}
|
|
148
|
+
rules={{ required: { value: false, message: 'This field is required' } }}
|
|
149
|
+
/>
|
|
150
|
+
</TestForm>
|
|
151
|
+
</QueryClientProvider>
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
expect(screen.queryByText('*')).toBeNull();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
});
|
|
91
158
|
});
|
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
import { OrganizationAutocomplete, OrgAutocompleteProps } from '@availity/mui-autocomplete';
|
|
2
2
|
import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
|
|
3
|
-
import { ControllerProps
|
|
3
|
+
import { ControllerProps } from './Types';
|
|
4
4
|
|
|
5
|
-
export type ControlledOrgAutocompleteProps = Omit<OrgAutocompleteProps,
|
|
6
|
-
'onBlur' | 'onChange' | 'value'
|
|
7
|
-
|
|
8
|
-
'onBlur' | 'onChange' | 'value'
|
|
9
|
-
> & ControllerProps
|
|
10
|
-
//TODO v1 - remove deprecated props
|
|
11
|
-
& Omit<DeprecatedRulesProps, 'max' | 'maxLength' | 'min' | 'minLength'
|
|
12
|
-
>;
|
|
5
|
+
export type ControlledOrgAutocompleteProps = Omit<OrgAutocompleteProps, 'onBlur' | 'onChange' | 'value' | 'name'> &
|
|
6
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
7
|
+
ControllerProps;
|
|
13
8
|
|
|
14
9
|
export const ControlledOrganizationAutocomplete = ({
|
|
15
10
|
name,
|
|
16
11
|
defaultValue,
|
|
17
|
-
deps,
|
|
18
12
|
onBlur,
|
|
19
13
|
onChange,
|
|
20
|
-
pattern,
|
|
21
|
-
required,
|
|
22
14
|
rules = {},
|
|
23
15
|
shouldUnregister,
|
|
24
|
-
validate,
|
|
25
16
|
value,
|
|
26
17
|
FieldProps,
|
|
27
18
|
...rest
|
|
@@ -31,13 +22,9 @@ export const ControlledOrganizationAutocomplete = ({
|
|
|
31
22
|
name={name}
|
|
32
23
|
defaultValue={defaultValue}
|
|
33
24
|
rules={{
|
|
34
|
-
deps,
|
|
35
25
|
onBlur,
|
|
36
26
|
onChange,
|
|
37
|
-
pattern,
|
|
38
|
-
required,
|
|
39
27
|
shouldUnregister,
|
|
40
|
-
validate,
|
|
41
28
|
value,
|
|
42
29
|
...rules,
|
|
43
30
|
}}
|
|
@@ -46,6 +33,7 @@ export const ControlledOrganizationAutocomplete = ({
|
|
|
46
33
|
<OrganizationAutocomplete
|
|
47
34
|
{...rest}
|
|
48
35
|
FieldProps={{
|
|
36
|
+
required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
|
|
49
37
|
...FieldProps,
|
|
50
38
|
error: !!error,
|
|
51
39
|
helperText: error?.message ? (
|
|
@@ -57,7 +45,7 @@ export const ControlledOrganizationAutocomplete = ({
|
|
|
57
45
|
) : (
|
|
58
46
|
FieldProps?.helperText
|
|
59
47
|
),
|
|
60
|
-
inputRef:ref
|
|
48
|
+
inputRef: ref,
|
|
61
49
|
}}
|
|
62
50
|
onChange={(event, value, reason) => {
|
|
63
51
|
if (reason === 'clear') {
|