@toptal/picasso-forms 67.0.0 → 67.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.
- package/dist-package/src/Autocomplete/Autocomplete.d.ts +2 -1
- package/dist-package/src/Autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist-package/src/Autocomplete/Autocomplete.js +2 -2
- package/dist-package/src/Autocomplete/Autocomplete.js.map +1 -1
- package/dist-package/src/AvatarUpload/AvatarUpload.d.ts +2 -1
- package/dist-package/src/AvatarUpload/AvatarUpload.d.ts.map +1 -1
- package/dist-package/src/AvatarUpload/AvatarUpload.js +3 -3
- package/dist-package/src/AvatarUpload/AvatarUpload.js.map +1 -1
- package/dist-package/src/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist-package/src/Checkbox/Checkbox.js +5 -2
- package/dist-package/src/Checkbox/Checkbox.js.map +1 -1
- package/dist-package/src/CheckboxGroup/CheckboxGroup.d.ts +2 -1
- package/dist-package/src/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
- package/dist-package/src/CheckboxGroup/CheckboxGroup.js +2 -2
- package/dist-package/src/CheckboxGroup/CheckboxGroup.js.map +1 -1
- package/dist-package/src/DatePicker/DatePicker.d.ts +2 -1
- package/dist-package/src/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist-package/src/DatePicker/DatePicker.js +2 -2
- package/dist-package/src/DatePicker/DatePicker.js.map +1 -1
- package/dist-package/src/Dropzone/Dropzone.d.ts +2 -1
- package/dist-package/src/Dropzone/Dropzone.d.ts.map +1 -1
- package/dist-package/src/Dropzone/Dropzone.js +1 -1
- package/dist-package/src/Dropzone/Dropzone.js.map +1 -1
- package/dist-package/src/FieldLabel/FieldLabel.d.ts +9 -4
- package/dist-package/src/FieldLabel/FieldLabel.d.ts.map +1 -1
- package/dist-package/src/FieldLabel/FieldLabel.js +2 -3
- package/dist-package/src/FieldLabel/FieldLabel.js.map +1 -1
- package/dist-package/src/FieldWrapper/FieldWrapper.d.ts +3 -4
- package/dist-package/src/FieldWrapper/FieldWrapper.d.ts.map +1 -1
- package/dist-package/src/FieldWrapper/FieldWrapper.js +2 -2
- package/dist-package/src/FieldWrapper/FieldWrapper.js.map +1 -1
- package/dist-package/src/FileInput/FileInput.d.ts +2 -1
- package/dist-package/src/FileInput/FileInput.d.ts.map +1 -1
- package/dist-package/src/FileInput/FileInput.js +1 -1
- package/dist-package/src/FileInput/FileInput.js.map +1 -1
- package/dist-package/src/Form/Form.d.ts +1 -0
- package/dist-package/src/Form/Form.d.ts.map +1 -1
- package/dist-package/src/Form/Form.js +2 -2
- package/dist-package/src/Form/Form.js.map +1 -1
- package/dist-package/src/FormCompound/index.d.ts +6 -1
- package/dist-package/src/FormCompound/index.d.ts.map +1 -1
- package/dist-package/src/Input/Input.d.ts +2 -1
- package/dist-package/src/Input/Input.d.ts.map +1 -1
- package/dist-package/src/Input/Input.js +2 -2
- package/dist-package/src/Input/Input.js.map +1 -1
- package/dist-package/src/NumberInput/NumberInput.d.ts +2 -1
- package/dist-package/src/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist-package/src/NumberInput/NumberInput.js +2 -2
- package/dist-package/src/NumberInput/NumberInput.js.map +1 -1
- package/dist-package/src/PasswordInput/PasswordInput.d.ts +2 -1
- package/dist-package/src/PasswordInput/PasswordInput.d.ts.map +1 -1
- package/dist-package/src/PasswordInput/PasswordInput.js +1 -1
- package/dist-package/src/PasswordInput/PasswordInput.js.map +1 -1
- package/dist-package/src/RadioGroup/RadioGroup.d.ts +2 -1
- package/dist-package/src/RadioGroup/RadioGroup.d.ts.map +1 -1
- package/dist-package/src/RadioGroup/RadioGroup.js +2 -2
- package/dist-package/src/RadioGroup/RadioGroup.js.map +1 -1
- package/dist-package/src/Rating/Rating.d.ts +2 -1
- package/dist-package/src/Rating/Rating.d.ts.map +1 -1
- package/dist-package/src/Rating/Rating.js +4 -4
- package/dist-package/src/Rating/Rating.js.map +1 -1
- package/dist-package/src/RichTextEditor/RichTextEditor.d.ts +2 -1
- package/dist-package/src/RichTextEditor/RichTextEditor.d.ts.map +1 -1
- package/dist-package/src/RichTextEditor/RichTextEditor.js +2 -2
- package/dist-package/src/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist-package/src/Select/Select.d.ts +2 -1
- package/dist-package/src/Select/Select.d.ts.map +1 -1
- package/dist-package/src/Select/Select.js +2 -2
- package/dist-package/src/Select/Select.js.map +1 -1
- package/dist-package/src/Switch/Switch.d.ts +2 -1
- package/dist-package/src/Switch/Switch.d.ts.map +1 -1
- package/dist-package/src/Switch/Switch.js +1 -1
- package/dist-package/src/Switch/Switch.js.map +1 -1
- package/dist-package/src/TagSelector/TagSelector.d.ts +2 -1
- package/dist-package/src/TagSelector/TagSelector.d.ts.map +1 -1
- package/dist-package/src/TagSelector/TagSelector.js +2 -2
- package/dist-package/src/TagSelector/TagSelector.js.map +1 -1
- package/dist-package/src/TimePicker/TimePicker.d.ts +2 -1
- package/dist-package/src/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist-package/src/TimePicker/TimePicker.js +2 -2
- package/dist-package/src/TimePicker/TimePicker.js.map +1 -1
- package/package.json +2 -2
- package/src/Autocomplete/Autocomplete.tsx +6 -2
- package/src/AvatarUpload/AvatarUpload.tsx +6 -1
- package/src/Checkbox/Checkbox.tsx +17 -7
- package/src/CheckboxGroup/CheckboxGroup.tsx +11 -2
- package/src/DatePicker/DatePicker.tsx +6 -2
- package/src/Dropzone/Dropzone.tsx +3 -1
- package/src/FieldLabel/FieldLabel.tsx +18 -5
- package/src/FieldWrapper/FieldWrapper.tsx +6 -6
- package/src/FieldWrapper/story/index.jsx +6 -1
- package/src/FileInput/FileInput.tsx +5 -1
- package/src/Form/Form.tsx +3 -0
- package/src/Form/story/Horizontal.example.tsx +68 -35
- package/src/Input/Input.tsx +6 -2
- package/src/NumberInput/NumberInput.tsx +14 -2
- package/src/PasswordInput/PasswordInput.tsx +5 -1
- package/src/RadioGroup/RadioGroup.tsx +6 -2
- package/src/Rating/Rating.tsx +15 -4
- package/src/RichTextEditor/RichTextEditor.tsx +13 -2
- package/src/Select/Select.tsx +11 -2
- package/src/Switch/Switch.tsx +9 -2
- package/src/TagSelector/TagSelector.tsx +6 -2
- package/src/TimePicker/TimePicker.tsx +6 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
1
2
|
import React from 'react'
|
|
2
3
|
import type { RequiredDecoration } from '@toptal/picasso'
|
|
3
4
|
import { Form as PicassoForm } from '@toptal/picasso'
|
|
@@ -8,11 +9,17 @@ import { useFormConfig } from '../FormConfig'
|
|
|
8
9
|
|
|
9
10
|
export type Props = {
|
|
10
11
|
name?: string
|
|
11
|
-
label?:
|
|
12
|
+
label?: ReactNode
|
|
13
|
+
/** Label's end adornment */
|
|
14
|
+
labelEndAdornment?: ReactNode
|
|
12
15
|
required?: boolean
|
|
13
|
-
alignment?: 'top' | 'middle'
|
|
14
16
|
} & TextLabelProps
|
|
15
17
|
|
|
18
|
+
type InternalProps = {
|
|
19
|
+
/** Whether label should be aligned to top of the container or not */
|
|
20
|
+
alignment?: 'top' | 'middle'
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
const getRequiredDecoration = (
|
|
17
24
|
required?: boolean,
|
|
18
25
|
requiredVariant?: RequiredVariant
|
|
@@ -31,9 +38,14 @@ const getRequiredDecoration = (
|
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
const FieldLabel = (
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
const FieldLabel = ({
|
|
42
|
+
label,
|
|
43
|
+
required,
|
|
44
|
+
titleCase,
|
|
45
|
+
name,
|
|
46
|
+
alignment,
|
|
47
|
+
labelEndAdornment,
|
|
48
|
+
}: Props & InternalProps) => {
|
|
37
49
|
const formConfig = useFormConfig()
|
|
38
50
|
|
|
39
51
|
if (!label) {
|
|
@@ -51,6 +63,7 @@ const FieldLabel = (props: Props) => {
|
|
|
51
63
|
htmlFor={name}
|
|
52
64
|
titleCase={titleCase}
|
|
53
65
|
alignment={alignment}
|
|
66
|
+
labelEndAdornment={labelEndAdornment}
|
|
54
67
|
>
|
|
55
68
|
{label}
|
|
56
69
|
</PicassoForm.Label>
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import type { ReactNode } from 'react'
|
|
2
1
|
import React from 'react'
|
|
3
2
|
|
|
4
3
|
import type { Props as FieldProps } from '../Field'
|
|
5
4
|
import type { ValueType, IFormComponentProps } from '../FieldBase'
|
|
5
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
6
6
|
import FieldLabel from '../FieldLabel'
|
|
7
7
|
import InputField from '../InputField'
|
|
8
8
|
|
|
9
9
|
export type Props<TWrappedComponentProps, TInputValue> = Omit<
|
|
10
10
|
FieldProps<TWrappedComponentProps, TInputValue>,
|
|
11
11
|
'label'
|
|
12
|
-
> &
|
|
13
|
-
|
|
14
|
-
}
|
|
12
|
+
> &
|
|
13
|
+
Omit<FieldLabelProps, 'name'>
|
|
15
14
|
|
|
16
15
|
const FieldWrapper = <
|
|
17
16
|
TWrappedComponentProps extends IFormComponentProps,
|
|
@@ -19,7 +18,7 @@ const FieldWrapper = <
|
|
|
19
18
|
>(
|
|
20
19
|
props: Props<TWrappedComponentProps, TInputValue>
|
|
21
20
|
) => {
|
|
22
|
-
const { label, name, titleCase, children, ...rest } = props
|
|
21
|
+
const { label, labelEndAdornment, name, titleCase, children, ...rest } = props
|
|
23
22
|
|
|
24
23
|
return (
|
|
25
24
|
<InputField<IFormComponentProps, TInputValue>
|
|
@@ -28,9 +27,10 @@ const FieldWrapper = <
|
|
|
28
27
|
label={
|
|
29
28
|
label ? (
|
|
30
29
|
<FieldLabel
|
|
31
|
-
name={
|
|
30
|
+
name={name}
|
|
32
31
|
required={props.required}
|
|
33
32
|
label={label}
|
|
33
|
+
labelEndAdornment={labelEndAdornment}
|
|
34
34
|
titleCase={titleCase}
|
|
35
35
|
/>
|
|
36
36
|
) : null
|
|
@@ -14,9 +14,14 @@ const componentDocs = PicassoBook.createComponentDocs(
|
|
|
14
14
|
},
|
|
15
15
|
label: {
|
|
16
16
|
name: 'label',
|
|
17
|
-
type: '
|
|
17
|
+
type: 'ReactNode',
|
|
18
18
|
description: 'The field label text',
|
|
19
19
|
},
|
|
20
|
+
labelEndAdornment: {
|
|
21
|
+
name: 'labelEndAdornment',
|
|
22
|
+
type: 'ReactNode',
|
|
23
|
+
description: "The label's end adornment",
|
|
24
|
+
},
|
|
20
25
|
hint: {
|
|
21
26
|
name: 'hint',
|
|
22
27
|
type: 'string',
|
|
@@ -6,12 +6,15 @@ import type { FieldInputProps as FinalFieldInputProps } from 'react-final-form'
|
|
|
6
6
|
import type { FieldProps } from '../Field'
|
|
7
7
|
import PicassoField from '../Field'
|
|
8
8
|
import FieldLabel from '../FieldLabel'
|
|
9
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
9
10
|
|
|
10
11
|
type FinalFormOnChangeType = FinalFieldInputProps<
|
|
11
12
|
FileInputProps['value']
|
|
12
13
|
>['onChange']
|
|
13
14
|
|
|
14
|
-
export type Props = FileInputProps &
|
|
15
|
+
export type Props = FileInputProps &
|
|
16
|
+
FieldProps<FileInputProps['value']> &
|
|
17
|
+
FieldLabelProps
|
|
15
18
|
|
|
16
19
|
export const FileInput = (props: Props) => {
|
|
17
20
|
const handleChange = (
|
|
@@ -53,6 +56,7 @@ export const FileInput = (props: Props) => {
|
|
|
53
56
|
name={props.name}
|
|
54
57
|
required={props.required}
|
|
55
58
|
label={props.label}
|
|
59
|
+
labelEndAdornment={props.labelEndAdornment}
|
|
56
60
|
titleCase={props.titleCase}
|
|
57
61
|
/>
|
|
58
62
|
) : null
|
package/src/Form/Form.tsx
CHANGED
|
@@ -21,6 +21,7 @@ export type Props<T = AnyObject> = FinalFormProps<T> & {
|
|
|
21
21
|
scrollOffsetTop?: number
|
|
22
22
|
layout?: 'horizontal' | 'vertical'
|
|
23
23
|
labelWidth?: FormProps['labelWidth']
|
|
24
|
+
className?: string
|
|
24
25
|
'data-testid'?: string
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -63,6 +64,7 @@ export const Form = <T extends AnyObject = AnyObject>(props: Props<T>) => {
|
|
|
63
64
|
'data-testid': dataTestId,
|
|
64
65
|
layout,
|
|
65
66
|
labelWidth,
|
|
67
|
+
className,
|
|
66
68
|
...rest
|
|
67
69
|
} = props
|
|
68
70
|
const { showSuccess, showError } = useNotifications()
|
|
@@ -136,6 +138,7 @@ export const Form = <T extends AnyObject = AnyObject>(props: Props<T>) => {
|
|
|
136
138
|
setActiveFieldTouched={form.mutators.setActiveFieldTouched}
|
|
137
139
|
labelWidth={labelWidth}
|
|
138
140
|
layout={layout}
|
|
141
|
+
className={className}
|
|
139
142
|
>
|
|
140
143
|
{children}
|
|
141
144
|
</FormRenderer>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Container,
|
|
5
|
+
FormActionsContainer,
|
|
6
|
+
Info16,
|
|
7
|
+
Tooltip,
|
|
8
|
+
} from '@toptal/picasso'
|
|
9
|
+
import { SPACING_4, isSubstring, SPACING_1 } from '@toptal/picasso/utils'
|
|
4
10
|
import type { Item } from '@toptal/picasso/Autocomplete'
|
|
5
11
|
import {
|
|
6
12
|
FormNonCompound as Form,
|
|
@@ -60,7 +66,7 @@ const filterOptions = (str = '', options: Item[] = []): Item[] | null => {
|
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
const initialValues = {
|
|
63
|
-
'
|
|
69
|
+
'horizontal-gender': 'female',
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
// eslint-disable-next-line max-lines-per-function
|
|
@@ -88,97 +94,124 @@ const Example = () => {
|
|
|
88
94
|
set('')
|
|
89
95
|
}}
|
|
90
96
|
required
|
|
91
|
-
name='
|
|
97
|
+
name='horizontal-firstName'
|
|
92
98
|
label='First name'
|
|
93
99
|
placeholder='e.g. Bruce'
|
|
94
100
|
/>
|
|
95
101
|
<Input
|
|
96
102
|
required
|
|
97
|
-
name='
|
|
103
|
+
name='horizontal-lastName'
|
|
98
104
|
label='Last name'
|
|
99
105
|
placeholder='e.g. Wayne'
|
|
100
106
|
size='small'
|
|
101
107
|
/>
|
|
102
108
|
<Input
|
|
103
109
|
required
|
|
104
|
-
name='
|
|
110
|
+
name='horizontal-nickName'
|
|
105
111
|
label='Nick name'
|
|
106
112
|
placeholder='e.g. Batman'
|
|
107
113
|
/>
|
|
108
114
|
<Input
|
|
109
115
|
required
|
|
110
|
-
name='
|
|
116
|
+
name='horizontal-website'
|
|
111
117
|
label='Website'
|
|
112
118
|
placeholder='e.g. google.com'
|
|
113
119
|
size='large'
|
|
114
120
|
/>
|
|
115
|
-
<Input
|
|
121
|
+
<Input
|
|
122
|
+
name='horizontal-multiline'
|
|
123
|
+
label='Description'
|
|
124
|
+
multiline
|
|
125
|
+
rows={4}
|
|
126
|
+
/>
|
|
116
127
|
<RichTextEditor
|
|
117
|
-
name='
|
|
118
|
-
id='
|
|
128
|
+
name='horizontal-richTextEditorName'
|
|
129
|
+
id='horizontal-richTextEditorName'
|
|
119
130
|
label='Rich text editor'
|
|
120
131
|
/>
|
|
121
|
-
<Dropzone label='Attachments' required name='
|
|
132
|
+
<Dropzone label='Attachments' required name='horizontal-attachments' />
|
|
122
133
|
<AvatarUpload
|
|
123
134
|
label='Profile photo xxsmall'
|
|
124
135
|
required
|
|
125
|
-
name='
|
|
136
|
+
name='horizontal-avatarUpload-xxsmall'
|
|
126
137
|
size='xxsmall'
|
|
127
138
|
/>
|
|
128
139
|
<AvatarUpload
|
|
129
140
|
label='Profile photo xsmall'
|
|
130
141
|
required
|
|
131
|
-
name='
|
|
142
|
+
name='horizontal-avatarUpload-xsmall'
|
|
132
143
|
size='xsmall'
|
|
133
144
|
/>
|
|
134
145
|
<AvatarUpload
|
|
135
146
|
label='Profile photo'
|
|
136
147
|
required
|
|
137
|
-
name='
|
|
148
|
+
name='horizontal-avatarUpload-small'
|
|
138
149
|
/>
|
|
139
150
|
<AvatarUpload
|
|
140
151
|
label='Profile photo medium'
|
|
141
152
|
required
|
|
142
|
-
name='
|
|
153
|
+
name='horizontal-avatarUpload-medium'
|
|
143
154
|
size='medium'
|
|
144
155
|
/>
|
|
145
156
|
<AvatarUpload
|
|
146
157
|
label='Profile photo large'
|
|
147
158
|
required
|
|
148
|
-
name='
|
|
159
|
+
name='horizontal-avatarUpload-large'
|
|
149
160
|
size='large'
|
|
150
161
|
/>
|
|
151
162
|
<NumberInput
|
|
152
163
|
enableReset
|
|
153
|
-
|
|
154
|
-
name='default-age'
|
|
164
|
+
name='horizontal-age'
|
|
155
165
|
label="What's your age?"
|
|
156
166
|
placeholder='e.g. 25'
|
|
167
|
+
labelEndAdornment={
|
|
168
|
+
<Container inline left={SPACING_1}>
|
|
169
|
+
<Tooltip content='Content goes here...' placement='right'>
|
|
170
|
+
<Button.Circular variant='flat' icon={<Info16 />} />
|
|
171
|
+
</Tooltip>
|
|
172
|
+
</Container>
|
|
173
|
+
}
|
|
157
174
|
/>
|
|
158
|
-
<RadioGroup
|
|
175
|
+
<RadioGroup
|
|
176
|
+
name='horizontal-gender'
|
|
177
|
+
label='Gender'
|
|
178
|
+
required
|
|
179
|
+
labelEndAdornment={
|
|
180
|
+
<Container inline left={SPACING_1}>
|
|
181
|
+
<Tooltip content='Content goes here...' placement='right'>
|
|
182
|
+
<Button.Circular variant='flat' icon={<Info16 />} />
|
|
183
|
+
</Tooltip>
|
|
184
|
+
</Container>
|
|
185
|
+
}
|
|
186
|
+
>
|
|
159
187
|
<Radio label='Male' value='male' />
|
|
160
188
|
<Radio label='Female' value='female' />
|
|
161
189
|
</RadioGroup>
|
|
162
|
-
<RadioGroup name='
|
|
190
|
+
<RadioGroup name='horizontal-language-radio' label='Languages'>
|
|
163
191
|
<Radio label='English' value='english' />
|
|
164
192
|
<Radio label='French' value='french' />
|
|
165
193
|
<Radio label='German' value='german' />
|
|
166
194
|
</RadioGroup>
|
|
167
|
-
<RadioGroup
|
|
195
|
+
<RadioGroup
|
|
196
|
+
name='horizontal-gender-2'
|
|
197
|
+
label='Gender'
|
|
198
|
+
horizontal
|
|
199
|
+
spacing={8}
|
|
200
|
+
>
|
|
168
201
|
<ButtonRadio value='male'>Male</ButtonRadio>
|
|
169
202
|
<ButtonRadio value='female'>Female</ButtonRadio>
|
|
170
203
|
</RadioGroup>
|
|
171
|
-
<CheckboxGroup name='
|
|
204
|
+
<CheckboxGroup name='horizontal-hobbies' label='Hobbies'>
|
|
172
205
|
<Checkbox label='Skiing' value='skiing' />
|
|
173
206
|
<Checkbox label='Free diving' value='freeDiving' />
|
|
174
207
|
<Checkbox label='Dancing' value='dancing' />
|
|
175
208
|
</CheckboxGroup>
|
|
176
|
-
<CheckboxGroup name='
|
|
209
|
+
<CheckboxGroup name='horizontal-language' label='Languages'>
|
|
177
210
|
<Checkbox label='English' value='english' />
|
|
178
211
|
<Checkbox label='French' value='french' />
|
|
179
212
|
</CheckboxGroup>
|
|
180
213
|
<CheckboxGroup
|
|
181
|
-
name='
|
|
214
|
+
name='horizontal-hobbies-buttons'
|
|
182
215
|
label='Hobbies'
|
|
183
216
|
horizontal
|
|
184
217
|
spacing={8}
|
|
@@ -187,10 +220,10 @@ const Example = () => {
|
|
|
187
220
|
<ButtonCheckbox value='freeDiving'>Free diving</ButtonCheckbox>
|
|
188
221
|
<ButtonCheckbox value='dancing'>Dancing</ButtonCheckbox>
|
|
189
222
|
</CheckboxGroup>
|
|
190
|
-
<DatePicker name='
|
|
191
|
-
<TimePicker name='
|
|
223
|
+
<DatePicker name='horizontal-dateOfBirth' label='Date of birth' />
|
|
224
|
+
<TimePicker name='horizontal-timeOfBirth' label='Time of birth' />
|
|
192
225
|
<TagSelector
|
|
193
|
-
name='
|
|
226
|
+
name='horizontal-skills'
|
|
194
227
|
label='Skills'
|
|
195
228
|
inputValue={skillInputValue}
|
|
196
229
|
options={skillOptions}
|
|
@@ -206,7 +239,7 @@ const Example = () => {
|
|
|
206
239
|
<Select
|
|
207
240
|
enableReset
|
|
208
241
|
required
|
|
209
|
-
name='
|
|
242
|
+
name='horizontal-businessType'
|
|
210
243
|
label='Business type'
|
|
211
244
|
width='auto'
|
|
212
245
|
options={[
|
|
@@ -215,13 +248,13 @@ const Example = () => {
|
|
|
215
248
|
]}
|
|
216
249
|
/>
|
|
217
250
|
<Select
|
|
218
|
-
name='
|
|
251
|
+
name='horizontal-origin_country'
|
|
219
252
|
label='Origin country'
|
|
220
253
|
width='auto'
|
|
221
254
|
options={countries}
|
|
222
255
|
/>
|
|
223
256
|
<Autocomplete
|
|
224
|
-
name='
|
|
257
|
+
name='horizontal-current_country'
|
|
225
258
|
label='Current country'
|
|
226
259
|
placeholder='Start typing country...'
|
|
227
260
|
width='auto'
|
|
@@ -245,28 +278,28 @@ const Example = () => {
|
|
|
245
278
|
getDisplayValue={getAutocompleteDisplayValue}
|
|
246
279
|
/>
|
|
247
280
|
<Rating.Stars
|
|
248
|
-
name='
|
|
281
|
+
name='horizontal-rating'
|
|
249
282
|
label='How much do you love Picasso?'
|
|
250
283
|
required
|
|
251
284
|
/>
|
|
252
285
|
<Rating.Thumbs
|
|
253
|
-
name='
|
|
286
|
+
name='horizontal-thumbs'
|
|
254
287
|
label='Would you recommend Picasso?'
|
|
255
288
|
required
|
|
256
289
|
/>
|
|
257
290
|
<FileInput
|
|
258
291
|
required
|
|
259
|
-
name='
|
|
292
|
+
name='horizontal-resume'
|
|
260
293
|
label='Resume'
|
|
261
294
|
status='No file selected.'
|
|
262
295
|
/>
|
|
263
296
|
<Checkbox
|
|
264
297
|
required
|
|
265
|
-
name='
|
|
298
|
+
name='horizontal-legal'
|
|
266
299
|
label='I confirm that I have legal permission from the client to feature this project.'
|
|
267
300
|
/>
|
|
268
301
|
<Switch
|
|
269
|
-
name='
|
|
302
|
+
name='horizontal-publicProfile'
|
|
270
303
|
label='Public Profile'
|
|
271
304
|
width='auto'
|
|
272
305
|
/>
|
package/src/Input/Input.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { Input as PicassoInput } from '@toptal/picasso'
|
|
|
4
4
|
import { useForm } from 'react-final-form'
|
|
5
5
|
|
|
6
6
|
import type { FieldProps } from '../Field'
|
|
7
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
7
8
|
import FieldLabel from '../FieldLabel'
|
|
8
9
|
import InputField from '../InputField'
|
|
9
10
|
|
|
@@ -11,7 +12,9 @@ export type FormInputProps = Omit<InputProps, 'onResetClick'> & {
|
|
|
11
12
|
/** Callback invoked when reset button was clicked */
|
|
12
13
|
onResetClick?: (set: (value: string) => void) => void
|
|
13
14
|
}
|
|
14
|
-
export type Props = FormInputProps &
|
|
15
|
+
export type Props = FormInputProps &
|
|
16
|
+
FieldProps<InputProps['value']> &
|
|
17
|
+
FieldLabelProps
|
|
15
18
|
|
|
16
19
|
const warnAutocompleteDisabledInput = (name?: string) => {
|
|
17
20
|
const autocompleteDisabled =
|
|
@@ -37,7 +40,7 @@ export const Input = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
|
|
|
37
40
|
mutators: { setHasMultilineCounter },
|
|
38
41
|
} = useForm()
|
|
39
42
|
|
|
40
|
-
const { label, titleCase, ...rest } = props
|
|
43
|
+
const { label, labelEndAdornment, titleCase, ...rest } = props
|
|
41
44
|
const { multiline, rows, rowsMax } = props
|
|
42
45
|
|
|
43
46
|
const alignment = useMemo(() => {
|
|
@@ -62,6 +65,7 @@ export const Input = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
|
|
|
62
65
|
name={props.name}
|
|
63
66
|
required={props.required}
|
|
64
67
|
label={label}
|
|
68
|
+
labelEndAdornment={labelEndAdornment}
|
|
65
69
|
titleCase={titleCase}
|
|
66
70
|
alignment={alignment}
|
|
67
71
|
/>
|
|
@@ -5,10 +5,13 @@ import type { FieldValidator } from 'final-form'
|
|
|
5
5
|
|
|
6
6
|
import { validators } from '../utils'
|
|
7
7
|
import type { FieldProps } from '../Field'
|
|
8
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
8
9
|
import FieldLabel from '../FieldLabel'
|
|
9
10
|
import InputField from '../InputField'
|
|
10
11
|
|
|
11
|
-
export type Props = NumberInputProps &
|
|
12
|
+
export type Props = NumberInputProps &
|
|
13
|
+
FieldProps<NumberInputProps['value']> &
|
|
14
|
+
FieldLabelProps
|
|
12
15
|
|
|
13
16
|
const MIN = -2147483648
|
|
14
17
|
const MAX = 2147483647
|
|
@@ -16,7 +19,15 @@ const MAX = 2147483647
|
|
|
16
19
|
const { composeValidators } = validators
|
|
17
20
|
|
|
18
21
|
export const NumberInput = (props: Props) => {
|
|
19
|
-
const {
|
|
22
|
+
const {
|
|
23
|
+
min = MIN,
|
|
24
|
+
max = MAX,
|
|
25
|
+
validate,
|
|
26
|
+
label,
|
|
27
|
+
labelEndAdornment,
|
|
28
|
+
titleCase,
|
|
29
|
+
...rest
|
|
30
|
+
} = props
|
|
20
31
|
|
|
21
32
|
const validateNumberLimits: FieldValidator<
|
|
22
33
|
NumberInputProps['value']
|
|
@@ -39,6 +50,7 @@ export const NumberInput = (props: Props) => {
|
|
|
39
50
|
name={props.name}
|
|
40
51
|
required={props.required}
|
|
41
52
|
label={label}
|
|
53
|
+
labelEndAdornment={labelEndAdornment}
|
|
42
54
|
titleCase={titleCase}
|
|
43
55
|
/>
|
|
44
56
|
) : null
|
|
@@ -6,13 +6,16 @@ import type { FieldValidator } from 'final-form'
|
|
|
6
6
|
|
|
7
7
|
import { validators } from '../utils'
|
|
8
8
|
import type { FieldProps } from '../Field'
|
|
9
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
9
10
|
import FieldLabel from '../FieldLabel'
|
|
10
11
|
import passwordValidators from './validators'
|
|
11
12
|
import InputField from '../InputField'
|
|
12
13
|
import FieldRenderer from './FieldRenderer'
|
|
13
14
|
|
|
14
15
|
export type Props = PasswordInputProps &
|
|
15
|
-
FieldProps<PasswordInputProps['value']> & {
|
|
16
|
+
FieldProps<PasswordInputProps['value']> & {
|
|
17
|
+
hideRequirements?: boolean
|
|
18
|
+
} & FieldLabelProps
|
|
16
19
|
|
|
17
20
|
const { composeValidators } = validators
|
|
18
21
|
|
|
@@ -121,6 +124,7 @@ export const PasswordInput = ({
|
|
|
121
124
|
name={rest.name}
|
|
122
125
|
required={rest.required}
|
|
123
126
|
label={rest.label}
|
|
127
|
+
labelEndAdornment={rest.labelEndAdornment}
|
|
124
128
|
titleCase={rest.titleCase}
|
|
125
129
|
/>
|
|
126
130
|
) : null
|
|
@@ -5,12 +5,15 @@ import { Radio as PicassoRadio } from '@toptal/picasso'
|
|
|
5
5
|
import type { FieldProps } from '../Field'
|
|
6
6
|
import PicassoField from '../Field'
|
|
7
7
|
import FieldLabel from '../FieldLabel'
|
|
8
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
8
9
|
import RadioGroupContext from './RadioGroupContext'
|
|
9
10
|
|
|
10
|
-
export type Props = RadioGroupProps &
|
|
11
|
+
export type Props = RadioGroupProps &
|
|
12
|
+
FieldProps<RadioProps['value']> &
|
|
13
|
+
FieldLabelProps
|
|
11
14
|
|
|
12
15
|
export const RadioGroup = (props: Props) => {
|
|
13
|
-
const { children, label, titleCase, ...rest } = props
|
|
16
|
+
const { children, label, labelEndAdornment, titleCase, ...rest } = props
|
|
14
17
|
|
|
15
18
|
const alignment = Children.count(children) > 2 ? 'top' : 'middle'
|
|
16
19
|
|
|
@@ -25,6 +28,7 @@ export const RadioGroup = (props: Props) => {
|
|
|
25
28
|
name={props.name}
|
|
26
29
|
required={props.required}
|
|
27
30
|
label={label}
|
|
31
|
+
labelEndAdornment={labelEndAdornment}
|
|
28
32
|
titleCase={titleCase}
|
|
29
33
|
alignment={alignment}
|
|
30
34
|
/>
|
package/src/Rating/Rating.tsx
CHANGED
|
@@ -8,13 +8,15 @@ import { Rating as PicassoRating } from '@toptal/picasso'
|
|
|
8
8
|
import type { FieldProps } from '../Field'
|
|
9
9
|
import PicassoField from '../Field'
|
|
10
10
|
import FieldLabel from '../FieldLabel'
|
|
11
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
11
12
|
import { validators } from '../utils'
|
|
12
13
|
|
|
13
14
|
export type RatingStarsProps = PicassoRatingStarsProps &
|
|
14
|
-
FieldProps<PicassoRatingStarsProps['value']>
|
|
15
|
+
FieldProps<PicassoRatingStarsProps['value']> &
|
|
16
|
+
FieldLabelProps
|
|
15
17
|
|
|
16
18
|
const Stars = (props: RatingStarsProps) => {
|
|
17
|
-
const { label, titleCase, ...rest } = props
|
|
19
|
+
const { label, labelEndAdornment, titleCase, ...rest } = props
|
|
18
20
|
|
|
19
21
|
return (
|
|
20
22
|
<PicassoField<PicassoRatingStarsProps>
|
|
@@ -26,6 +28,7 @@ const Stars = (props: RatingStarsProps) => {
|
|
|
26
28
|
name={props.name}
|
|
27
29
|
required={props.required}
|
|
28
30
|
label={label}
|
|
31
|
+
labelEndAdornment={labelEndAdornment}
|
|
29
32
|
titleCase={titleCase}
|
|
30
33
|
/>
|
|
31
34
|
) : null
|
|
@@ -58,8 +61,15 @@ const thumbsRequired = (value: boolean | undefined) =>
|
|
|
58
61
|
value == null ? validators.required(null) : undefined
|
|
59
62
|
|
|
60
63
|
const Thumbs = (props: RatingThumbsProps) => {
|
|
61
|
-
const {
|
|
62
|
-
|
|
64
|
+
const {
|
|
65
|
+
required,
|
|
66
|
+
validate,
|
|
67
|
+
requirePositive,
|
|
68
|
+
label,
|
|
69
|
+
labelEndAdornment,
|
|
70
|
+
titleCase,
|
|
71
|
+
...rest
|
|
72
|
+
} = props
|
|
63
73
|
|
|
64
74
|
const validateOverride = validators.composeValidators([
|
|
65
75
|
required && !requirePositive ? thumbsRequired : undefined,
|
|
@@ -77,6 +87,7 @@ const Thumbs = (props: RatingThumbsProps) => {
|
|
|
77
87
|
name={props.name}
|
|
78
88
|
required={props.required}
|
|
79
89
|
label={label}
|
|
90
|
+
labelEndAdornment={labelEndAdornment}
|
|
80
91
|
titleCase={titleCase}
|
|
81
92
|
/>
|
|
82
93
|
) : null
|
|
@@ -10,6 +10,7 @@ import { useForm } from 'react-final-form'
|
|
|
10
10
|
import type { FieldProps } from '../FieldWrapper'
|
|
11
11
|
import InputField from '../InputField'
|
|
12
12
|
import FieldLabel from '../FieldLabel'
|
|
13
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
13
14
|
import { useEnforceHighlightAutofill } from './hooks'
|
|
14
15
|
|
|
15
16
|
type OverriddenProps = {
|
|
@@ -20,12 +21,21 @@ type OverriddenProps = {
|
|
|
20
21
|
|
|
21
22
|
export type Props = RichTextEditorProps &
|
|
22
23
|
Except<FieldProps<string>, keyof OverriddenProps> &
|
|
23
|
-
OverriddenProps
|
|
24
|
+
OverriddenProps &
|
|
25
|
+
FieldLabelProps
|
|
24
26
|
|
|
25
27
|
type InternalProps = RichTextEditorProps & { value: string }
|
|
26
28
|
|
|
27
29
|
export const RichTextEditor = (props: Props) => {
|
|
28
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
onChange,
|
|
32
|
+
onFocus,
|
|
33
|
+
defaultValue,
|
|
34
|
+
label,
|
|
35
|
+
labelEndAdornment,
|
|
36
|
+
titleCase,
|
|
37
|
+
...rest
|
|
38
|
+
} = props
|
|
29
39
|
|
|
30
40
|
const { enforceHighlightAutofill, registerChangeOrFocus } =
|
|
31
41
|
useEnforceHighlightAutofill()
|
|
@@ -64,6 +74,7 @@ export const RichTextEditor = (props: Props) => {
|
|
|
64
74
|
name={hiddenInputId}
|
|
65
75
|
required={props.required}
|
|
66
76
|
label={label}
|
|
77
|
+
labelEndAdornment={labelEndAdornment}
|
|
67
78
|
titleCase={titleCase}
|
|
68
79
|
alignment='top'
|
|
69
80
|
/>
|
package/src/Select/Select.tsx
CHANGED
|
@@ -6,16 +6,24 @@ import { generateRandomStringOrGetEmptyInTest } from '@toptal/picasso-utils'
|
|
|
6
6
|
import type { FieldProps } from '../Field'
|
|
7
7
|
import InputField from '../InputField'
|
|
8
8
|
import FieldLabel from '../FieldLabel'
|
|
9
|
+
import type { Props as FieldLabelProps } from '../FieldLabel'
|
|
9
10
|
|
|
10
11
|
export type Props<
|
|
11
12
|
T extends SelectValueType,
|
|
12
13
|
M extends boolean = false
|
|
13
|
-
> = SelectProps<T, M> & FieldProps<SelectProps<T, M>['value']>
|
|
14
|
+
> = SelectProps<T, M> & FieldProps<SelectProps<T, M>['value']> & FieldLabelProps
|
|
14
15
|
|
|
15
16
|
export const Select = <T extends SelectValueType, M extends boolean = false>(
|
|
16
17
|
props: Props<T, M>
|
|
17
18
|
) => {
|
|
18
|
-
const {
|
|
19
|
+
const {
|
|
20
|
+
name,
|
|
21
|
+
id = name,
|
|
22
|
+
label,
|
|
23
|
+
labelEndAdornment,
|
|
24
|
+
titleCase,
|
|
25
|
+
...rest
|
|
26
|
+
} = props
|
|
19
27
|
const randomizedId = id ? generateRandomStringOrGetEmptyInTest(id) : undefined
|
|
20
28
|
|
|
21
29
|
return (
|
|
@@ -29,6 +37,7 @@ export const Select = <T extends SelectValueType, M extends boolean = false>(
|
|
|
29
37
|
name={randomizedId}
|
|
30
38
|
required={rest.required}
|
|
31
39
|
label={label}
|
|
40
|
+
labelEndAdornment={labelEndAdornment}
|
|
32
41
|
titleCase={titleCase}
|
|
33
42
|
/>
|
|
34
43
|
) : null
|