UNPKG

@carbon/ibm-products

Version:
137 lines (135 loc) 5.45 kB
/** * Copyright IBM Corp. 2020, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const require_runtime = require("../../_virtual/_rolldown/runtime.js"); const require_index = require("../../node_modules/classnames/index.js"); const require_settings = require("../../settings.js"); const require_useIsomorphicEffect = require("../../global/js/hooks/useIsomorphicEffect.js"); const require_devtools = require("../../global/js/utils/devtools.js"); let react = require("react"); react = require_runtime.__toESM(react); let prop_types = require("prop-types"); prop_types = require_runtime.__toESM(prop_types); let _carbon_react = require("@carbon/react"); //#region src/components/TruncatedList/TruncatedList.tsx /** * Copyright IBM Corp. 2024, 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. */ var import_classnames = /* @__PURE__ */ require_runtime.__toESM(require_index.default); const blockClass = `${require_settings.pkg.prefix}--truncated-list`; const componentName = "TruncatedList"; const defaults = { as: "ul", collapsedItemsLimit: 5, expandedItemsLimit: 10, onClick: () => {}, viewLessLabel: "View less", viewMoreLabel: (value) => `View more (${value})` }; /** * The `TruncatedList` allows consumers to control how many items are * revealed to the user while giving the user the ability to expand * and see the entire list. */ const TruncatedList = react.default.forwardRef(({ children, className, as: List = defaults.as, buttonClassName, collapsedItemsLimit = defaults.collapsedItemsLimit, expandedItemsLimit = defaults.expandedItemsLimit, onClick = defaults.onClick, viewLessLabel = defaults.viewLessLabel, viewMoreLabel = defaults.viewMoreLabel, ...rest }, ref) => { const childrenArray = react.Children.toArray(children); const minItems = Math.max(collapsedItemsLimit, 1); const maxItems = Math.min(expandedItemsLimit, childrenArray.length); const [isCollapsed, setIsCollapsed] = (0, react.useState)(true); const [listHeight, setListHeight] = (0, react.useState)(minItems * 16); const listRef = (0, react.useRef)(void 0); const carbonPrefix = (0, _carbon_react.usePrefix)(); const handleToggle = () => { setIsCollapsed((prev) => !prev); }; (0, react.useEffect)(() => { onClick(isCollapsed); }, [isCollapsed, onClick]); (0, react.useEffect)(() => { if (listRef && childrenArray.length > 0) { const numItemsToShow = isCollapsed ? minItems : maxItems; const items = listRef.current?.childNodes; let listHeight = 0; for (let index = 0; index < numItemsToShow; index++) if (items && items[index]) { const itemElement = items[index]; const height = window?.getComputedStyle(itemElement)?.height || "16"; listHeight += parseInt(height); } setListHeight(listHeight); } }, [ childrenArray, minItems, maxItems, isCollapsed, listRef ]); require_useIsomorphicEffect.useIsomorphicEffect(() => { if (listRef.current) listRef.current.style.height = `${listHeight}px`; }, [listHeight]); return /* @__PURE__ */ react.default.createElement("div", { ...rest, className: (0, import_classnames.default)(blockClass, className, isCollapsed ? `${blockClass}--collapsed` : `${blockClass}--expanded`, !isCollapsed && childrenArray.length <= maxItems && `${blockClass}--expanded-all`), ref, ...require_devtools.getDevtoolsProps(componentName) }, /* @__PURE__ */ react.default.createElement(List, { className: `${blockClass}__list`, ref: listRef }, isCollapsed ? childrenArray.slice(0, minItems) : children), childrenArray.length > minItems && /* @__PURE__ */ react.default.createElement(_carbon_react.Button, { className: (0, import_classnames.default)(`${blockClass}__button`, `${carbonPrefix}--link`, buttonClassName), kind: "ghost", size: "sm", onClick: handleToggle }, isCollapsed ? viewMoreLabel(childrenArray.length - minItems) : viewLessLabel)); }); TruncatedList.displayName = componentName; TruncatedList.propTypes = { /** * The type of list element to render. * This could be a `ul`, `ol`, or a custom React component. */ as: prop_types.default.oneOfType([prop_types.default.elementType, prop_types.default.string]), /** * Optional class name for expand/collapse button. */ buttonClassName: prop_types.default.string, /** * The contents of the TruncatedList. */ children: prop_types.default.node.isRequired, /** * Provide an optional class to be applied to the containing node. */ className: prop_types.default.string, /** * Number of items to render and display when the list is truncated and collapsed. * Scrolling is not enabled when collapsed. The smallest number is 1. */ collapsedItemsLimit: prop_types.default.number, /** * Maximum number of items to show when the list is expanded. All * items are rendered when the list is expanded. Scrolling is enabled * if there are more items to display than this number. */ expandedItemsLimit: prop_types.default.number, /** * Optional callback reports the collapsed state of the list. */ onClick: prop_types.default.func, /** * Text label for when the list is expanded. */ viewLessLabel: prop_types.default.string, /** * Callback function for building the label when the list is collapsed. */ viewMoreLabel: prop_types.default.func }; //#endregion exports.TruncatedList = TruncatedList;