"use client";
import { motion } from "framer-motion";
import { COLORS, VizFrame } from "./common";
type ModalityKey = "tabular" | "image" | "text" | "audio" | "video";
const W_DEFAULT = 1040;
const H_DEFAULT = 460;
const MODS: { key: ModalityKey; title: string; shape: string; example: string }[] = [
{ key: "tabular", title: "Tabular", shape: "(N, F)", example: "rows × features · sensor logs, telemetry" },
{ key: "image", title: "Image", shape: "(H, W, C)", example: "pixels × channels · drone camera frame" },
{ key: "text", title: "Text", shape: "(T,)", example: "sequence of tokens · radio chatter" },
{ key: "audio", title: "Audio", shape: "(T,) · (F, T)", example: "waveform → spectrogram · motor sounds" },
{ key: "video", title: "Video", shape: "(T, H, W, C)", example: "frames over time · flight footage" },
];
function Tabular({ w, h }: { w: number; h: number }) {
const rows = 5;
const cols = 4;
const cellW = (w - 24) / cols;
const cellH = (h - 30) / rows;
return (
{Array.from({ length: rows * cols }, (_, i) => {
const r = Math.floor(i / cols);
const c = i % cols;
const v = ((c * 31 + r * 17) % 9) / 9;
return (
{v.toFixed(2)}
);
})}
);
}
function ImageMod({ w, h }: { w: number; h: number }) {
const N = 10;
const cellW = (w - 24) / N;
const cellH = (h - 30) / N;
return (
{Array.from({ length: N * N }, (_, i) => {
const r = Math.floor(i / N);
const c = i % N;
const cx = N / 2;
const cy = N / 2;
const dist = Math.sqrt((c - cx) ** 2 + (r - cy) ** 2);
const v = Math.max(0, 1 - dist / (N * 0.6));
return (
);
})}
);
}
function TextMod({ w }: { w: number; h: number }) {
const tokens = ["the", "drone", "approaches", "a", "yellow", "gate"];
const ids = [102, 451, 9882, 19, 6022, 309];
return (
{tokens.map((t, i) => {
const px = (i % 3) * ((w - 24) / 3);
const py = Math.floor(i / 3) * 40;
return (
{t}
id {ids[i]}
);
})}
);
}
function AudioMod({ w, h }: { w: number; h: number }) {
const N = 36;
const innerW = w - 24;
const innerH = h - 30;
const cy = 22 + innerH / 2;
return (
{Array.from({ length: N }, (_, i) => {
const phase = (i / N) * Math.PI * 4;
const env = 1 - Math.abs(i / N - 0.5) * 1.4;
const a = Math.sin(phase) * 0.6 * Math.max(0.1, env);
const x = 12 + (i / (N - 1)) * innerW;
const len = a * (innerH * 0.4);
return (
);
})}
);
}
function VideoMod({ w, h }: { w: number; h: number }) {
const frames = 4;
const innerW = w - 24;
const fw = innerW / frames - 6;
const fh = h - 36;
return (
{Array.from({ length: frames }, (_, i) => (
{/* Sky */}
{/* Ground */}
{/* Moving target */}
t={i}
))}
);
}
export function DataModalities({
width = W_DEFAULT,
height = H_DEFAULT,
}: {
width?: number;
height?: number;
}) {
// 5 modalities — render a 3×2 grid (last cell empty)
const cols = 3;
const rows = 2;
const padX = 16;
const padY = 16;
const gap = 14;
const innerW = width - padX * 2;
const innerH = height - padY * 2;
const cellW = (innerW - gap * (cols - 1)) / cols;
const cellH = (innerH - gap * (rows - 1)) / rows;
return (
);
}