UNPKG

wix-style-react

Version:
233 lines (204 loc) • 6.85 kB
import React from 'react'; import PropTypes from 'prop-types'; import CheckboxChecked from 'wix-ui-icons-common/system/CheckboxChecked'; import CheckboxIndeterminate from 'wix-ui-icons-common/system/CheckboxIndeterminate'; import { st, classes } from './Checkbox.st.css'; import Text from '../Text'; import { withFocusable } from 'wix-ui-core/dist/src/hocs/Focusable/FocusableHOC'; import deprecationLog from '../utils/deprecationLog'; import { generateID } from '../utils/generateId'; import Tooltip from '../Tooltip'; import * as DATA_ATTR from './DataAttr'; import { dataHooks } from './constants'; import { TooltipCommonProps } from '../common/PropTypes/TooltipCommon'; /** a simple WixStyle checkbox */ class Checkbox extends React.PureComponent { // TODO fix me please. We need to get away from ids. _id = `${Checkbox.displayName}-${generateID()}`; checkboxRef = React.createRef(); focus = () => { this.checkboxRef.current && this.checkboxRef.current.focus(); }; _getDataAttributes = () => { const { checked, indeterminate, disabled, hasError } = this.props; return { [DATA_ATTR.DATA_CHECK_TYPE]: indeterminate ? DATA_ATTR.CHECK_TYPES.INDETERMINATE : checked ? DATA_ATTR.CHECK_TYPES.CHECKED : DATA_ATTR.CHECK_TYPES.UNCHECKED, [DATA_ATTR.DATA_HAS_ERROR]: hasError && !disabled, [DATA_ATTR.DATA_DISABLED]: disabled, }; }; render() { const { id = this._id, checked, indeterminate, disabled, hasError, errorMessage, selectionArea, vAlign, size, onChange, children, dataHook, focusableOnFocus, focusableOnBlur, className, tooltipProps, tooltipContent, selectionAreaSkin, selectionAreaPadding, } = this.props; if (errorMessage) { deprecationLog( '<Checkbox/> - errorMessage prop is deprecated and will be removed in next major release, please use tooltipContent instead', ); } const isTooltipDisabled = (tooltipProps && tooltipProps.disabled) || disabled || (!tooltipContent && (!hasError || !errorMessage)); return ( <div data-hook={dataHook} className={st( classes.root, { vAlign, selectionArea, selectionAreaSkin, disabled, error: hasError && !disabled, selection: indeterminate ? 'indeterminate' : checked ? 'checked' : 'unchecked', indeterminate, }, className, )} onFocus={focusableOnFocus} onBlur={focusableOnBlur} tabIndex={disabled ? null : 0} {...this._getDataAttributes()} role="checkbox" aria-checked={checked} ref={this.checkboxRef} > <input data-hook={dataHooks.input} type="checkbox" id={id} checked={checked} disabled={disabled} onChange={disabled ? null : onChange} style={{ display: 'none' }} /> <label htmlFor={id} data-hook={dataHooks.label} className={classes.label} > <div className={classes.labelInner} style={{ padding: selectionAreaPadding }} > <Tooltip dataHook={dataHooks.boxTooltip} disabled={isTooltipDisabled} content={tooltipContent || errorMessage || ' '} textAlign="center" maxWidth={230} hideDelay={150} zIndex={10000} {...tooltipProps} > <div className={classes.outer}> <div data-hook={dataHooks.box} className={classes.checkbox}> <div className={classes.inner} onClick={e => e.stopPropagation()} > {indeterminate ? ( <CheckboxIndeterminate /> ) : ( <CheckboxChecked /> )} </div> </div> </div> </Tooltip> {children && ( <Text size={size} onClick={e => e.stopPropagation()} weight="thin" dataHook={dataHooks.children} className={classes.children} > {children} </Text> )} </div> </label> </div> ); } } Checkbox.displayName = 'Checkbox'; Checkbox.propTypes = { /** Applies a data-hook HTML attribute that can be used in tests */ dataHook: PropTypes.string, /** Specifies whether a checkbox is selected */ checked: PropTypes.bool, /** Renders any component passed within <Checkbox> tags as the label of a checkbox. The default value is a text string. */ children: PropTypes.node, /** Specifies whether a checkbox is disabled */ disabled: PropTypes.bool, /** Specifies whether a checkbox has an error */ hasError: PropTypes.bool, /** Assigns a unique identifier for the checkbox */ id: PropTypes.string, /** Specifies whether a checkbox is in an indeterminate state */ indeterminate: PropTypes.bool, /** * The error message when there's an error * @deprecated * */ errorMessage: PropTypes.string, /** Controls the selection area highlight visibility */ selectionArea: PropTypes.oneOf(['none', 'hover', 'always']), /** Controls checkbox alignment to the label on the Y axis */ vAlign: PropTypes.oneOf(['center', 'top']), /** Controls the size of the checkbox label */ size: PropTypes.oneOf(['small', 'medium']), /** Defines a callback function which is called every time the checkbox state is changed */ onChange: PropTypes.func, /** Specifies a CSS class name to be appended to the component’s root element */ className: PropTypes.string, /** Sets the design of the selection area */ selectionAreaSkin: PropTypes.oneOf(['filled', 'outlined']), /** Sets the amount of white space around the checkbox label in pixels */ selectionAreaPadding: PropTypes.string, /** Defines a message to be displayed in a tooltip. Tooltip is displayed on a checkbox hover. */ tooltipContent: PropTypes.node, /** Allows you to pass all common tooltip props. Check `<Tooltip/>` for the full API. */ tooltipProps: PropTypes.shape(TooltipCommonProps), }; Checkbox.defaultProps = { checked: false, size: 'medium', selectionArea: 'none', vAlign: 'center', onChange: e => e.stopPropagation(), hasError: false, disabled: false, indeterminate: false, selectionAreaSkin: 'filled', }; export default withFocusable(Checkbox);