@availity/mui-controlled-form 1.1.3 → 1.2.1

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.
@@ -1,5 +1,5 @@
1
1
  import { AsyncAutocomplete, AsyncAutocompleteProps } from '@availity/mui-autocomplete';
2
- import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
2
+ import { RegisterOptions, FieldValues, Controller, useFormContext } from 'react-hook-form';
3
3
  import { ChipTypeMap } from '@mui/material/Chip';
4
4
  import { ControllerProps } from './Types';
5
5
 
@@ -9,7 +9,7 @@ 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<
12
+ > = { defaultToFirstOption?: boolean; defaultToOnlyOption?: boolean } & Omit<
13
13
  AsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>,
14
14
  'onBlur' | 'onChange' | 'value' | 'name'
15
15
  > &
@@ -30,19 +30,16 @@ export const ControlledAsyncAutocomplete = <
30
30
  shouldUnregister,
31
31
  value,
32
32
  FieldProps,
33
+ defaultToFirstOption,
34
+ defaultToOnlyOption,
33
35
  ...rest
34
36
  }: ControlledAsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>) => {
37
+ const { setValue } = useFormContext();
35
38
  return (
36
39
  <Controller
37
40
  name={name}
38
41
  defaultValue={rest.defaultValue}
39
- rules={{
40
- onBlur,
41
- onChange,
42
- shouldUnregister,
43
- value,
44
- ...rules,
45
- }}
42
+ rules={{ onBlur, onChange, shouldUnregister, value, ...rules }}
46
43
  shouldUnregister={shouldUnregister}
47
44
  render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
48
45
  <AsyncAutocomplete
@@ -70,6 +67,19 @@ export const ControlledAsyncAutocomplete = <
70
67
  }}
71
68
  onBlur={onBlur}
72
69
  value={value || null}
70
+ loadOptions={async (offset, limit, inputValue) => {
71
+ const { options, hasMore, offset: returnedOffsetValue } = await rest.loadOptions(offset, limit, inputValue);
72
+
73
+ if (defaultToFirstOption && offset === 0) {
74
+ setValue(name, rest.multiple ? [options[0]] : options[0]);
75
+ }
76
+
77
+ if (defaultToOnlyOption && offset === 0 && options.length === 1) {
78
+ setValue(name, rest.multiple ? [options[0]] : options[0]);
79
+ }
80
+
81
+ return { options, hasMore, offset: returnedOffsetValue };
82
+ }}
73
83
  />
74
84
  )}
75
85
  />
@@ -1,10 +1,25 @@
1
- import { CodesAutocomplete, CodesAutocompleteProps } from '@availity/mui-autocomplete';
2
- import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
3
- import { ControllerProps } from './Types';
1
+ import type { Code } from '@availity/mui-autocomplete';
2
+ import { fetchCodes, handleGetCodesOptionLabel } from '@availity/mui-autocomplete';
3
+ import { ApiConfig } from '@availity/api-axios';
4
+ import { ChipTypeMap } from '@mui/material/Chip';
5
+ import type { Optional } from './utils';
6
+ import { ControlledAsyncAutocomplete, ControlledAsyncAutocompleteProps } from './AsyncAutocomplete';
4
7
 
5
- export type ControlledCodesAutocompleteProps = Omit<CodesAutocompleteProps, 'onBlur' | 'onChange' | 'value' | 'name'> &
6
- Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
7
- ControllerProps;
8
+ export interface ControlledCodesAutocompleteProps<
9
+ Option = Code,
10
+ Multiple extends boolean | undefined = false,
11
+ DisableClearable extends boolean | undefined = false,
12
+ FreeSolo extends boolean | undefined = false,
13
+ ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
14
+ > extends Omit<
15
+ Optional<ControlledAsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>, 'queryKey'>,
16
+ 'loadOptions'
17
+ > {
18
+ /** The code list id. */
19
+ list: string;
20
+ /** Config passed to the AvCodesApi.query function */
21
+ apiConfig?: ApiConfig;
22
+ }
8
23
 
9
24
  export const ControlledCodesAutocomplete = ({
10
25
  name,
@@ -15,48 +30,38 @@ export const ControlledCodesAutocomplete = ({
15
30
  shouldUnregister,
16
31
  value,
17
32
  FieldProps,
33
+ apiConfig = {},
34
+ queryOptions,
35
+ queryKey = 'codes-autocomplete',
36
+ list,
37
+ watchParams,
18
38
  ...rest
19
39
  }: ControlledCodesAutocompleteProps) => {
40
+ const handleLoadOptions = async (offset: number, limit: number, inputValue: string) => {
41
+ const resp = await fetchCodes({
42
+ ...apiConfig,
43
+ params: { ...apiConfig.params, list, offset, limit, q: inputValue },
44
+ });
45
+
46
+ return resp;
47
+ };
48
+
20
49
  return (
21
- <Controller
50
+ <ControlledAsyncAutocomplete
22
51
  name={name}
23
52
  defaultValue={defaultValue}
24
- rules={{
25
- onBlur,
26
- onChange,
27
- shouldUnregister,
28
- value,
29
- ...rules,
30
- }}
53
+ onBlur={onBlur}
54
+ onChange={onChange}
55
+ rules={rules}
31
56
  shouldUnregister={shouldUnregister}
32
- render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
33
- <CodesAutocomplete
34
- {...rest}
35
- FieldProps={{
36
- required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
37
- ...FieldProps,
38
- error: !!error,
39
- helperText: error?.message ? (
40
- <>
41
- {error.message}
42
- <br />
43
- {FieldProps?.helperText}
44
- </>
45
- ) : (
46
- FieldProps?.helperText
47
- ),
48
- inputRef: ref,
49
- }}
50
- onChange={(event, value, reason) => {
51
- if (reason === 'clear') {
52
- onChange(null);
53
- }
54
- onChange(value);
55
- }}
56
- onBlur={onBlur}
57
- value={value || null}
58
- />
59
- )}
57
+ value={value}
58
+ FieldProps={FieldProps}
59
+ getOptionLabel={handleGetCodesOptionLabel}
60
+ queryKey={queryKey}
61
+ queryOptions={{ enabled: !!list, ...queryOptions }}
62
+ watchParams={{ list, ...watchParams }}
63
+ {...rest}
64
+ loadOptions={handleLoadOptions}
60
65
  />
61
66
  );
62
67
  };
@@ -1,10 +1,23 @@
1
- import { OrganizationAutocomplete, OrgAutocompleteProps } from '@availity/mui-autocomplete';
2
- import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
3
- import { ControllerProps } from './Types';
1
+ import type { Organization } from '@availity/mui-autocomplete';
2
+ import { handleGetOrgOptionLabel, fetchOrgs } from '@availity/mui-autocomplete';
3
+ import type { ChipTypeMap } from '@mui/material/Chip';
4
+ import type { ApiConfig } from '@availity/api-axios';
5
+ import type { Optional } from './utils';
6
+ import { ControlledAsyncAutocomplete, ControlledAsyncAutocompleteProps } from './AsyncAutocomplete';
4
7
 
5
- export type ControlledOrgAutocompleteProps = Omit<OrgAutocompleteProps, 'onBlur' | 'onChange' | 'value' | 'name'> &
6
- Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
7
- ControllerProps;
8
+ export interface ControlledOrgAutocompleteProps<
9
+ Option = Organization,
10
+ Multiple extends boolean | undefined = false,
11
+ DisableClearable extends boolean | undefined = false,
12
+ FreeSolo extends boolean | undefined = false,
13
+ ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
14
+ > extends Omit<
15
+ Optional<ControlledAsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>, 'queryKey'>,
16
+ 'loadOptions'
17
+ > {
18
+ /** Axios ApiConfig */
19
+ apiConfig?: ApiConfig;
20
+ }
8
21
 
9
22
  export const ControlledOrganizationAutocomplete = ({
10
23
  name,
@@ -15,48 +28,29 @@ export const ControlledOrganizationAutocomplete = ({
15
28
  shouldUnregister,
16
29
  value,
17
30
  FieldProps,
31
+ queryKey = 'org-autocomplete',
32
+ apiConfig = {},
18
33
  ...rest
19
34
  }: ControlledOrgAutocompleteProps) => {
35
+ const handleLoadOptions = async (offset: number, limit: number) => {
36
+ const resp = await fetchOrgs({ ...apiConfig, params: { dropdown: true, ...apiConfig.params, offset, limit } });
37
+
38
+ return resp;
39
+ };
20
40
  return (
21
- <Controller
41
+ <ControlledAsyncAutocomplete
22
42
  name={name}
23
43
  defaultValue={defaultValue}
24
- rules={{
25
- onBlur,
26
- onChange,
27
- shouldUnregister,
28
- value,
29
- ...rules,
30
- }}
44
+ onBlur={onBlur}
45
+ onChange={onChange}
46
+ rules={rules}
31
47
  shouldUnregister={shouldUnregister}
32
- render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
33
- <OrganizationAutocomplete
34
- {...rest}
35
- FieldProps={{
36
- required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
37
- ...FieldProps,
38
- error: !!error,
39
- helperText: error?.message ? (
40
- <>
41
- {error.message}
42
- <br />
43
- {FieldProps?.helperText}
44
- </>
45
- ) : (
46
- FieldProps?.helperText
47
- ),
48
- inputRef: ref,
49
- }}
50
- onChange={(event, value, reason) => {
51
- if (reason === 'clear') {
52
- onChange(null);
53
- }
54
- onChange(value);
55
- }}
56
- onBlur={onBlur}
57
- value={value || null}
58
- />
59
- )}
48
+ value={value}
49
+ FieldProps={FieldProps}
50
+ getOptionLabel={handleGetOrgOptionLabel}
51
+ queryKey={queryKey}
52
+ {...rest}
53
+ loadOptions={handleLoadOptions}
60
54
  />
61
55
  );
62
56
  };
@@ -1,13 +1,25 @@
1
- import { ProviderAutocomplete, ProviderAutocompleteProps } from '@availity/mui-autocomplete';
2
- import { Controller, RegisterOptions, FieldValues } from 'react-hook-form';
3
- import { ControllerProps } from './Types';
1
+ import type { Provider } from '@availity/mui-autocomplete';
2
+ import { handleGetProviderOptionLabel, fetchProviders } from '@availity/mui-autocomplete';
3
+ import type { ChipTypeMap } from '@mui/material/Chip';
4
+ import type { Optional } from './utils';
5
+ import type { ApiConfig } from '@availity/api-axios';
6
+ import { ControlledAsyncAutocomplete, type ControlledAsyncAutocompleteProps } from './AsyncAutocomplete';
4
7
 
5
- export type ControlledProviderAutocompleteProps = Omit<
6
- ProviderAutocompleteProps,
7
- 'onBlur' | 'onChange' | 'value' | 'name'
8
- > &
9
- Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
10
- ControllerProps;
8
+ export interface ControlledProviderAutocompleteProps<
9
+ Option = Provider,
10
+ Multiple extends boolean | undefined = false,
11
+ DisableClearable extends boolean | undefined = false,
12
+ FreeSolo extends boolean | undefined = false,
13
+ ChipComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
14
+ > extends Omit<
15
+ Optional<ControlledAsyncAutocompleteProps<Option, Multiple, DisableClearable, FreeSolo, ChipComponent>, 'queryKey'>,
16
+ 'loadOptions'
17
+ > {
18
+ /** Customer ID of the Organization you are requesting the providers for */
19
+ customerId: string;
20
+ /** Config passed to the AvProvidersApi.getProviders function */
21
+ apiConfig?: ApiConfig;
22
+ }
11
23
 
12
24
  export const ControlledProviderAutocomplete = ({
13
25
  name,
@@ -18,47 +30,35 @@ export const ControlledProviderAutocomplete = ({
18
30
  shouldUnregister,
19
31
  value,
20
32
  FieldProps,
33
+ apiConfig = {},
34
+ customerId,
35
+ queryKey = 'prov-autocomplete',
21
36
  ...rest
22
37
  }: ControlledProviderAutocompleteProps) => {
38
+ const handleLoadOptions = async (offset: number, limit: number, inputValue: string) => {
39
+ const resp = await fetchProviders(customerId, {
40
+ ...apiConfig,
41
+ params: { ...apiConfig.params, offset, limit, q: inputValue },
42
+ });
43
+
44
+ return resp;
45
+ };
23
46
  return (
24
- <Controller
47
+ <ControlledAsyncAutocomplete
25
48
  name={name}
26
49
  defaultValue={defaultValue}
27
- rules={{
28
- onBlur,
29
- onChange,
30
- shouldUnregister,
31
- value,
32
- ...rules,
33
- }}
50
+ onBlur={onBlur}
51
+ onChange={onChange}
52
+ rules={rules}
34
53
  shouldUnregister={shouldUnregister}
35
- render={({ field: { onChange, value, onBlur }, fieldState: { error } }) => (
36
- <ProviderAutocomplete
37
- {...rest}
38
- FieldProps={{
39
- required: typeof rules.required === 'object' ? rules.required.value : !!rules.required,
40
- ...FieldProps,
41
- error: !!error,
42
- helperText: error?.message ? (
43
- <>
44
- {error.message}
45
- <br />
46
- {FieldProps?.helperText}
47
- </>
48
- ) : (
49
- FieldProps?.helperText
50
- ),
51
- }}
52
- onChange={(event, value, reason) => {
53
- if (reason === 'clear') {
54
- onChange(null);
55
- }
56
- onChange(value);
57
- }}
58
- onBlur={onBlur}
59
- value={value || null}
60
- />
61
- )}
54
+ value={value}
55
+ FieldProps={FieldProps}
56
+ getOptionLabel={handleGetProviderOptionLabel}
57
+ queryOptions={{ enabled: !!customerId }}
58
+ queryKey={queryKey}
59
+ watchParams={{ customerId }}
60
+ {...rest}
61
+ loadOptions={handleLoadOptions}
62
62
  />
63
63
  );
64
64
  };
package/src/lib/Types.tsx CHANGED
@@ -242,6 +242,8 @@ export const RadioGroupPropsCategorized: RadioGroupPropsObject = {
242
242
 
243
243
  export const ProviderAutocompletePropsCategorized: ProviderAutocompletePropsObject = {
244
244
  classes: { table: { category: 'Input Props' } },
245
+ defaultToFirstOption: { table: { category: 'Input Props' } },
246
+ defaultToOnlyOption: { table: { category: 'Input Props' } },
245
247
  id: { table: { category: 'Input Props' } },
246
248
  onKeyDown: { table: { category: 'Input Props' } },
247
249
  sx: { table: { category: 'Input Props' } },
@@ -297,6 +299,8 @@ export const ProviderAutocompletePropsCategorized: ProviderAutocompletePropsObje
297
299
 
298
300
  export const OrganizationAutocompletePropsCategorized: OrganizationAutocompletePropsObject = {
299
301
  classes: { table: { category: 'Input Props' } },
302
+ defaultToFirstOption: { table: { category: 'Input Props' } },
303
+ defaultToOnlyOption: { table: { category: 'Input Props' } },
300
304
  id: { table: { category: 'Input Props' } },
301
305
  onKeyDown: { table: { category: 'Input Props' } },
302
306
  sx: { table: { category: 'Input Props' } },
@@ -400,6 +404,8 @@ export const DatepickerPropsCategorized: DatepickerPropsObject = {
400
404
 
401
405
  export const CodesAutocompletePropsCategorized: CodesAutocompletePropsObject = {
402
406
  classes: { table: { category: 'Input Props' } },
407
+ defaultToFirstOption: { table: { category: 'Input Props' } },
408
+ defaultToOnlyOption: { table: { category: 'Input Props' } },
403
409
  id: { table: { category: 'Input Props' } },
404
410
  onKeyDown: { table: { category: 'Input Props' } },
405
411
  sx: { table: { category: 'Input Props' } },
@@ -455,6 +461,8 @@ export const CodesAutocompletePropsCategorized: CodesAutocompletePropsObject = {
455
461
 
456
462
  export const AsyncAutocompletePropsCategorized: AsyncAutocompletePropsObject = {
457
463
  classes: { table: { category: 'Input Props' } },
464
+ defaultToFirstOption: { table: { category: 'Input Props' } },
465
+ defaultToOnlyOption: { table: { category: 'Input Props' } },
458
466
  id: { table: { category: 'Input Props' } },
459
467
  onKeyDown: { table: { category: 'Input Props' } },
460
468
  sx: { table: { category: 'Input Props' } },
@@ -0,0 +1 @@
1
+ export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;