Files
2022-12-15 13:44:49 -05:00

98 lines
2.2 KiB
TypeScript

import { styled } from '@mui/material/styles';
import React from 'react';
import icons from './Icon/icons';
import transientOptions from '@staticcms/core/lib/util/transientOptions';
import type { IconType } from './Icon/icons';
interface IconWrapperProps {
$width: number;
$height: number;
$rotation: string;
}
const IconWrapper = styled(
'span',
transientOptions,
)<IconWrapperProps>(
({ $width, $height, $rotation }) => `
display: inline-block;
line-height: 0;
width: ${$width}px;
height: ${$height}px;
transform: rotate(${$rotation});
& path:not(.no-fill),
& circle:not(.no-fill),
& polygon:not(.no-fill),
& rect:not(.no-fill) {
fill: currentColor;
}
& path.clipped {
fill: transparent;
}
svg {
width: 100%;
height: 100%;
}
`,
);
const rotations = { right: 90, down: 180, left: 270, up: 360 };
export type Direction = keyof typeof rotations;
/**
* Calculates rotation for icons that have a `direction` property configured
* in the imported icon definition object. If no direction is configured, a
* neutral rotation value is returned.
*
* Returned value is a string of shape `${degrees}deg`, for use in a CSS
* transform.
*/
function getRotation(iconDirection?: Direction, newDirection?: Direction) {
if (!iconDirection || !newDirection) {
return '0deg';
}
const degrees = rotations[newDirection] - rotations[iconDirection];
return `${degrees}deg`;
}
const sizes = {
xsmall: 12,
small: 18,
medium: 24,
large: 32,
};
export interface IconProps {
type: IconType;
direction?: Direction;
width?: number;
height?: number;
size?: keyof typeof sizes;
className?: string;
}
const Icon = ({ type, direction, width, height, size = 'medium', className }: IconProps) => {
const IconSvg = icons[type].image;
return (
<IconWrapper
className={className}
$width={width ? width : size in sizes ? sizes[size as keyof typeof sizes] : sizes['medium']}
$height={
height ? height : size in sizes ? sizes[size as keyof typeof sizes] : sizes['medium']
}
$rotation={getRotation(icons[type].direction, direction)}
>
<IconSvg />
</IconWrapper>
);
};
export default Icon;