UNPKG

mdc-react

Version:

Material Components for the web implemented in React

82 lines (71 loc) 2.6 kB
import { forwardRef, Children, useCallback } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { isUndefined, isArray } from '../types'; import { create, clone } from '../component'; import { cssClasses } from './constants'; import SegmentedButtonSegment from './SegmentedButtonSegment'; const SegmentedButton = forwardRef(({ value, segments, singleSelect = !isUndefined(value) && !isArray(value), ripple = true, touch = false, onChange = Function.prototype, element = 'div', component: Element = element, className, children = segments?.map(segment => create(SegmentedButtonSegment, segment)), ...props }, ref) => { const handleClick = useCallback(event => { const segmentValue = event.currentTarget.value; const newValue = singleSelect ? segmentValue : (value.includes(segmentValue) ? value.filter(v => v !== segmentValue) : value.concat(segmentValue) ); onChange(newValue); }, [value, singleSelect, onChange]); const classNames = classnames(cssClasses.ROOT, { [cssClasses.SINGLE_SELECT]: singleSelect }, className); return ( <Element ref={ref} className={classNames} role={singleSelect ? 'radiogroup' : 'group'} {...props} > {isUndefined(value) ? children : Children.map(children, segment => { const ariaProp = singleSelect ? 'aria-checked' : 'aria-pressed'; const selected = singleSelect ? value === segment.props.value : value.includes(segment.props.value); return clone(segment, { ripple, touch, selected, role: singleSelect ? 'radio' : undefined, [ariaProp]: selected, onClickCapture: handleClick }); }) } </Element> ); }); SegmentedButton.displayName = 'MDCSegmentedButton'; SegmentedButton.propTypes = { value: PropTypes.any, segments: PropTypes.arrayOf(PropTypes.oneOfType([ PropTypes.object, PropTypes.element ])), singleSelect: PropTypes.bool, ripple: PropTypes.bool, touch: PropTypes.bool, onChange: PropTypes.func }; export default SegmentedButton;