@carbon/ibm-products
Version:
Carbon for IBM Products
137 lines (135 loc) • 5.45 kB
JavaScript
/**
* 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;