diff --git a/src/Card/Card.jsx b/src/Card/Card.jsx deleted file mode 100644 index 8a4e0fe8..00000000 --- a/src/Card/Card.jsx +++ /dev/null @@ -1,111 +0,0 @@ -import React, { createElement } from 'react'; -import classNames from 'classnames'; -import PropTypes from 'prop-types'; - -import { LoadingSkeleton } from 'src/LoadingSkeleton'; - -import './Card.scss'; - -export const CardSizes = { - EXTRA_SMALL: 'xs', - SMALL: 'sm', - MEDIUM: 'md', - LARGE: 'lg', -}; - -const Card = ({ - children, - className, - divided, - elementType, - helperText, - isLoading, - loadingSkeleton, - loadingSkeletonParagraphCount, - noPadding, - size, - subTitle, - title, - ...props -}) => { - const defaultLoadingSkeleton = ( - <> - -
- {Array(loadingSkeletonParagraphCount).fill(0).map((_, i) => ( - // eslint-disable-next-line react/no-array-index-key -
- -
- ))} - - ); - const getLoadingSkeleton = () => loadingSkeleton || defaultLoadingSkeleton; - - const cardChildren = ( - <> - {isLoading ? ( - getLoadingSkeleton()) : ( - <> - { title && ( -
-

{title}

- { helperText && {helperText}} -
- )} - - { divided &&
} - { subTitle &&

{subTitle}

} - { children } - - )} - - ); - - return createElement( - elementType, - { - ...props, - className: classNames( - 'Card', - { [`Card--${size}`]: size }, - className, - { - 'Card--divided': divided, - 'Card--no-padding': noPadding, - }, - ), - }, - cardChildren, - ); -}; - -Card.propTypes = { - className: PropTypes.string, - divided: PropTypes.bool, - elementType: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), - helperText: PropTypes.string, - isLoading: PropTypes.bool, - loadingSkeleton: PropTypes.node, - loadingSkeletonParagraphCount: PropTypes.number, - noPadding: PropTypes.bool, - size: PropTypes.string, - subTitle: PropTypes.string, - title: PropTypes.node, -}; - -Card.defaultProps = { - className: undefined, - divided: false, - elementType: 'section', - helperText: undefined, - isLoading: undefined, - loadingSkeleton: undefined, - loadingSkeletonParagraphCount: 1, - noPadding: false, - size: undefined, - subTitle: undefined, - title: undefined, -}; - -export default Card; diff --git a/src/Card/Card.tsx b/src/Card/Card.tsx new file mode 100644 index 00000000..8a8280b5 --- /dev/null +++ b/src/Card/Card.tsx @@ -0,0 +1,98 @@ +import React, { + createElement, + type DetailedHTMLProps, + type HTMLAttributes, + type ReactNode, +} from 'react'; +import classNames from 'classnames'; + +import { LoadingSkeleton } from 'src/LoadingSkeleton'; + +import './Card.scss'; + +export const CardSizes = { + EXTRA_SMALL: 'xs', + SMALL: 'sm', + MEDIUM: 'md', + LARGE: 'lg', +} as const; + +type ElementProps = DetailedHTMLProps, HTMLElement>; + +type CardProps = { + children?: ReactNode; + className?: string; + divided?: boolean; + elementType?: string; + helperText?: ReactNode; + isLoading?: boolean; + loadingSkeleton?: ReactNode; + loadingSkeletonParagraphCount?: number; + noPadding?: boolean; + size: 'xs' | 'sm' | 'md' | 'lg'; + subTitle?: ReactNode; + title?: ReactNode; +} & ElementProps; + +const Card = ({ + children, + className, + divided = false, + elementType = 'section', + helperText, + isLoading = false, + loadingSkeleton, + loadingSkeletonParagraphCount = 1, + noPadding = false, + size, + subTitle, + title, + ...props +}: CardProps) => { + const defaultLoadingSkeleton = ( + <> + +
+ {Array(loadingSkeletonParagraphCount).fill(0).map((_, i) => ( + // eslint-disable-next-line react/no-array-index-key +
+ +
+ ))} + + ); + + return createElement( + elementType, + { + ...props, + className: classNames( + 'Card', + { [`Card--${size}`]: size }, + className, + { + 'Card--divided': divided, + 'Card--no-padding': noPadding, + }, + ), + }, + <> + {isLoading ? (loadingSkeleton || defaultLoadingSkeleton) : ( + <> + {title && ( +
+

{title}

+ {helperText && {helperText}} +
+ )} + + {divided &&
} + {subTitle &&

{subTitle}

} + {children} + + )} + , + ); +}; + +export default Card; diff --git a/src/Card/index.js b/src/Card/index.ts similarity index 100% rename from src/Card/index.js rename to src/Card/index.ts