/* eslint-disable react/no-multi-comp */
import React from 'react'
import { get } from 'lodash'
import classnames from 'classnames'
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
import type { ProductColors, CategoryColors, BackgroundColors, StatusColors } from '../types/colors'
import Icon from '../pb_icon/_icon'
import Flex from '../pb_flex/_flex'
import Draggable from '../pb_draggable/_draggable'
type CardPropTypes = {
aria?: {[key: string]: string},
background?: BackgroundColors | ProductColors | "none",
borderNone?: boolean,
borderRadius?: "xs" | "sm" | "md" | "lg" | "xl" | "none" | "rounded",
children: React.ReactChild[] | React.ReactChild | number,
className?: string,
data?: {[key: string]: string},
dragId?: string,
draggableItem?: boolean,
dragHandle?: boolean,
htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
highlight?: {
position?: "side" | "top",
color?: string,
},
id?: string,
length?: number,
padding?: string,
selected?: boolean,
tag?: "div" | "section" | "footer" | "header" | "article" | "aside" | "main" | "nav",
} & GlobalProps
type CardHeaderProps = {
headerColor?: BackgroundColors | ProductColors | CategoryColors | StatusColors | "none",
headerColorStriped?: boolean,
children: React.ReactChild[] | React.ReactChild,
className?: string,
padding?: string,
} & GlobalProps
type CardBodyProps = {
children: React.ReactChild[] | React.ReactChild | string,
className?: string,
padding?: string,
} & GlobalProps
// Header component
const Header = (props: CardHeaderProps) => {
const { children, className, headerColor = 'category_1', headerColorStriped = false } = props
const headerCSS = buildCss('pb_card_header_kit', `${headerColor}`, headerColorStriped ? 'striped' : '')
const headerSpacing = globalProps(props)
return (
{children}
)
}
// Body component
const Body = (props: CardBodyProps) => {
const { children, className } = props
const bodyCSS = buildCss('pb_card_body_kit')
const bodySpacing = globalProps(props)
return (
{children}
)
}
const Card = (props: CardPropTypes): React.ReactElement => {
const {
aria = {},
background = 'none',
borderNone = false,
borderRadius = 'md',
children,
className,
data = {},
dragId,
dragHandle = true,
draggableItem = false,
highlight = {},
htmlOptions = {},
selected = false,
tag = 'div',
} = props
const borderCSS = borderNone == true ? 'border_none' : ''
const selectedCSS = selected == true ? 'selected' : 'deselected'
const backgroundCSS = background == 'none' ? '' : `background_${background}`
const cardCss = buildCss('pb_card_kit', selectedCSS, borderCSS, `border_radius_${borderRadius}`, backgroundCSS, {
[`highlight_${highlight.position}`]: highlight.position,
[`highlight_${highlight.color}`]: highlight.color,
})
const ariaProps: {[key: string]: string} = buildAriaProps(aria)
const dataProps: {[key: string]: string} = buildDataProps(data)
const htmlProps = buildHtmlProps(htmlOptions);
// coerce to array
const cardChildren = React.Children.toArray(children)
const dynamicInlineProps = globalInlineProps(props);
const { style: htmlStyle = {}, ...restHtmlProps } = htmlProps as { style?: React.CSSProperties };
const mergedStyles: React.CSSProperties = { ...htmlStyle, ...dynamicInlineProps };
const subComponentTags = (tagName: string) => {
return cardChildren.filter((c: string) => (
get(c, 'type.displayName') === tagName
)).map((child, i) => {
if(React.isValidElement(child)) {
return React.cloneElement(child, { key: `${tagName.toLowerCase()}-${i}` })
}
})
}
const nonHeaderChildren = cardChildren.filter((child: Node) => (get(child, 'type.displayName') !== 'Header'))
const tagOptions = ['div', 'section', 'footer', 'header', 'article', 'aside', 'main', 'nav']
const Tag = tagOptions.includes(tag) ? tag : 'div'
return (
<>
{
draggableItem ? (
{subComponentTags('Header')}
{
dragHandle ? (
{nonHeaderChildren}
) : (
nonHeaderChildren
)
}
) : (
{subComponentTags('Header')}
{nonHeaderChildren}
)
}
>
)
}
Card.Header = Header
Card.Body = Body
export default Card