@carbon/ibm-products
Version:
Carbon for IBM Products
183 lines (181 loc) • 6.32 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_CardContext = require("./CardContext.js");
const require_CardHeader = require("./CardHeader.js");
const require_CardBody = require("./CardBody.js");
const require_CardFooter = require("./CardFooter.js");
const require_CardHeaderMedia = require("./CardHeaderMedia.js");
const require_CardMedia = require("./CardMedia.js");
const require_CardTitle = require("./CardTitle.js");
const require_CardTitleMedia = require("./CardTitleMedia.js");
const require_CardActions = require("./CardActions.js");
const require_CardAction = require("./CardAction.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/Card/next/Card.tsx
/**
* Copyright IBM Corp. 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.
*/
var import_classnames = /* @__PURE__ */ require_runtime.__toESM(require_index.default);
const componentName = "Card";
const blockClass = `${require_settings.pkg.prefix}--card-next`;
/**
* Card component - Root container for composable card
*/
let CardComponent = (0, react.forwardRef)(({ clickable = false, onClick, onKeyDown, disabled = false, density = "productive", decorator, horizontal = false, className, children, ...rest }, ref) => {
const hasAILabel = (0, react.useMemo)(() => (0, react.isValidElement)(decorator) && decorator.type === _carbon_react.AILabel, [decorator]);
const contextValue = (0, react.useMemo)(() => ({
clickable,
disabled,
decorator,
horizontal
}), [
clickable,
disabled,
decorator,
horizontal
]);
const handleKeyDown = (0, react.useCallback)((event) => {
if (clickable && !disabled && (event.key === "Enter" || event.key === " ")) {
event.preventDefault();
onClick?.(event);
}
onKeyDown?.(event);
}, [
clickable,
disabled,
onClick,
onKeyDown
]);
const handleClick = (0, react.useCallback)((event) => {
if (!disabled) onClick?.(event);
}, [disabled, onClick]);
const cardClasses = (0, import_classnames.default)(blockClass, className, {
[`${blockClass}--clickable`]: clickable && !disabled,
[`${blockClass}--disabled`]: disabled,
[`${blockClass}--${density}`]: density,
[`${blockClass}--has-ai-label`]: hasAILabel,
[`${blockClass}--horizontal`]: horizontal
});
const cardProps = {
...rest,
ref,
className: cardClasses,
...clickable && {
role: "button",
tabIndex: disabled ? -1 : 0,
onClick: handleClick,
onKeyDown: handleKeyDown,
"aria-disabled": disabled
}
};
const { mediaChildren, contentChildren, mediaIsFirst } = (0, react.useMemo)(() => {
if (!horizontal) return {
mediaChildren: [],
contentChildren: [],
mediaIsFirst: false
};
const childArray = react.default.Children.toArray(children);
const isMedia = (child) => react.default.isValidElement(child) && child.type === require_CardMedia.CardMedia;
return {
mediaChildren: childArray.filter(isMedia),
contentChildren: childArray.filter((c) => !isMedia(c)),
mediaIsFirst: childArray.findIndex(isMedia) < childArray.findIndex((c) => !isMedia(c))
};
}, [children, horizontal]);
let renderedChildren = children;
if (horizontal) {
const contentWrapper = /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__content` }, contentChildren);
renderedChildren = mediaIsFirst ? /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, mediaChildren, contentWrapper) : /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, contentWrapper, mediaChildren);
}
return /* @__PURE__ */ react.default.createElement(require_CardContext.CardContext.Provider, { value: contextValue }, /* @__PURE__ */ react.default.createElement("div", cardProps, renderedChildren));
});
CardComponent.propTypes = {
/**
* Card content
*/
children: prop_types.default.node,
/**
* Additional CSS class names
*/
className: prop_types.default.string,
/**
* Makes the entire card clickable
*/
clickable: prop_types.default.bool,
/**
* Optional decorator component (typically AILabel from Carbon)
*/
decorator: prop_types.default.node,
/**
* Density variant: productive uses heading-compact-02, expressive uses heading-03
*/
density: prop_types.default.oneOf(["productive", "expressive"]),
/**
* Disables the card and all interactive elements
*/
disabled: prop_types.default.bool,
/**
* When true, renders media on the left and content (header/body/footer) on the right
*/
horizontal: prop_types.default.bool,
/**
* Click handler for clickable cards
*/
onClick: prop_types.default.func,
/**
* Keyboard event handler for clickable cards
*/
onKeyDown: prop_types.default.func
};
CardComponent = require_settings.pkg.checkComponentEnabled(CardComponent, componentName);
CardComponent.displayName = componentName;
/**
* -------
* Exports
* -------
*/
const Header = require_CardHeader.CardHeader;
Header.displayName = "Card.Header";
const Body = require_CardBody.CardBody;
Body.displayName = "Card.Body";
const Footer = require_CardFooter.CardFooter;
Footer.displayName = "Card.Footer";
const HeaderMedia = require_CardHeaderMedia.CardHeaderMedia;
HeaderMedia.displayName = "Card.HeaderMedia";
const Media = require_CardMedia.CardMedia;
Media.displayName = "Card.Media";
const Title = require_CardTitle.CardTitle;
Title.displayName = "Card.Title";
const TitleMedia = require_CardTitleMedia.CardTitleMedia;
TitleMedia.displayName = "Card.TitleMedia";
const Actions = require_CardActions.CardActions;
Actions.displayName = "Card.Actions";
const Action = require_CardAction.CardAction;
Action.displayName = "Card.Action";
const Card = Object.assign(CardComponent, {
Header,
Body,
Footer,
HeaderMedia,
Media,
Title,
TitleMedia,
Actions,
Action
});
//#endregion
exports.Card = Card;