mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-02 06:07:06 +01:00
7b323b8a30
* Part of #17670: Replace Typography with Text component for 10 files. * Update radio-group.component.js * Update create-password.test.js.snap * Update custom-spending-cap.test.js.snap * Update add-network-modal.test.js.snap * Update recovery-phrase-reminder.js
300 lines
7.9 KiB
JavaScript
300 lines
7.9 KiB
JavaScript
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import classNames from 'classnames';
|
|
|
|
import Box from '../box/box';
|
|
import {
|
|
TextAlign,
|
|
DISPLAY,
|
|
TextVariant,
|
|
AlignItems,
|
|
TextColor,
|
|
} from '../../../helpers/constants/design-system';
|
|
|
|
import NumericInput from '../numeric-input/numeric-input.component';
|
|
import InfoTooltip from '../info-tooltip/info-tooltip';
|
|
import { Text } from '../../component-library';
|
|
|
|
export default function FormField({
|
|
dataTestId,
|
|
titleText = '',
|
|
TitleTextCustomComponent,
|
|
titleUnit = '',
|
|
TitleUnitCustomComponent,
|
|
tooltipText = '',
|
|
TooltipCustomComponent,
|
|
titleDetail = '',
|
|
titleDetailWrapperProps,
|
|
titleHeadingWrapperProps,
|
|
error,
|
|
onChange = undefined,
|
|
value = 0,
|
|
numeric,
|
|
detailText = '',
|
|
autoFocus = false,
|
|
password = false,
|
|
allowDecimals = false,
|
|
disabled = false,
|
|
placeholder,
|
|
warning,
|
|
passwordStrength,
|
|
passwordStrengthText,
|
|
id,
|
|
inputProps,
|
|
wrappingLabelProps,
|
|
inputRef,
|
|
}) {
|
|
return (
|
|
<div
|
|
className={classNames('form-field', {
|
|
'form-field__row--error': error,
|
|
})}
|
|
>
|
|
<Box as="label" {...wrappingLabelProps}>
|
|
<div className="form-field__heading">
|
|
<Box
|
|
className="form-field__heading-title"
|
|
display={DISPLAY.FLEX}
|
|
alignItems={AlignItems.baseline}
|
|
{...titleHeadingWrapperProps}
|
|
>
|
|
{TitleTextCustomComponent ||
|
|
(titleText && (
|
|
<Text
|
|
tag="label"
|
|
htmlFor={id}
|
|
html
|
|
variant={TextVariant.bodySmBold}
|
|
as="h6"
|
|
display={DISPLAY.INLINE_BLOCK}
|
|
>
|
|
{titleText}
|
|
</Text>
|
|
))}
|
|
{TitleUnitCustomComponent ||
|
|
(titleUnit && (
|
|
<Text
|
|
tag={TextVariant.bodySm}
|
|
variant={TextVariant.bodySm}
|
|
as="h6"
|
|
color={TextColor.textAlternative}
|
|
display={DISPLAY.INLINE_BLOCK}
|
|
>
|
|
{titleUnit}
|
|
</Text>
|
|
))}
|
|
{TooltipCustomComponent ||
|
|
(tooltipText && (
|
|
<InfoTooltip position="top" contentText={tooltipText} />
|
|
))}
|
|
</Box>
|
|
{titleDetail && (
|
|
<Box
|
|
className="form-field__heading-detail"
|
|
textAlign={TextAlign.End}
|
|
marginRight={2}
|
|
{...titleDetailWrapperProps}
|
|
>
|
|
{titleDetail}
|
|
</Box>
|
|
)}
|
|
</div>
|
|
{numeric ? (
|
|
<NumericInput
|
|
error={error}
|
|
onChange={onChange}
|
|
value={value}
|
|
detailText={detailText}
|
|
autoFocus={autoFocus}
|
|
allowDecimals={allowDecimals}
|
|
disabled={disabled}
|
|
dataTestId={dataTestId}
|
|
placeholder={placeholder}
|
|
id={id}
|
|
inputRef={inputRef}
|
|
/>
|
|
) : (
|
|
<input
|
|
className={classNames('form-field__input', {
|
|
'form-field__input--error': error,
|
|
'form-field__input--warning': warning,
|
|
})}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
value={value}
|
|
type={password ? 'password' : 'text'}
|
|
autoFocus={autoFocus}
|
|
disabled={disabled}
|
|
data-testid={dataTestId}
|
|
placeholder={placeholder}
|
|
id={id}
|
|
ref={inputRef}
|
|
{...inputProps}
|
|
/>
|
|
)}
|
|
{error && (
|
|
<Text
|
|
color={TextColor.errorDefault}
|
|
variant={TextVariant.bodySm}
|
|
as="h6"
|
|
className="form-field__error"
|
|
>
|
|
{error}
|
|
</Text>
|
|
)}
|
|
{warning && (
|
|
<Text
|
|
color={TextColor.textAlternative}
|
|
variant={TextVariant.bodySm}
|
|
as="h6"
|
|
className="form-field__warning"
|
|
>
|
|
{warning}
|
|
</Text>
|
|
)}
|
|
{passwordStrength && (
|
|
<Text
|
|
color={TextColor.textDefault}
|
|
variant={TextVariant.bodySm}
|
|
as="h6"
|
|
className="form-field__password-strength"
|
|
>
|
|
{passwordStrength}
|
|
</Text>
|
|
)}
|
|
{passwordStrengthText && (
|
|
<Text
|
|
color={TextColor.textAlternative}
|
|
variant={TextVariant.bodyXs}
|
|
as="h6"
|
|
className="form-field__password-strength-text"
|
|
>
|
|
{passwordStrengthText}
|
|
</Text>
|
|
)}
|
|
</Box>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
FormField.propTypes = {
|
|
/**
|
|
* Identifier for testing purpose
|
|
*/
|
|
dataTestId: PropTypes.string,
|
|
/**
|
|
* Form Fields Title
|
|
*/
|
|
titleText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
/**
|
|
* A custom component to replace the title text Typography component
|
|
* titleText will be ignored if this is provided
|
|
*/
|
|
TitleTextCustomComponent: PropTypes.node,
|
|
/**
|
|
* Show unit (eg. ETH)
|
|
*/
|
|
titleUnit: PropTypes.string,
|
|
/**
|
|
* A custom component to replace the title unit Typography component
|
|
* titleUnit will be ignored if this is provided
|
|
*/
|
|
TitleUnitCustomComponent: PropTypes.node,
|
|
/**
|
|
* Add Tooltip and text content
|
|
*/
|
|
tooltipText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
/**
|
|
* A custom component to replace the tooltip component
|
|
* tooltipText will be ignored if this is provided
|
|
*/
|
|
TooltipCustomComponent: PropTypes.node,
|
|
/**
|
|
* Show content (text, image, component) in title
|
|
*/
|
|
titleDetail: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
/**
|
|
* Props to pass to wrapping Box component of the titleDetail component
|
|
* Accepts all props of the Box component
|
|
*/
|
|
titleDetailWrapperProps: PropTypes.shape({
|
|
...Box.propTypes,
|
|
}),
|
|
/**
|
|
* Props to pass to wrapping Box component of the titleHeading component
|
|
* Accepts all props of the Box component
|
|
*/
|
|
titleHeadingWrapperProps: PropTypes.shape({
|
|
...Box.propTypes,
|
|
}),
|
|
/**
|
|
* Show error message
|
|
*/
|
|
error: PropTypes.string,
|
|
/**
|
|
* Show warning message
|
|
*/
|
|
warning: PropTypes.string,
|
|
/**
|
|
* Handler when fields change
|
|
*/
|
|
onChange: PropTypes.func,
|
|
/**
|
|
* Field value
|
|
*/
|
|
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
/**
|
|
* Show detail text if field mode is numeric
|
|
*/
|
|
detailText: PropTypes.string,
|
|
/**
|
|
* Set autofocus on render
|
|
*/
|
|
autoFocus: PropTypes.bool,
|
|
/**
|
|
* Set numeric mode, the default is text
|
|
*/
|
|
numeric: PropTypes.bool,
|
|
/**
|
|
* Set password mode
|
|
*/
|
|
password: PropTypes.bool,
|
|
/**
|
|
* Allow decimals on the field
|
|
*/
|
|
allowDecimals: PropTypes.bool,
|
|
/**
|
|
* Check if the form disabled
|
|
*/
|
|
disabled: PropTypes.bool,
|
|
/**
|
|
* Set the placeholder text for the input field
|
|
*/
|
|
placeholder: PropTypes.string,
|
|
/**
|
|
* Show password strength according to the score
|
|
*/
|
|
passwordStrength: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
/**
|
|
* Show password strength description
|
|
*/
|
|
passwordStrengthText: PropTypes.string,
|
|
/**
|
|
* The id of the input element. Should be used when the wrapping label is changed to a div to ensure accessibility.
|
|
*/
|
|
id: PropTypes.string,
|
|
/**
|
|
* Any additional input attributes or overrides not provided by exposed props
|
|
*/
|
|
inputProps: PropTypes.object,
|
|
/**
|
|
* The FormField is wrapped in a Box component that is rendered as a <label/> using the polymorphic "as" prop.
|
|
* This object allows you to override the rendering of the label by using the wrapperProps={{ as: 'div' }} prop.
|
|
* If used ensure the id prop is set on the input and a label element is present using htmlFor with the same id to ensure accessibility.
|
|
*/
|
|
wrappingLabelProps: PropTypes.object,
|
|
/**
|
|
* ref for input component
|
|
*/
|
|
inputRef: PropTypes.object,
|
|
};
|