@carbon/react
Version:
React components for the Carbon Design System
170 lines (165 loc) • 6.02 kB
JavaScript
/**
* 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 { RadioButtonChecked, RadioButton, CheckmarkFilled } from '@carbon/icons-react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import React, { cloneElement } from 'react';
import { Enter, Space } from '../../internal/keyboard/keys.js';
import { matches } from '../../internal/keyboard/match.js';
import { useFallbackId } from '../../internal/useId.js';
import { usePrefix } from '../../internal/usePrefix.js';
import deprecate from '../../prop-types/deprecate.js';
import { noopFn } from '../../internal/noopFn.js';
import '../Text/index.js';
import { useFeatureFlag } from '../FeatureFlags/index.js';
import { AILabel } from '../AILabel/index.js';
import { isComponentElement } from '../../internal/utils.js';
import { Text } from '../Text/Text.js';
var _RadioButtonChecked, _RadioButton, _CheckmarkFilled;
const RadioTile = /*#__PURE__*/React.forwardRef(function RadioTile({
children,
className: customClassName,
decorator,
disabled,
light,
checked,
name,
value,
id,
onChange = noopFn,
tabIndex = 0,
hasRoundedCorners,
slug,
required,
...rest
}, ref) {
const prefix = usePrefix();
const inputId = useFallbackId(id);
const className = cx(customClassName, `${prefix}--tile`, `${prefix}--tile--selectable`, `${prefix}--tile--radio`, {
[`${prefix}--tile--is-selected`]: checked,
[`${prefix}--tile--light`]: light,
[`${prefix}--tile--disabled`]: disabled,
[`${prefix}--tile--slug`]: slug,
[`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners,
[`${prefix}--tile--decorator`]: decorator,
[`${prefix}--tile--decorator-rounded`]: decorator && hasRoundedCorners
});
const v12TileRadioIcons = useFeatureFlag('enable-v12-tile-radio-icons');
function icon() {
if (v12TileRadioIcons) {
if (checked) {
return _RadioButtonChecked || (_RadioButtonChecked = /*#__PURE__*/React.createElement(RadioButtonChecked, null));
} else {
return _RadioButton || (_RadioButton = /*#__PURE__*/React.createElement(RadioButton, null));
}
} else {
return _CheckmarkFilled || (_CheckmarkFilled = /*#__PURE__*/React.createElement(CheckmarkFilled, null));
}
}
function handleOnChange(evt) {
onChange(value, name, evt);
}
function handleOnKeyDown(evt) {
if (matches(evt, [Enter, Space])) {
evt.preventDefault();
onChange(value, name, evt);
}
}
// AILabel is always size `xs`
const candidate = slug ?? decorator;
const candidateIsAILabel = isComponentElement(candidate, AILabel);
const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
size: 'xs'
}) : null;
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("input", {
checked: checked,
className: `${prefix}--tile-input`,
disabled: disabled,
id: inputId,
name: name,
onChange: !disabled ? handleOnChange : undefined,
onKeyDown: !disabled ? handleOnKeyDown : undefined,
tabIndex: !disabled ? tabIndex : undefined,
type: "radio",
value: value,
ref: ref,
required: required
}), /*#__PURE__*/React.createElement("label", _extends({}, rest, {
htmlFor: inputId,
className: className
}), /*#__PURE__*/React.createElement("span", {
className: `${prefix}--tile__checkmark`
}, icon()), /*#__PURE__*/React.createElement(Text, {
className: `${prefix}--tile-content`
}, children), slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
className: `${prefix}--tile--inner-decorator`
}, normalizedDecorator) : ''));
});
RadioTile.displayName = 'RadioTile';
RadioTile.propTypes = {
/**
* Specify whether the `RadioTile` should be checked.
*/
checked: PropTypes.bool,
/**
* The `RadioTile` content.
*/
children: PropTypes.node,
/**
* Provide an optional `className` to be applied to the underlying `<label>`.
*/
className: PropTypes.string,
/**
* **Experimental**: Provide a `decorator` component to be rendered inside the `RadioTile` component
*/
decorator: PropTypes.node,
/**
* Specify whether the `RadioTile` should be disabled.
*/
disabled: PropTypes.bool,
/**
* Specify if the `ExpandableTile` component should be rendered with rounded corners.
* Only valid when `slug` prop is present
*/
hasRoundedCorners: PropTypes.bool,
/**
* Provide a unique id for the underlying `<input>`.
*/
id: PropTypes.string,
/**
* `true` to use the light version. For use on `$layer-01` backgrounds only.
* Don't use this to make tile background color same as container background color.
*/
light: deprecate(PropTypes.bool, 'The `light` prop for `RadioTile` is no longer needed and has ' + 'been deprecated in v11 in favor of the new `Layer` component. It will be removed in the next major release.'),
/**
* Provide a `name` for the underlying `<input>`.
*/
name: PropTypes.string,
/**
* Provide an optional `onChange` hook that is called each time the value of
* the underlying `<input>` changes.
*/
onChange: PropTypes.func,
/**
* `true` to specify if the control is required.
*/
required: PropTypes.bool,
/**
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioTile` component
*/
slug: deprecate(PropTypes.node, 'The `slug` prop for `RadioTile` has ' + 'been deprecated in favor of the new `decorator` prop. It will be removed in the next major release.'),
/**
* Specify the tab index of the underlying `<input>`.
*/
tabIndex: PropTypes.number,
/**
* Specify the value of the underlying `<input>`.
*/
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
};
export { RadioTile as default };