envoc-form 5.0.3 → 5.0.6

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 (145) hide show
  1. package/README.md +163 -20
  2. package/es/ConfirmBaseForm/ConfirmBaseForm.js +2 -2
  3. package/es/DatePicker/DatePickerGroup.js +2 -2
  4. package/es/FieldArray/FieldArray.js +4 -4
  5. package/es/File/FileGroup.js +3 -3
  6. package/es/Form/Form.js +2 -2
  7. package/es/Group.js +3 -3
  8. package/es/Input/CheckboxGroup.d.ts +6 -0
  9. package/es/Input/CheckboxGroup.js +14 -0
  10. package/es/Input/CheckboxInputGroup.d.ts +13 -0
  11. package/es/Input/CheckboxInputGroup.js +41 -0
  12. package/es/Input/IconInputGroup.js +2 -2
  13. package/es/Input/InputGroup.js +2 -2
  14. package/es/Input/MoneyInputGroup.js +2 -2
  15. package/es/Input/NumberInputGroup.js +2 -2
  16. package/es/Input/PhoneNumberInputGroup.js +2 -2
  17. package/es/Input/StringInputGroup.js +2 -2
  18. package/es/Select/SelectGroup.js +3 -3
  19. package/es/StandardFormActions.js +3 -3
  20. package/es/SubmitFormButton.js +2 -2
  21. package/es/TextArea/TextAreaGroup.js +2 -2
  22. package/es/index.d.ts +2 -0
  23. package/es/index.js +1 -0
  24. package/lib/ConfirmBaseForm/ConfirmBaseForm.js +2 -5
  25. package/lib/DatePicker/DatePickerGroup.js +2 -2
  26. package/lib/FieldArray/FieldArray.js +4 -4
  27. package/lib/File/FileGroup.js +3 -3
  28. package/lib/Form/Form.js +2 -2
  29. package/lib/Group.js +3 -3
  30. package/lib/Input/CheckboxGroup.d.ts +6 -0
  31. package/lib/Input/CheckboxGroup.js +20 -0
  32. package/lib/Input/CheckboxInputGroup.d.ts +13 -0
  33. package/lib/Input/CheckboxInputGroup.js +46 -0
  34. package/lib/Input/IconInputGroup.js +2 -2
  35. package/lib/Input/InputGroup.js +2 -2
  36. package/lib/Input/MoneyInputGroup.js +2 -2
  37. package/lib/Input/NumberInputGroup.js +2 -2
  38. package/lib/Input/PhoneNumberInputGroup.js +2 -2
  39. package/lib/Input/StringInputGroup.js +2 -2
  40. package/lib/Select/SelectGroup.js +3 -3
  41. package/lib/StandardFormActions.js +3 -3
  42. package/lib/SubmitFormButton.js +2 -2
  43. package/lib/TextArea/TextAreaGroup.js +2 -2
  44. package/lib/index.d.ts +2 -0
  45. package/lib/index.js +3 -1
  46. package/package.json +111 -111
  47. package/src/AddressInput/AddressInput.test.tsx +27 -27
  48. package/src/AddressInput/AddressInput.tsx +82 -82
  49. package/src/AddressInput/UsStates.ts +55 -55
  50. package/src/AddressInput/__snapshots__/AddressInput.test.tsx.snap +182 -182
  51. package/src/ConfirmBaseForm/ConfirmBaseForm.test.tsx +24 -24
  52. package/src/ConfirmBaseForm/ConfirmBaseForm.tsx +74 -74
  53. package/src/ConfirmBaseForm/__snapshots__/ConfirmBaseForm.test.tsx.snap +23 -23
  54. package/src/ConfirmDeleteForm/ConfirmDeleteForm.test.tsx +24 -24
  55. package/src/ConfirmDeleteForm/ConfirmDeleteForm.tsx +87 -87
  56. package/src/ConfirmDeleteForm/__snapshots__/ConfirmDeleteForm.test.tsx.snap +25 -25
  57. package/src/DatePicker/DatePicker.test.tsx +48 -48
  58. package/src/DatePicker/DatePickerGroup.tsx +109 -115
  59. package/src/DatePicker/DatePickerHelper.ts +4 -4
  60. package/src/DatePicker/StringDateOnlyPickerGroup.tsx +28 -28
  61. package/src/DatePicker/StringDatePickerGroup.tsx +20 -20
  62. package/src/DatePicker/__snapshots__/DatePicker.test.tsx.snap +152 -152
  63. package/src/Field/CustomFieldInputProps.ts +10 -10
  64. package/src/Field/CustomFieldMetaProps.ts +5 -5
  65. package/src/Field/Field.tsx +113 -113
  66. package/src/Field/FieldErrorScrollTarget.tsx +12 -12
  67. package/src/Field/FieldNameContext.ts +6 -6
  68. package/src/Field/FieldSection.tsx +18 -18
  69. package/src/Field/InjectedFieldProps.ts +8 -8
  70. package/src/Field/StandAloneInput.tsx +55 -55
  71. package/src/Field/useStandardField.ts +125 -125
  72. package/src/FieldArray/FieldArray.tsx +154 -154
  73. package/src/File/FileGroup.test.tsx +35 -35
  74. package/src/File/FileGroup.tsx +82 -85
  75. package/src/File/FileList.tsx +21 -21
  76. package/src/File/__snapshots__/FileGroup.test.tsx.snap +34 -34
  77. package/src/File/humanFileSize.ts +8 -8
  78. package/src/Form/FocusError.tsx +55 -55
  79. package/src/Form/Form.test.tsx +14 -14
  80. package/src/Form/Form.tsx +234 -237
  81. package/src/Form/FormBasedPreventNavigation.tsx +56 -56
  82. package/src/Form/LegacyFormBasedPreventNavigation.tsx +77 -77
  83. package/src/Form/NewFormBasedPreventNavigation.tsx +59 -59
  84. package/src/Form/ServerErrorContext.ts +18 -18
  85. package/src/Form/__snapshots__/Form.test.tsx.snap +10 -10
  86. package/src/FormActions.tsx +47 -47
  87. package/src/FormDefaults.ts +2 -2
  88. package/src/Group.tsx +62 -62
  89. package/src/Input/CheckboxGroup.tsx +60 -0
  90. package/src/Input/CheckboxInputGroup.tsx +78 -0
  91. package/src/Input/IconInputGroup.tsx +54 -54
  92. package/src/Input/InputGroup.tsx +66 -72
  93. package/src/Input/MoneyInputGroup.tsx +47 -50
  94. package/src/Input/NumberInputGroup.tsx +45 -48
  95. package/src/Input/PhoneNumberInputGroup.tsx +45 -45
  96. package/src/Input/StringInputGroup.tsx +50 -53
  97. package/src/Input/__Tests__/CheckboxInputGroup.test.tsx +26 -0
  98. package/src/Input/__Tests__/IconInputGroup.test.tsx +35 -35
  99. package/src/Input/__Tests__/MoneyInputGroup.test.tsx +37 -37
  100. package/src/Input/__Tests__/NumberInputGroup.test.tsx +35 -35
  101. package/src/Input/__Tests__/PhoneNumberInputGroup.test.tsx +36 -36
  102. package/src/Input/__Tests__/StringInputGroup.test.tsx +27 -27
  103. package/src/Input/__Tests__/__snapshots__/CheckboxInputGroup.test.tsx.snap +33 -0
  104. package/src/Input/__Tests__/__snapshots__/IconInputGroup.test.tsx.snap +32 -32
  105. package/src/Input/__Tests__/__snapshots__/MoneyInputGroup.test.tsx.snap +34 -34
  106. package/src/Input/__Tests__/__snapshots__/NumberInputGroup.test.tsx.snap +32 -32
  107. package/src/Input/__Tests__/__snapshots__/PhoneNumberInputGroup.test.tsx.snap +33 -33
  108. package/src/Input/__Tests__/__snapshots__/StringInputGroup.test.tsx.snap +31 -31
  109. package/src/Normalization/NormalizationFunction.ts +4 -4
  110. package/src/Normalization/normalizers.ts +44 -44
  111. package/src/Select/BooleanSelectGroup.tsx +28 -28
  112. package/src/Select/NumberSelectGroup.tsx +16 -16
  113. package/src/Select/SelectGroup.tsx +124 -124
  114. package/src/Select/SelectGroupPropsHelper.ts +4 -4
  115. package/src/Select/StringSelectGroup.tsx +16 -16
  116. package/src/Select/__tests__/BooleanSelectGroup.test.tsx +35 -35
  117. package/src/Select/__tests__/NumberSelectGroup.test.tsx +87 -87
  118. package/src/Select/__tests__/StringSelectGroup.test.tsx +89 -89
  119. package/src/Select/__tests__/__snapshots__/BooleanSelectGroup.test.tsx.snap +98 -98
  120. package/src/Select/__tests__/__snapshots__/NumberSelectGroup.test.tsx.snap +195 -195
  121. package/src/Select/__tests__/__snapshots__/StringSelectGroup.test.tsx.snap +195 -195
  122. package/src/StandardFormActions.tsx +41 -41
  123. package/src/SubmitFormButton.tsx +54 -54
  124. package/src/TextArea/TextAreaGroup.tsx +64 -64
  125. package/src/Validation/ValidatedApiResult.ts +8 -8
  126. package/src/Validation/ValidationError.ts +6 -6
  127. package/src/Validation/ValidationFunction.ts +4 -4
  128. package/src/Validation/validators.test.tsx +81 -81
  129. package/src/Validation/validators.ts +97 -97
  130. package/src/__Tests__/FormTestBase.tsx +65 -64
  131. package/src/__Tests__/RealisticForm.test.tsx +82 -82
  132. package/src/__Tests__/StandardFormActions.test.tsx +17 -17
  133. package/src/__Tests__/SubmitFormButton.test.tsx +17 -17
  134. package/src/__Tests__/__snapshots__/StandardFormActions.test.tsx.snap +27 -27
  135. package/src/__Tests__/__snapshots__/SubmitFormButton.test.tsx.snap +20 -20
  136. package/src/__Tests__/index.ts +3 -3
  137. package/src/_variables.scss +11 -11
  138. package/src/index.ts +156 -153
  139. package/src/react-app-env.d.ts +1 -1
  140. package/src/setupTests.ts +1 -1
  141. package/src/utils/objectContainsNonSerializableProperty.test.tsx +49 -49
  142. package/src/utils/objectContainsNonSerializableProperty.ts +17 -17
  143. package/src/utils/objectToFormData.test.tsx +76 -76
  144. package/src/utils/objectToFormData.ts +105 -105
  145. package/src/utils/typeChecks.ts +18 -18
@@ -1,32 +1,32 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`NumberInputGroup has matching snapshot 1`] = `
4
- <DocumentFragment>
5
- <form
6
- action="#"
7
- class="envoc-form-form"
8
- >
9
- <div
10
- class="envoc-form-number-group envoc-form-input-group envoc-form-group"
11
- >
12
- <div
13
- id="numberofarms-error-scroll-target"
14
- style="display: none;"
15
- />
16
- <label
17
- for="numberOfArms"
18
- >
19
- Arm Count
20
- </label>
21
- <input
22
- aria-invalid="false"
23
- class="envoc-form-number-group envoc-form-input-group"
24
- id="numberOfArms"
25
- name="numberOfArms"
26
- type="number"
27
- value=""
28
- />
29
- </div>
30
- </form>
31
- </DocumentFragment>
32
- `;
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`NumberInputGroup has matching snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <form
6
+ action="#"
7
+ class="envoc-form-form"
8
+ >
9
+ <div
10
+ class="envoc-form-number-group envoc-form-input-group envoc-form-group"
11
+ >
12
+ <div
13
+ id="numberofarms-error-scroll-target"
14
+ style="display: none;"
15
+ />
16
+ <label
17
+ for="numberOfArms"
18
+ >
19
+ Arm Count
20
+ </label>
21
+ <input
22
+ aria-invalid="false"
23
+ class="envoc-form-number-group envoc-form-input-group"
24
+ id="numberOfArms"
25
+ name="numberOfArms"
26
+ type="number"
27
+ value=""
28
+ />
29
+ </div>
30
+ </form>
31
+ </DocumentFragment>
32
+ `;
@@ -1,33 +1,33 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`PhoneNumberInputGroup has matching snapshot 1`] = `
4
- <DocumentFragment>
5
- <form
6
- action="#"
7
- class="envoc-form-form"
8
- >
9
- <div
10
- class="something-here envoc-form-phone-number-group envoc-form-input-group envoc-form-group"
11
- >
12
- <div
13
- id="phonenumber-error-scroll-target"
14
- style="display: none;"
15
- />
16
- <label
17
- for="phoneNumber"
18
- >
19
- Phone Number
20
- </label>
21
- <input
22
- aria-invalid="false"
23
- autocomplete="tel-national"
24
- class="something-here envoc-form-phone-number-group envoc-form-input-group"
25
- id="phoneNumber"
26
- name="phoneNumber"
27
- type="text"
28
- value=""
29
- />
30
- </div>
31
- </form>
32
- </DocumentFragment>
33
- `;
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`PhoneNumberInputGroup has matching snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <form
6
+ action="#"
7
+ class="envoc-form-form"
8
+ >
9
+ <div
10
+ class="something-here envoc-form-phone-number-group envoc-form-input-group envoc-form-group"
11
+ >
12
+ <div
13
+ id="phonenumber-error-scroll-target"
14
+ style="display: none;"
15
+ />
16
+ <label
17
+ for="phoneNumber"
18
+ >
19
+ Phone Number
20
+ </label>
21
+ <input
22
+ aria-invalid="false"
23
+ autocomplete="tel-national"
24
+ class="something-here envoc-form-phone-number-group envoc-form-input-group"
25
+ id="phoneNumber"
26
+ name="phoneNumber"
27
+ type="text"
28
+ value=""
29
+ />
30
+ </div>
31
+ </form>
32
+ </DocumentFragment>
33
+ `;
@@ -1,31 +1,31 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`StringInputGroup has matching snapshot 1`] = `
4
- <DocumentFragment>
5
- <form
6
- action="#"
7
- class="envoc-form-form"
8
- >
9
- <div
10
- class="envoc-form-string-group envoc-form-input-group envoc-form-group"
11
- >
12
- <div
13
- id="name-error-scroll-target"
14
- style="display: none;"
15
- />
16
- <label
17
- for="name"
18
- >
19
- Name
20
- </label>
21
- <input
22
- aria-invalid="false"
23
- class="envoc-form-string-group envoc-form-input-group"
24
- id="name"
25
- name="name"
26
- value=""
27
- />
28
- </div>
29
- </form>
30
- </DocumentFragment>
31
- `;
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`StringInputGroup has matching snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <form
6
+ action="#"
7
+ class="envoc-form-form"
8
+ >
9
+ <div
10
+ class="envoc-form-string-group envoc-form-input-group envoc-form-group"
11
+ >
12
+ <div
13
+ id="name-error-scroll-target"
14
+ style="display: none;"
15
+ />
16
+ <label
17
+ for="name"
18
+ >
19
+ Name
20
+ </label>
21
+ <input
22
+ aria-invalid="false"
23
+ class="envoc-form-string-group envoc-form-input-group"
24
+ id="name"
25
+ name="name"
26
+ value=""
27
+ />
28
+ </div>
29
+ </form>
30
+ </DocumentFragment>
31
+ `;
@@ -1,4 +1,4 @@
1
- /** Normalization of values */
2
- export interface NormalizationFunction<TValue> {
3
- (value: TValue): TValue;
4
- }
1
+ /** Normalization of values */
2
+ export interface NormalizationFunction<TValue> {
3
+ (value: TValue): TValue;
4
+ }
@@ -1,44 +1,44 @@
1
- /** Normalizer for converting a string into a valid phone number. */
2
- export const phoneNumber = (value: string | undefined | null) => {
3
- if (!value) {
4
- return undefined;
5
- }
6
-
7
- const onlyNums = value.replace(/[^\d]/g, '');
8
- if (onlyNums.length <= 3) {
9
- return onlyNums;
10
- }
11
- if (onlyNums.length <= 7) {
12
- return `${onlyNums.slice(0, 3)}-${onlyNums.slice(3)}`;
13
- }
14
- if (onlyNums.length <= 10) {
15
- return `${onlyNums.slice(0, 3)}-${onlyNums.slice(3, 6)}-${onlyNums.slice(
16
- 6,
17
- 10
18
- )}`;
19
- }
20
- if (onlyNums.length <= 13) {
21
- const countryCodeLength = onlyNums.length - 10;
22
- return `+${onlyNums.slice(0, countryCodeLength)} ${onlyNums.slice(
23
- countryCodeLength,
24
- 3 + countryCodeLength
25
- )}-${onlyNums.slice(
26
- 3 + countryCodeLength,
27
- 6 + countryCodeLength
28
- )}-${onlyNums.slice(6 + countryCodeLength, onlyNums.length)}`;
29
- }
30
-
31
- return onlyNums;
32
- };
33
-
34
- /** Normalizer for converting a string into a valid zip code. Allows for XXXXX and XXXXX-XXXX format. */
35
- export const zipCode = (value: string | undefined | null) => {
36
- if (!value) {
37
- return undefined;
38
- }
39
- const onlyNums = value.replace(/[^\d]/g, '');
40
- if (onlyNums.length > 5) {
41
- return onlyNums.substring(0, 5) + '-' + onlyNums.substring(5, 9);
42
- }
43
- return onlyNums;
44
- };
1
+ /** Normalizer for converting a string into a valid phone number. */
2
+ export const phoneNumber = (value: string | undefined | null) => {
3
+ if (!value) {
4
+ return undefined;
5
+ }
6
+
7
+ const onlyNums = value.replace(/[^\d]/g, '');
8
+ if (onlyNums.length <= 3) {
9
+ return onlyNums;
10
+ }
11
+ if (onlyNums.length <= 7) {
12
+ return `${onlyNums.slice(0, 3)}-${onlyNums.slice(3)}`;
13
+ }
14
+ if (onlyNums.length <= 10) {
15
+ return `${onlyNums.slice(0, 3)}-${onlyNums.slice(3, 6)}-${onlyNums.slice(
16
+ 6,
17
+ 10
18
+ )}`;
19
+ }
20
+ if (onlyNums.length <= 13) {
21
+ const countryCodeLength = onlyNums.length - 10;
22
+ return `+${onlyNums.slice(0, countryCodeLength)} ${onlyNums.slice(
23
+ countryCodeLength,
24
+ 3 + countryCodeLength
25
+ )}-${onlyNums.slice(
26
+ 3 + countryCodeLength,
27
+ 6 + countryCodeLength
28
+ )}-${onlyNums.slice(6 + countryCodeLength, onlyNums.length)}`;
29
+ }
30
+
31
+ return onlyNums;
32
+ };
33
+
34
+ /** Normalizer for converting a string into a valid zip code. Allows for XXXXX and XXXXX-XXXX format. */
35
+ export const zipCode = (value: string | undefined | null) => {
36
+ if (!value) {
37
+ return undefined;
38
+ }
39
+ const onlyNums = value.replace(/[^\d]/g, '');
40
+ if (onlyNums.length > 5) {
41
+ return onlyNums.substring(0, 5) + '-' + onlyNums.substring(5, 9);
42
+ }
43
+ return onlyNums;
44
+ };
@@ -1,28 +1,28 @@
1
- import SelectGroup, { SelectOption } from './SelectGroup';
2
- import { SelectGroupPropsHelper } from './SelectGroupPropsHelper';
3
-
4
- const booleanOptions: SelectOption<boolean>[] = [
5
- {
6
- label: 'Yes',
7
- value: true,
8
- },
9
- {
10
- label: 'No',
11
- value: false,
12
- },
13
- ];
14
-
15
- export interface BooleanSelectGroupProps
16
- extends Omit<SelectGroupPropsHelper<boolean | undefined | null>, 'options'> {
17
- options?: SelectOption<boolean>[];
18
- }
19
- /** A `<SelectGroup/>` dropdown with two options. Default options are 'Yes' and 'No' with values of `true` and `false`. */
20
- export function BooleanSelectGroup(props: BooleanSelectGroupProps) {
21
- return (
22
- <SelectGroup
23
- multiple={false}
24
- {...props}
25
- options={props.options ?? booleanOptions}
26
- />
27
- );
28
- }
1
+ import SelectGroup, { SelectOption } from './SelectGroup';
2
+ import { SelectGroupPropsHelper } from './SelectGroupPropsHelper';
3
+
4
+ const booleanOptions: SelectOption<boolean>[] = [
5
+ {
6
+ label: 'Yes',
7
+ value: true,
8
+ },
9
+ {
10
+ label: 'No',
11
+ value: false,
12
+ },
13
+ ];
14
+
15
+ export interface BooleanSelectGroupProps
16
+ extends Omit<SelectGroupPropsHelper<boolean | undefined | null>, 'options'> {
17
+ options?: SelectOption<boolean>[];
18
+ }
19
+ /** A `<SelectGroup/>` dropdown with two options. Default options are 'Yes' and 'No' with values of `true` and `false`. */
20
+ export function BooleanSelectGroup(props: BooleanSelectGroupProps) {
21
+ return (
22
+ <SelectGroup
23
+ multiple={false}
24
+ {...props}
25
+ options={props.options ?? booleanOptions}
26
+ />
27
+ );
28
+ }
@@ -1,16 +1,16 @@
1
- import SelectGroup from './SelectGroup';
2
- import { SelectGroupPropsHelper } from './SelectGroupPropsHelper';
3
-
4
- export interface MultiNumberSelectGroupProps
5
- extends SelectGroupPropsHelper<number[] | undefined | null> {}
6
- /** A `<SelectGroup/>` dropdown with values as numbers. Many options can be selected at a time. */
7
- export function MultiNumberSelectGroup(props: MultiNumberSelectGroupProps) {
8
- return <SelectGroup multiple={true} {...props} />;
9
- }
10
-
11
- export interface SingleNumberSelectGroupProps
12
- extends SelectGroupPropsHelper<number | undefined | null> {}
13
- /** A `<SelectGroup/>` dropdown with values as numbers. Only one option can be selected at a time. */
14
- export function SingleNumberSelectGroup(props: SingleNumberSelectGroupProps) {
15
- return <SelectGroup multiple={false} {...props} />;
16
- }
1
+ import SelectGroup from './SelectGroup';
2
+ import { SelectGroupPropsHelper } from './SelectGroupPropsHelper';
3
+
4
+ export interface MultiNumberSelectGroupProps
5
+ extends SelectGroupPropsHelper<number[] | undefined | null> {}
6
+ /** A `<SelectGroup/>` dropdown with values as numbers. Many options can be selected at a time. */
7
+ export function MultiNumberSelectGroup(props: MultiNumberSelectGroupProps) {
8
+ return <SelectGroup multiple={true} {...props} />;
9
+ }
10
+
11
+ export interface SingleNumberSelectGroupProps
12
+ extends SelectGroupPropsHelper<number | undefined | null> {}
13
+ /** A `<SelectGroup/>` dropdown with values as numbers. Only one option can be selected at a time. */
14
+ export function SingleNumberSelectGroup(props: SingleNumberSelectGroupProps) {
15
+ return <SelectGroup multiple={false} {...props} />;
16
+ }
@@ -1,124 +1,124 @@
1
- import { default as ReactSelect } from 'react-select';
2
- import classNames from 'classnames';
3
- import { InjectedFieldProps } from '../Field/InjectedFieldProps';
4
- import { FormDefaults } from '../FormDefaults';
5
- import Group, { GroupProps } from '../Group';
6
-
7
- export interface SelectOption<TValue> {
8
- /** Value for the select. This will be sent to the API. */
9
- value: (TValue extends Array<infer P> ? P : TValue) | undefined;
10
- /** Label for the select. This is displayed to the user. */
11
- label: string;
12
- }
13
-
14
- // types roughly like the useService (envoc-core) result
15
- interface OptionsApiResult<TValue> {
16
- // we must apply Partial here because all results from template code gen are optional
17
- result?: Partial<SelectOption<TValue>>[];
18
- }
19
-
20
- interface OptionsUseServiceResult<TValue> {
21
- loading?: boolean;
22
- // we must apply Partial here because all results from template code gen are optional
23
- resp?: Partial<SelectOption<TValue>>[] | OptionsApiResult<TValue> | null;
24
- error?: any;
25
- }
26
-
27
- export interface SelectGroupProps<TValue>
28
- extends InjectedFieldProps<TValue | undefined | null>,
29
- Omit<GroupProps, 'input' | 'meta' | 'children'> {
30
- // allows for "useService" or other handles to control the data - including cache
31
- // TODO: do we still want a version of select that has a "url" or maybe a promise func or something?
32
- // eventually we can just add the shape of, say, useQuery (TanStack) to the union type
33
- /** Options for the dropdown. Includes the label and value. */
34
- options: SelectOption<TValue>[] | OptionsUseServiceResult<TValue>;
35
- /** Whether the user should be able to have multiple values selected. */
36
- multiple: TValue extends Array<any> ? true : false;
37
- /** Text diplayed when no value is selected. */
38
- placeholder?: string;
39
- }
40
-
41
- // TODO: we could also name this "ReactSelectGroup" or similar but the types are strongly defined now so kept the names consistent
42
- /** Generic select dropdown. Uses [react-select](https://react-select.com/home). */
43
- export default function SelectGroup<TValue>({
44
- input,
45
- meta,
46
- className,
47
- required,
48
- disabled,
49
- options,
50
- multiple,
51
- placeholder,
52
- ...rest
53
- }: SelectGroupProps<TValue>) {
54
- const effectiveOptions: Partial<SelectOption<TValue>>[] = !options
55
- ? []
56
- : Array.isArray(options)
57
- ? options
58
- : 'resp' in options &&
59
- !!options.resp &&
60
- 'result' in options.resp &&
61
- !!options.resp.result
62
- ? options.resp.result
63
- : 'resp' in options && !!options.resp && Array.isArray(options.resp)
64
- ? options.resp
65
- : [];
66
-
67
- const isLoading =
68
- (options && 'loading' in options && options.loading) || false;
69
-
70
- return (
71
- <Group
72
- {...rest}
73
- input={input}
74
- meta={meta}
75
- required={required}
76
- disabled={disabled}
77
- className={classNames(
78
- className,
79
- {
80
- [FormDefaults.cssClassPrefix + 'multiple']: multiple,
81
- [FormDefaults.cssClassPrefix + 'loading']: isLoading,
82
- },
83
- FormDefaults.cssClassPrefix + 'select-group'
84
- )}>
85
- <ReactSelect<
86
- Partial<SelectOption<TValue>>,
87
- TValue extends Array<any> ? true : false
88
- >
89
- inputId={input.id}
90
- isMulti={multiple}
91
- isDisabled={disabled}
92
- options={effectiveOptions}
93
- onBlur={input.onBlur}
94
- value={getValue()}
95
- onChange={(e: any) => {
96
- if (multiple === true) {
97
- input.onChange(e?.map((x: any) => x.value));
98
- } else {
99
- input.onChange(e?.value as any);
100
- }
101
- }}
102
- getOptionLabel={(option) => option?.label ?? ''}
103
- className={classNames(
104
- className,
105
- FormDefaults.cssClassPrefix + 'select-group'
106
- )}
107
- classNamePrefix="react-select"
108
- menuPortalTarget={document.body}
109
- menuPlacement="auto"
110
- placeholder={placeholder}
111
- />
112
- </Group>
113
- );
114
-
115
- function getValue() {
116
- if (multiple) {
117
- return effectiveOptions.filter(
118
- (o) =>
119
- Array.isArray(input.value) && !!input.value.find((x) => o.value === x)
120
- );
121
- }
122
- return effectiveOptions.find((o) => o.value === input.value);
123
- }
124
- }
1
+ import { default as ReactSelect } from 'react-select';
2
+ import { clsx } from 'clsx';
3
+ import { InjectedFieldProps } from '../Field/InjectedFieldProps';
4
+ import { FormDefaults } from '../FormDefaults';
5
+ import Group, { GroupProps } from '../Group';
6
+
7
+ export interface SelectOption<TValue> {
8
+ /** Value for the select. This will be sent to the API. */
9
+ value: (TValue extends Array<infer P> ? P : TValue) | undefined;
10
+ /** Label for the select. This is displayed to the user. */
11
+ label: string;
12
+ }
13
+
14
+ // types roughly like the useService (envoc-core) result
15
+ interface OptionsApiResult<TValue> {
16
+ // we must apply Partial here because all results from template code gen are optional
17
+ result?: Partial<SelectOption<TValue>>[];
18
+ }
19
+
20
+ interface OptionsUseServiceResult<TValue> {
21
+ loading?: boolean;
22
+ // we must apply Partial here because all results from template code gen are optional
23
+ resp?: Partial<SelectOption<TValue>>[] | OptionsApiResult<TValue> | null;
24
+ error?: any;
25
+ }
26
+
27
+ export interface SelectGroupProps<TValue>
28
+ extends InjectedFieldProps<TValue | undefined | null>,
29
+ Omit<GroupProps, 'input' | 'meta' | 'children'> {
30
+ // allows for "useService" or other handles to control the data - including cache
31
+ // TODO: do we still want a version of select that has a "url" or maybe a promise func or something?
32
+ // eventually we can just add the shape of, say, useQuery (TanStack) to the union type
33
+ /** Options for the dropdown. Includes the label and value. */
34
+ options: SelectOption<TValue>[] | OptionsUseServiceResult<TValue>;
35
+ /** Whether the user should be able to have multiple values selected. */
36
+ multiple: TValue extends Array<any> ? true : false;
37
+ /** Text diplayed when no value is selected. */
38
+ placeholder?: string;
39
+ }
40
+
41
+ // TODO: we could also name this "ReactSelectGroup" or similar but the types are strongly defined now so kept the names consistent
42
+ /** Generic select dropdown. Uses [react-select](https://react-select.com/home). */
43
+ export default function SelectGroup<TValue>({
44
+ input,
45
+ meta,
46
+ className,
47
+ required,
48
+ disabled,
49
+ options,
50
+ multiple,
51
+ placeholder,
52
+ ...rest
53
+ }: SelectGroupProps<TValue>) {
54
+ const effectiveOptions: Partial<SelectOption<TValue>>[] = !options
55
+ ? []
56
+ : Array.isArray(options)
57
+ ? options
58
+ : 'resp' in options &&
59
+ !!options.resp &&
60
+ 'result' in options.resp &&
61
+ !!options.resp.result
62
+ ? options.resp.result
63
+ : 'resp' in options && !!options.resp && Array.isArray(options.resp)
64
+ ? options.resp
65
+ : [];
66
+
67
+ const isLoading =
68
+ (options && 'loading' in options && options.loading) || false;
69
+
70
+ return (
71
+ <Group
72
+ {...rest}
73
+ input={input}
74
+ meta={meta}
75
+ required={required}
76
+ disabled={disabled}
77
+ className={clsx(
78
+ className,
79
+ {
80
+ [FormDefaults.cssClassPrefix + 'multiple']: multiple,
81
+ [FormDefaults.cssClassPrefix + 'loading']: isLoading,
82
+ },
83
+ FormDefaults.cssClassPrefix + 'select-group'
84
+ )}>
85
+ <ReactSelect<
86
+ Partial<SelectOption<TValue>>,
87
+ TValue extends Array<any> ? true : false
88
+ >
89
+ inputId={input.id}
90
+ isMulti={multiple}
91
+ isDisabled={disabled}
92
+ options={effectiveOptions}
93
+ onBlur={input.onBlur}
94
+ value={getValue()}
95
+ onChange={(e: any) => {
96
+ if (multiple === true) {
97
+ input.onChange(e?.map((x: any) => x.value));
98
+ } else {
99
+ input.onChange(e?.value as any);
100
+ }
101
+ }}
102
+ getOptionLabel={(option) => option?.label ?? ''}
103
+ className={clsx(
104
+ className,
105
+ FormDefaults.cssClassPrefix + 'select-group'
106
+ )}
107
+ classNamePrefix="react-select"
108
+ menuPortalTarget={document.body}
109
+ menuPlacement="auto"
110
+ placeholder={placeholder}
111
+ />
112
+ </Group>
113
+ );
114
+
115
+ function getValue() {
116
+ if (multiple) {
117
+ return effectiveOptions.filter(
118
+ (o) =>
119
+ Array.isArray(input.value) && !!input.value.find((x) => o.value === x)
120
+ );
121
+ }
122
+ return effectiveOptions.find((o) => o.value === input.value);
123
+ }
124
+ }
@@ -1,4 +1,4 @@
1
- import { SelectGroupProps } from './SelectGroup';
2
-
3
- export interface SelectGroupPropsHelper<T>
4
- extends Omit<SelectGroupProps<T>, 'multiple'> {}
1
+ import { SelectGroupProps } from './SelectGroup';
2
+
3
+ export interface SelectGroupPropsHelper<T>
4
+ extends Omit<SelectGroupProps<T>, 'multiple'> {}