import { Box, Skeleton } from '@mui/material' import type { SxProps, Theme } from '@mui/material' const styles = { container: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexDirection: 'column', gap: ({ spacing }) => spacing(1), height: ({ spacing }) => spacing(38), }, grid: { position: 'relative', flex: '1 1 auto', width: '100%', }, legend: { display: 'flex', alignItems: 'center', gap: ({ spacing }) => spacing(2), height: ({ spacing }) => spacing(5), }, legendItem: { display: 'flex', alignItems: 'center', gap: ({ spacing }) => spacing(1.5), }, } satisfies Record> // `sx` callback that needs runtime args — extracted at module scope so the // `styles` object can satisfy `Record>` cleanly // (function `sx`-with-args isn't assignable to plain `SxProps`). const dotSx = (top: string, left: string, size: number): SxProps => ({ position: 'absolute', top, left, width: size, height: size, borderRadius: '50%', }) export interface ScatterplotSkeletonProps { /** Number of dots to render. */ count?: number } /** * Loading state for the Scatterplot widget. Mirrors a scatter chart's * silhouette — a deterministic spread of small circular dots in the plot * area plus a legend stub — so the skeleton reads as "a scatter chart" * rather than a generic list. Matches bar/histogram/pie skeleton structure * (grid stub + legend stub in a flex column). */ export function ScatterplotSkeleton({ count = 24 }: ScatterplotSkeletonProps) { // Deterministic pseudo-scatter positions so the skeleton doesn't flicker. const dots = Array.from({ length: count }, (_, i) => { const top = 10 + ((i * 37) % 80) const left = 5 + ((i * 53) % 90) const size = 8 + ((i * 7) % 6) return { top: `${top}%`, left: `${left}%`, size } }) return ( {dots.map((d, i) => ( ))} {[0, 1].map((i) => ( ))} ) }