UNPKG

wix-style-react

Version:
116 lines (100 loc) 3.44 kB
import React from 'react'; import PropTypes from 'prop-types'; import Text from '../Text'; import { st, classes } from './LabelledElement.st.css'; import { FontUpgradeContext } from '../FontUpgrade/context'; import DataHooks from './dataHooks'; import { generateID } from '../utils/generateId'; class LabelledElement extends React.Component { static displayName = 'LabelledElement'; static propTypes = { /** Specifies a data-hook for tests */ dataHook: PropTypes.string, /** Sets the field label. */ label: PropTypes.string, /** Specifies the value of rendered child input. */ value: PropTypes.string, }; state = { hasFocus: false, inputId: `labelled-element-${generateID()}`, value: undefined, }; _isInputEmpty = () => { return this._isInputControlled() ? !this.props.value : !this.state.value; }; _isInputControlled = () => typeof this.props.value !== 'undefined'; _handleFocus = event => { const { children } = this.props; const childrenOnFocus = children && children.props.onFocus; this.setState({ hasFocus: true }); childrenOnFocus && childrenOnFocus(event); }; _handleBlur = event => { const { children } = this.props; const childrenOnBlur = children && children.props.onBlur; this.setState({ hasFocus: false, }); childrenOnBlur && childrenOnBlur(event); }; _handleOnChange = event => { const { children } = this.props; const childrenOnChange = children && children.props.onChange; if (!this._isInputControlled()) { this.setState({ value: event.target.value, }); } childrenOnChange && childrenOnChange(event); }; _placeLabelOnTop = () => this.state.hasFocus || !this._isInputEmpty(); _getPlaceholder = placeholder => (this._placeLabelOnTop() ? placeholder : ''); render() { const { inputId } = this.state; const { dataHook, label, children } = this.props; const labelTop = this._placeLabelOnTop(); return ( <FontUpgradeContext.Consumer> {({ active: isMadefor }) => ( <div className={classes.root} data-hook={dataHook}> <label data-hook={DataHooks.label} data-top={labelTop} htmlFor={inputId} className={st(classes.label, { labelTop, })} > <Text size="medium" light={!labelTop} secondary={!labelTop} weight={isMadefor ? 'thin' : 'normal'} className={classes.labelText} > {label} </Text> </label> {children && ( <div data-hook={DataHooks.childrenWrapper}> {React.cloneElement(children, { id: inputId, onFocus: this._handleFocus, onBlur: this._handleBlur, onChange: this._handleOnChange, /** should have a different height than regular large input */ className: classes.inputContainer, placeholder: children.props.placeholder ? this._getPlaceholder(children.props.placeholder) : undefined, })} </div> )} </div> )} </FontUpgradeContext.Consumer> ); } } export default LabelledElement;