@carbon/react
Version:
React components for the Carbon Design System
138 lines (134 loc) • 4.1 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 PropTypes from 'prop-types';
import React, { forwardRef, useRef, useState, useLayoutEffect } from 'react';
import cx from 'classnames';
import { useId } from '../../internal/useId.js';
import { usePrefix } from '../../internal/usePrefix.js';
import Tag, { SIZES } from './Tag.js';
import '../Tooltip/DefinitionTooltip.js';
import { Tooltip } from '../Tooltip/Tooltip.js';
import '../Text/index.js';
import { isEllipsisActive } from './isEllipsisActive.js';
import mergeRefs from '../../tools/mergeRefs.js';
import { useControllableState } from '../../internal/useControllableState.js';
import { Text } from '../Text/Text.js';
const SelectableTag = /*#__PURE__*/forwardRef(({
className,
disabled,
id,
renderIcon,
onChange,
onClick,
selected,
size,
text,
defaultSelected = false,
...other
}, forwardRef) => {
const prefix = usePrefix();
const tagRef = useRef(null);
const tagId = id || `tag-${useId()}`;
const [selectedTag, setSelectedTag] = useControllableState({
value: selected,
onChange: onChange,
defaultValue: defaultSelected
});
const tagClasses = cx(`${prefix}--tag--selectable`, className, {
[`${prefix}--tag--selectable-selected`]: selectedTag
});
const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
useLayoutEffect(() => {
const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
setIsEllipsisApplied(isEllipsisActive(newElement));
}, [prefix, tagRef]);
const tooltipClasses = cx(`${prefix}--icon-tooltip`, `${prefix}--tag-label-tooltip`);
const combinedRef = mergeRefs(tagRef, forwardRef);
const handleClick = e => {
setSelectedTag(!selectedTag);
onClick?.(e);
};
if (isEllipsisApplied) {
return /*#__PURE__*/React.createElement(Tooltip, {
label: text,
align: "bottom",
className: tooltipClasses,
leaveDelayMs: 0,
onMouseEnter: () => false
}, /*#__PURE__*/React.createElement(Tag, _extends({
"aria-pressed": selectedTag !== false,
ref: combinedRef,
size: size,
renderIcon: renderIcon,
disabled: disabled,
className: tagClasses,
id: tagId,
onClick: handleClick
}, other), /*#__PURE__*/React.createElement(Text, {
title: text,
className: `${prefix}--tag__label`
}, text)));
}
return /*#__PURE__*/React.createElement(Tag, _extends({
"aria-pressed": selectedTag !== false,
ref: combinedRef,
size: size,
renderIcon: renderIcon,
disabled: disabled,
className: tagClasses,
id: tagId,
onClick: handleClick
}, other), /*#__PURE__*/React.createElement(Text, {
title: text,
className: `${prefix}--tag__label`
}, text));
});
SelectableTag.propTypes = {
/**
* Provide a custom className that is applied to the containing <span>
*/
className: PropTypes.string,
/**
* Specify if the `SelectableTag` is disabled
*/
disabled: PropTypes.bool,
/**
* Specify the id for the tag.
*/
id: PropTypes.string,
/**
* A component used to render an icon.
*/
renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
/**
* Provide an optional hook that is called when selected is changed
*/
onChange: PropTypes.func,
/**
* Provide an optional function to be called when the tag is clicked.
*/
onClick: PropTypes.func,
/**
* Specify the state of the selectable tag.
*/
selected: PropTypes.bool,
/**
* Specify the default state of the selectable tag.
*/
defaultSelected: PropTypes.bool,
/**
* Specify the size of the Tag. Currently supports either `sm`,
* `md` (default) or `lg` sizes.
*/
size: PropTypes.oneOf(Object.keys(SIZES)),
/**
* Provide text to be rendered inside of a the tag.
*/
text: PropTypes.string
};
export { SelectableTag as default };