@availity/mui-controlled-form 0.3.2 → 1.0.0-alpha.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 +19 -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/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
- /package/{introduction.stories.mdx → introduction.mdx} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@availity/mui-controlled-form",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
4
|
"description": "Availity MUI/react-hook-form controlled form components - part of the @availity/element design system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -40,32 +40,32 @@
|
|
|
40
40
|
"publish:canary": "yarn npm publish --access public --tag canary"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@availity/mui-autocomplete": "^0.
|
|
44
|
-
"@availity/mui-checkbox": "^0.
|
|
45
|
-
"@availity/mui-datepicker": "^0.
|
|
46
|
-
"@availity/mui-form-utils": "^0.
|
|
47
|
-
"@availity/mui-textfield": "^0.
|
|
48
|
-
"react-hook-form": "^7.
|
|
43
|
+
"@availity/mui-autocomplete": "^1.0.0-alpha.0",
|
|
44
|
+
"@availity/mui-checkbox": "^1.0.0-alpha.0",
|
|
45
|
+
"@availity/mui-datepicker": "^1.0.0-alpha.0",
|
|
46
|
+
"@availity/mui-form-utils": "^1.0.0-alpha.0",
|
|
47
|
+
"@availity/mui-textfield": "^1.0.0-alpha.0",
|
|
48
|
+
"react-hook-form": "^7.54.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@availity/api-axios": "^
|
|
52
|
-
"@availity/mui-button": "^0.
|
|
53
|
-
"@availity/mui-layout": "^0.
|
|
54
|
-
"@availity/mui-menu": "^0.
|
|
55
|
-
"@availity/mui-paper": "^0.
|
|
56
|
-
"@availity/mui-typography": "^0.
|
|
57
|
-
"@hookform/resolvers": "^
|
|
58
|
-
"@mui/material": "^
|
|
51
|
+
"@availity/api-axios": "^10.0.0",
|
|
52
|
+
"@availity/mui-button": "^1.0.0-alpha.0",
|
|
53
|
+
"@availity/mui-layout": "^1.0.0-alpha.0",
|
|
54
|
+
"@availity/mui-menu": "^1.0.0-alpha.0",
|
|
55
|
+
"@availity/mui-paper": "^1.0.0-alpha.0",
|
|
56
|
+
"@availity/mui-typography": "^1.0.0-alpha.0",
|
|
57
|
+
"@hookform/resolvers": "^4.0.0",
|
|
58
|
+
"@mui/material": "^6.4.5",
|
|
59
59
|
"@tanstack/react-query": "^4.36.1",
|
|
60
60
|
"dayjs": "^1.11.13",
|
|
61
61
|
"react": "18.2.0",
|
|
62
62
|
"react-dom": "18.2.0",
|
|
63
|
-
"tsup": "^8.
|
|
63
|
+
"tsup": "^8.3.6",
|
|
64
64
|
"typescript": "^5.4.5",
|
|
65
65
|
"yup": "^1.6.1"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
|
-
"@mui/material": "^
|
|
68
|
+
"@mui/material": "^6.4.5",
|
|
69
69
|
"react": ">=16.3.0"
|
|
70
70
|
},
|
|
71
71
|
"publishConfig": {
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,6 @@ export * from './/lib/AsyncAutocomplete';
|
|
|
2
2
|
export * from './lib/Autocomplete';
|
|
3
3
|
export * from './lib/Checkbox';
|
|
4
4
|
export * from './lib/CodesAutocomplete';
|
|
5
|
-
export * from './lib/ControlledForm';
|
|
6
5
|
export * from './lib/Datepicker';
|
|
7
6
|
export * from './lib/Input';
|
|
8
7
|
export * from './lib/OrganizationAutocomplete';
|
|
@@ -66,17 +66,17 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
test('should loadOptions successfully', async () => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
80
|
</TestForm>
|
|
81
81
|
</QueryClientProvider>
|
|
82
82
|
);
|
|
@@ -91,7 +91,7 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
91
91
|
test('should set the value and submit the form data', async () => {
|
|
92
92
|
const screen = render(
|
|
93
93
|
<QueryClientProvider client={client}>
|
|
94
|
-
<TestForm UseFormOptions={{values: { controlledAutocomplete: undefined }}} onSubmit={onSubmit}>
|
|
94
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: undefined } }} onSubmit={onSubmit}>
|
|
95
95
|
<ControlledAsyncAutocomplete
|
|
96
96
|
name="controlledAsyncAutocomplete"
|
|
97
97
|
FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
|
|
@@ -100,9 +100,9 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
100
100
|
limit={10}
|
|
101
101
|
queryKey="example"
|
|
102
102
|
/>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
</TestForm>
|
|
104
|
+
</QueryClientProvider>
|
|
105
|
+
);
|
|
106
106
|
|
|
107
107
|
const dropdown = screen.getByRole('combobox');
|
|
108
108
|
fireEvent.click(dropdown);
|
|
@@ -123,4 +123,68 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
123
123
|
expect(controlledAsyncAutocompleteValue.id).toBeDefined(); // This is a unique id
|
|
124
124
|
});
|
|
125
125
|
});
|
|
126
|
-
|
|
126
|
+
|
|
127
|
+
describe('when using rules', () => {
|
|
128
|
+
describe('when required', () => {
|
|
129
|
+
test('should indicate it is required when passing a string', async () => {
|
|
130
|
+
const screen = render(
|
|
131
|
+
<QueryClientProvider client={client}>
|
|
132
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: undefined } }} onSubmit={onSubmit}>
|
|
133
|
+
<ControlledAsyncAutocomplete
|
|
134
|
+
name="controlledAsyncAutocomplete"
|
|
135
|
+
FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
|
|
136
|
+
getOptionLabel={(val: Option) => val.label}
|
|
137
|
+
loadOptions={loadOptions}
|
|
138
|
+
limit={10}
|
|
139
|
+
queryKey="example"
|
|
140
|
+
rules={{ required: 'This field is required' }}
|
|
141
|
+
/>
|
|
142
|
+
</TestForm>
|
|
143
|
+
</QueryClientProvider>
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('should indicate it is required when passing an object with true', async () => {
|
|
150
|
+
const screen = render(
|
|
151
|
+
<QueryClientProvider client={client}>
|
|
152
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: undefined } }} onSubmit={onSubmit}>
|
|
153
|
+
<ControlledAsyncAutocomplete
|
|
154
|
+
name="controlledAsyncAutocomplete"
|
|
155
|
+
FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
|
|
156
|
+
getOptionLabel={(val: Option) => val.label}
|
|
157
|
+
loadOptions={loadOptions}
|
|
158
|
+
limit={10}
|
|
159
|
+
queryKey="example"
|
|
160
|
+
rules={{ required: { value: true, message: 'This field is required' } }}
|
|
161
|
+
/>
|
|
162
|
+
</TestForm>
|
|
163
|
+
</QueryClientProvider>
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('should not indicate it is required when passing an object with false', async () => {
|
|
170
|
+
const screen = render(
|
|
171
|
+
<QueryClientProvider client={client}>
|
|
172
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: undefined } }} onSubmit={onSubmit}>
|
|
173
|
+
<ControlledAsyncAutocomplete
|
|
174
|
+
name="controlledAsyncAutocomplete"
|
|
175
|
+
FieldProps={{ label: 'Async Select', helperText: 'Helper Text', fullWidth: false }}
|
|
176
|
+
getOptionLabel={(val: Option) => val.label}
|
|
177
|
+
loadOptions={loadOptions}
|
|
178
|
+
limit={10}
|
|
179
|
+
queryKey="example"
|
|
180
|
+
rules={{ required: { value: false, message: 'This field is required' } }}
|
|
181
|
+
/>
|
|
182
|
+
</TestForm>
|
|
183
|
+
</QueryClientProvider>
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
expect(screen.queryByText('*')).toBeNull();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AsyncAutocomplete, AsyncAutocompleteProps } from '@availity/mui-autocomplete';
|
|
2
2
|
import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
|
|
3
3
|
import { ChipTypeMap } from '@mui/material/Chip';
|
|
4
|
-
import { ControllerProps
|
|
4
|
+
import { ControllerProps } from './Types';
|
|
5
5
|
|
|
6
6
|
export type ControlledAsyncAutocompleteProps<
|
|
7
7
|
Option,
|
|
@@ -9,13 +9,12 @@ export type ControlledAsyncAutocompleteProps<
|
|
|
9
9
|
DisableClearable extends boolean | undefined,
|
|
10
10
|
FreeSolo extends boolean | undefined,
|
|
11
11
|
ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
|
|
12
|
-
> = Omit<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
> &
|
|
17
|
-
|
|
18
|
-
& DeprecatedRulesProps;
|
|
12
|
+
> = Omit<
|
|
13
|
+
AsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>,
|
|
14
|
+
'onBlur' | 'onChange' | 'value' | 'name'
|
|
15
|
+
> &
|
|
16
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
17
|
+
ControllerProps;
|
|
19
18
|
|
|
20
19
|
export const ControlledAsyncAutocomplete = <
|
|
21
20
|
Option,
|
|
@@ -25,18 +24,10 @@ export const ControlledAsyncAutocomplete = <
|
|
|
25
24
|
ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
|
|
26
25
|
>({
|
|
27
26
|
name,
|
|
28
|
-
deps,
|
|
29
|
-
max,
|
|
30
|
-
maxLength,
|
|
31
|
-
min,
|
|
32
|
-
minLength,
|
|
33
27
|
onBlur,
|
|
34
28
|
onChange,
|
|
35
|
-
pattern,
|
|
36
|
-
required,
|
|
37
29
|
rules = {},
|
|
38
30
|
shouldUnregister,
|
|
39
|
-
validate,
|
|
40
31
|
value,
|
|
41
32
|
FieldProps,
|
|
42
33
|
...rest
|
|
@@ -46,17 +37,9 @@ export const ControlledAsyncAutocomplete = <
|
|
|
46
37
|
name={name}
|
|
47
38
|
defaultValue={rest.defaultValue}
|
|
48
39
|
rules={{
|
|
49
|
-
deps,
|
|
50
|
-
max,
|
|
51
|
-
maxLength,
|
|
52
|
-
min,
|
|
53
|
-
minLength,
|
|
54
40
|
onBlur,
|
|
55
41
|
onChange,
|
|
56
|
-
pattern,
|
|
57
|
-
required,
|
|
58
42
|
shouldUnregister,
|
|
59
|
-
validate,
|
|
60
43
|
value,
|
|
61
44
|
...rules,
|
|
62
45
|
}}
|
|
@@ -65,6 +48,7 @@ export const ControlledAsyncAutocomplete = <
|
|
|
65
48
|
<AsyncAutocomplete
|
|
66
49
|
{...rest}
|
|
67
50
|
FieldProps={{
|
|
51
|
+
required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
|
|
68
52
|
...FieldProps,
|
|
69
53
|
error: !!error,
|
|
70
54
|
helperText: error?.message ? (
|
|
@@ -76,7 +60,7 @@ export const ControlledAsyncAutocomplete = <
|
|
|
76
60
|
) : (
|
|
77
61
|
FieldProps?.helperText
|
|
78
62
|
),
|
|
79
|
-
inputRef:ref
|
|
63
|
+
inputRef: ref,
|
|
80
64
|
}}
|
|
81
65
|
onChange={(event, value, reason) => {
|
|
82
66
|
if (reason === 'clear') {
|
|
@@ -13,11 +13,8 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
13
13
|
|
|
14
14
|
test('should set the value and submit the form', async () => {
|
|
15
15
|
const screen = render(
|
|
16
|
-
<TestForm UseFormOptions={{values: { controlledAutocomplete: null}}} onSubmit={onSubmit}>
|
|
17
|
-
<ControlledAutocomplete
|
|
18
|
-
name="controlledAutocomplete"
|
|
19
|
-
options={['Option 1', 'Option 2']}
|
|
20
|
-
/>
|
|
16
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: null } }} onSubmit={onSubmit}>
|
|
17
|
+
<ControlledAutocomplete name="controlledAutocomplete" options={['Option 1', 'Option 2']} />
|
|
21
18
|
</TestForm>
|
|
22
19
|
);
|
|
23
20
|
|
|
@@ -37,4 +34,53 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
37
34
|
expect(controlledAutocompleteValue).toBe('Option 1');
|
|
38
35
|
});
|
|
39
36
|
});
|
|
40
|
-
|
|
37
|
+
|
|
38
|
+
describe('when using rules', () => {
|
|
39
|
+
describe('when required', () => {
|
|
40
|
+
test('should indicate it is required when passing a string', async () => {
|
|
41
|
+
const screen = render(
|
|
42
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: null } }} onSubmit={onSubmit}>
|
|
43
|
+
<ControlledAutocomplete
|
|
44
|
+
FieldProps={{ label: 'Autocomplete Label' }}
|
|
45
|
+
name="controlledAutocomplete"
|
|
46
|
+
options={['Option 1', 'Option 2']}
|
|
47
|
+
rules={{ required: 'This field is required' }}
|
|
48
|
+
/>
|
|
49
|
+
</TestForm>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('should indicate it is required when passing an object with true', async () => {
|
|
56
|
+
const screen = render(
|
|
57
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: null } }} onSubmit={onSubmit}>
|
|
58
|
+
<ControlledAutocomplete
|
|
59
|
+
FieldProps={{ label: 'Autocomplete Label' }}
|
|
60
|
+
name="controlledAutocomplete"
|
|
61
|
+
options={['Option 1', 'Option 2']}
|
|
62
|
+
rules={{ required: { value: true, message: 'This field is required' } }}
|
|
63
|
+
/>
|
|
64
|
+
</TestForm>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('should not indicate it is required when passing an object with false', async () => {
|
|
71
|
+
const screen = render(
|
|
72
|
+
<TestForm UseFormOptions={{ values: { controlledAutocomplete: null } }} onSubmit={onSubmit}>
|
|
73
|
+
<ControlledAutocomplete
|
|
74
|
+
FieldProps={{ label: 'Autocomplete Label' }}
|
|
75
|
+
name="controlledAutocomplete"
|
|
76
|
+
options={['Option 1', 'Option 2']}
|
|
77
|
+
rules={{ required: { value: false, message: 'This field is required' } }}
|
|
78
|
+
/>
|
|
79
|
+
</TestForm>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
expect(screen.queryByText('*')).toBeNull();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
package/src/lib/Autocomplete.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Autocomplete, AutocompleteProps } from '@availity/mui-autocomplete';
|
|
2
2
|
import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
|
|
3
3
|
import { ChipTypeMap } from '@mui/material/Chip';
|
|
4
|
-
import { ControllerProps
|
|
4
|
+
import { ControllerProps } from './Types';
|
|
5
5
|
|
|
6
6
|
export type ControlledAutocompleteProps<
|
|
7
7
|
T,
|
|
@@ -10,13 +10,11 @@ export type ControlledAutocompleteProps<
|
|
|
10
10
|
FreeSolo extends boolean | undefined,
|
|
11
11
|
ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
|
|
12
12
|
> = Omit<
|
|
13
|
-
AutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>,
|
|
14
|
-
'onBlur' | 'onChange' | 'value' | 'name'
|
|
15
|
-
> &
|
|
16
|
-
'onBlur' | 'onChange' | 'value'
|
|
17
|
-
|
|
18
|
-
//TODO v1 - remove deprecated props
|
|
19
|
-
& DeprecatedRulesProps;
|
|
13
|
+
AutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>,
|
|
14
|
+
'onBlur' | 'onChange' | 'value' | 'name'
|
|
15
|
+
> &
|
|
16
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
17
|
+
ControllerProps;
|
|
20
18
|
|
|
21
19
|
export const ControlledAutocomplete = <
|
|
22
20
|
T,
|
|
@@ -29,17 +27,9 @@ export const ControlledAutocomplete = <
|
|
|
29
27
|
FieldProps,
|
|
30
28
|
defaultValue,
|
|
31
29
|
rules = {},
|
|
32
|
-
deps,
|
|
33
|
-
max,
|
|
34
|
-
maxLength,
|
|
35
|
-
min,
|
|
36
|
-
minLength,
|
|
37
30
|
onBlur,
|
|
38
31
|
onChange,
|
|
39
|
-
pattern,
|
|
40
|
-
required,
|
|
41
32
|
shouldUnregister,
|
|
42
|
-
validate,
|
|
43
33
|
value,
|
|
44
34
|
...rest
|
|
45
35
|
}: ControlledAutocompleteProps<T, Multiple, DisableClearable, FreeSolo, ChipComponent>) => {
|
|
@@ -48,17 +38,9 @@ export const ControlledAutocomplete = <
|
|
|
48
38
|
name={name}
|
|
49
39
|
defaultValue={defaultValue}
|
|
50
40
|
rules={{
|
|
51
|
-
deps,
|
|
52
|
-
max,
|
|
53
|
-
maxLength,
|
|
54
|
-
min,
|
|
55
|
-
minLength,
|
|
56
41
|
onBlur,
|
|
57
42
|
onChange,
|
|
58
|
-
pattern,
|
|
59
|
-
required,
|
|
60
43
|
shouldUnregister,
|
|
61
|
-
validate,
|
|
62
44
|
value,
|
|
63
45
|
...rules,
|
|
64
46
|
}}
|
|
@@ -67,18 +49,19 @@ export const ControlledAutocomplete = <
|
|
|
67
49
|
<Autocomplete
|
|
68
50
|
{...rest}
|
|
69
51
|
FieldProps={{
|
|
52
|
+
required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
|
|
70
53
|
...FieldProps,
|
|
71
54
|
error: !!error,
|
|
72
55
|
helperText: error?.message ? (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
inputRef: ref
|
|
56
|
+
<>
|
|
57
|
+
{error.message}
|
|
58
|
+
<br />
|
|
59
|
+
{FieldProps?.helperText}
|
|
60
|
+
</>
|
|
61
|
+
) : (
|
|
62
|
+
FieldProps?.helperText
|
|
63
|
+
),
|
|
64
|
+
inputRef: ref,
|
|
82
65
|
}}
|
|
83
66
|
onChange={(event, value, reason) => {
|
|
84
67
|
if (reason === 'clear') {
|
package/src/lib/Checkbox.tsx
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { Checkbox, CheckboxProps } from '@availity/mui-checkbox';
|
|
2
2
|
import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
|
|
3
|
-
import { ControllerProps
|
|
3
|
+
import { ControllerProps } from './Types';
|
|
4
4
|
|
|
5
|
-
export type ControlledCheckboxProps = Omit<CheckboxProps,
|
|
6
|
-
'disabled' | 'onBlur' | 'onChange' | 'value'
|
|
7
|
-
|
|
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'>;
|
|
5
|
+
export type ControlledCheckboxProps = Omit<CheckboxProps, 'disabled' | 'onBlur' | 'onChange' | 'value' | 'name'> &
|
|
6
|
+
Pick<RegisterOptions<FieldValues, string>, 'disabled' | 'onBlur' | 'onChange' | 'value'> &
|
|
7
|
+
ControllerProps;
|
|
18
8
|
|
|
19
9
|
export const ControlledCheckbox = ({
|
|
20
10
|
name,
|
|
@@ -25,8 +15,6 @@ export const ControlledCheckbox = ({
|
|
|
25
15
|
defaultValue = false,
|
|
26
16
|
rules = {},
|
|
27
17
|
shouldUnregister,
|
|
28
|
-
deps,
|
|
29
|
-
validate,
|
|
30
18
|
...rest
|
|
31
19
|
}: ControlledCheckboxProps) => {
|
|
32
20
|
return (
|
|
@@ -39,13 +27,17 @@ export const ControlledCheckbox = ({
|
|
|
39
27
|
onBlur,
|
|
40
28
|
value,
|
|
41
29
|
shouldUnregister,
|
|
42
|
-
deps,
|
|
43
|
-
validate,
|
|
44
30
|
...rules,
|
|
45
31
|
}}
|
|
46
32
|
shouldUnregister={shouldUnregister}
|
|
47
33
|
render={({ field }) => (
|
|
48
|
-
<Checkbox
|
|
34
|
+
<Checkbox
|
|
35
|
+
required={typeof rules.required === 'object' ? rules.required.value : !!rules.required}
|
|
36
|
+
{...rest}
|
|
37
|
+
{...field}
|
|
38
|
+
checked={field.value}
|
|
39
|
+
onChange={(e) => field.onChange(e.target.checked)}
|
|
40
|
+
/>
|
|
49
41
|
)}
|
|
50
42
|
/>
|
|
51
43
|
);
|
|
@@ -43,9 +43,9 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
43
43
|
}}
|
|
44
44
|
limit={15}
|
|
45
45
|
/>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
</TestForm>
|
|
47
|
+
</QueryClientProvider>
|
|
48
|
+
);
|
|
49
49
|
|
|
50
50
|
const dropdown = screen.getByRole('combobox');
|
|
51
51
|
fireEvent.click(dropdown);
|
|
@@ -55,20 +55,20 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
test('should set the value and submit the form data', async () => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
72
|
</TestForm>
|
|
73
73
|
</QueryClientProvider>
|
|
74
74
|
);
|
|
@@ -91,4 +91,77 @@ describe('ControlledAsyncAutocomplete', () => {
|
|
|
91
91
|
expect(controlledCodesAutocompleteValue.value).toBe('Acupuncturist');
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
|
+
|
|
95
|
+
describe('when using rules', () => {
|
|
96
|
+
describe('when required', () => {
|
|
97
|
+
test('should indicate it is required when passing a string', async () => {
|
|
98
|
+
const screen = render(
|
|
99
|
+
<QueryClientProvider client={client}>
|
|
100
|
+
<TestForm onSubmit={onSubmit}>
|
|
101
|
+
<ControlledCodesAutocomplete
|
|
102
|
+
name="controlledCodesAutocomplete"
|
|
103
|
+
list="ABC"
|
|
104
|
+
FieldProps={{
|
|
105
|
+
label: 'Code Select',
|
|
106
|
+
helperText: 'Select a code from the list',
|
|
107
|
+
placeholder: 'Select...',
|
|
108
|
+
fullWidth: false,
|
|
109
|
+
}}
|
|
110
|
+
limit={15}
|
|
111
|
+
rules={{ required: 'This field is required' }}
|
|
112
|
+
/>
|
|
113
|
+
</TestForm>
|
|
114
|
+
</QueryClientProvider>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('should indicate it is required when passing an object with true', async () => {
|
|
121
|
+
const screen = render(
|
|
122
|
+
<QueryClientProvider client={client}>
|
|
123
|
+
<TestForm onSubmit={onSubmit}>
|
|
124
|
+
<ControlledCodesAutocomplete
|
|
125
|
+
name="controlledCodesAutocomplete"
|
|
126
|
+
list="ABC"
|
|
127
|
+
FieldProps={{
|
|
128
|
+
label: 'Code Select',
|
|
129
|
+
helperText: 'Select a code from the list',
|
|
130
|
+
placeholder: 'Select...',
|
|
131
|
+
fullWidth: false,
|
|
132
|
+
}}
|
|
133
|
+
limit={15}
|
|
134
|
+
rules={{ required: { value: true, message: 'This field is required' } }}
|
|
135
|
+
/>
|
|
136
|
+
</TestForm>
|
|
137
|
+
</QueryClientProvider>
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
expect(screen.getByText('*')).toBeDefined();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test('should not indicate it is required when passing an object with false', async () => {
|
|
144
|
+
const screen = render(
|
|
145
|
+
<QueryClientProvider client={client}>
|
|
146
|
+
<TestForm onSubmit={onSubmit}>
|
|
147
|
+
<ControlledCodesAutocomplete
|
|
148
|
+
name="controlledCodesAutocomplete"
|
|
149
|
+
list="ABC"
|
|
150
|
+
FieldProps={{
|
|
151
|
+
label: 'Code Select',
|
|
152
|
+
helperText: 'Select a code from the list',
|
|
153
|
+
placeholder: 'Select...',
|
|
154
|
+
fullWidth: false,
|
|
155
|
+
}}
|
|
156
|
+
limit={15}
|
|
157
|
+
rules={{ required: { value: false, message: 'This field is required' } }}
|
|
158
|
+
/>
|
|
159
|
+
</TestForm>
|
|
160
|
+
</QueryClientProvider>
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
expect(screen.queryByText('*')).toBeNull();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
94
167
|
});
|
|
@@ -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') {
|