@wfp/react
Version:
WFP UI Kit
159 lines (134 loc) • 4.19 kB
JavaScript
import PropTypes from "prop-types";
import React from "react";
import classNames from "classnames";
import RadioButton from "../RadioButton";
import warning from "warning";
import { withWFPCoreSettings } from "../WFPCoreSettings";
class InputGroup extends React.Component {
state = { selected: this.props.valueSelected || this.props.defaultSelected };
static propTypes = {
prefix: PropTypes.string.isRequired,
/**
* Provide a collection of <RadioButton> components to render in the group
*/
children: PropTypes.node,
/**
* Provide an optional className to be applied to the container node
*/
className: PropTypes.string,
/**
* Provide an optional className to be applied to the container node
*/
controlled: PropTypes.bool,
/**
* Specify the <RadioButton> to be selected by default
*/
defaultSelected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/**
* Specify the name of the underlying `input` nodes
*/
name: PropTypes.string.isRequired,
/**
* Specify whether the group is disabled
*/
disabled: PropTypes.bool,
/**
* Provide an optional `onChange` hook that is called whenever the value of
* the group changes
*/
onChange: PropTypes.func,
/**
* Specify the value that is currently selected in the group
*/
valueSelected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/**
* Specify whether you want the underlying label to be visually hidden
*/
hideLabel: PropTypes.bool,
/**
* Provide text that is used alongside the control label for additional help
*/
helperText: PropTypes.node,
/**
* Provide the text that will be read by a screen reader when visiting this
* control
*/
labelText: PropTypes.node,
};
static defaultProps = {
onChange: /* istanbul ignore next */ () => {},
controlled: false,
};
static getDerivedStateFromProps({ valueSelected, defaultSelected }, state) {
const { prevValueSelected } = state;
return prevValueSelected === valueSelected
? null
: {
selected: valueSelected || defaultSelected,
prevValueSelected: valueSelected,
};
}
getRadioButtons = () => {
const children = React.Children.map(this.props.children, (radioButton) => {
const { value, ...other } = radioButton.props;
/* istanbul ignore if */
if (radioButton.props.hasOwnProperty("checked")) {
warning(
false,
`Instead of using the checked property on the RadioButton, set
the defaultSelected property or valueSelected property on the InputGroup.`
);
}
return (
<RadioButton
{...other}
name={this.props.name}
key={value}
value={value}
onChange={this.handleChange}
checked={value === this.state.selected}
/>
);
});
return children;
};
handleChange = (newSelection, value, evt) => {
if (newSelection !== this.state.selected) {
this.setState({ selected: newSelection });
this.props.onChange(newSelection, this.props.name, evt);
}
};
render() {
const { prefix } = this.props;
const {
children,
disabled,
labelText,
helperText,
controlled,
hideLabel,
className = `${prefix}--input-group`,
} = this.props;
const labelClasses = classNames(`${prefix}--label`, {
[`${prefix}--visually-hidden`]: hideLabel,
});
const label = labelText ? (
<span className={labelClasses}>{labelText}</span>
) : null;
const helper = helperText ? (
<div className={`${prefix}--form__helper-text`}>{helperText}</div>
) : null;
return (
<div className={`${prefix}--form-item`}>
<div className={className} disabled={disabled}>
{label}
{helper}
<div className={`${prefix}--input-group-inside`}>
{controlled ? this.getRadioButtons() : children}
</div>
</div>
</div>
);
}
}
export default withWFPCoreSettings(InputGroup);