// @flow strict import * as React from 'react'; import { borderRadiusCircle, borderRadiusMedium, borderRadiusNone, borderRadiusXSmall, } from '../../styles/variables/_border'; import {size40, sizeFluid} from '../../styles/variables/_size'; import classify from '../../utils/classify'; import {appendPx} from '../../utils/string'; import css from './Shimmer.module.css'; type ClassNames = $ReadOnly<{wrapper?: string}>; export const SHIMMER_TYPES = Object.freeze({ text: 'text', rounded: 'rounded', circular: 'circular', rectangular: 'rectangular', }); export const SHIMMER_TYPE_TO_BORDER_RADIUS_MAP = Object.freeze({ text: borderRadiusXSmall, rounded: borderRadiusMedium, circular: borderRadiusCircle, rectangular: borderRadiusNone, }); export type ShimmerType = $Values; export type ShimmerProps = { classNames?: ClassNames, show?: boolean, type?: ShimmerType, width?: number | string, height?: number | string, borderRadius?: number | string, children?: React.Node, }; export type ShimmerWrapperProps = { children?: React.Node, }; /** * Note(Nishant): ShimmerWrapper is a wrapper component for Shimmer component. This should only be used for Text based Shimmers * This solves a very annoying problem with out text components where the display prop is set to flex. * Genesis assumes that every element is flexible for simplicity and for text text shimmers to work in use cases * where text wraps across multiple lines, we need to wrap the shimmer in a span element. * to avoid the misuse where consumers use there own / other block level components, we have this wrapper. * This would ensure the layout remains same even when you toggle the shimmer to show your actual content * @param {React.Node} children - The children to be rendered */ export const ShimmerWrapper = ({ children, }: ShimmerWrapperProps): React$Element<'span'> => {children}; export const Shimmer: React$AbstractComponent = React.forwardRef( ( { classNames, show = true, type = SHIMMER_TYPES.text, children, width = size40, height = sizeFluid, borderRadius, }: ShimmerProps, ref, ) => { if (!show) { return <>{children}; } const borderRadiusValue = borderRadius ?? SHIMMER_TYPE_TO_BORDER_RADIUS_MAP[type]; return ( ); }, ); type KPIShimmerClassNames = $ReadOnly<{ wrapper?: string, icon?: string, text?: string, }>; export type KPIShimmerProps = { textWidth?: number | string, hasTopContent?: boolean, hasMiddleContent?: boolean, hasBottomContent?: boolean, hasIcon?: boolean, classNames?: KPIShimmerClassNames, }; export const KPIShimmer = ({ textWidth = 150, hasBottomContent = true, hasIcon = true, hasTopContent = true, hasMiddleContent = true, classNames, }: KPIShimmerProps): React.Node => (
{hasIcon && (
)}
{hasTopContent && ( )} {hasMiddleContent && ( )} {hasBottomContent && ( )}
);