@toptal/picasso-forms 6.0.5 → 7.1.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.
Files changed (237) hide show
  1. package/{dist-package/Autocomplete → Autocomplete}/Autocomplete.d.ts +0 -0
  2. package/{dist-package/Autocomplete → Autocomplete}/Autocomplete.js +0 -0
  3. package/{dist-package/Autocomplete → Autocomplete}/Autocomplete.js.map +0 -0
  4. package/{dist-package/Autocomplete → Autocomplete}/index.d.ts +0 -0
  5. package/{dist-package/Autocomplete → Autocomplete}/index.js +0 -0
  6. package/{dist-package/Autocomplete → Autocomplete}/index.js.map +0 -0
  7. package/{dist-package/ButtonCheckbox → ButtonCheckbox}/ButtonCheckbox.d.ts +0 -0
  8. package/{dist-package/ButtonCheckbox → ButtonCheckbox}/ButtonCheckbox.js +0 -0
  9. package/{dist-package/ButtonCheckbox → ButtonCheckbox}/ButtonCheckbox.js.map +0 -0
  10. package/{dist-package/ButtonCheckbox → ButtonCheckbox}/index.d.ts +0 -0
  11. package/{dist-package/ButtonCheckbox → ButtonCheckbox}/index.js +0 -0
  12. package/{dist-package/ButtonCheckbox → ButtonCheckbox}/index.js.map +0 -0
  13. package/{dist-package/ButtonRadio → ButtonRadio}/ButtonRadio.d.ts +0 -0
  14. package/{dist-package/ButtonRadio → ButtonRadio}/ButtonRadio.js +0 -0
  15. package/{dist-package/ButtonRadio → ButtonRadio}/ButtonRadio.js.map +0 -0
  16. package/{dist-package/ButtonRadio → ButtonRadio}/index.d.ts +0 -0
  17. package/{dist-package/ButtonRadio → ButtonRadio}/index.js +0 -0
  18. package/{dist-package/ButtonRadio → ButtonRadio}/index.js.map +0 -0
  19. package/{dist-package/Checkbox → Checkbox}/Checkbox.d.ts +0 -0
  20. package/{dist-package/Checkbox → Checkbox}/Checkbox.js +0 -0
  21. package/{dist-package/Checkbox → Checkbox}/Checkbox.js.map +0 -0
  22. package/{dist-package/Checkbox → Checkbox}/index.d.ts +0 -0
  23. package/{dist-package/Checkbox → Checkbox}/index.js +0 -0
  24. package/{dist-package/Checkbox → Checkbox}/index.js.map +0 -0
  25. package/{dist-package/CheckboxGroup → CheckboxGroup}/CheckboxGroup.d.ts +0 -0
  26. package/{dist-package/CheckboxGroup → CheckboxGroup}/CheckboxGroup.js +0 -0
  27. package/{dist-package/CheckboxGroup → CheckboxGroup}/CheckboxGroup.js.map +0 -0
  28. package/{dist-package/CheckboxGroup → CheckboxGroup}/CheckboxGroupContext.d.ts +0 -0
  29. package/{dist-package/CheckboxGroup → CheckboxGroup}/CheckboxGroupContext.js +0 -0
  30. package/{dist-package/CheckboxGroup → CheckboxGroup}/CheckboxGroupContext.js.map +0 -0
  31. package/{dist-package/CheckboxGroup → CheckboxGroup}/index.d.ts +0 -0
  32. package/{dist-package/CheckboxGroup → CheckboxGroup}/index.js +0 -0
  33. package/{dist-package/CheckboxGroup → CheckboxGroup}/index.js.map +0 -0
  34. package/{dist-package/DatePicker → DatePicker}/DatePicker.d.ts +0 -0
  35. package/{dist-package/DatePicker → DatePicker}/DatePicker.js +0 -0
  36. package/{dist-package/DatePicker → DatePicker}/DatePicker.js.map +0 -0
  37. package/{dist-package/DatePicker → DatePicker}/index.d.ts +0 -0
  38. package/{dist-package/DatePicker → DatePicker}/index.js +0 -0
  39. package/{dist-package/DatePicker → DatePicker}/index.js.map +0 -0
  40. package/{dist-package/FieldWrapper → FieldWrapper}/FieldWrapper.d.ts +0 -0
  41. package/{dist-package/FieldWrapper → FieldWrapper}/FieldWrapper.js +0 -0
  42. package/{dist-package/FieldWrapper → FieldWrapper}/FieldWrapper.js.map +0 -0
  43. package/{dist-package/FieldWrapper → FieldWrapper}/index.d.ts +0 -0
  44. package/{dist-package/FieldWrapper → FieldWrapper}/index.js +0 -0
  45. package/{dist-package/FieldWrapper → FieldWrapper}/index.js.map +0 -0
  46. package/{dist-package/FileInput → FileInput}/FileInput.d.ts +0 -0
  47. package/{dist-package/FileInput → FileInput}/FileInput.js +0 -0
  48. package/{dist-package/FileInput → FileInput}/FileInput.js.map +0 -0
  49. package/{dist-package/FileInput → FileInput}/index.d.ts +0 -0
  50. package/{dist-package/FileInput → FileInput}/index.js +0 -0
  51. package/{dist-package/FileInput → FileInput}/index.js.map +0 -0
  52. package/{dist-package/Form → Form}/Form.d.ts +0 -0
  53. package/{dist-package/Form → Form}/Form.js +0 -0
  54. package/{dist-package/Form → Form}/Form.js.map +0 -0
  55. package/{dist-package/Form → Form}/FormContext.d.ts +0 -0
  56. package/{dist-package/Form → Form}/FormContext.js +0 -0
  57. package/{dist-package/Form → Form}/FormContext.js.map +0 -0
  58. package/{dist-package/Form → Form}/index.d.ts +0 -0
  59. package/{dist-package/Form → Form}/index.js +0 -0
  60. package/{dist-package/Form → Form}/index.js.map +0 -0
  61. package/{dist-package/FormConfig → FormConfig}/FormConfig.d.ts +0 -0
  62. package/{dist-package/FormConfig → FormConfig}/FormConfig.js +0 -0
  63. package/{dist-package/FormConfig → FormConfig}/FormConfig.js.map +0 -0
  64. package/{dist-package/FormConfig → FormConfig}/index.d.ts +0 -0
  65. package/{dist-package/FormConfig → FormConfig}/index.js +0 -0
  66. package/{dist-package/FormConfig → FormConfig}/index.js.map +0 -0
  67. package/{dist-package/Input → Input}/Input.d.ts +0 -0
  68. package/Input/Input.js +25 -0
  69. package/Input/Input.js.map +1 -0
  70. package/{dist-package/Input → Input}/index.d.ts +0 -0
  71. package/{dist-package/Input → Input}/index.js +0 -0
  72. package/{dist-package/Input → Input}/index.js.map +0 -0
  73. package/{dist-package/NumberInput → NumberInput}/NumberInput.d.ts +0 -0
  74. package/{dist-package/NumberInput → NumberInput}/NumberInput.js +0 -0
  75. package/{dist-package/NumberInput → NumberInput}/NumberInput.js.map +0 -0
  76. package/{dist-package/NumberInput → NumberInput}/index.d.ts +0 -0
  77. package/{dist-package/NumberInput → NumberInput}/index.js +0 -0
  78. package/{dist-package/NumberInput → NumberInput}/index.js.map +0 -0
  79. package/{dist-package/Radio → Radio}/Radio.d.ts +0 -0
  80. package/{dist-package/Radio → Radio}/Radio.js +0 -0
  81. package/{dist-package/Radio → Radio}/Radio.js.map +0 -0
  82. package/{dist-package/Radio → Radio}/index.d.ts +0 -0
  83. package/{dist-package/Radio → Radio}/index.js +0 -0
  84. package/{dist-package/Radio → Radio}/index.js.map +0 -0
  85. package/{dist-package/RadioGroup → RadioGroup}/RadioGroup.d.ts +0 -0
  86. package/{dist-package/RadioGroup → RadioGroup}/RadioGroup.js +0 -0
  87. package/{dist-package/RadioGroup → RadioGroup}/RadioGroup.js.map +0 -0
  88. package/{dist-package/RadioGroup → RadioGroup}/RadioGroupContext.d.ts +0 -0
  89. package/{dist-package/RadioGroup → RadioGroup}/RadioGroupContext.js +0 -0
  90. package/{dist-package/RadioGroup → RadioGroup}/RadioGroupContext.js.map +0 -0
  91. package/{dist-package/RadioGroup → RadioGroup}/index.d.ts +0 -0
  92. package/{dist-package/RadioGroup → RadioGroup}/index.js +0 -0
  93. package/{dist-package/RadioGroup → RadioGroup}/index.js.map +0 -0
  94. package/{dist-package/Rating → Rating}/Rating.d.ts +0 -0
  95. package/{dist-package/Rating → Rating}/Rating.js +0 -0
  96. package/{dist-package/Rating → Rating}/Rating.js.map +0 -0
  97. package/{dist-package/Rating → Rating}/index.d.ts +0 -0
  98. package/{dist-package/Rating → Rating}/index.js +0 -0
  99. package/{dist-package/Rating → Rating}/index.js.map +0 -0
  100. package/{dist-package/Select → Select}/Select.d.ts +0 -0
  101. package/{dist-package/Select → Select}/Select.js +0 -0
  102. package/{dist-package/Select → Select}/Select.js.map +0 -0
  103. package/{dist-package/Select → Select}/index.d.ts +0 -0
  104. package/{dist-package/Select → Select}/index.js +0 -0
  105. package/{dist-package/Select → Select}/index.js.map +0 -0
  106. package/{dist-package/SubmitButton → SubmitButton}/SubmitButton.d.ts +0 -0
  107. package/{dist-package/SubmitButton → SubmitButton}/SubmitButton.js +0 -0
  108. package/{dist-package/SubmitButton → SubmitButton}/SubmitButton.js.map +0 -0
  109. package/{dist-package/SubmitButton → SubmitButton}/index.d.ts +0 -0
  110. package/{dist-package/SubmitButton → SubmitButton}/index.js +0 -0
  111. package/{dist-package/SubmitButton → SubmitButton}/index.js.map +0 -0
  112. package/{dist-package/Switch → Switch}/Switch.d.ts +0 -0
  113. package/{dist-package/Switch → Switch}/Switch.js +0 -0
  114. package/{dist-package/Switch → Switch}/Switch.js.map +0 -0
  115. package/{dist-package/Switch → Switch}/index.d.ts +0 -0
  116. package/{dist-package/Switch → Switch}/index.js +0 -0
  117. package/{dist-package/Switch → Switch}/index.js.map +0 -0
  118. package/{dist-package/TagSelector → TagSelector}/TagSelector.d.ts +0 -0
  119. package/{dist-package/TagSelector → TagSelector}/TagSelector.js +0 -0
  120. package/{dist-package/TagSelector → TagSelector}/TagSelector.js.map +0 -0
  121. package/{dist-package/TagSelector → TagSelector}/index.d.ts +0 -0
  122. package/{dist-package/TagSelector → TagSelector}/index.js +0 -0
  123. package/{dist-package/TagSelector → TagSelector}/index.js.map +0 -0
  124. package/{dist-package/TimePicker → TimePicker}/TimePicker.d.ts +0 -0
  125. package/{dist-package/TimePicker → TimePicker}/TimePicker.js +0 -0
  126. package/{dist-package/TimePicker → TimePicker}/TimePicker.js.map +0 -0
  127. package/{dist-package/TimePicker → TimePicker}/index.d.ts +0 -0
  128. package/{dist-package/TimePicker → TimePicker}/index.js +0 -0
  129. package/{dist-package/TimePicker → TimePicker}/index.js.map +0 -0
  130. package/{dist-package/index.d.ts → index.d.ts} +0 -0
  131. package/{dist-package/index.js → index.js} +0 -0
  132. package/{dist-package/index.js.map → index.js.map} +0 -0
  133. package/package.json +6 -6
  134. package/{dist-package/utils → utils}/flat-map.d.ts +0 -0
  135. package/{dist-package/utils → utils}/flat-map.js +0 -0
  136. package/{dist-package/utils → utils}/flat-map.js.map +0 -0
  137. package/{dist-package/utils → utils}/index.d.ts +0 -0
  138. package/{dist-package/utils → utils}/index.js +0 -0
  139. package/{dist-package/utils → utils}/index.js.map +0 -0
  140. package/{dist-package/utils → utils}/scroll-to-error-decorator.d.ts +0 -0
  141. package/{dist-package/utils → utils}/scroll-to-error-decorator.js +0 -0
  142. package/{dist-package/utils → utils}/scroll-to-error-decorator.js.map +0 -0
  143. package/{dist-package/utils → utils}/validators.d.ts +0 -0
  144. package/{dist-package/utils → utils}/validators.js +0 -0
  145. package/{dist-package/utils → utils}/validators.js.map +0 -0
  146. package/CHANGELOG.md +0 -657
  147. package/dist-package/Input/Input.js +0 -26
  148. package/dist-package/Input/Input.js.map +0 -1
  149. package/dist-package/Input/utils/get-input-name.d.ts +0 -2
  150. package/dist-package/Input/utils/get-input-name.js +0 -9
  151. package/dist-package/Input/utils/get-input-name.js.map +0 -1
  152. package/dist-package/Input/utils/get-input-name.test.d.ts +0 -1
  153. package/dist-package/Input/utils/get-input-name.test.js +0 -12
  154. package/dist-package/Input/utils/get-input-name.test.js.map +0 -1
  155. package/dist-package/README.md +0 -29
  156. package/dist-package/package.json +0 -44
  157. package/src/Autocomplete/Autocomplete.tsx +0 -21
  158. package/src/Autocomplete/index.ts +0 -1
  159. package/src/ButtonCheckbox/ButtonCheckbox.tsx +0 -57
  160. package/src/ButtonCheckbox/index.ts +0 -1
  161. package/src/ButtonRadio/ButtonRadio.tsx +0 -24
  162. package/src/ButtonRadio/index.ts +0 -1
  163. package/src/Checkbox/Checkbox.tsx +0 -73
  164. package/src/Checkbox/__snapshots__/test.tsx.snap +0 -254
  165. package/src/Checkbox/index.ts +0 -1
  166. package/src/Checkbox/test.tsx +0 -91
  167. package/src/CheckboxGroup/CheckboxGroup.tsx +0 -30
  168. package/src/CheckboxGroup/CheckboxGroupContext.ts +0 -3
  169. package/src/CheckboxGroup/index.ts +0 -3
  170. package/src/CheckboxGroup/test.tsx +0 -35
  171. package/src/DatePicker/DatePicker.tsx +0 -26
  172. package/src/DatePicker/index.ts +0 -1
  173. package/src/FieldWrapper/FieldWrapper.tsx +0 -287
  174. package/src/FieldWrapper/index.ts +0 -2
  175. package/src/FieldWrapper/story/index.jsx +0 -137
  176. package/src/FileInput/FileInput.tsx +0 -66
  177. package/src/FileInput/index.ts +0 -1
  178. package/src/Form/Form.tsx +0 -181
  179. package/src/Form/FormContext.ts +0 -38
  180. package/src/Form/__image_snapshots__/form-default-snap.png +0 -0
  181. package/src/Form/__image_snapshots__/form-form-level-configurations-snap.png +0 -0
  182. package/src/Form/__snapshots__/test.tsx.snap +0 -61
  183. package/src/Form/index.ts +0 -1
  184. package/src/Form/story/BackendCommunication.example.tsx +0 -139
  185. package/src/Form/story/CustomFormLevelConfiguration.example.tsx +0 -26
  186. package/src/Form/story/CustomValidator.example.tsx +0 -45
  187. package/src/Form/story/Default.example.tsx +0 -177
  188. package/src/Form/story/FileInput.example.tsx +0 -42
  189. package/src/Form/story/ParseInput.example.tsx +0 -28
  190. package/src/Form/story/TitleCase.example.tsx +0 -167
  191. package/src/Form/story/ValidateOnSubmit.example.tsx +0 -85
  192. package/src/Form/story/index.jsx +0 -203
  193. package/src/Form/test.tsx +0 -27
  194. package/src/FormConfig/FormConfig.ts +0 -12
  195. package/src/FormConfig/index.ts +0 -1
  196. package/src/FormConfig/test.tsx +0 -44
  197. package/src/Input/Input.tsx +0 -27
  198. package/src/Input/index.ts +0 -1
  199. package/src/Input/test.tsx +0 -34
  200. package/src/Input/utils/get-input-name.test.ts +0 -16
  201. package/src/Input/utils/get-input-name.ts +0 -11
  202. package/src/NumberInput/NumberInput.tsx +0 -45
  203. package/src/NumberInput/index.ts +0 -1
  204. package/src/Radio/Radio.tsx +0 -24
  205. package/src/Radio/__snapshots__/test.tsx.snap +0 -231
  206. package/src/Radio/index.ts +0 -1
  207. package/src/Radio/test.tsx +0 -49
  208. package/src/RadioGroup/RadioGroup.tsx +0 -39
  209. package/src/RadioGroup/RadioGroupContext.ts +0 -3
  210. package/src/RadioGroup/index.ts +0 -3
  211. package/src/RadioGroup/test.tsx +0 -35
  212. package/src/Rating/Rating.tsx +0 -22
  213. package/src/Rating/index.ts +0 -1
  214. package/src/Select/Select.tsx +0 -47
  215. package/src/Select/index.ts +0 -1
  216. package/src/SubmitButton/SubmitButton.tsx +0 -70
  217. package/src/SubmitButton/__image_snapshots__/submitbutton-button-types-snap.png +0 -0
  218. package/src/SubmitButton/__image_snapshots__/submitbutton-default-snap.png +0 -0
  219. package/src/SubmitButton/index.ts +0 -6
  220. package/src/SubmitButton/story/ButtonTypes.example.tsx +0 -46
  221. package/src/SubmitButton/story/Default.example.tsx +0 -15
  222. package/src/SubmitButton/story/index.jsx +0 -32
  223. package/src/Switch/Switch.tsx +0 -23
  224. package/src/Switch/index.ts +0 -1
  225. package/src/TagSelector/TagSelector.tsx +0 -25
  226. package/src/TagSelector/index.ts +0 -1
  227. package/src/TimePicker/TimePicker.tsx +0 -24
  228. package/src/TimePicker/index.ts +0 -1
  229. package/src/index.ts +0 -16
  230. package/src/story/Deserialization.example.tsx +0 -34
  231. package/src/story/FormSpy.example.tsx +0 -42
  232. package/src/story/index.jsx +0 -37
  233. package/src/utils/flat-map.ts +0 -4
  234. package/src/utils/index.ts +0 -3
  235. package/src/utils/scroll-to-error-decorator.ts +0 -78
  236. package/src/utils/validators.ts +0 -18
  237. package/tsconfig.build.json +0 -7
package/src/Form/Form.tsx DELETED
@@ -1,181 +0,0 @@
1
- import React, { useMemo, ReactNode, useRef } from 'react'
2
- import {
3
- Form as FinalForm,
4
- FormProps as FinalFormProps
5
- } from 'react-final-form'
6
- import { FormApi, SubmissionErrors, getIn, setIn, AnyObject } from 'final-form'
7
- import { Form as PicassoForm, Container } from '@toptal/picasso'
8
- import { useNotifications } from '@toptal/picasso/utils'
9
-
10
- import Autocomplete from '../Autocomplete'
11
- import Input from '../Input'
12
- import Select from '../Select'
13
- import Radio from '../Radio'
14
- import ButtonRadio from '../ButtonRadio'
15
- import RadioGroup from '../RadioGroup'
16
- import Checkbox from '../Checkbox'
17
- import ButtonCheckbox from '../ButtonCheckbox'
18
- import CheckboxGroup from '../CheckboxGroup'
19
- import NumberInput from '../NumberInput'
20
- import FileInput from '../FileInput'
21
- import DatePicker from '../DatePicker'
22
- import TimePicker from '../TimePicker'
23
- import TagSelector from '../TagSelector'
24
- import SubmitButton from '../SubmitButton'
25
- import Switch from '../Switch'
26
- import Rating from '../Rating'
27
- import { FormConfigContext } from '../FormConfig'
28
- import { createScrollToErrorDecorator } from '../utils'
29
- import {
30
- FormContext,
31
- Validators,
32
- FormContextProps,
33
- createFormContext
34
- } from './FormContext'
35
-
36
- export type Props<T = AnyObject> = FinalFormProps<T> & {
37
- autoComplete?: HTMLFormElement['autocomplete']
38
- successSubmitMessage?: ReactNode
39
- failedSubmitMessage?: ReactNode
40
- scrollOffsetTop?: number
41
- 'data-testid'?: string
42
- }
43
-
44
- const getValidationErrors = (
45
- validators: Validators,
46
- formValues: any,
47
- form: FormApi<any>
48
- ): SubmissionErrors | void => {
49
- let errors: SubmissionErrors
50
-
51
- Object.entries(validators).forEach(([key, validator]) => {
52
- const fieldValue = getIn(formValues, key)
53
- const fieldMetaState = form.getFieldState(key)
54
-
55
- if (!validator) {
56
- return
57
- }
58
-
59
- const error = validator(fieldValue, formValues, fieldMetaState)
60
-
61
- if (error) {
62
- errors = setIn(errors || {}, key, error)
63
- }
64
- })
65
-
66
- return errors
67
- }
68
-
69
- export const Form = <T extends any = AnyObject>(props: Props<T>) => {
70
- const {
71
- children,
72
- autoComplete,
73
- onSubmit,
74
- successSubmitMessage,
75
- failedSubmitMessage,
76
- decorators = [],
77
- 'data-testid': dataTestId,
78
- ...rest
79
- } = props
80
- const { showSuccess, showError } = useNotifications()
81
- const scrollToErrorDecorator = useMemo(
82
- () => createScrollToErrorDecorator(),
83
- []
84
- )
85
-
86
- const validationObject = useRef<FormContextProps>(createFormContext())
87
-
88
- const showSuccessNotification = () => {
89
- if (!successSubmitMessage) {
90
- return
91
- }
92
-
93
- showSuccess(successSubmitMessage)
94
- }
95
-
96
- const showErrorNotification = (errors: SubmissionErrors) => {
97
- if (typeof errors === 'string') {
98
- showError(errors, undefined, { persist: true })
99
-
100
- return
101
- }
102
-
103
- if (!failedSubmitMessage) {
104
- return
105
- }
106
-
107
- showError(failedSubmitMessage, undefined, { persist: true })
108
- }
109
-
110
- const handleSubmit = async (
111
- values: T,
112
- form: FormApi<T>,
113
- callback?: (errors?: SubmissionErrors) => void
114
- ) => {
115
- const validationErrors = getValidationErrors(
116
- validationObject.current.getValidators(),
117
- values,
118
- form
119
- )
120
-
121
- if (validationErrors) {
122
- return validationErrors
123
- }
124
-
125
- const submissionErrors = await onSubmit(values, form, callback)
126
-
127
- if (!submissionErrors) {
128
- showSuccessNotification()
129
- } else {
130
- showErrorNotification(submissionErrors)
131
- }
132
-
133
- return submissionErrors
134
- }
135
-
136
- return (
137
- <FormContext.Provider value={validationObject}>
138
- <FinalForm
139
- render={({ handleSubmit }) => (
140
- <Container>
141
- <PicassoForm
142
- autoComplete={autoComplete}
143
- onSubmit={handleSubmit}
144
- data-testid={dataTestId}
145
- >
146
- {children}
147
- </PicassoForm>
148
- </Container>
149
- )}
150
- onSubmit={handleSubmit}
151
- decorators={[...decorators, scrollToErrorDecorator]}
152
- {...rest}
153
- />
154
- </FormContext.Provider>
155
- )
156
- }
157
-
158
- Form.defaultProps = {}
159
-
160
- Form.displayName = 'Form'
161
-
162
- Form.Autocomplete = Autocomplete
163
- Form.Input = Input
164
- Form.Select = Select
165
- Form.Radio = Radio
166
- Form.ButtonRadio = ButtonRadio
167
- Form.RadioGroup = RadioGroup
168
- Form.Checkbox = Checkbox
169
- Form.ButtonCheckbox = ButtonCheckbox
170
- Form.CheckboxGroup = CheckboxGroup
171
- Form.NumberInput = NumberInput
172
- Form.FileInput = FileInput
173
- Form.DatePicker = DatePicker
174
- Form.TimePicker = TimePicker
175
- Form.TagSelector = TagSelector
176
- Form.SubmitButton = SubmitButton
177
- Form.ConfigProvider = FormConfigContext.Provider
178
- Form.Switch = Switch
179
- Form.Rating = Rating
180
-
181
- export default Form
@@ -1,38 +0,0 @@
1
- import { createContext, useContext, MutableRefObject } from 'react'
2
- import { FieldValidator } from 'final-form'
3
-
4
- export type Validators = Record<string, FieldValidator<unknown>>
5
-
6
- export type FormContextProps = {
7
- getValidators: () => Validators
8
- setValidators: (fieldName: string, validator: FieldValidator<unknown>) => void
9
- clearValidators: (fieldName: string) => void
10
- }
11
-
12
- export const createFormContext = (): FormContextProps => {
13
- const validators: Validators = {}
14
-
15
- return {
16
- getValidators: () => validators,
17
- setValidators: (fieldName, validator) => {
18
- validators[fieldName] = validator
19
- },
20
- clearValidators: fieldName => {
21
- delete validators[fieldName]
22
- }
23
- }
24
- }
25
-
26
- export const FormContext = createContext<MutableRefObject<
27
- FormContextProps
28
- > | null>(null)
29
-
30
- export const useFormContext = () => {
31
- const context = useContext(FormContext)
32
-
33
- if (!context) {
34
- throw new Error('Form Field cannot be rendered outside Form component')
35
- }
36
-
37
- return context.current
38
- }
@@ -1,61 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Form renders 1`] = `
4
- <div>
5
- <div
6
- class="Picasso-root"
7
- >
8
- <div
9
- class=""
10
- >
11
- <form>
12
- <div
13
- class="PicassoFormField-root"
14
- data-field-has-error="false"
15
- >
16
- <div
17
- class="MuiInputBase-root MuiOutlinedInput-root PicassoOutlinedInput-root PicassoInput-root PicassoOutlinedInput-rootAuto PicassoOutlinedInput-rootMedium MuiInputBase-adornedStart MuiOutlinedInput-adornedStart MuiInputBase-adornedEnd MuiOutlinedInput-adornedEnd"
18
- >
19
- <input
20
- aria-invalid="false"
21
- autocomplete="none"
22
- class="MuiInputBase-input MuiOutlinedInput-input PicassoOutlinedInput-input PicassoOutlinedInput-inputMedium MuiInputBase-inputAdornedStart MuiOutlinedInput-inputAdornedStart MuiInputBase-inputAdornedEnd MuiOutlinedInput-inputAdornedEnd"
23
- id="test"
24
- name="test"
25
- placeholder="test input"
26
- type="text"
27
- value=""
28
- />
29
- <fieldset
30
- aria-hidden="true"
31
- class="PrivateNotchedOutline-root MuiOutlinedInput-notchedOutline PicassoOutlinedInput-notchedOutline"
32
- style="padding-left: 8px;"
33
- >
34
- <legend
35
- class="PrivateNotchedOutline-legend"
36
- style="width: 0.01px;"
37
- >
38
- <span>
39
-
40
- </span>
41
- </legend>
42
- </fieldset>
43
- </div>
44
- </div>
45
- <button
46
- class="MuiButtonBase-root PicassoButton-medium PicassoButton-primary PicassoButton-root"
47
- data-component-type="button"
48
- tabindex="0"
49
- type="submit"
50
- >
51
- <span
52
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
53
- >
54
- Submit
55
- </span>
56
- </button>
57
- </form>
58
- </div>
59
- </div>
60
- </div>
61
- `;
package/src/Form/index.ts DELETED
@@ -1 +0,0 @@
1
- export { default } from './Form'
@@ -1,139 +0,0 @@
1
- import React, { useCallback } from 'react'
2
- import { Container } from '@toptal/picasso'
3
- import { Form } from '@toptal/picasso-forms'
4
-
5
- const BackendCommunicationExample = () => {
6
- const handleSuccessSubmit = useCallback(
7
- (values: any) => api.successSubmit(values),
8
- []
9
- )
10
- const handleSubmitWithInlineError = useCallback(
11
- (values: any) => api.submitWithInlineError(values),
12
- []
13
- )
14
- const handleSubmitWithCustomNotificationError = useCallback(
15
- (values: any) => api.submitWithCustomNotificationError(values),
16
- []
17
- )
18
-
19
- return (
20
- <Container
21
- style={{
22
- display: 'grid',
23
- gap: '2rem',
24
- gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))'
25
- }}
26
- >
27
- <Form
28
- onSubmit={handleSuccessSubmit}
29
- successSubmitMessage='Login successful!'
30
- >
31
- <Form.Input
32
- required
33
- name='successName'
34
- label='First name'
35
- placeholder='e.g. Bruce'
36
- width='full'
37
- />
38
- <Form.Input
39
- required
40
- name='successSurname'
41
- label='Last name'
42
- placeholder='e.g. Wayne'
43
- width='full'
44
- />
45
-
46
- <Container top='small'>
47
- <Form.SubmitButton
48
- variant='positive'
49
- data-testid='success-submit-button'
50
- >
51
- Login Success
52
- </Form.SubmitButton>
53
- </Container>
54
- </Form>
55
-
56
- <Form
57
- onSubmit={handleSubmitWithInlineError}
58
- failedSubmitMessage='Login failed! Please try another combination of first and last names.'
59
- >
60
- <Form.Input
61
- required
62
- name='inlineErrorName'
63
- label='First name'
64
- placeholder='e.g. Bruce'
65
- width='full'
66
- />
67
- <Form.Input
68
- required
69
- name='inlineErrorSurname'
70
- label='Last name'
71
- placeholder='e.g. Wayne'
72
- width='full'
73
- />
74
-
75
- <Container top='small'>
76
- <Form.SubmitButton
77
- variant='negative'
78
- data-testid='submit-with-inline-error-button'
79
- >
80
- Login with Inline Error
81
- </Form.SubmitButton>
82
- </Container>
83
- </Form>
84
-
85
- <Form onSubmit={handleSubmitWithCustomNotificationError}>
86
- <Form.Input
87
- required
88
- name='customNotificationErrorName'
89
- label='First name'
90
- placeholder='e.g. Bruce'
91
- width='full'
92
- />
93
- <Form.Input
94
- required
95
- name='customNotificationErrorSurname'
96
- label='Last name'
97
- placeholder='e.g. Wayne'
98
- width='full'
99
- />
100
-
101
- <Container top='small'>
102
- <Form.SubmitButton
103
- variant='negative'
104
- data-testid='submit-with-custom-notification-button'
105
- >
106
- Login with Custom Notification Error
107
- </Form.SubmitButton>
108
- </Container>
109
- </Form>
110
- </Container>
111
- )
112
- }
113
-
114
- // the emulation of the api call
115
- const responseWithDelay = async (response: any) =>
116
- new Promise(resolve => setTimeout(() => resolve(response), 2000))
117
-
118
- const api = {
119
- successSubmit: (values: any) => {
120
- // do something with received values
121
- console.log('Success submit. Form values:', values)
122
-
123
- return responseWithDelay(undefined)
124
- },
125
- submitWithInlineError: (values: any) => {
126
- console.log('Submit with Inline Errors. Form values:', values)
127
-
128
- return responseWithDelay({
129
- inlineErrorName: 'Unknown first name'
130
- })
131
- },
132
- submitWithCustomNotificationError: (values: any) => {
133
- console.log('Submit with Custom Notification Errors. Form values:', values)
134
-
135
- return responseWithDelay('Custom Notification Message!')
136
- }
137
- }
138
-
139
- export default BackendCommunicationExample
@@ -1,26 +0,0 @@
1
- import React from 'react'
2
- import { Container } from '@toptal/picasso'
3
- import { Form, FormConfigProps } from '@toptal/picasso-forms'
4
-
5
- const formConfig: FormConfigProps = {
6
- requiredVariant: 'asterisk'
7
- }
8
-
9
- const Example = () => (
10
- <Form.ConfigProvider value={formConfig}>
11
- <Form onSubmit={() => {}}>
12
- <Form.Input
13
- required
14
- name='formConfig.firstName'
15
- label='First name'
16
- placeholder='e.g. Bruce'
17
- />
18
-
19
- <Container top='small'>
20
- <Form.SubmitButton>Submit</Form.SubmitButton>
21
- </Container>
22
- </Form>
23
- </Form.ConfigProvider>
24
- )
25
-
26
- export default Example
@@ -1,45 +0,0 @@
1
- import React from 'react'
2
- import { Container } from '@toptal/picasso'
3
- import { Form } from '@toptal/picasso-forms'
4
-
5
- const minMaxValidator = (value?: string | number) => {
6
- if (value === undefined) {
7
- return undefined
8
- }
9
-
10
- const number = Number(value)
11
-
12
- if (number < 0) {
13
- return "Age can't be negative"
14
- }
15
-
16
- if (number > 120) {
17
- return "Age can't have value more than 120 years"
18
- }
19
-
20
- return undefined
21
- }
22
-
23
- const CustomValidatorExample = () => (
24
- <Form onSubmit={values => window.alert(values)}>
25
- <Form.Input
26
- required
27
- name='userName'
28
- label='First name'
29
- placeholder='e.g. Bruce'
30
- />
31
- <Form.NumberInput
32
- required
33
- validate={minMaxValidator}
34
- name='userAge'
35
- label="What's your age?"
36
- placeholder='e.g. 25'
37
- />
38
-
39
- <Container top='small'>
40
- <Form.SubmitButton>Submit</Form.SubmitButton>
41
- </Container>
42
- </Form>
43
- )
44
-
45
- export default CustomValidatorExample
@@ -1,177 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Container } from '@toptal/picasso'
3
- import { Item } from '@toptal/picasso/Autocomplete'
4
- import { isSubstring } from '@toptal/picasso/utils'
5
- import { Form } from '@toptal/picasso-forms'
6
-
7
- const countries = [
8
- { value: 'Afghanistan', text: 'Afghanistan' },
9
- { value: 'Albania', text: 'Albania' },
10
- { value: 'Algeria', text: 'Algeria' },
11
- { value: 'Belarus', text: 'Belarus' },
12
- { value: 'Croatia', text: 'Croatia' },
13
- { value: 'Lithuania', text: 'Lithuania' },
14
- { value: 'Slovakia', text: 'Slovakia' },
15
- { value: 'Spain', text: 'Spain' },
16
- { value: 'Ukraine', text: 'Ukraine' }
17
- ]
18
-
19
- const skills = [
20
- { value: 0, text: 'HTML' },
21
- { value: 1, text: 'CSS' },
22
- { value: 2, text: 'Javascript' }
23
- ]
24
-
25
- const EMPTY_INPUT_VALUE = ''
26
- const getAutocompleteDisplayValue = (item: Item | null) =>
27
- item?.text || EMPTY_INPUT_VALUE
28
-
29
- const filterOptions = (str = '', options: Item[] = []): Item[] | null => {
30
- if (!str) {
31
- return options
32
- }
33
- const result = options.filter(option =>
34
- option?.text ? isSubstring(str, option.text) : false
35
- )
36
-
37
- return result.length > 0 ? result : null
38
- }
39
-
40
- const Example = () => {
41
- const [skillInputValue, setSkillInputValue] = useState<string>(
42
- EMPTY_INPUT_VALUE
43
- )
44
- const skillOptions = filterOptions(skillInputValue, skills)
45
-
46
- const [autocompleteValue, setAutocompleteValue] = useState<string>(
47
- EMPTY_INPUT_VALUE
48
- )
49
- const [autocompleteOptions, setAutocompleteOptions] = useState<Item[] | null>(
50
- countries
51
- )
52
-
53
- return (
54
- <Form
55
- autoComplete='off'
56
- onSubmit={values => window.alert(values)}
57
- initialValues={{ gender: 'female' }}
58
- >
59
- <Form.Input
60
- enableReset
61
- onResetClick={(set: (value: string) => void) => {
62
- set('')
63
- }}
64
- required
65
- name='firstName'
66
- label='First name'
67
- placeholder='e.g. Bruce'
68
- />
69
- <Form.Input
70
- required
71
- name='lastName'
72
- label='Last name'
73
- placeholder='e.g. Wayne'
74
- />
75
- <Form.NumberInput
76
- enableReset
77
- required
78
- name='age'
79
- label="What's your age?"
80
- placeholder='e.g. 25'
81
- />
82
- <Form.RadioGroup name='gender' label='Gender'>
83
- <Form.Radio label='Male' value='male' />
84
- <Form.Radio label='Female' value='female' />
85
- </Form.RadioGroup>
86
- <Form.RadioGroup name='gender' label='Gender' horizontal spacing={8}>
87
- <Form.ButtonRadio value='male'>Male</Form.ButtonRadio>
88
- <Form.ButtonRadio value='female'>Female</Form.ButtonRadio>
89
- </Form.RadioGroup>
90
- <Form.DatePicker name='dateOfBirth' label='Date of birth' />
91
- <Form.TimePicker name='timeOfBirth' label='Time of birth' />
92
- <Form.TagSelector
93
- name='skills'
94
- label='Skills'
95
- inputValue={skillInputValue}
96
- options={skillOptions}
97
- onInputChange={setSkillInputValue}
98
- />
99
- <Form.CheckboxGroup name='hobbies' label='Hobbies'>
100
- <Form.Checkbox label='Skiing' value='skiing' />
101
- <Form.Checkbox label='Free diving' value='freeDiving' />
102
- <Form.Checkbox label='Dancing' value='dancing' />
103
- </Form.CheckboxGroup>
104
- <Form.CheckboxGroup name='hobbies' label='Hobbies' horizontal spacing={8}>
105
- <Form.ButtonCheckbox value='skiing'>Skiing</Form.ButtonCheckbox>
106
- <Form.ButtonCheckbox value='freeDiving'>
107
- Free diving
108
- </Form.ButtonCheckbox>
109
- <Form.ButtonCheckbox value='dancing'>Dancing</Form.ButtonCheckbox>
110
- </Form.CheckboxGroup>
111
- <Form.Select
112
- enableReset
113
- required
114
- name='businessType'
115
- label='Business type'
116
- width='auto'
117
- options={[
118
- { value: 0, text: 'Company' },
119
- { value: 1, text: 'Individual' }
120
- ]}
121
- />
122
- <Form.Select
123
- name='origin_country'
124
- label='Origin country'
125
- width='auto'
126
- options={countries}
127
- />
128
- <Form.Autocomplete
129
- name='current_country'
130
- label='Current country'
131
- placeholder='Start typing country...'
132
- width='auto'
133
- value={autocompleteValue}
134
- options={autocompleteOptions}
135
- onSelect={(item: Item) => {
136
- console.log('onSelect returns item object:', item)
137
-
138
- const itemValue = getAutocompleteDisplayValue(item)
139
-
140
- if (autocompleteValue !== itemValue) {
141
- setAutocompleteValue(itemValue)
142
- }
143
- }}
144
- onChange={(newValue: string) => {
145
- console.log('onChange returns just item value:', newValue)
146
-
147
- setAutocompleteOptions(filterOptions(newValue, countries))
148
- setAutocompleteValue(newValue)
149
- }}
150
- getDisplayValue={getAutocompleteDisplayValue}
151
- />
152
- <Form.Rating
153
- name='rating'
154
- label='How much do you love Picasso?'
155
- required
156
- />
157
- <Form.FileInput
158
- required
159
- name='avatar'
160
- label='Avatar'
161
- status='No file selected.'
162
- />
163
- <Form.Checkbox
164
- required
165
- name='legal'
166
- label='I confirm that I have legal permission from the client to feature this project.'
167
- />
168
- <Form.Switch name='publicProfile' label='Public Profile' width='auto' />
169
-
170
- <Container top='small'>
171
- <Form.SubmitButton>Submit</Form.SubmitButton>
172
- </Container>
173
- </Form>
174
- )
175
- }
176
-
177
- export default Example