wix-style-react
Version:
156 lines (133 loc) • 3.98 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import { st, classes } from './CheckToggle.st.css';
import { dataHooks } from './constants';
import Tooltip from '../Tooltip';
import { TooltipCommonProps } from '../common/PropTypes/TooltipCommon';
import { withFocusable } from 'wix-ui-core/dist/src/hocs/Focusable/FocusableHOC';
import ConfirmSmall from 'wix-ui-icons-common/ConfirmSmall';
import Confirm from 'wix-ui-icons-common/Confirm';
const icon = {
small: <ConfirmSmall />,
medium: <Confirm />,
};
/** CheckToggle */
class CheckToggle extends React.PureComponent {
state = {
checked: !!this.props.checked,
};
/**
* Checks if the component is controlled or uncontrolled.
* The component is controlled only if prop checked is provided.
*
* @returns boolean
* @private
*/
_isControlled = () => {
return this.props.hasOwnProperty('checked');
};
/**
* Toggles checked state and triggers the onChange callback.
* Except when disabled
*/
_handleChange = changeEvent => {
const { checked } = this.state;
const { onChange } = this.props;
this.setState({ checked: !checked }, () => {
if (onChange) onChange(changeEvent);
});
};
/**
* Renders the toggle itself
* @returns React.ReactNode
* @private
*/
_renderInput = () => {
const { checked } = this._isControlled() ? this.props : this.state;
const { size, disabled, onChange } = this.props;
return (
<>
<input
type="checkbox"
className={classes.input}
data-hook={dataHooks.toggle}
checked={checked}
disabled={disabled}
onChange={this._isControlled() ? onChange : this._handleChange}
/>
<span className={classes.toggle}>{icon[size]}</span>
</>
);
};
/**
* Renders a tooltip wrapper
* @returns React.ReactNode
* @private
*/
_renderTooltip = () => {
const { tooltipContent, tooltipProps } = this.props;
return (
<Tooltip
dataHook={dataHooks.tooltip}
content={tooltipContent}
{...tooltipProps}
>
{this._renderInput()}
</Tooltip>
);
};
render() {
const { checked } = this._isControlled() ? this.props : this.state;
const {
dataHook,
size,
skin,
disabled,
tooltipContent,
focusableOnFocus,
focusableOnBlur,
className,
} = this.props;
return (
<label
className={st(
classes.root,
{ checked, size, skin, disabled },
className,
)}
data-hook={dataHook}
onFocus={focusableOnFocus}
onBlur={focusableOnBlur}
>
{tooltipContent ? this._renderTooltip() : this._renderInput()}
</label>
);
}
}
CheckToggle.displayName = 'CheckToggle';
CheckToggle.propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests */
dataHook: PropTypes.string,
/** Specifies a CSS class name to be appended to the component’s root element */
className: PropTypes.string,
/** Specifies whether a check is selected */
checked: PropTypes.bool,
/** Defines a callback function which is called every time the check value is changed */
onChange: PropTypes.func,
/** Specifies whether toggle interactions should be disabled */
disabled: PropTypes.bool,
/** Controls the size of the component */
size: PropTypes.oneOf(['small', 'medium']),
/** Controls the skin of the component */
skin: PropTypes.oneOf(['standard', 'success']),
/** Defines a message to be displayed in a tooltip. Tooltip is displayed on component hover. */
tooltipContent: PropTypes.node,
/** Allows to pass all common tooltip props. Check `<Tooltip/>` for a full API. */
tooltipProps: PropTypes.shape(TooltipCommonProps),
};
CheckToggle.defaultProps = {
disabled: false,
size: 'small',
skin: 'standard',
};
export default withFocusable(CheckToggle);