@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
@@ -1,91 +0,0 @@
1
- import React from 'react'
2
- import { render } from '@toptal/picasso/test-utils'
3
-
4
- import { FormConfigProps } from '../FormConfig'
5
- import Form from '../Form'
6
- import CheckboxGroup from '../CheckboxGroup'
7
- import Checkbox, { Props } from './Checkbox'
8
-
9
- const renderCheckbox = (
10
- { required, titleCase }: Props,
11
- formConfig: FormConfigProps = {}
12
- ) =>
13
- render(
14
- <Form.ConfigProvider value={formConfig}>
15
- <Form onSubmit={() => {}}>
16
- <Checkbox
17
- name='single-checkbox'
18
- label='The checkbox label'
19
- value='checkbox-value'
20
- data-testid='single-checkbox'
21
- required={required}
22
- titleCase={titleCase}
23
- />
24
- </Form>
25
- </Form.ConfigProvider>
26
- )
27
-
28
- const renderCheckboxInGroup = () =>
29
- render(
30
- <Form onSubmit={() => {}}>
31
- <CheckboxGroup name='checkbox-group' label='checkbox-group-label'>
32
- <Checkbox label='checkbox-label-0' value='checkbox-value-0' />
33
- <Checkbox label='checkbox-label-1' value='checkbox-value-1' />
34
- </CheckboxGroup>
35
- </Form>
36
- )
37
-
38
- describe('Form.Checkbox', () => {
39
- it('default render for single checkbox', () => {
40
- const { container } = renderCheckbox({})
41
-
42
- expect(container).toMatchSnapshot()
43
- })
44
-
45
- describe('when required prop is passed', () => {
46
- it('does not set "required" attribute to input tag, to avoid Chrome tooltip', () => {
47
- const { container } = renderCheckbox({})
48
-
49
- expect(
50
- container.querySelector('[name="single-checkbox"]')
51
- ).toMatchSnapshot()
52
- })
53
- })
54
-
55
- it('default render for checkboxes in a group', () => {
56
- const { container } = renderCheckboxInGroup()
57
-
58
- expect(container).toMatchSnapshot()
59
- })
60
-
61
- it('required with asterisk single checkbox', () => {
62
- const { container } = renderCheckbox(
63
- {
64
- required: true
65
- },
66
- {
67
- requiredVariant: 'asterisk'
68
- }
69
- )
70
-
71
- expect(container).toMatchSnapshot()
72
- })
73
-
74
- it('never shows (optional) postfix for single checkbox', () => {
75
- const { getByTestId } = renderCheckbox({})
76
-
77
- expect(getByTestId('single-checkbox')).not.toHaveTextContent('(optional)')
78
- })
79
-
80
- it('shows the label in default case', () => {
81
- const { getByLabelText } = renderCheckbox({})
82
-
83
- expect(getByLabelText('The checkbox label')).toBeInTheDocument()
84
- })
85
-
86
- it('shows the label in title case', () => {
87
- const { getByLabelText } = renderCheckbox({ titleCase: true })
88
-
89
- expect(getByLabelText('The Checkbox Label')).toBeInTheDocument()
90
- })
91
- })
@@ -1,30 +0,0 @@
1
- /* eslint-disable react/jsx-props-no-spreading */
2
- import React from 'react'
3
- import {
4
- Checkbox as PicassoCheckbox,
5
- CheckboxProps,
6
- CheckboxGroupProps
7
- } from '@toptal/picasso'
8
-
9
- import FieldWrapper, { FieldProps } from '../FieldWrapper'
10
- import CheckboxGroupContext from './CheckboxGroupContext'
11
-
12
- export type Props = CheckboxGroupProps & FieldProps<CheckboxProps['value']>
13
-
14
- export const CheckboxGroup = (props: Props) => {
15
- const { children, titleCase, ...rest } = props
16
-
17
- return (
18
- <CheckboxGroupContext.Provider value={props.name}>
19
- <FieldWrapper titleCase={titleCase} {...rest} type='checkbox'>
20
- {() => (
21
- <PicassoCheckbox.Group {...rest}>{children}</PicassoCheckbox.Group>
22
- )}
23
- </FieldWrapper>
24
- </CheckboxGroupContext.Provider>
25
- )
26
- }
27
-
28
- CheckboxGroup.displayName = 'CheckboxGroup'
29
-
30
- export default CheckboxGroup
@@ -1,3 +0,0 @@
1
- import { createContext } from 'react'
2
-
3
- export default createContext<string | undefined>(undefined)
@@ -1,3 +0,0 @@
1
- export { default } from './CheckboxGroup'
2
- export { default as CheckboxGroupContext } from './CheckboxGroupContext'
3
- export type { Props } from './CheckboxGroup'
@@ -1,35 +0,0 @@
1
- import { render } from '@toptal/picasso/test-utils'
2
- import React from 'react'
3
-
4
- import Checkbox from '../Checkbox'
5
- import Form from '../Form'
6
- import CheckboxGroup, { Props } from './CheckboxGroup'
7
-
8
- const arrangeTest = ({ titleCase }: Partial<Props> = {}) =>
9
- render(
10
- <Form onSubmit={() => {}}>
11
- <CheckboxGroup
12
- required
13
- name='checkbox-group'
14
- label='Checkbox group label'
15
- titleCase={titleCase}
16
- >
17
- <Checkbox label='checkbox-label-0' value='checkbox-value-0' />
18
- <Checkbox label='checkbox-label-1' value='checkbox-value-1' />
19
- </CheckboxGroup>
20
- </Form>
21
- )
22
-
23
- describe('CheckboxGroup', () => {
24
- it('shows the label in default case', () => {
25
- const { getByText } = arrangeTest()
26
-
27
- expect(getByText('Checkbox group label')).toBeInTheDocument()
28
- })
29
-
30
- it('shows the label in title case', () => {
31
- const { getByText } = arrangeTest({ titleCase: true })
32
-
33
- expect(getByText('Checkbox Group Label')).toBeInTheDocument()
34
- })
35
- })
@@ -1,26 +0,0 @@
1
- import React from 'react'
2
- import {
3
- DatePicker as PicassoDatePicker,
4
- DatePickerProps
5
- } from '@toptal/picasso-lab'
6
-
7
- import FieldWrapper, { FieldProps } from '../FieldWrapper'
8
-
9
- export type FormDatePickerProps = Omit<DatePickerProps, 'onChange'> & {
10
- onChange?: DatePickerProps['onChange']
11
- }
12
- export type Props = FormDatePickerProps & FieldProps<DatePickerProps['value']>
13
-
14
- export const DatePicker = (props: Props) => (
15
- <FieldWrapper<FormDatePickerProps> {...props}>
16
- {(inputProps: DatePickerProps) => {
17
- return <PicassoDatePicker {...inputProps} />
18
- }}
19
- </FieldWrapper>
20
- )
21
-
22
- DatePicker.defaultProps = {}
23
-
24
- DatePicker.displayName = 'DatePicker'
25
-
26
- export default DatePicker
@@ -1 +0,0 @@
1
- export { default } from './DatePicker'
@@ -1,287 +0,0 @@
1
- import React, { ChangeEvent, FocusEvent, useCallback, useEffect } from 'react'
2
- import {
3
- useField,
4
- FieldProps as FinalFieldProps,
5
- FieldMetaState,
6
- FieldRenderProps
7
- } from 'react-final-form'
8
- import { Form as PicassoForm, RequiredDecoration } from '@toptal/picasso'
9
- import { Item } from '@toptal/picasso/Autocomplete'
10
- import { FileUpload } from '@toptal/picasso/FileInput'
11
- import { DateOrDateRangeType } from '@toptal/picasso-lab'
12
- import { TextLabelProps } from '@toptal/picasso-shared'
13
-
14
- import { useFormContext } from '../Form/FormContext'
15
- import { useFormConfig, FormConfigProps, RequiredVariant } from '../FormConfig'
16
- import { validators } from '../utils'
17
-
18
- const { composeValidators, required: requiredValidator } = validators
19
-
20
- type ValueType =
21
- | string
22
- | string[]
23
- | number
24
- | boolean
25
- | null
26
- | undefined
27
- | FileUpload[]
28
- | DateOrDateRangeType
29
- | Item
30
- | Item[]
31
-
32
- export type FieldProps<TInputValue> = FinalFieldProps<
33
- TInputValue,
34
- FieldRenderProps<TInputValue, HTMLInputElement>,
35
- HTMLInputElement
36
- > &
37
- TextLabelProps
38
-
39
- export type Props<
40
- TInputValue,
41
- TWrappedComponentProps
42
- > = TWrappedComponentProps &
43
- FieldProps<TInputValue> &
44
- TextLabelProps & {
45
- name: string
46
- type?: string
47
- hideFieldLabel?: boolean
48
- hideLabelRequiredDecoration?: boolean
49
- fieldType?: string
50
- children: (props: any) => React.ReactNode
51
- }
52
-
53
- type FieldMeta<T> = FieldMetaState<T> & {
54
- dirtyAfterBlur?: boolean
55
- }
56
-
57
- const getInputError = <T extends ValueType>(
58
- meta: FieldMeta<T>,
59
- formConfig: FormConfigProps
60
- ) => {
61
- if (formConfig.validateOnSubmit && meta.modifiedSinceLastSubmit) {
62
- return null
63
- }
64
-
65
- if (!meta.error && !meta.submitError) {
66
- return null
67
- }
68
-
69
- if (!meta.touched) {
70
- return null
71
- }
72
-
73
- if (meta.error) {
74
- return meta.error
75
- }
76
-
77
- if (meta.dirtySinceLastSubmit) {
78
- return null
79
- }
80
-
81
- return meta.submitError
82
- }
83
-
84
- const getValidators = (required: boolean, validate?: any) => {
85
- if (required && validate) {
86
- return composeValidators([requiredValidator, validate])
87
- }
88
-
89
- if (required && !validate) {
90
- return requiredValidator
91
- }
92
-
93
- return validate
94
- }
95
-
96
- const getProps = ({
97
- hideFieldLabel,
98
- error,
99
- label
100
- }: {
101
- hideFieldLabel?: boolean
102
- error: string
103
- label: string
104
- }) => {
105
- if (hideFieldLabel) {
106
- return {
107
- label
108
- }
109
- }
110
-
111
- return {
112
- error: Boolean(error)
113
- }
114
- }
115
-
116
- const getRequiredDecoration = (
117
- hideLabelRequiredDecoration?: boolean,
118
- required?: boolean,
119
- requiredVariant?: RequiredVariant
120
- ): RequiredDecoration | undefined => {
121
- if (hideLabelRequiredDecoration) {
122
- return
123
- }
124
-
125
- const showAsterisk = required && requiredVariant === 'asterisk'
126
-
127
- if (showAsterisk) {
128
- return 'asterisk'
129
- }
130
-
131
- const showOptional =
132
- !required && (!requiredVariant || requiredVariant === 'default')
133
-
134
- if (showOptional) {
135
- return 'optional'
136
- }
137
- }
138
-
139
- const FieldWrapper = <
140
- TWrappedComponentProps extends { value?: ValueType },
141
- TInputValue extends ValueType = TWrappedComponentProps['value']
142
- >(
143
- props: Props<TInputValue, TWrappedComponentProps>
144
- ) => {
145
- const {
146
- type,
147
- hideFieldLabel,
148
- hideLabelRequiredDecoration,
149
- hint,
150
- label,
151
- required,
152
- enableReset,
153
- onResetClick,
154
- 'data-testid': dataTestId,
155
- // FieldProps - https://final-form.org/docs/react-final-form/types/FieldProps
156
- afterSubmit,
157
- allowNull,
158
- beforeSubmit,
159
- children,
160
- data,
161
- defaultValue,
162
- format,
163
- formatOnBlur,
164
- initialValue,
165
- isEqual,
166
- name,
167
- id = name,
168
- parse,
169
- subscription,
170
- validate,
171
- validateFields,
172
- value,
173
- titleCase,
174
- //
175
- ...rest
176
- } = props
177
-
178
- const formConfig = useFormConfig()
179
- const { setValidators, clearValidators } = useFormContext()
180
- const validators = getValidators(required, validate)
181
-
182
- if (formConfig.validateOnSubmit) {
183
- setValidators(name, validators)
184
- }
185
-
186
- useEffect(() => {
187
- return () => {
188
- if (formConfig.validateOnSubmit) {
189
- clearValidators(name)
190
- }
191
- }
192
- }, [clearValidators, formConfig.validateOnSubmit, name])
193
-
194
- const { meta, input } = useField<TInputValue>(name, {
195
- validate: formConfig.validateOnSubmit ? undefined : validators,
196
- type,
197
- afterSubmit,
198
- allowNull,
199
- beforeSubmit,
200
- data,
201
- defaultValue,
202
- format,
203
- formatOnBlur,
204
- initialValue,
205
- isEqual,
206
- parse,
207
- subscription,
208
- validateFields,
209
- value
210
- })
211
-
212
- const defaultResetClickHandler = useCallback(() => {
213
- input.onChange('')
214
- }, [input])
215
-
216
- const resetClickHandler = useCallback(() => {
217
- onResetClick((resetValue: string) => {
218
- input.onChange(resetValue)
219
- })
220
- }, [input, onResetClick])
221
-
222
- const error = getInputError<TInputValue>(meta, formConfig)
223
-
224
- const childProps: Record<string, unknown> = {
225
- id,
226
- ...rest,
227
- ...input,
228
- ...getProps({ hideFieldLabel, error, label }),
229
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
230
- onChange: (event: ChangeEvent<HTMLElement> | any) => {
231
- input.onChange(event)
232
-
233
- if (rest.onChange) {
234
- rest.onChange(event)
235
- }
236
- },
237
- onBlur: (event: FocusEvent<HTMLElement>) => {
238
- input.onBlur(event)
239
-
240
- if (rest.onBlur) {
241
- rest.onBlur(event)
242
- }
243
- },
244
- onFocus: (event: FocusEvent<HTMLElement>) => {
245
- input.onFocus(event)
246
-
247
- if (rest.onFocus) {
248
- rest.onFocus(event)
249
- }
250
- }
251
- }
252
-
253
- if (enableReset) {
254
- childProps.onResetClick = onResetClick
255
- ? resetClickHandler
256
- : defaultResetClickHandler
257
- childProps.enableReset = enableReset
258
- }
259
-
260
- const requiredDecoration = getRequiredDecoration(
261
- hideLabelRequiredDecoration,
262
- required,
263
- formConfig.requiredVariant
264
- )
265
-
266
- return (
267
- <PicassoForm.Field error={error} hint={hint} data-testid={dataTestId}>
268
- {!hideFieldLabel && label && (
269
- <PicassoForm.Label
270
- requiredDecoration={requiredDecoration}
271
- htmlFor={id}
272
- disabled={rest.disabled}
273
- titleCase={titleCase}
274
- >
275
- {label}
276
- </PicassoForm.Label>
277
- )}
278
- {children(childProps)}
279
- </PicassoForm.Field>
280
- )
281
- }
282
-
283
- FieldWrapper.defaultProps = {}
284
-
285
- FieldWrapper.displayName = 'FieldWrapper'
286
-
287
- export default FieldWrapper
@@ -1,2 +0,0 @@
1
- export { default } from './FieldWrapper'
2
- export * from './FieldWrapper'
@@ -1,137 +0,0 @@
1
- import FieldWrapper from '../FieldWrapper'
2
- import PicassoBook from '~/.storybook/components/PicassoBook'
3
-
4
- const componentDocs = PicassoBook.createComponentDocs(
5
- FieldWrapper,
6
- 'Form.Field',
7
- undefined,
8
- {
9
- name: {
10
- name: 'name',
11
- type: 'string',
12
- description: 'The field name',
13
- required: true
14
- },
15
- label: {
16
- name: 'label',
17
- type: 'string',
18
- description: 'The field label text'
19
- },
20
- hint: {
21
- name: 'hint',
22
- type: 'string',
23
- description: 'The hint of the field with some additional information'
24
- },
25
- required: {
26
- name: 'required',
27
- type: 'boolean',
28
- description: 'Makes field to be required in the form'
29
- },
30
- // FieldProps - https://final-form.org/docs/react-final-form/types/FieldProps
31
- afterSubmit: {
32
- name: 'afterSubmit',
33
- type: {
34
- name: 'function',
35
- description: '() => void'
36
- },
37
- description:
38
- 'A callback to notify fields after submission has completed successfully'
39
- },
40
- allowNull: {
41
- name: 'allowNull',
42
- type: 'boolean',
43
- description: 'By default null value is converted to empty string',
44
- defaultValue: false
45
- },
46
- beforeSubmit: {
47
- name: 'beforeSubmit',
48
- type: {
49
- name: 'function',
50
- description: '() => void | false'
51
- },
52
- description: 'A function to call just before calling onSubmit'
53
- },
54
- data: {
55
- name: 'data',
56
- type: 'object',
57
- description: 'Initial state for arbitrary values to be placed by mutators'
58
- },
59
- defaultValue: {
60
- name: 'defaultValue',
61
- type: 'any',
62
- description: 'Default value of the field upon creation'
63
- },
64
- format: {
65
- name: 'format',
66
- type: {
67
- name: 'function',
68
- description: '(value: any, name: string) => any'
69
- },
70
- description:
71
- 'A function that takes the value from the form values and the name of the field and formats the value to give to the input'
72
- },
73
- formatOnBlur: {
74
- name: 'formatOnBlur',
75
- type: 'boolean',
76
- description:
77
- 'If true, the format function will only be called when the field is blurred. If false, format will be called on every render'
78
- },
79
- initialValue: {
80
- name: 'initialValue',
81
- type: 'any',
82
- description: 'The initial value for the field'
83
- },
84
- isEqual: {
85
- name: 'isEqual',
86
- type: {
87
- name: 'function',
88
- description: '(a: any, b: any) => boolean'
89
- },
90
- description: 'A function to determine if two values are equal'
91
- },
92
- parse: {
93
- name: 'parse',
94
- type: {
95
- name: 'function',
96
- description: '(value: any, name: string) => any'
97
- },
98
- description:
99
- "A function that takes the value from the input and name of the field and converts the value into the value you want stored as this field's value in the form"
100
- },
101
- subscription: {
102
- name: 'subscription',
103
- type: {
104
- name: 'object',
105
- description: '{ [string]: boolean }'
106
- },
107
- description:
108
- 'An object of the parts of FieldState (final-form) to subscribe to'
109
- },
110
- validate: {
111
- name: 'validate',
112
- type: {
113
- name: 'function',
114
- description:
115
- '(value: ?any, allValues: Object, meta: ?FieldState) => ?any'
116
- },
117
- description:
118
- 'A function that takes the field value, all the values of the form and the meta data about the field and returns an error if the value is invalid, or undefined if the value is valid'
119
- },
120
- validateFields: {
121
- name: 'validateFields',
122
- type: 'string[]',
123
- description: 'An array of field names to validate when this field changes'
124
- },
125
- // //
126
- allFieldProps: {
127
- name: '<all field props>',
128
- type: 'any',
129
- description:
130
- 'This component also accepts all the native props from the corresponding form component, ex. Form.Input accepts all the Picasso Input props'
131
- }
132
- }
133
- )
134
-
135
- export default {
136
- componentDocs
137
- }
@@ -1,66 +0,0 @@
1
- import React from 'react'
2
- import { FileInput as PicassoFileInput, FileInputProps } from '@toptal/picasso'
3
- import { FieldInputProps as FinalFieldInputProps } from 'react-final-form'
4
- import { FileUpload } from '@toptal/picasso/FileInput'
5
-
6
- import FieldWrapper, { FieldProps } from '../FieldWrapper'
7
-
8
- type FinalFormOnChangeType = FinalFieldInputProps<
9
- FileInputProps['value']
10
- >['onChange']
11
-
12
- export type Props = FileInputProps & FieldProps<FileInputProps['value']>
13
-
14
- export const FileInput = (props: Props) => {
15
- const handleChange = (
16
- event: React.ChangeEvent<HTMLInputElement>,
17
- value: FileUpload[] | undefined = [],
18
- finalFormOnChange: FinalFormOnChangeType
19
- ) => {
20
- if (!event.target || !event.target.files || !event.target.files.length) {
21
- return null
22
- }
23
-
24
- const newFiles = Array.from(event.target.files).map(file => ({
25
- file,
26
- uploading: false
27
- }))
28
-
29
- finalFormOnChange([...value, ...newFiles])
30
-
31
- // reset input
32
- event.target.value = ''
33
- }
34
-
35
- const handleRemove = (
36
- fileIndex: number,
37
- value: FileUpload[] | undefined = [],
38
- finalFormOnChange: FinalFormOnChangeType
39
- ) => {
40
- const updatedFiles = value.filter((_, index) => index !== fileIndex)
41
-
42
- finalFormOnChange(updatedFiles)
43
- }
44
-
45
- return (
46
- <FieldWrapper<FileInputProps, FileUpload[] | undefined> {...props}>
47
- {inputProps => (
48
- <PicassoFileInput
49
- {...inputProps}
50
- onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
51
- handleChange(event, inputProps.value, inputProps.onChange)
52
- }}
53
- onRemove={(fileName: string, index: number) => {
54
- handleRemove(index, inputProps.value, inputProps.onChange)
55
- }}
56
- />
57
- )}
58
- </FieldWrapper>
59
- )
60
- }
61
-
62
- FileInput.defaultProps = {}
63
-
64
- FileInput.displayName = 'FileInput'
65
-
66
- export default FileInput
@@ -1 +0,0 @@
1
- export { default } from './FileInput'