This repository has been archived by the owner on Mar 4, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 55
/
FormField.tsx
132 lines (107 loc) · 3.47 KB
/
FormField.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { Accessibility } from '@fluentui/accessibility'
import * as customPropTypes from '@fluentui/react-proptypes'
import * as PropTypes from 'prop-types'
import * as React from 'react'
import {
UIComponent,
childrenExist,
createShorthandFactory,
UIComponentProps,
ChildrenComponentProps,
commonPropTypes,
ShorthandFactory,
} from '../../utils'
import { WithAsProp, ShorthandValue, withSafeTypeForAs } from '../../types'
import Text, { TextProps } from '../Text/Text'
import Input from '../Input/Input'
import Box, { BoxProps } from '../Box/Box'
export interface FormFieldProps extends UIComponentProps, ChildrenComponentProps {
/**
* Accessibility behavior if overridden by the user.
*/
accessibility?: Accessibility
/** A control for the form field. */
control?: ShorthandValue<BoxProps>
/** The HTML input id. This will be set on the control element and will be use for linking it with the label for correct accessibility. */
id?: string
/** A field can have its label next to instead of above it. */
inline?: boolean
/** A label for the form field. */
label?: ShorthandValue<TextProps>
/** Text message that will be displayed below the control (can be used for error, warning, success messages). */
message?: ShorthandValue<TextProps>
/** The HTML input name. */
name?: string
/** A field can show that input is mandatory. */
required?: boolean
/** The HTML input type. */
type?: string
}
class FormField extends UIComponent<WithAsProp<FormFieldProps>, any> {
static displayName = 'FormField'
static className = 'ui-form__field'
static create: ShorthandFactory<FormFieldProps>
static propTypes = {
...commonPropTypes.createCommon({
content: false,
}),
control: customPropTypes.itemShorthand,
id: PropTypes.string,
inline: PropTypes.bool,
label: customPropTypes.itemShorthand,
message: customPropTypes.itemShorthand,
name: PropTypes.string,
required: PropTypes.bool,
type: PropTypes.string,
}
static defaultProps = {
as: 'div',
control: { as: Input },
}
renderComponent({
ElementType,
classes,
accessibility,
styles,
unhandledProps,
}): React.ReactNode {
const { children, control, id, label, message, name, required, type } = this.props
const labelElement = Text.create(label, {
defaultProps: () => ({
as: 'label',
htmlFor: id,
styles: styles.label,
}),
})
const messageElement = Text.create(message, {
defaultProps: () => ({
styles: styles.message,
}),
})
const controlElement = Box.create(control || {}, {
defaultProps: () => ({ required, id, name, type, styles: styles.control }),
})
const content = (
<>
{this.shouldControlAppearFirst() && controlElement}
{labelElement}
{!this.shouldControlAppearFirst() && controlElement}
{messageElement}
</>
)
return (
<ElementType className={classes.root} {...accessibility.attributes.root} {...unhandledProps}>
{childrenExist(children) ? children : content}
</ElementType>
)
}
shouldControlAppearFirst = () => {
const { type } = this.props
return type && (type === 'checkbox' || type === 'radio')
}
}
FormField.create = createShorthandFactory({ Component: FormField, mappedProp: 'label' })
/**
* A FormField represents a Form element containing a label and an input.
*/
export default withSafeTypeForAs<typeof FormField, FormFieldProps>(FormField)