envoc-form 4.0.1-0 → 4.0.1-10

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 (136) hide show
  1. package/README.md +2 -2
  2. package/es/ConfirmBaseForm/ConfirmBaseForm.d.ts +3 -1
  3. package/es/ConfirmBaseForm/ConfirmBaseForm.js +3 -2
  4. package/es/ConfirmDeleteForm/ConfirmDeleteForm.js +2 -1
  5. package/es/DatePicker/DatePickerGroup.d.ts +9 -0
  6. package/es/DatePicker/DatePickerGroup.js +77 -0
  7. package/es/DatePicker/DatePickerHelper.d.ts +3 -0
  8. package/es/DatePicker/DatePickerHelper.js +1 -0
  9. package/es/DatePicker/StringDateOnlyPickerGroup.d.ts +5 -0
  10. package/es/DatePicker/StringDateOnlyPickerGroup.js +24 -0
  11. package/es/DatePicker/StringDatePickerGroup.d.ts +5 -0
  12. package/es/DatePicker/StringDatePickerGroup.js +19 -0
  13. package/es/Field/Field.d.ts +3 -3
  14. package/es/Field/Field.js +9 -4
  15. package/es/Field/StandAloneInput.d.ts +9 -0
  16. package/es/Field/StandAloneInput.js +49 -0
  17. package/es/FieldArray/FieldArray.js +10 -7
  18. package/es/File/FileGroup.js +5 -3
  19. package/es/File/FileList.js +2 -1
  20. package/es/Form/Form.d.ts +8 -3
  21. package/es/Form/Form.js +32 -3
  22. package/es/FormActions.js +5 -1
  23. package/es/FormDefaults.d.ts +3 -0
  24. package/es/FormDefaults.js +1 -0
  25. package/es/Group.d.ts +3 -2
  26. package/es/Group.js +8 -5
  27. package/es/Input/IconInputGroup.js +2 -1
  28. package/es/Input/InputGroup.d.ts +1 -1
  29. package/es/Input/InputGroup.js +3 -2
  30. package/es/Input/MoneyInputGroup.js +2 -1
  31. package/es/Input/NumberInputGroup.js +2 -1
  32. package/es/Input/StringInputGroup.d.ts +1 -1
  33. package/es/Input/StringInputGroup.js +2 -1
  34. package/es/Select/SelectGroup.d.ts +1 -1
  35. package/es/Select/SelectGroup.js +8 -3
  36. package/es/StandardFormActions.js +2 -1
  37. package/es/SubmitFormButton.js +4 -2
  38. package/es/TextArea/TextAreaGroup.d.ts +8 -0
  39. package/es/TextArea/TextAreaGroup.js +34 -0
  40. package/es/Validation/validators.d.ts +1 -1
  41. package/es/Validation/validators.js +1 -1
  42. package/es/__Tests__/FormTestBase.d.ts +3 -3
  43. package/es/index.d.ts +21 -5
  44. package/es/index.js +10 -1
  45. package/lib/ConfirmBaseForm/ConfirmBaseForm.d.ts +3 -1
  46. package/lib/ConfirmBaseForm/ConfirmBaseForm.js +3 -2
  47. package/lib/ConfirmDeleteForm/ConfirmDeleteForm.js +2 -1
  48. package/lib/DatePicker/DatePickerGroup.d.ts +9 -0
  49. package/lib/DatePicker/DatePickerGroup.js +85 -0
  50. package/lib/DatePicker/DatePickerHelper.d.ts +3 -0
  51. package/lib/DatePicker/DatePickerHelper.js +2 -0
  52. package/lib/DatePicker/StringDateOnlyPickerGroup.d.ts +5 -0
  53. package/lib/DatePicker/StringDateOnlyPickerGroup.js +30 -0
  54. package/lib/DatePicker/StringDatePickerGroup.d.ts +5 -0
  55. package/lib/DatePicker/StringDatePickerGroup.js +25 -0
  56. package/lib/Field/Field.d.ts +3 -3
  57. package/lib/Field/Field.js +9 -4
  58. package/lib/Field/StandAloneInput.d.ts +9 -0
  59. package/lib/Field/StandAloneInput.js +75 -0
  60. package/lib/FieldArray/FieldArray.js +10 -7
  61. package/lib/File/FileGroup.js +5 -3
  62. package/lib/File/FileList.js +2 -1
  63. package/lib/Form/Form.d.ts +8 -3
  64. package/lib/Form/Form.js +32 -3
  65. package/lib/FormActions.js +5 -1
  66. package/lib/FormDefaults.d.ts +3 -0
  67. package/lib/FormDefaults.js +4 -0
  68. package/lib/Group.d.ts +3 -2
  69. package/lib/Group.js +8 -5
  70. package/lib/Input/IconInputGroup.js +2 -1
  71. package/lib/Input/InputGroup.d.ts +1 -1
  72. package/lib/Input/InputGroup.js +3 -2
  73. package/lib/Input/MoneyInputGroup.js +2 -1
  74. package/lib/Input/NumberInputGroup.js +2 -1
  75. package/lib/Input/StringInputGroup.d.ts +1 -1
  76. package/lib/Input/StringInputGroup.js +2 -1
  77. package/lib/Select/SelectGroup.d.ts +1 -1
  78. package/lib/Select/SelectGroup.js +8 -3
  79. package/lib/StandardFormActions.js +2 -1
  80. package/lib/SubmitFormButton.js +4 -2
  81. package/lib/TextArea/TextAreaGroup.d.ts +8 -0
  82. package/lib/TextArea/TextAreaGroup.js +39 -0
  83. package/lib/Validation/validators.d.ts +1 -1
  84. package/lib/Validation/validators.js +1 -1
  85. package/lib/__Tests__/FormTestBase.d.ts +3 -3
  86. package/lib/index.d.ts +21 -5
  87. package/lib/index.js +19 -3
  88. package/package.json +4 -2
  89. package/src/AddressInput/__snapshots__/AddressInput.test.tsx.snap +15 -10
  90. package/src/ConfirmBaseForm/ConfirmBaseForm.tsx +13 -3
  91. package/src/ConfirmBaseForm/__snapshots__/ConfirmBaseForm.test.tsx.snap +3 -3
  92. package/src/ConfirmDeleteForm/ConfirmDeleteForm.tsx +8 -1
  93. package/src/ConfirmDeleteForm/__snapshots__/ConfirmDeleteForm.test.tsx.snap +2 -2
  94. package/src/{DatePickerInput/DatePickerInput.test.tsx → DatePicker/DatePicker.test.tsx} +3 -3
  95. package/src/DatePicker/DatePickerGroup.tsx +108 -0
  96. package/src/DatePicker/DatePickerHelper.ts +4 -0
  97. package/src/DatePicker/StringDateOnlyPickerGroup.tsx +23 -0
  98. package/src/DatePicker/StringDatePickerGroup.tsx +14 -0
  99. package/src/{DatePickerInput/__snapshots__/DatePickerInput.test.tsx.snap → DatePicker/__snapshots__/DatePicker.test.tsx.snap} +3 -2
  100. package/src/Field/Field.tsx +28 -10
  101. package/src/Field/StandAloneInput.tsx +51 -0
  102. package/src/FieldArray/FieldArray.tsx +21 -9
  103. package/src/File/FileGroup.tsx +14 -2
  104. package/src/File/FileList.tsx +3 -1
  105. package/src/File/__snapshots__/FileGroup.test.tsx.snap +5 -3
  106. package/src/Form/Form.tsx +56 -4
  107. package/src/Form/__snapshots__/Form.test.tsx.snap +1 -0
  108. package/src/FormActions.tsx +8 -2
  109. package/src/FormDefaults.ts +1 -0
  110. package/src/Group.tsx +22 -7
  111. package/src/Input/IconInputGroup.tsx +5 -2
  112. package/src/Input/InputGroup.tsx +11 -2
  113. package/src/Input/MoneyInputGroup.tsx +5 -1
  114. package/src/Input/NumberInputGroup.tsx +5 -1
  115. package/src/Input/StringInputGroup.tsx +14 -2
  116. package/src/Input/__Tests__/__snapshots__/IconInputGroup.test.tsx.snap +4 -2
  117. package/src/Input/__Tests__/__snapshots__/MoneyInputGroup.test.tsx.snap +4 -2
  118. package/src/Input/__Tests__/__snapshots__/NumberInputGroup.test.tsx.snap +4 -2
  119. package/src/Input/__Tests__/__snapshots__/StringInputGroup.test.tsx.snap +4 -2
  120. package/src/Select/SelectGroup.tsx +15 -3
  121. package/src/Select/__tests__/__snapshots__/BooleanSelectGroup.test.tsx.snap +3 -2
  122. package/src/Select/__tests__/__snapshots__/NumberSelectGroup.test.tsx.snap +6 -4
  123. package/src/Select/__tests__/__snapshots__/StringSelectGroup.test.tsx.snap +6 -4
  124. package/src/StandardFormActions.tsx +4 -1
  125. package/src/SubmitFormButton.tsx +7 -1
  126. package/src/TextArea/TextAreaGroup.tsx +64 -0
  127. package/src/Validation/validators.ts +2 -2
  128. package/src/__Tests__/FormTestBase.tsx +3 -3
  129. package/src/__Tests__/__snapshots__/StandardFormActions.test.tsx.snap +4 -2
  130. package/src/__Tests__/__snapshots__/SubmitFormButton.test.tsx.snap +3 -1
  131. package/src/index.ts +41 -5
  132. package/es/DatePickerInput/DatePickerInput.d.ts +0 -14
  133. package/es/DatePickerInput/DatePickerInput.js +0 -63
  134. package/lib/DatePickerInput/DatePickerInput.d.ts +0 -14
  135. package/lib/DatePickerInput/DatePickerInput.js +0 -69
  136. package/src/DatePickerInput/DatePickerInput.tsx +0 -85
@@ -0,0 +1,51 @@
1
+ import { ElementType, useRef } from 'react';
2
+ import * as uuid from 'uuid';
3
+ import { CustomFieldInputProps } from './CustomFieldInputProps';
4
+ import { CustomFieldMetaProps } from './CustomFieldMetaProps';
5
+ import { RenderComponent, RenderComponentProps } from './Field';
6
+ import { InjectedFieldProps } from './InjectedFieldProps';
7
+
8
+ export type StandAloneInputProps<
9
+ TValue,
10
+ TRenderComponent extends ElementType
11
+ > = {
12
+ Component: RenderComponent<TValue, TRenderComponent>;
13
+ value: TValue;
14
+ onChange: (arg: TValue) => void;
15
+ } & Omit<
16
+ RenderComponentProps<TValue, TRenderComponent>,
17
+ | keyof InjectedFieldProps<TValue>
18
+ | 'value'
19
+ | 'onChange'
20
+ | 'normalize'
21
+ | 'validate'
22
+ >;
23
+
24
+ export default function StandAloneInput<TValue, TComponent extends ElementType>(
25
+ props: StandAloneInputProps<TValue, TComponent>
26
+ ) {
27
+ const { Component, value, onChange, disabled, ...rest } = props;
28
+ const handleChange = (arg: TValue) => {
29
+ if (!disabled) {
30
+ onChange(arg);
31
+ }
32
+ };
33
+ const Wrapped = Component as React.ComponentType<InjectedFieldProps<TValue>>;
34
+ const idRef = useRef(uuid.v4());
35
+ const input: CustomFieldInputProps<TValue> = {
36
+ id: idRef.current,
37
+ name: idRef.current,
38
+ value: value,
39
+ onChange: handleChange,
40
+ onBlur: () => {},
41
+ };
42
+
43
+ const meta: CustomFieldMetaProps<TValue> = {
44
+ warning: undefined,
45
+ value: value,
46
+ touched: false,
47
+ initialTouched: false,
48
+ };
49
+
50
+ return <Wrapped {...rest} disabled={disabled} input={input} meta={meta} />;
51
+ }
@@ -4,6 +4,7 @@ import Field, { FieldProps } from '../Field/Field';
4
4
  import { FieldNameContext } from '../Field/FieldNameContext';
5
5
  import useStandardFormInput from '../Field/useStandardField';
6
6
  import { ValidationFunction } from '../Validation/ValidationFunction';
7
+ import { FormDefaults } from '../FormDefaults';
7
8
 
8
9
  export type FieldArrayProps<
9
10
  TForm extends object,
@@ -64,18 +65,23 @@ export default function FieldArray<
64
65
  : [];
65
66
 
66
67
  return (
67
- <div className="field-array">
68
- <div className="field-array-header">
69
- <div className="field-array-title">{label}</div>
68
+ <div className={FormDefaults.cssClassPrefix + 'field-array'}>
69
+ <div className={FormDefaults.cssClassPrefix + 'field-array-header'}>
70
+ <div className={FormDefaults.cssClassPrefix + 'field-array-title'}>
71
+ {label}
72
+ </div>
70
73
  <button
71
- className={classNames('add-array-item-button', { disabled })}
74
+ className={classNames(
75
+ FormDefaults.cssClassPrefix + 'add-array-item-button',
76
+ { [FormDefaults.cssClassPrefix + 'disabled']: disabled }
77
+ )}
72
78
  title="Add Item"
73
79
  type="button"
74
80
  onClick={addItem}>
75
81
  +
76
82
  </button>
77
83
  </div>
78
- <div className="field-array-body">
84
+ <div className={FormDefaults.cssClassPrefix + 'field-array-body'}>
79
85
  {values.map((value, index) => {
80
86
  const itemName = `${input.name}[${index}]`;
81
87
  return (
@@ -85,9 +91,12 @@ export default function FieldArray<
85
91
  (value && value['id']) ||
86
92
  itemName
87
93
  }
88
- className={classNames('field-array-item', {
89
- removed: value.isDeleted,
90
- })}
94
+ className={classNames(
95
+ FormDefaults.cssClassPrefix + 'field-array-item',
96
+ {
97
+ [FormDefaults.cssClassPrefix + 'removed']: value.isDeleted,
98
+ }
99
+ )}
91
100
  role="listitem">
92
101
  <FieldNameContext.Provider value={itemName}>
93
102
  {children({
@@ -96,7 +105,10 @@ export default function FieldArray<
96
105
  } as any)}
97
106
  </FieldNameContext.Provider>
98
107
  <button
99
- className={classNames('remove-array-item-button', { disabled })}
108
+ className={classNames(
109
+ FormDefaults.cssClassPrefix + 'remove-array-item-button',
110
+ { [FormDefaults.cssClassPrefix + 'disabled']: disabled }
111
+ )}
100
112
  type="button"
101
113
  title="Remove Item"
102
114
  onClick={() => removeItem(value)}>
@@ -3,6 +3,7 @@ import classNames from 'classnames';
3
3
  import FileList from './FileList';
4
4
  import { InjectedFieldProps } from '../Field/InjectedFieldProps';
5
5
  import Group, { GroupProps } from '../Group';
6
+ import { FormDefaults } from '../FormDefaults';
6
7
 
7
8
  export interface FileGroupProps
8
9
  // note: file props are of type "any" with the current type generation
@@ -22,6 +23,8 @@ function FileGroup(
22
23
  label,
23
24
  helpText,
24
25
  className,
26
+ required,
27
+ disabled,
25
28
  multiple,
26
29
  ...rest
27
30
  }: FileGroupProps,
@@ -33,7 +36,13 @@ function FileGroup(
33
36
  meta={meta}
34
37
  label={label}
35
38
  helpText={helpText}
36
- className={classNames(className, { multiple }, 'file-group')}>
39
+ className={classNames(
40
+ className,
41
+ { [FormDefaults.cssClassPrefix + 'multiple']: multiple },
42
+ FormDefaults.cssClassPrefix + 'file-group'
43
+ )}
44
+ required={required}
45
+ disabled={disabled}>
37
46
  <input
38
47
  {...input}
39
48
  {...rest}
@@ -56,7 +65,10 @@ function FileGroup(
56
65
  value={undefined}
57
66
  ref={ref}
58
67
  type="file"
59
- className={classNames(className, 'file-group')}
68
+ className={classNames(
69
+ className,
70
+ FormDefaults.cssClassPrefix + 'file-group'
71
+ )}
60
72
  />
61
73
  {/* Note: because input.value is any - due to how files are currently handled - type safeness isn't great here */}
62
74
  <FileList files={input.value} />
@@ -1,10 +1,12 @@
1
+ import { FormDefaults } from '../FormDefaults';
2
+
1
3
  export interface FileListProps {
2
4
  files?: File | File[] | undefined;
3
5
  rejectedFiles?: File | File[] | undefined;
4
6
  }
5
7
  export default function FileList({ files, rejectedFiles }: FileListProps) {
6
8
  return (
7
- <div className="file-list">
9
+ <div className={FormDefaults.cssClassPrefix + 'file-list'}>
8
10
  {!files ? null : Array.isArray(files) ? (
9
11
  files.map((x, i) => <File file={x} key={i} />)
10
12
  ) : (
@@ -4,9 +4,10 @@ exports[`FileGroup has matching snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <form
6
6
  action="#"
7
+ class="envoc-form-form"
7
8
  >
8
9
  <div
9
- class="file-group group"
10
+ class="envoc-form-file-group envoc-form-group"
10
11
  >
11
12
  <div
12
13
  id="profileimage-error-scroll-target"
@@ -18,13 +19,14 @@ exports[`FileGroup has matching snapshot 1`] = `
18
19
  Profile Image
19
20
  </label>
20
21
  <input
21
- class="file-group"
22
+ class="envoc-form-file-group"
23
+ id="profileImage"
22
24
  name="profileImage"
23
25
  type="file"
24
26
  value=""
25
27
  />
26
28
  <div
27
- class="file-list"
29
+ class="envoc-form-file-list"
28
30
  />
29
31
  </div>
30
32
  </form>
package/src/Form/Form.tsx CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  useMemo,
6
6
  useState,
7
7
  } from 'react';
8
+ import classNames from 'classnames';
8
9
  import {
9
10
  Form as FormikFormWrapper,
10
11
  Formik,
@@ -20,6 +21,7 @@ import {
20
21
  } from './ServerErrorContext';
21
22
  import Field, { FieldProps } from '../Field/Field';
22
23
  import FieldArray, { FieldArrayProps } from '../FieldArray/FieldArray';
24
+ import { FormDefaults } from '../FormDefaults';
23
25
  import objectContainsNonSerializableProperty from '../utils/objectContainsNonSerializableProperty';
24
26
  import objectToFormData from '../utils/objectToFormData';
25
27
  import { ValidatedApiResult } from '../Validation/ValidatedApiResult';
@@ -38,10 +40,14 @@ export type FormBuilderProp<TForm extends object> = {
38
40
  ) => JSX.Element;
39
41
  };
40
42
 
41
- export interface FormProps<TForm extends object> {
43
+ export interface FullFormProps<TForm extends object> {
42
44
  children: (formBuilder: FormBuilderProp<TForm>) => JSX.Element;
43
45
  onSubmit: (
44
- formValues: FormData | TForm,
46
+ formValues: TForm,
47
+ formikBag: FormikHelpers<TForm>
48
+ ) => Promise<ValidatedApiResult>;
49
+ onFormDataSubmit: (
50
+ formValues: FormData,
45
51
  formikBag: FormikHelpers<TForm>
46
52
  ) => Promise<ValidatedApiResult>;
47
53
  className?: string;
@@ -50,12 +56,26 @@ export interface FormProps<TForm extends object> {
50
56
  initialValues?: TForm;
51
57
  }
52
58
 
59
+ type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<
60
+ T,
61
+ Exclude<keyof T, Keys>
62
+ > &
63
+ {
64
+ [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
65
+ }[Keys];
66
+
67
+ export type FormProps<TForm extends object> = RequireAtLeastOne<
68
+ FullFormProps<TForm>,
69
+ 'onSubmit' | 'onFormDataSubmit'
70
+ >;
71
+
53
72
  export default function Form<TForm extends object>({
54
73
  children,
55
74
  className,
56
75
  style,
57
76
  ignoreLostChanges,
58
77
  onSubmit,
78
+ onFormDataSubmit,
59
79
  initialValues,
60
80
  ...props
61
81
  }: FormProps<TForm>) {
@@ -92,7 +112,12 @@ export default function Form<TForm extends object>({
92
112
  onSubmit={handleSubmit}
93
113
  {...props}>
94
114
  <ServerErrorContext.Provider value={serverErrorContextValue}>
95
- <FormikFormWrapper className={className} style={style}>
115
+ <FormikFormWrapper
116
+ className={classNames(
117
+ className,
118
+ FormDefaults.cssClassPrefix + 'form'
119
+ )}
120
+ style={style}>
96
121
  <FocusError serverErrors={serverErrorContextValue} />
97
122
  <FormBasedPreventNavigation ignoreLostChanges={ignoreLostChanges} />
98
123
  {children({
@@ -107,6 +132,7 @@ export default function Form<TForm extends object>({
107
132
 
108
133
  function handleSubmit(values: TForm, formikBag: FormikHelpers<TForm>) {
109
134
  let formData: FormData | undefined = undefined;
135
+ let submitFunc: () => Promise<ValidatedApiResult>;
110
136
  if (objectContainsNonSerializableProperty(values)) {
111
137
  formData = objectToFormData(values, {
112
138
  indices: true,
@@ -114,9 +140,35 @@ export default function Form<TForm extends object>({
114
140
  allowEmptyArrays: true,
115
141
  noFileListBrackets: true,
116
142
  });
143
+ if (onFormDataSubmit === undefined) {
144
+ throw new Error(
145
+ 'No onFormDataSubmit supplied for non-serializable properties.'
146
+ );
147
+ }
148
+ submitFunc = () =>
149
+ onFormDataSubmit(formData ?? new FormData(), formikBag);
150
+ } else {
151
+ if (onSubmit === undefined) {
152
+ formData = objectToFormData(values, {
153
+ indices: true,
154
+ dotNotation: true,
155
+ allowEmptyArrays: true,
156
+ noFileListBrackets: true,
157
+ });
158
+ if (onFormDataSubmit === undefined) {
159
+ // This error should never occur, as this case is covered by RequireAtLeastOne type safety
160
+ throw new Error(
161
+ 'No onFormDataSubmit supplied for non-serializable properties.'
162
+ );
163
+ }
164
+ submitFunc = () =>
165
+ onFormDataSubmit(formData ?? new FormData(), formikBag);
166
+ } else {
167
+ submitFunc = () => onSubmit(values, formikBag);
168
+ }
117
169
  }
118
170
 
119
- return onSubmit(formData ?? values, formikBag)
171
+ return submitFunc()
120
172
  .then((response) => {
121
173
  return response;
122
174
  })
@@ -4,6 +4,7 @@ exports[`FormTestBase has matching snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <form
6
6
  action="#"
7
+ class="envoc-form-form"
7
8
  />
8
9
  </DocumentFragment>
9
10
  `;
@@ -1,3 +1,4 @@
1
+ import { FormDefaults } from './FormDefaults';
1
2
  import { useFormikContext } from 'formik';
2
3
  import SubmitFormButton from './SubmitFormButton';
3
4
 
@@ -15,13 +16,18 @@ export default function FormActions({
15
16
  return (
16
17
  <>
17
18
  <SubmitFormButton
18
- className="form-actions"
19
+ className={FormDefaults.cssClassPrefix + 'form-actions'}
19
20
  allowPristineSubmit={allowPristineSubmit}
20
21
  disabled={disabled}
21
22
  />
22
23
  <button
23
24
  type="button"
24
- className="form-actions cancel-form-button"
25
+ className={
26
+ FormDefaults.cssClassPrefix +
27
+ 'form-actions ' +
28
+ FormDefaults.cssClassPrefix +
29
+ 'cancel-form-button'
30
+ }
25
31
  disabled={isSubmitting || disabled}
26
32
  onClick={handleCancel || goBack}>
27
33
  Cancel
@@ -0,0 +1 @@
1
+ export const FormDefaults = { cssClassPrefix: 'envoc-form-' };
package/src/Group.tsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import classNames from 'classnames';
2
+ import { FormDefaults } from './FormDefaults';
2
3
  import FieldErrorScrollTarget from './Field/FieldErrorScrollTarget';
3
4
  import { InjectedFieldProps } from './Field/InjectedFieldProps';
4
5
 
@@ -11,9 +12,11 @@ export interface GroupProps extends InjectedFieldProps<any> {
11
12
  label?: string;
12
13
 
13
14
  /** simple helper text after the input*/
14
- helpText?: string;
15
+ helpText?: string | React.ReactNode;
15
16
 
16
17
  disabled?: boolean;
18
+
19
+ required?: boolean;
17
20
  }
18
21
 
19
22
  /** contains standard field bits like a label, helper text, error scroll target, validation message container, etc */
@@ -25,19 +28,31 @@ export default function Group({
25
28
  meta,
26
29
  input,
27
30
  disabled,
31
+ required,
28
32
  }: GroupProps) {
29
33
  return (
30
34
  <div
31
- className={classNames(className, 'group', {
32
- 'is-invalid': meta.error,
33
- disabled: disabled,
35
+ className={classNames(className, FormDefaults.cssClassPrefix + 'group', {
36
+ [FormDefaults.cssClassPrefix + 'invalid']: meta.error,
37
+ [FormDefaults.cssClassPrefix + 'disabled']: disabled,
38
+ [FormDefaults.cssClassPrefix + 'required']: required,
34
39
  })}>
35
40
  <FieldErrorScrollTarget />
36
- {meta.warning && <div className="warning">{meta.warning}</div>}
41
+ {meta.warning && (
42
+ <div className={FormDefaults.cssClassPrefix + 'warning'}>
43
+ {meta.warning}
44
+ </div>
45
+ )}
37
46
  <label htmlFor={input.id}>{label}</label>
38
47
  {children}
39
- {meta.error && <div className="error">{meta.error}</div>}
40
- {helpText && <div className="help">{helpText}</div>}
48
+ {meta.error && (
49
+ <div className={FormDefaults.cssClassPrefix + 'error'}>
50
+ {meta.error}
51
+ </div>
52
+ )}
53
+ {helpText && (
54
+ <div className={FormDefaults.cssClassPrefix + 'help'}>{helpText}</div>
55
+ )}
41
56
  </div>
42
57
  );
43
58
  }
@@ -1,7 +1,7 @@
1
1
  import React, { LegacyRef } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import InputGroupWithRef, { InputGroupProps } from './InputGroup';
4
- import useStandardFormInput from '../Field/useStandardField';
4
+ import { FormDefaults } from '../FormDefaults';
5
5
 
6
6
  // TODO: make className tailwind-able instead of css. make it typeof string ????
7
7
  // or should we just give a div a className and let each project decide? (this seems to be the patern)
@@ -26,7 +26,10 @@ function IconInputGroup(
26
26
  <InputGroupWithRef
27
27
  icon={icon}
28
28
  ref={ref}
29
- className={classNames(className, 'icon-input-group')}
29
+ className={classNames(
30
+ className,
31
+ FormDefaults.cssClassPrefix + 'icon-input-group'
32
+ )}
30
33
  value={input.value || ''}
31
34
  onChange={(e) => {
32
35
  if (!e.target.value) {
@@ -2,6 +2,7 @@ import React, { ChangeEventHandler, LegacyRef } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import { InjectedFieldProps } from '../Field/InjectedFieldProps';
4
4
  import Group, { GroupProps } from '../Group';
5
+ import { FormDefaults } from '../FormDefaults';
5
6
 
6
7
  export interface InputGroupProps<TValue>
7
8
  extends InjectedFieldProps<TValue>,
@@ -23,6 +24,7 @@ function InputGroup<TValue>(
23
24
  label,
24
25
  helpText,
25
26
  className,
27
+ required,
26
28
  disabled,
27
29
  onChange,
28
30
  value,
@@ -35,10 +37,14 @@ function InputGroup<TValue>(
35
37
  <Group
36
38
  input={input}
37
39
  meta={meta}
40
+ required={required}
38
41
  disabled={disabled}
39
42
  label={label}
40
43
  helpText={helpText}
41
- className={classNames(className, 'input-group')}>
44
+ className={classNames(
45
+ className,
46
+ FormDefaults.cssClassPrefix + 'input-group'
47
+ )}>
42
48
  {icon}
43
49
  <input
44
50
  {...input}
@@ -46,7 +52,10 @@ function InputGroup<TValue>(
46
52
  value={value}
47
53
  onChange={onChange}
48
54
  ref={ref}
49
- className={classNames(className, 'input-group')}
55
+ className={classNames(
56
+ className,
57
+ FormDefaults.cssClassPrefix + 'input-group'
58
+ )}
50
59
  />
51
60
  </Group>
52
61
  );
@@ -1,6 +1,7 @@
1
1
  import React, { LegacyRef } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import InputGroup, { InputGroupProps } from './InputGroup';
4
+ import { FormDefaults } from '../FormDefaults';
4
5
 
5
6
  export interface MoneyInputGroupProps
6
7
  extends Omit<
@@ -24,7 +25,10 @@ function MoneyInputGroup(
24
25
  min={0}
25
26
  {...rest}
26
27
  type="number"
27
- className={classNames(className, 'money-group')}
28
+ className={classNames(
29
+ className,
30
+ FormDefaults.cssClassPrefix + 'money-group'
31
+ )}
28
32
  value={input.value || ''}
29
33
  onChange={(e) => {
30
34
  if (!e.target.value) {
@@ -1,6 +1,7 @@
1
1
  import React, { LegacyRef } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import InputGroup, { InputGroupProps } from './InputGroup';
4
+ import { FormDefaults } from '../FormDefaults';
4
5
 
5
6
  export interface NumberInputGroupProps
6
7
  extends Omit<
@@ -22,7 +23,10 @@ function NumberInputGroup(
22
23
  ref={ref}
23
24
  {...rest}
24
25
  type="number"
25
- className={classNames(className, 'number-group')}
26
+ className={classNames(
27
+ className,
28
+ FormDefaults.cssClassPrefix + 'number-group'
29
+ )}
26
30
  value={input.value || ''}
27
31
  onChange={(e) => {
28
32
  if (!e.target.value) {
@@ -1,13 +1,22 @@
1
1
  import React, { LegacyRef } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import InputGroup, { InputGroupProps } from './InputGroup';
4
+ import { FormDefaults } from '../FormDefaults';
4
5
 
5
6
  export interface StringInputGroupProps
6
7
  extends Omit<
7
8
  InputGroupProps<string | undefined>,
8
9
  'onChange' | 'type' | 'value'
9
10
  > {
10
- type?: 'color' | 'email' | 'search' | 'tel' | 'text' | 'url';
11
+ type?:
12
+ | 'color'
13
+ | 'email'
14
+ | 'search'
15
+ | 'tel'
16
+ | 'text'
17
+ | 'url'
18
+ | 'password'
19
+ | 'textarea';
11
20
  }
12
21
 
13
22
  function StringInputGroup(
@@ -20,7 +29,10 @@ function StringInputGroup(
20
29
  <InputGroup
21
30
  ref={ref}
22
31
  {...rest}
23
- className={classNames(className, 'string-group')}
32
+ className={classNames(
33
+ className,
34
+ FormDefaults.cssClassPrefix + 'string-group'
35
+ )}
24
36
  value={input.value || ''}
25
37
  onChange={(e) => {
26
38
  if (!e.target.value) {
@@ -4,9 +4,10 @@ exports[`IconInputGroup has matching snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <form
6
6
  action="#"
7
+ class="envoc-form-form"
7
8
  >
8
9
  <div
9
- class="icon-input-group input-group group"
10
+ class="envoc-form-icon-input-group envoc-form-input-group envoc-form-group"
10
11
  >
11
12
  <div
12
13
  id="namewithicon-error-scroll-target"
@@ -19,7 +20,8 @@ exports[`IconInputGroup has matching snapshot 1`] = `
19
20
  Pretend this is an icon
20
21
  </span>
21
22
  <input
22
- class="icon-input-group input-group"
23
+ class="envoc-form-icon-input-group envoc-form-input-group"
24
+ id="nameWithIcon"
23
25
  name="nameWithIcon"
24
26
  value=""
25
27
  />
@@ -4,9 +4,10 @@ exports[`MoneyInputGroup has matching snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <form
6
6
  action="#"
7
+ class="envoc-form-form"
7
8
  >
8
9
  <div
9
- class="something-here money-group input-group group"
10
+ class="something-here envoc-form-money-group envoc-form-input-group envoc-form-group"
10
11
  >
11
12
  <div
12
13
  id="yearlysalaryusd-error-scroll-target"
@@ -18,7 +19,8 @@ exports[`MoneyInputGroup has matching snapshot 1`] = `
18
19
  Salary
19
20
  </label>
20
21
  <input
21
- class="something-here money-group input-group"
22
+ class="something-here envoc-form-money-group envoc-form-input-group"
23
+ id="yearlySalaryUSD"
22
24
  min="0"
23
25
  name="yearlySalaryUSD"
24
26
  step="0.01"
@@ -4,9 +4,10 @@ exports[`NumberInputGroup has matching snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <form
6
6
  action="#"
7
+ class="envoc-form-form"
7
8
  >
8
9
  <div
9
- class="number-group input-group group"
10
+ class="envoc-form-number-group envoc-form-input-group envoc-form-group"
10
11
  >
11
12
  <div
12
13
  id="numberofarms-error-scroll-target"
@@ -18,7 +19,8 @@ exports[`NumberInputGroup has matching snapshot 1`] = `
18
19
  Arm Count
19
20
  </label>
20
21
  <input
21
- class="number-group input-group"
22
+ class="envoc-form-number-group envoc-form-input-group"
23
+ id="numberOfArms"
22
24
  name="numberOfArms"
23
25
  type="number"
24
26
  value=""
@@ -4,9 +4,10 @@ exports[`StringInputGroup has matching snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <form
6
6
  action="#"
7
+ class="envoc-form-form"
7
8
  >
8
9
  <div
9
- class="string-group input-group group"
10
+ class="envoc-form-string-group envoc-form-input-group envoc-form-group"
10
11
  >
11
12
  <div
12
13
  id="name-error-scroll-target"
@@ -18,7 +19,8 @@ exports[`StringInputGroup has matching snapshot 1`] = `
18
19
  Name
19
20
  </label>
20
21
  <input
21
- class="string-group input-group"
22
+ class="envoc-form-string-group envoc-form-input-group"
23
+ id="name"
22
24
  name="name"
23
25
  value=""
24
26
  />