UNPKG

@carbon/react

Version:

React components for the Carbon Design System

122 lines (115 loc) 3.91 kB
/** * Copyright IBM Corp. 2016, 2023 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js'; import PropTypes from 'prop-types'; import React, { useState, useEffect, Children, isValidElement, cloneElement } from 'react'; import RadioTile from '../RadioTile/RadioTile.js'; import { usePrefix } from '../../internal/usePrefix.js'; import { noopFn } from '../../internal/noopFn.js'; const TileGroup = ({ children, className, defaultSelected, disabled, legend, name, onChange = noopFn, valueSelected, required }) => { const prefix = usePrefix(); const [selected, setSelected] = useState(valueSelected ?? defaultSelected); useEffect(() => { if (typeof valueSelected !== 'undefined' && valueSelected !== selected) { setSelected(valueSelected); } }, [valueSelected, selected]); const handleChange = (value, name, evt) => { if (value !== selected) { setSelected(value); onChange(value, name ?? '', evt); } }; const getRadioTilesWithWrappers = elements => { const traverseAndModifyChildren = elements => { return Children.map(elements, child => { if (! /*#__PURE__*/isValidElement(child)) return child; // If a `RadioTile` is found, return it with necessary props, if (/*#__PURE__*/isValidElement(child) && child.type === RadioTile) { const { value, ...otherProps } = child.props; return /*#__PURE__*/React.createElement(RadioTile, _extends({}, otherProps, { required: required, name: name, key: value, value: value, onChange: handleChange, checked: value === selected })); } // If the child is not RadioTile and has children, recheck the children const children = child.props.children; const hasChildren = Children.count(children) > 0; if (hasChildren) { return /*#__PURE__*/cloneElement(child, undefined, traverseAndModifyChildren(children)); } // If the child is neither a RadioTile nor has children, return it as is return child; }); }; return /*#__PURE__*/React.createElement(React.Fragment, null, traverseAndModifyChildren(elements)); }; return /*#__PURE__*/React.createElement("fieldset", { className: className ?? `${prefix}--tile-group`, disabled: disabled }, legend && /*#__PURE__*/React.createElement("legend", { className: `${prefix}--label` }, legend), /*#__PURE__*/React.createElement("div", null, getRadioTilesWithWrappers(children))); }; TileGroup.displayName = 'TileGroup'; TileGroup.propTypes = { /** * Provide a collection of <RadioTile> components to render in the group */ children: PropTypes.node, /** * Provide an optional className to be applied to the container node */ className: PropTypes.string, /** * Specify the the value of <RadioTile> to be selected by default */ defaultSelected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** * Specify whether the group is disabled */ disabled: PropTypes.bool, /** * Provide an optional legend for this group */ legend: PropTypes.string, /** * Specify the name of the underlying `<input>` nodes */ name: PropTypes.string.isRequired, /** * Provide an optional `onChange` hook that is called whenever the value of * the group changes */ onChange: PropTypes.func, /** * `true` to specify if input selection in group is required. */ required: PropTypes.bool, /** * Specify the value that is currently selected in the group */ valueSelected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) }; export { TileGroup };