61 lines
1.4 KiB
TypeScript
61 lines
1.4 KiB
TypeScript
import type { Particle } from "@/api/types";
|
|
import { MediaParticleView } from "./media-particle-view";
|
|
import { TextParticleView } from "./text-particle-view";
|
|
import { FallbackParticleView } from "./fallback-particle-view";
|
|
|
|
interface ParticleRendererProps {
|
|
particle: Particle;
|
|
paused: boolean;
|
|
onNext: () => void;
|
|
onPrev: () => void;
|
|
}
|
|
|
|
export function ParticleRenderer({
|
|
particle,
|
|
paused,
|
|
onNext,
|
|
onPrev,
|
|
}: ParticleRendererProps) {
|
|
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
const x = (e.clientX - rect.left) / rect.width;
|
|
if (x < 0.3) onPrev();
|
|
else if (x > 0.7) onNext();
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="relative flex h-full w-full cursor-pointer items-center justify-center"
|
|
onClick={handleClick}
|
|
>
|
|
<ParticleContent particle={particle} paused={paused} onEnded={onNext} />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ParticleContent({
|
|
particle,
|
|
paused,
|
|
onEnded,
|
|
}: {
|
|
particle: Particle;
|
|
paused: boolean;
|
|
onEnded: () => void;
|
|
}) {
|
|
switch (particle.type) {
|
|
case "media":
|
|
return (
|
|
<MediaParticleView
|
|
key={particle.id}
|
|
particle={particle}
|
|
paused={paused}
|
|
onEnded={onEnded}
|
|
/>
|
|
);
|
|
case "text":
|
|
return <TextParticleView particle={particle} />;
|
|
default:
|
|
return <FallbackParticleView particle={particle} />;
|
|
}
|
|
}
|