UNPKG

@carbon/ibm-products

Version:
258 lines (256 loc) 12.3 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_CardHeader = require("./CardHeader.js"); const require_CardFooter = require("./CardFooter.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"); let _carbon_react_icons = require("@carbon/react/icons"); //#region src/components/Card/Card.tsx var import_classnames = /* @__PURE__ */ require_runtime.__toESM(require_index.default); const componentName = "Card"; const Card = (0, react.forwardRef)(({ actionIcons = Object.freeze([]), actionsPlacement = "bottom", decorator, metadata = Object.freeze([]), children, className, clickZone = "one", description, disabled, footerActionIcon, getStarted, label, media, mediaPosition = "top", onClick, onKeyDown, onPrimaryButtonClick, onSecondaryButtonClick, overflowActions = Object.freeze([]), overflowAriaLabel, pictogram: Pictogram, primaryButtonDisabled, primaryButtonHref, primaryButtonIcon, primaryButtonKind = "primary", primaryButtonPlacement = "bottom", primaryButtonText, productive = false, secondaryButtonDisabled, secondaryButtonHref, secondaryButtonIcon, secondaryButtonKind = "secondary", secondaryButtonPlacement = "bottom", secondaryButtonText, slug, status, sequence, title, titleSize = "default", iconDescription = "Options", ...rest }, ref) => { const getIcons = () => getStarted ? metadata : actionIcons; const blockClass = `${require_settings.pkg.prefix}--card`; const hasActions = getIcons().length > 0 || overflowActions.length > 0 || !!primaryButtonText && primaryButtonPlacement === "top"; const hasHeaderActions = hasActions && actionsPlacement === "top"; const hasFooterActions = hasActions && actionsPlacement === "bottom"; const hasFooterButton = !!secondaryButtonText || !!primaryButtonText && primaryButtonPlacement === "bottom"; const hasBottomBar = hasFooterActions || hasFooterButton; const hasClickEvent = !!onClick || !!onKeyDown; const clickableProps = { onClick, onKeyDown, role: "button", tabIndex: 0 }; const getActions = () => { if (overflowActions.length > 0) { const pos = actionsPlacement === "top" ? "bottom-end" : "top-end"; const size = actionsPlacement === "top" ? "sm" : "md"; return /* @__PURE__ */ react.default.createElement(_carbon_react.Layer, { level: 2 }, /* @__PURE__ */ react.default.createElement(_carbon_react.unstable_FeatureFlags, { enableV12Overflowmenu: true }, /* @__PURE__ */ react.default.createElement(_carbon_react.OverflowMenu, { autoAlign: true, menuAlignment: pos, size, label: overflowAriaLabel || iconDescription }, overflowActions.map(({ id, itemText, onKeyDown, onClick, ...rest }) => /* @__PURE__ */ react.default.createElement(_carbon_react.MenuItem, { ...rest, key: id, label: itemText ?? "", onKeyDown, onClick }))))); } return getIcons().map(({ id, icon: Icon, onClick, iconDescription, href: deprecatedHref, link, ...rest }) => { const { href, ...linkProps } = link ?? { href: deprecatedHref }; if (getStarted) return /* @__PURE__ */ react.default.createElement("span", { key: id, className: `${blockClass}__icon` }, Icon && /* @__PURE__ */ react.default.createElement(Icon, { "aria-label": iconDescription }), iconDescription); if (productive) return /* @__PURE__ */ react.default.createElement(_carbon_react.Button, { ...rest, key: id, renderIcon: Icon, hasIconOnly: true, onClick, size: actionsPlacement === "top" ? "sm" : "md", iconDescription, kind: "ghost", href, ...linkProps }); if (href) return /* @__PURE__ */ react.default.createElement("a", { key: id, className: `${blockClass}__icon`, href, onClick, ...linkProps }, Icon && /* @__PURE__ */ react.default.createElement(Icon, { "aria-label": iconDescription })); return /* @__PURE__ */ react.default.createElement(_carbon_react.IconButton, { key: id, label: iconDescription, className: `${blockClass}__icon`, onClick, kind: "ghost", size: "sm" }, Icon && /* @__PURE__ */ react.default.createElement(Icon, { "aria-label": iconDescription })); }); }; const getCardProps = () => { const clickable = hasClickEvent && !productive || hasClickEvent && productive && clickZone === "one"; return { ...rest, ref, className: (0, import_classnames.default)(blockClass, { [`${blockClass}__disabled`]: disabled, [`${blockClass}__get-started`]: getStarted, [`${blockClass}__productive`]: productive, [`${blockClass}__clickable`]: clickable, [`${blockClass}__media-left`]: mediaPosition === "left", [`${blockClass}--has-slug`]: !!slug, [`${blockClass}--has-decorator`]: !!decorator && decorator["type"]?.displayName !== "AILabel", [`${blockClass}--has-ai-label`]: !!decorator && decorator["type"]?.displayName === "AILabel" }, className), ...clickable && clickableProps }; }; const getHeaderBodyProps = () => { const clickable = hasClickEvent && clickZone === "two"; return { className: (0, import_classnames.default)(`${blockClass}__header-body-container`, { [`${blockClass}__clickable`]: clickable }), ...clickable && clickableProps }; }; const getHeaderProps = () => ({ actions: actionsPlacement === "top" ? getActions() : "", decorator, noActionIcons: getIcons().length > 0 && actionsPlacement === "top" ? false : true, actionsPlacement, onPrimaryButtonClick, onSecondaryButtonClick, primaryButtonIcon, primaryButtonPlacement, primaryButtonText, primaryButtonDisabled, description, hasActions: hasHeaderActions, inClickableCard: hasClickEvent, label, secondaryButtonDisabled, secondaryButtonHref, secondaryButtonIcon, secondaryButtonPlacement, secondaryButtonText, slug, title, titleSize }); const getBodyProps = () => { const clickable = hasClickEvent && clickZone === "three"; return { className: (0, import_classnames.default)(`${blockClass}__body`, { [`${blockClass}__clickable`]: clickable }), ...clickable && clickableProps }; }; const getFooterProps = () => ({ actions: actionsPlacement === "bottom" ? getActions() : "", actionsPlacement, disabled, footerActionIcon, hasActions: hasFooterActions, hasButton: hasFooterButton, onPrimaryButtonClick, onSecondaryButtonClick, primaryButtonDisabled, primaryButtonHref, primaryButtonIcon, primaryButtonKind, primaryButtonPlacement, primaryButtonText, productive, secondaryButtonDisabled, secondaryButtonHref, secondaryButtonIcon, secondaryButtonKind, secondaryButtonPlacement, secondaryButtonText }); return /* @__PURE__ */ react.default.createElement(_carbon_react.Section, { as: "div", "aria-disabled": disabled, ...getCardProps() }, !getStarted && media && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__media` }, media), Pictogram && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__pictogram` }, /* @__PURE__ */ react.default.createElement(Pictogram, null)), getStarted && sequence && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__sequence` }, sequence), getStarted && status && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__status` }, status === "incomplete" && /* @__PURE__ */ react.default.createElement(_carbon_react_icons.Incomplete, null), status === "complete" && /* @__PURE__ */ react.default.createElement(_carbon_react_icons.CheckmarkOutline, null)), /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__content-container` }, /* @__PURE__ */ react.default.createElement("div", getHeaderBodyProps(), /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__header-wrapper` }, /* @__PURE__ */ react.default.createElement(require_CardHeader.CardHeader, getHeaderProps()), /* @__PURE__ */ react.default.createElement("div", getBodyProps(), children)), getStarted && media && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__media` }, media)), hasBottomBar && /* @__PURE__ */ react.default.createElement(require_CardFooter.CardFooter, getFooterProps()))); }); Card.propTypes = { /**@ts-ignore */ actionIcons: prop_types.default.arrayOf(prop_types.default.shape({ id: prop_types.default.string, icon: prop_types.default.oneOfType([prop_types.default.func, prop_types.default.object]), onKeyDown: prop_types.default.func, onClick: prop_types.default.func, iconDescription: prop_types.default.string, /** * @deprecated please use the `link.href` instead */ href: prop_types.default.string, link: prop_types.default.shape({ href: prop_types.default.string.isRequired }) })), actionsPlacement: prop_types.default.oneOf(["top", "bottom"]), children: prop_types.default.node, className: prop_types.default.string, clickZone: prop_types.default.oneOf([ "one", "two", "three" ]), /** * Optional prop that allows you to pass any component. */ decorator: prop_types.default.oneOfType([prop_types.default.node, prop_types.default.bool]), /**@ts-ignore */ description: prop_types.default.oneOfType([prop_types.default.string, prop_types.default.node]), disabled: prop_types.default.bool, /**@ts-ignore */ footerActionIcon: prop_types.default.oneOfType([prop_types.default.func, prop_types.default.object]), getStarted: prop_types.default.bool, label: prop_types.default.oneOfType([prop_types.default.string, prop_types.default.node]), media: prop_types.default.node, mediaPosition: prop_types.default.oneOf(["top", "left"]), /**@ts-ignore */ metadata: prop_types.default.arrayOf(prop_types.default.shape({ id: prop_types.default.string, icon: prop_types.default.oneOfType([prop_types.default.func, prop_types.default.object]), iconDescription: prop_types.default.string })), onClick: prop_types.default.func, onKeyDown: prop_types.default.func, onPrimaryButtonClick: prop_types.default.func, onSecondaryButtonClick: prop_types.default.func, /**@ts-ignore */ overflowActions: prop_types.default.arrayOf(prop_types.default.shape({ id: prop_types.default.string, itemText: prop_types.default.string, onClick: prop_types.default.func, onKeyDown: prop_types.default.func })), overflowAriaLabel: prop_types.default.string, /**@ts-ignore */ pictogram: prop_types.default.oneOfType([prop_types.default.func, prop_types.default.object]), primaryButtonDisabled: prop_types.default.bool, primaryButtonHref: prop_types.default.string, /**@ts-ignore */ primaryButtonIcon: prop_types.default.oneOfType([prop_types.default.func, prop_types.default.object]), primaryButtonKind: prop_types.default.oneOf(["primary", "ghost"]), primaryButtonPlacement: prop_types.default.oneOf(["top", "bottom"]), primaryButtonText: prop_types.default.string, productive: prop_types.default.bool, secondaryButtonDisabled: prop_types.default.bool, secondaryButtonHref: prop_types.default.string, /**@ts-ignore */ secondaryButtonIcon: prop_types.default.oneOfType([prop_types.default.func, prop_types.default.object]), secondaryButtonKind: prop_types.default.oneOf(["secondary", "ghost"]), secondaryButtonPlacement: prop_types.default.oneOf(["top", "bottom"]), secondaryButtonText: prop_types.default.string, sequence: prop_types.default.number, /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. * @deprecated please use the `decorator` prop */ slug: prop_types.default.oneOfType([prop_types.default.node, prop_types.default.bool]), status: prop_types.default.oneOf(["complete", "incomplete"]), title: prop_types.default.oneOfType([prop_types.default.string, prop_types.default.node]), titleSize: prop_types.default.oneOf(["default", "large"]) }; Card.displayName = componentName; //#endregion exports.Card = Card;