81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import React from 'react';
|
|
import { LucideIcon } from 'lucide-react';
|
|
import { Box, BoxProps } from './primitives/Box';
|
|
|
|
export interface IconProps extends Omit<BoxProps<'div'>, 'children'> {
|
|
icon: LucideIcon | React.ReactNode;
|
|
size?: number | string;
|
|
color?: string;
|
|
strokeWidth?: number;
|
|
animate?: string;
|
|
transition?: boolean;
|
|
groupHoverTextColor?: string;
|
|
groupHoverScale?: boolean;
|
|
}
|
|
|
|
export function Icon({
|
|
icon: IconProp,
|
|
size = 4,
|
|
color,
|
|
className = '',
|
|
style,
|
|
animate,
|
|
transition,
|
|
groupHoverTextColor,
|
|
groupHoverScale,
|
|
...props
|
|
}: IconProps) {
|
|
const sizeMap: Record<string | number, string> = {
|
|
3: 'w-3 h-3',
|
|
3.5: 'w-3.5 h-3.5',
|
|
4: 'w-4 h-4',
|
|
5: 'w-5 h-5',
|
|
6: 'w-6 h-6',
|
|
7: 'w-7 h-7',
|
|
8: 'w-8 h-8',
|
|
10: 'w-10 h-10',
|
|
12: 'w-12 h-12',
|
|
16: 'w-16 h-16',
|
|
'full': 'w-full h-full'
|
|
};
|
|
|
|
const sizeClass = sizeMap[size] || 'w-4 h-4';
|
|
|
|
// If color starts with 'text-', it's a tailwind class, so pass it as color prop to Box
|
|
const isTailwindColor = typeof color === 'string' && color.startsWith('text-');
|
|
const combinedStyle = color && !isTailwindColor ? { color, ...style } : style;
|
|
const boxColor = isTailwindColor ? color : undefined;
|
|
|
|
const classes = [
|
|
sizeClass,
|
|
animate === 'spin' ? 'animate-spin' : '',
|
|
transition ? 'transition-all duration-150' : '',
|
|
groupHoverTextColor ? `group-hover:text-${groupHoverTextColor}` : '',
|
|
groupHoverScale ? 'group-hover:scale-110 transition-transform' : '',
|
|
className
|
|
].filter(Boolean).join(' ');
|
|
|
|
const renderIcon = () => {
|
|
if (!IconProp) return null;
|
|
if (typeof IconProp === 'function' || (typeof IconProp === 'object' && 'render' in IconProp)) {
|
|
const LucideIconComponent = IconProp as LucideIcon;
|
|
return <LucideIconComponent size="100%" strokeWidth={props.strokeWidth} />;
|
|
}
|
|
return IconProp;
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
className={classes}
|
|
style={combinedStyle}
|
|
color={boxColor}
|
|
display="inline-flex"
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
{...props}
|
|
>
|
|
{renderIcon()}
|
|
</Box>
|
|
);
|
|
}
|