wix-style-react
Version:
130 lines (111 loc) • 3.15 kB
JavaScript
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import { st, classes } from './Radio.st.css';
import Text from '../Text';
import { generateDataAttr } from '../utils/generateDataAttr';
import { generateID } from '../utils/generateId';
import { dataHooks } from './constants';
import { withFocusable } from 'wix-ui-core/dist/src/hocs/Focusable/FocusableHOC';
const Radio = ({
dataHook,
checked,
disabled,
label,
id,
name,
value,
focusableOnFocus,
focusableOnBlur,
onChange,
alignItems,
className,
style,
}) => {
const defaultId = generateID();
const _onClick = event => {
if (!disabled && !checked) {
onChange({ value, ...event });
}
};
const renderLabel = useMemo(() => {
return (
<Text tagName="div" size="medium" weight="thin" secondary>
{label}
</Text>
);
}, [label]);
const radioId = id || defaultId;
return (
<div
className={st(
classes.root,
{
checked,
disabled,
alignItems,
},
className,
)}
{...generateDataAttr({ checked, disabled }, ['checked', 'disabled'])}
style={style}
data-hook={dataHook}
onClick={_onClick}
aria-checked={!!checked}
>
<input
type="radio"
className={classes.input}
data-hook={dataHooks.input}
disabled={disabled}
checked={checked}
value={value}
name={name}
id={radioId}
onChange={() => null}
onFocus={focusableOnFocus}
onBlur={focusableOnBlur}
/>
<span className={classes.icon} data-hook={dataHooks.icon}></span>
{label && (
<label
className={classes.label}
data-hook={dataHooks.label}
htmlFor={radioId}
onClick={e => e.stopPropagation()}
>
{renderLabel}
</label>
)}
</div>
);
};
Radio.displayName = 'Radio';
Radio.propTypes = {
/** Applies a data-hook HTML attribute that can be used in tests */
dataHook: PropTypes.string,
/** Specifies a CSS class name to be appended to the component’s root element */
className: PropTypes.string,
/** Specifies whether a radio is selected */
checked: PropTypes.bool,
/** Specifies whether radio should be disabled */
disabled: PropTypes.bool,
/** Sets the label on the right side of a radio. The default accepted value is a text string, but it can be overridden to any other component. */
label: PropTypes.node,
/** Sets a unique name for the radio */
name: PropTypes.node,
/** Assigns an unique identifier for the radio */
id: PropTypes.string,
/** Sets the value that the radio represents */
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/** Defines a callback function which is called when radio is selected */
onChange: PropTypes.func,
/** Control radio alignment with a label */
alignItems: PropTypes.oneOf(['top', 'center']),
};
Radio.defaultProps = {
checked: false,
disabled: false,
alignItems: 'center',
onChange: () => null,
};
export default withFocusable(Radio);