wix-style-react
Version:
162 lines (143 loc) • 4.46 kB
JavaScript
import React, { Children, PureComponent } from 'react';
import PropTypes from 'prop-types';
import FieldLabelAttributes from '../FieldLabelAttributes/FieldLabelAttributes';
import { DATA_HOOKS } from './constants';
import { st, classes } from './Range.st.css';
const ELEMENT_POSITION = {
first: 'first',
last: 'last',
};
const getFocusedElementPosition = (hasFocusFirst, hasFocusLast) => {
if (hasFocusFirst) {
return ELEMENT_POSITION.first;
}
if (hasFocusLast) {
return ELEMENT_POSITION.last;
}
};
class Range extends PureComponent {
state = {
hasFocusFirst: false,
hasFocusLast: false,
};
_doKeyDown(e) {
const keys = {
upArrow: 38,
downArrow: 40,
};
if (e.keyCode === keys.upArrow && !isNaN(e.target.value)) {
e.preventDefault();
e.target.value++;
}
if (e.keyCode === keys.downArrow && !isNaN(e.target.value)) {
e.preventDefault();
e.target.value--;
}
}
_handleFocusFirst() {
this.setState({ hasFocusFirst: true });
}
_handleBlurFirst() {
this.setState({ hasFocusFirst: false });
}
_handleFocusLast() {
this.setState({ hasFocusLast: true });
}
_handleBlurLast() {
this.setState({ hasFocusLast: false });
}
render() {
const { children, dataHook } = this.props;
const { hasFocusFirst, hasFocusLast } = this.state;
const childrenArr = Children.toArray(children);
const rangeType = children[1].type.displayName;
const label =
children.length === 3 ? (
<div className={classes.label} data-hook={DATA_HOOKS.label}>
{children[0]}
{this.props.required || this.props.info || this.props.tooltip ? (
<FieldLabelAttributes
dataHook="field-label-attributes"
required={this.props.required}
info={this.props.info}
tooltip={this.props.tooltip}
appendToParent={this.props.appendToParent}
/>
) : null}
</div>
) : null;
const firstInput =
childrenArr.length === 3 ? childrenArr[1] : childrenArr[0];
const lastInput =
childrenArr.length === 3 ? childrenArr[2] : childrenArr[1];
const additionalFirstInputProps = {
className:
rangeType === 'DatePicker' ? classes.firstDate : classes.firstinput,
noRightBorderRadius: true,
onKeyDown: e => this._doKeyDown(e),
onFocus: e => this._handleFocusFirst(e),
onBlur: e => this._handleBlurFirst(e),
...(rangeType === 'DatePicker' &&
!!firstInput.props.inputProps &&
firstInput.props.inputProps),
};
const additionalLastInputProps = {
className:
rangeType === 'DatePicker' ? classes.lastDate : classes.lastinput,
noLeftBorderRadius: true,
onKeyDown: e => this._doKeyDown(e),
onFocus: e => this._handleFocusLast(e),
onBlur: e => this._handleBlurLast(e),
...(rangeType === 'DatePicker' &&
!!lastInput.props.inputProps &&
lastInput.props.inputProps),
};
return (
<div
data-hook={dataHook}
className={st(classes.root, {
focusedElementPosition: getFocusedElementPosition(
hasFocusFirst,
hasFocusLast,
),
})}
>
{label}
<div
className={classes.inputWrapper}
data-hook={DATA_HOOKS.inputWrapper}
>
{React.cloneElement(
firstInput,
rangeType === 'DatePicker'
? { inputProps: additionalFirstInputProps }
: additionalFirstInputProps,
)}
{React.cloneElement(
lastInput,
rangeType === 'DatePicker'
? { inputProps: additionalLastInputProps }
: additionalLastInputProps,
)}
</div>
</div>
);
}
}
Range.displayName = 'Range';
Range.propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests. */
dataHook: PropTypes.string,
/** Accept any component as a child item. At the moment it is most commonly used with `<DatePicker/>` or `<Input/>`*/
children: PropTypes.any,
/** @deprecated Do not use this prop */
required: PropTypes.bool,
/** @deprecated Do not use this prop */
info: PropTypes.string,
/** @deprecated Do not use this prop */
appendToParent: PropTypes.bool,
};
Range.defaultProps = {
appendToParent: false,
};
export default Range;