'use client'; import { forwardRef, HTMLAttributes } from 'react'; import styles from './three-d-text.module.css'; export interface ThreeDTextProps extends HTMLAttributes { /** Text to display */ children: string; /** Number of shadow layers for depth */ depth?: number; /** Direction of the 3D extrusion */ direction?: 'top-left' | 'top' | 'top-right' | 'right' | 'bottom-right' | 'bottom' | 'bottom-left' | 'left'; /** Shadow color */ color?: string; /** Shadow opacity (0-1) */ opacity?: number; /** Pixels between each layer */ spacing?: number; } export const ThreeDText = forwardRef( ( { children, depth = 5, direction = 'bottom-right', color = '#000000', opacity = 0.8, spacing = 2, className, style, ...props }, ref ) => { // Generate shadow string based on direction and depth const generateShadow = () => { const shadows = []; const safeDepth = Math.max(1, Math.min(depth, 20)); const safeOpacity = Math.max(0, Math.min(opacity, 1)); for (let i = 1; i <= safeDepth; i++) { const offset = i * spacing; const layerOpacity = safeOpacity * (1 - (i - 1) / safeDepth * 0.5); let x = 0; let y = 0; switch (direction) { case 'top-left': x = -offset; y = -offset; break; case 'top': x = 0; y = -offset; break; case 'top-right': x = offset; y = -offset; break; case 'right': x = offset; y = 0; break; case 'bottom-right': x = offset; y = offset; break; case 'bottom': x = 0; y = offset; break; case 'bottom-left': x = -offset; y = offset; break; case 'left': x = -offset; y = 0; break; } // Convert hex color to rgba for opacity const hexToRgb = (hex: string) => { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16), } : { r: 0, g: 0, b: 0 }; }; const rgb = hexToRgb(color); shadows.push(`${x}px ${y}px 0 rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${layerOpacity})`); } return shadows.join(', '); }; return ( {children} ); } ); ThreeDText.displayName = 'ThreeDText'; export default ThreeDText;