Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 21x 21x 21x 1x 1x 1x 21x 21x 3x 3x 3x 21x 21x 21x 21x 21x 21x 21x 1x | import { SPIN_SPEED } from '@/constants/common';
import { isSpinSpeed } from '@/utils/typeGuards/common';
import { keyframes, styled } from '@mui/material/styles';
import { cloneElement, isValidElement, FC } from 'react';
const spin = keyframes`
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
`;
// Defined at module scope (not inside the component) so the styled component
// keeps a stable identity across re-renders; otherwise a parent re-render —
// e.g. an updating result count — remounts the node and restarts the animation.
const SpinningWrapper = styled('div', {
shouldForwardProp: (prop) => prop !== 'speed',
})<{ speed: number }>(({ speed }) => ({
display: 'inline-flex',
animation: `${spin} ${speed}s linear infinite`,
}));
/**
* A component that adds a spinning animation to any icon component passed as a child.
* The component preserves any existing styles while adding the spinning animation.
*
* @component
* @param props - The props from Material-UI's SvgIcon component
* @returns An animated version of the provided icon
*
* @example
* ```typescript
* // Simple icon with default size and speed
* <IconSpinner>
* <MyIcon />
* </IconSpinner>
*
* // Icon with custom size, default speed
* <IconSpinner>
* <MyIcon style={{ width: 100, height: 100 }} />
* </IconSpinner>
*
* // Icon with custom speed (as string)
* <IconSpinner speed={"fast"}>
* <MyIcon style={{ width: 100, height: 100 }} />
* </IconSpinner>
*
* // Icon with custom speed (as number)
* <IconSpinner speed={2}>
* <MyIcon style={{ width: 100, height: 100 }} />
* </IconSpinner>
*
* // Icon with custom speed from SpinSpeeds enum
* <IconSpinner speed={SpinSpeeds.MEDIUM}>
* <MyIcon style={{ width: 100, height: 100 }} />
* </IconSpinner>
* ```
* @source
*/
const IconSpinner: FC<IconSpinnerProps> = (props: IconSpinnerProps) => {
let { speed = 2 } = props;
if (typeof speed === 'string') {
const key = speed.toUpperCase();
speed = isSpinSpeed(key) ? SPIN_SPEED[key] : SPIN_SPEED.MEDIUM;
}
// Clone the child element to preserve its props
if (!isValidElement(props.children)) {
return null;
}
const child = cloneElement(props.children);
return (
<SpinningWrapper speed={speed} data-testid="spinning-wrapper">
{child}
</SpinningWrapper>
);
};
export default IconSpinner;
|