'use client';
import { forwardRef, HTMLAttributes, useId } from 'react';
export interface ChromaticAberrationProps extends HTMLAttributes {
/** Aberration intensity */
intensity?: 'subtle' | 'medium' | 'intense' | 'extreme';
/** Red channel offset in pixels */
redOffset?: number;
/** Green channel offset in pixels */
greenOffset?: number;
/** Blue channel offset in pixels */
blueOffset?: number;
/** Enable on hover only */
hoverOnly?: boolean;
/** Animate the effect */
animated?: boolean;
/** Animation speed */
animationSpeed?: number;
}
export const ChromaticAberration = forwardRef(
(
{
intensity = 'medium',
redOffset,
greenOffset,
blueOffset,
hoverOnly = false,
animated = false,
animationSpeed = 1,
className = '',
children,
...props
},
ref
) => {
const id = useId();
const offsets = {
subtle: { red: 1, green: 0, blue: -1 },
medium: { red: 3, green: 0, blue: -3 },
intense: { red: 6, green: 0, blue: -6 },
extreme: { red: 10, green: 0, blue: -10 },
}[intensity];
const finalRedOffset = redOffset ?? offsets.red;
const finalGreenOffset = greenOffset ?? offsets.green;
const finalBlueOffset = blueOffset ?? offsets.blue;
const hoverOnlyStyle = hoverOnly
? `
.chromatic-aberration-hover-${id} .chromatic-channel-red-${id} { transform: translateX(0); }
.chromatic-aberration-hover-${id} .chromatic-channel-green-${id} { transform: translateX(0); }
.chromatic-aberration-hover-${id} .chromatic-channel-blue-${id} { transform: translateX(0); }
.chromatic-aberration-hover-${id}:hover .chromatic-channel-red-${id} { transform: translateX(${finalRedOffset}px); }
.chromatic-aberration-hover-${id}:hover .chromatic-channel-green-${id} { transform: translateX(${finalGreenOffset}px); }
.chromatic-aberration-hover-${id}:hover .chromatic-channel-blue-${id} { transform: translateX(${finalBlueOffset}px); }
`
: `
.chromatic-channel-red-${id} { transform: translateX(${finalRedOffset}px); }
.chromatic-channel-green-${id} { transform: translateX(${finalGreenOffset}px); }
.chromatic-channel-blue-${id} { transform: translateX(${finalBlueOffset}px); }
`;
return (
<>
{children}
{children}
{children}
>
);
}
);
ChromaticAberration.displayName = 'ChromaticAberration';
export default ChromaticAberration;