import React, { useId, useMemo } from "react"; import classNames from "classnames"; import { useLocale } from "@react-aria/i18n"; import { GradientEndPoint, GradientMidPoint, Svg, } from "./SkeletonLoader.styles"; import { HasClassName } from "../../../types"; // Based on https://github.com/danilowoz/react-content-loader export interface SkeletonLoaderProps extends Omit, "className">, HasClassName { /** Whether or not to animate the skeleton */ isAnimated?: boolean; /** Width of the animated gradient with repsect to the viewbox witdth */ gradientRatio?: number; /** Length in seconds that the animation should take */ duration?: number; /** Used to describe the element for accessibility */ title?: string; } /** * Renders a skeleton loader component. This component is used to show a loading state for a component. * * You provide svg elements as children to the component and it will animate a gradient over the top of them. */ export function SkeletonLoader(props: SkeletonLoaderProps) { const { children, isAnimated = true, gradientRatio = 2, duration = 1.2, title = "", viewBox, width, height, className, ...rest } = props; const { direction } = useLocale(); // get the baseURL from the document const baseUrl = useMemo(() => { const base = document.querySelector("base"); if (base) { return base.href; } return ""; }, []); const fixedId = useId(); const idClip = `${fixedId}-diff`; const idGradient = `${fixedId}-animated-diff`; const idAria = `${fixedId}-aria`; const durationSeconds = `${duration}s`; const from = `${gradientRatio * -1} 0`; const to = `${gradientRatio} 0`; return ( {title && {title}} {children} {isAnimated && ( )} ); }