import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Card/card'; import { CardContext } from './Card'; import { CardHeaderMain } from './CardHeaderMain'; import { CardActions } from './CardActions'; import { CardSelectableActions } from './CardSelectableActions'; import { Button } from '../Button'; import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; import { Radio } from '../Radio'; import { Checkbox } from '../Checkbox'; export interface CardHeaderActionsObject { /** Actions of the card header */ actions: React.ReactNode; /** Flag indicating that the actions have no offset */ hasNoOffset?: boolean; /** Additional classes added to the actions wrapper */ className?: string; } export interface CardHeaderSelectableActionsObject { /** Determines the type of input to be used for a selectable card. */ variant?: 'single' | 'multiple'; /** Flag indicating that the actions have no offset */ hasNoOffset?: boolean; /** Additional classes added to the selectable actions wrapper */ className?: string; /** ID passed to the selectable or clickable input */ selectableActionId: string; /** Adds an accessible label to the selectable or clickable input */ selectableActionAriaLabel?: string; /** Adds an accessible label to the selectable or clickable input by passing in a * space separated list of id's. */ selectableActionAriaLabelledby?: string; /** Callback for when a selectable card input changes */ onChange?: (event: React.FormEvent, checked: boolean) => void; /** Action to call when clickable card is clicked */ onClickAction?: (event: React.FormEvent | React.MouseEvent) => void; /** Link to navigate to when clickable card is clicked */ to?: string; /** Flag to indicate whether a clickable card's link should open in a new tab/window. */ isExternalLink?: boolean; /** Name for the input element of a clickable or selectable card. */ name?: string; /** Flag indicating whether the selectable card input is checked */ isChecked?: boolean; } export interface CardHeaderProps extends React.HTMLProps { /** Content rendered inside the card header */ children?: React.ReactNode; /** Additional classes added to the card header */ className?: string; /** Actions of the card header */ actions?: CardHeaderActionsObject; /** Selectable actions of the card header */ selectableActions?: CardHeaderSelectableActionsObject; /** ID of the card header. */ id?: string; /** Callback expandable card */ onExpand?: (event: React.MouseEvent, id: string) => void; /** Additional props for expandable toggle button */ toggleButtonProps?: any; /** Whether to right-align expandable toggle button */ isToggleRightAligned?: boolean; } export const CardHeader: React.FunctionComponent = ({ children, className, actions, selectableActions, id, onExpand, toggleButtonProps, isToggleRightAligned, ...props }: CardHeaderProps) => ( {/* TODO: Remove hasSelectableInput when deprecated props are removed */} {({ cardId, isClickable, isSelectable, isDisabled: isCardDisabled, hasSelectableInput }) => { const cardHeaderToggle = (
); const isClickableOrSelectableOnly = (isClickable && !isSelectable) || (isSelectable && !isClickable); // TODO: Remove following variable and update if block when deprecated prop is removed // We don't want to throw a warning for the deprecated card const isDeprecatedSelectableCard = hasSelectableInput; if (actions?.actions && isClickableOrSelectableOnly && !isDeprecatedSelectableCard) { // eslint-disable-next-line no-console console.warn( `${ isClickable ? 'Clickable' : 'Selectable' } only cards should not contain any other actions. If you wish to include additional actions, use a clickable and selectable card.` ); } const handleActionClick = (event: React.FormEvent | React.MouseEvent) => { if (isClickable) { if (selectableActions?.onClickAction) { selectableActions.onClickAction(event); } else if (selectableActions?.to) { window.open(selectableActions.to, selectableActions.isExternalLink ? '_blank' : '_self'); } } }; const getClickableSelectableProps = () => { const baseProps = { className: 'pf-m-standalone', inputClassName: isClickable && !isSelectable && 'pf-v5-screen-reader', label: <>, 'aria-label': selectableActions.selectableActionAriaLabel, 'aria-labelledby': selectableActions.selectableActionAriaLabelledby, id: selectableActions.selectableActionId, name: selectableActions.name, isDisabled: isCardDisabled }; if (isClickable && !isSelectable) { return { ...baseProps, onClick: handleActionClick }; } if (isSelectable) { return { ...baseProps, onChange: selectableActions.onChange, isChecked: selectableActions.isChecked }; } return baseProps; }; return (
{onExpand && !isToggleRightAligned && cardHeaderToggle} {(actions || (selectableActions && (isClickable || isSelectable))) && ( {actions?.actions} {selectableActions && (isClickable || isSelectable) && ( {selectableActions?.variant === 'single' || (isClickable && !isSelectable) ? ( ) : ( )} )} )} {children && {children}} {onExpand && isToggleRightAligned && cardHeaderToggle}
); }}
); CardHeader.displayName = 'CardHeader';