@automattic/form-components
Version:
React-based form components, as used on WordPress.com
103 lines (90 loc) • 2.38 kB
JSX
/**
* External dependencies
*/
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { noop } from 'lodash';
export default class FormToggle extends PureComponent {
static propTypes = {
onChange: PropTypes.func,
onKeyDown: PropTypes.func,
checked: PropTypes.bool,
disabled: PropTypes.bool,
id: PropTypes.string,
className: PropTypes.string,
toggling: PropTypes.bool,
'aria-label': PropTypes.string,
children: PropTypes.node,
};
static defaultProps = {
checked: false,
disabled: false,
onKeyDown: noop,
onChange: noop,
};
static idNum = 0;
componentWillMount() {
this.id = this.constructor.idNum++;
}
onKeyDown = event => {
if ( this.props.disabled ) {
return;
}
if ( event.key === 'Enter' || event.key === ' ' ) {
event.preventDefault();
this.props.onChange( ! this.props.checked );
}
this.props.onKeyDown( event );
};
onClick = () => {
if ( ! this.props.disabled ) {
this.props.onChange( ! this.props.checked );
}
};
onLabelClick = event => {
if ( this.props.disabled ) {
return;
}
const nodeName = event.target.nodeName.toLowerCase();
if ( nodeName !== 'a' && nodeName !== 'input' && nodeName !== 'select' ) {
event.preventDefault();
this.props.onChange( ! this.props.checked );
}
};
render() {
const id = this.props.id || 'toggle-' + this.id;
const wrapperClasses = classNames( 'form-toggle__wrapper', {
'is-disabled': this.props.disabled,
} );
const toggleClasses = classNames( 'form-toggle', this.props.className, {
'is-toggling': this.props.toggling,
} );
return (
<span className={ wrapperClasses }>
<input
id={ id }
className={ toggleClasses }
type="checkbox"
checked={ this.props.checked }
readOnly={ true }
disabled={ this.props.disabled }
/>
<label className="form-toggle__label" htmlFor={ id }>
<span
className="form-toggle__switch"
onClick={ this.onClick }
onKeyDown={ this.onKeyDown }
role="checkbox"
aria-checked={ this.props.checked }
aria-label={ this.props[ 'aria-label' ] }
tabIndex={ this.props.disabled ? -1 : 0 }
/>
<span className="form-toggle__label-content" onClick={ this.onLabelClick }>
{ this.props.children }
</span>
</label>
</span>
);
}
}