Pulastya B
feat: Initial commit - Data Science Agent with React frontend and FastAPI backend
226ac39
'use client';
import React, { useRef, useId, useEffect, CSSProperties } from 'react';
import { animate, useMotionValue, AnimationPlaybackControls, motion } from 'framer-motion';
import { cn } from '../lib/utils';
// Type definitions
interface ResponsiveImage {
src: string;
alt?: string;
srcSet?: string;
}
interface AnimationConfig {
preview?: boolean;
scale: number;
speed: number;
}
interface NoiseConfig {
opacity: number;
scale: number;
}
interface ShadowOverlayProps {
type?: 'preset' | 'custom';
presetIndex?: number;
customImage?: ResponsiveImage;
sizing?: 'fill' | 'stretch';
color?: string;
animation?: AnimationConfig;
noise?: NoiseConfig;
style?: CSSProperties;
className?: string;
title?: string;
description?: string;
}
function mapRange(
value: number,
fromLow: number,
fromHigh: number,
toLow: number,
toHigh: number
): number {
if (fromLow === fromHigh) {
return toLow;
}
const percentage = (value - fromLow) / (fromHigh - fromLow);
return toLow + percentage * (toHigh - toLow);
}
const useInstanceId = (): string => {
const id = useId();
const cleanId = id.replace(/:/g, "");
const instanceId = `shadowoverlay-${cleanId}`;
return instanceId;
};
export function ShadowSection({
sizing = 'fill',
color = 'rgba(99, 102, 241, 0.6)',
animation = { scale: 50, speed: 15 },
noise = { opacity: 0.1, scale: 0.5 },
style,
className,
title = "Cognitive Core",
description = "The unseen intelligence powering your most critical decisions."
}: ShadowOverlayProps) {
const id = useInstanceId();
const animationEnabled = animation && animation.scale > 0;
const feColorMatrixRef = useRef<SVGFEColorMatrixElement>(null);
const hueRotateMotionValue = useMotionValue(180);
const hueRotateAnimation = useRef<AnimationPlaybackControls | null>(null);
const displacementScale = animation ? mapRange(animation.scale, 1, 100, 20, 100) : 0;
const animationDuration = animation ? mapRange(animation.speed, 1, 100, 1000, 50) : 1;
useEffect(() => {
if (feColorMatrixRef.current && animationEnabled) {
if (hueRotateAnimation.current) {
hueRotateAnimation.current.stop();
}
hueRotateMotionValue.set(0);
hueRotateAnimation.current = animate(hueRotateMotionValue, 360, {
duration: animationDuration / 25,
repeat: Infinity,
repeatType: "loop",
repeatDelay: 0,
ease: "linear",
delay: 0,
onUpdate: (value: number) => {
if (feColorMatrixRef.current) {
feColorMatrixRef.current.setAttribute("values", String(value));
}
}
});
return () => {
if (hueRotateAnimation.current) {
hueRotateAnimation.current.stop();
}
};
}
}, [animationEnabled, animationDuration, hueRotateMotionValue]);
return (
<section
className={cn("relative w-full h-[70vh] min-h-[500px] overflow-hidden bg-[#030303]", className)}
style={style}
>
<div
style={{
position: "absolute",
inset: -displacementScale,
filter: animationEnabled ? `url(#${id}) blur(8px)` : "none"
}}
>
{animationEnabled && (
<svg style={{ position: "absolute", width: 0, height: 0 }}>
<defs>
<filter id={id}>
<feTurbulence
result="undulation"
numOctaves="2"
baseFrequency={`${mapRange(animation.scale, 0, 100, 0.001, 0.0005)},${mapRange(animation.scale, 0, 100, 0.004, 0.002)}`}
seed="0"
type="turbulence"
/>
<feColorMatrix
ref={feColorMatrixRef}
in="undulation"
type="hueRotate"
values="180"
/>
<feColorMatrix
in="dist"
result="circulation"
type="matrix"
values="4 0 0 0 1 4 0 0 0 1 4 0 0 0 1 1 0 0 0 0"
/>
<feDisplacementMap
in="SourceGraphic"
in2="circulation"
scale={displacementScale}
result="dist"
/>
<feDisplacementMap
in="dist"
in2="undulation"
scale={displacementScale}
result="output"
/>
</filter>
</defs>
</svg>
)}
<div
style={{
backgroundColor: color,
maskImage: `url('https://framerusercontent.com/images/ceBGguIpUU8luwByxuQz79t7To.png')`,
maskSize: sizing === "stretch" ? "100% 100%" : "cover",
maskRepeat: "no-repeat",
maskPosition: "center",
width: "100%",
height: "100%"
}}
/>
</div>
<div
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
textAlign: "center",
zIndex: 20,
width: '100%',
padding: '0 2rem'
}}
>
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
className="md:text-7xl text-5xl lg:text-8xl font-heading font-bold text-center text-white relative z-20 tracking-tighter mb-4"
>
{title}
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.2 }}
className="text-white/60 text-lg md:text-xl font-sans max-w-xl mx-auto"
>
{description}
</motion.p>
</div>
{noise && noise.opacity > 0 && (
<div
style={{
position: "absolute",
inset: 0,
backgroundImage: `url("https://framerusercontent.com/images/g0QcWrxr87K0ufOxIUFBakwYA8.png")`,
backgroundSize: noise.scale * 200,
backgroundRepeat: "repeat",
opacity: noise.opacity / 2,
zIndex: 15
}}
/>
)}
{/* Bottom Vignette */}
<div className="absolute inset-x-0 bottom-0 h-40 bg-gradient-to-t from-[#030303] to-transparent z-30" />
<div className="absolute inset-x-0 top-0 h-40 bg-gradient-to-b from-[#030303] to-transparent z-30" />
</section>
);
}