UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

85 lines (84 loc) 3.81 kB
'use client'; import LinkAccessibleRole from '@ui5/webcomponents/dist/types/LinkAccessibleRole.js'; import { useI18nBundle, useStylesheet } from '@ui5/webcomponents-react-base'; import { clsx } from 'clsx'; import { forwardRef, useId, useState } from 'react'; import { CLOSE_POPOVER, SHOW_FULL_TEXT, SHOW_LESS, SHOW_MORE } from '../../i18n/i18n-defaults.js'; import { Link } from '../../webComponents/index.js'; import { ResponsivePopover } from '../../webComponents/ResponsivePopover/index.js'; import { Text } from '../../webComponents/Text/index.js'; import { classNames, styleData } from './ExpandableText.module.css.js'; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; /** * The `ExpandableText` component can be used to display long texts inside a table, list or form. * * Initially, only the first characters from the text are shown with a "Show More" link which allows the full text to be displayed. The `showOverflowInPopover` property determines if the full text will be displayed expanded in place (default) or in a popover (`showOverflowInPopover: true`). If the text is expanded a "Show Less" link is displayed, which allows collapsing the text field. * * @since 1.23.0 */ const ExpandableText = /*#__PURE__*/forwardRef((props, ref) => { const { children, showOverflowInPopover, maxCharacters = 100, renderWhitespace, className, ...rest } = props; useStylesheet(styleData, ExpandableText.displayName); const [collapsed, setCollapsed] = useState(true); const [popoverOpen, setPopoverOpen] = useState(false); const uniqueId = useId(); const i18nBundle = useI18nBundle('@ui5/webcomponents-react'); const trimmedChildren = renderWhitespace ? children : children?.replace(/\s+/g, ' ').trim(); const isOverflow = trimmedChildren?.length >= maxCharacters; const strippedChildren = isOverflow && (collapsed || showOverflowInPopover) ? trimmedChildren?.slice(0, maxCharacters) : children; const handleClick = () => { if (showOverflowInPopover) { setPopoverOpen(prev => !prev); } setCollapsed(prev => !prev); }; const closePopover = () => { setCollapsed(true); setPopoverOpen(false); }; return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsxs("span", { className: clsx(classNames.expandableText, className), ...rest, ref: ref, children: [/*#__PURE__*/_jsx(Text, { className: clsx(classNames.text, renderWhitespace && classNames.renderWhitespace), children: strippedChildren }), isOverflow && /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx("span", { className: classNames.ellipsis, children: showOverflowInPopover || collapsed ? '… ' : ' ' }), /*#__PURE__*/_jsx(Link, { accessibleName: showOverflowInPopover ? collapsed ? i18nBundle.getText(SHOW_FULL_TEXT) : i18nBundle.getText(CLOSE_POPOVER) : undefined, accessibleRole: LinkAccessibleRole.Button, accessibilityAttributes: showOverflowInPopover ? { hasPopup: 'dialog' } : { expanded: !collapsed }, onClick: handleClick, id: `${uniqueId}-link`, children: collapsed ? i18nBundle.getText(SHOW_MORE) : i18nBundle.getText(SHOW_LESS) })] })] }), showOverflowInPopover && popoverOpen && /*#__PURE__*/_jsx(ResponsivePopover, { opener: `${uniqueId}-link`, open: true, onClose: closePopover, className: classNames.popover, children: /*#__PURE__*/_jsx(Text, { className: clsx(classNames.text, renderWhitespace && classNames.renderWhitespace), children: children }) })] }); }); ExpandableText.displayName = 'ExpandableText'; export { ExpandableText };