import React, { CSSProperties, FunctionComponent } from 'react'; import ReactPlaceholder from 'react-placeholder'; import CSS from 'csstype'; import _ from 'lodash'; import { StandardProps } from '../../util/component-types'; import { lucidClassNames } from '../../util/style-helpers'; import LoadingIndicator from '../LoadingIndicator/LoadingIndicator'; import Panel from '../Panel/Panel'; export interface IStandardSkeleton extends StandardProps { className?: string; /** LoadingSkeleton height. */ height?: number | string; /** LoadingSkeleton width. */ width?: number | string; } export interface ILoadingSkeletonProps extends IStandardSkeleton { /** Allows custom skeleton to be injected. */ Skeleton?: FunctionComponent; /** Controls the visibility of the `LoadingSkeleton`. */ isLoading: boolean; /** Children controls wrapped by skeleton. */ children?: React.ReactNode; /** Displays LoadingSkeleton custom header. */ header?: React.ReactNode; style?: CSSProperties; /** Controls if LoadingSkeleton is wrapped in Panel. */ isPanel?: boolean; /** Controls if built-in LoadingIndicator has overlay. Does not apply to other skeletons */ hasOverlay?: boolean; /** Style variations for the overlay behind the loading indicator for built-in LoadingIndicator. Does not apply to other skeletons */ overlayKind?: 'light' | 'dark'; /** Controls if LoadingSkeleton replicated in number of rows. Default = 1. */ numRows?: number; /** Controls if LoadingSkeleton replicated in number of columns. Default = 1. */ numColumns?: number; marginBottom?: string | number | undefined; marginTop?: string | number | undefined; marginLeft?: string | number | undefined; marginRight?: string | number | undefined; } const animationStyle = lucidClassNames.bind( '&-LoadingSkeleton-animatedSkeleton' ); export const LoadingSkeleton: FunctionComponent = ( props ) => { const { Skeleton, isLoading, children, className, header, style, width = undefined, height = undefined, isPanel = false, hasOverlay = false, overlayKind = 'light', numRows = 1, numColumns = 1, marginTop = 2, marginBottom = 2, marginRight = 2, marginLeft = 2, } = { ...props }; if (!isLoading) { return (
{children}
); } if (!Skeleton) { return ( ); } const skeletonProps = { ...style, width, height, display: 'flex' }; const skeletonPlaceholder = ( ); const matrix = _.times(numColumns, (column) => (
{_.times(numRows, (row) => (
{header ? (
{header}
) : null} {}
))}
)); const skeletonMatrix =
{matrix}
; return isPanel ? ( {skeletonMatrix} ) : ( skeletonMatrix ); }; export default LoadingSkeleton;