UNPKG

@carbon/ibm-products

Version:

Carbon for IBM Products

118 lines (113 loc) 4.71 kB
/** * Copyright IBM Corp. 2020, 2025 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js'); var React = require('react'); var index = require('../../_virtual/index.js'); var cx = require('classnames'); var devtools = require('../../global/js/utils/devtools.js'); var settings = require('../../settings.js'); var react = require('@carbon/react'); var enums = require('./utils/enums.js'); var propsHelper = require('../../global/js/utils/props-helper.js'); var useIsomorphicEffect = require('../../global/js/hooks/useIsomorphicEffect.js'); const blockClass = `${settings.pkg.prefix}--string-formatter`; const componentName = 'StringFormatter'; const defaults = { lines: 1, tooltipDirection: enums.StringFormatterAlignment.BOTTOM_START, truncate: false, width: null }; /** * StringFormatter allows for truncating text while displaying a tooltip * overlay on hover or focus with the entirety of the provided copy. */ exports.StringFormatter = /*#__PURE__*/React.forwardRef((_ref, ref) => { let { className, lines = defaults.lines, tooltipDirection = defaults.tooltipDirection, truncate = defaults.truncate, width = defaults.width, value, ...rest } = _ref; const outerRef = React.useRef(null); const contentRef = React.useRef(null); const [isTextTruncated, setIsTextTruncated] = React.useState(false); const mergedRefs = node => { outerRef.current = node; if (typeof ref === 'function') { ref(node); } else if (ref) { ref.current = node; } }; useIsomorphicEffect.useIsomorphicEffect(() => { const checkTruncation = () => { const element = contentRef.current; if (element) { element.style.webkitLineClamp = truncate ? lines : undefined; element.style.maxWidth = width; const buffer = element.clientHeight / (2 * lines); // add a buffer of at least half of line height/clientHeight. to get a stable outcome. const isOverflowing = element.scrollHeight > element.clientHeight + buffer; setIsTextTruncated(isOverflowing); } }; const resizeObserver = new ResizeObserver(checkTruncation); if (outerRef.current) { resizeObserver.observe(outerRef.current); checkTruncation(); } return () => { resizeObserver.disconnect(); }; }, [lines, value, width, truncate]); const stringFormatterContent = /*#__PURE__*/React.createElement("span", { ref: contentRef, className: cx(`${blockClass}--content`, { [`${blockClass}--truncate`]: truncate }) }, value); return /*#__PURE__*/React.createElement("span", _rollupPluginBabelHelpers.extends({}, rest, { className: cx(blockClass, className), ref: mergedRefs }, devtools.getDevtoolsProps(componentName)), truncate && isTextTruncated ? /*#__PURE__*/React.createElement(react.DefinitionTooltip, { className: `${blockClass}__tooltip`, align: tooltipDirection, definition: value, openOnHover: true }, stringFormatterContent) : stringFormatterContent); }); exports.StringFormatter = settings.pkg.checkComponentEnabled(exports.StringFormatter, componentName); exports.StringFormatter.displayName = componentName; exports.StringFormatter.validateAlignment = () => (props, propName, componentName) => { const prop = props[propName]; const deprecatedAlignValues = Object.values(enums.deprecated_StringFormatterAlignment); if (deprecatedAlignValues.includes(prop)) { const mappedNewProp = enums.propMappingFunction(prop); console.warn(`"${prop}" is a deprecated value for the "${propName}" prop on the "${componentName}" component. Use "${mappedNewProp}" instead. Allowable values are: ${Object.values(enums.StringFormatterAlignment).join(', ')}.`); } }; exports.StringFormatter.propTypes = { /** * Provide an optional class to be applied to the containing node. */ className: index.default.string, /** Number of lines to clamp value. */ lines: index.default.number, /** Specify the direction of the tooltip. Can be either top or bottom. */ tooltipDirection: propsHelper.allPropTypes([exports.StringFormatter.validateAlignment(), index.default.oneOf(Object.values(enums.deprecated_StringFormatterAlignment), Object.values(enums.StringFormatterAlignment))]), /** Whether or not the value should be truncated. if it exceeds lines. */ truncate: index.default.bool, /** Value to format. */ value: index.default.string.isRequired, /** Maximum width of value which should include */ width: index.default.string };