// Components for Holistic Radar landing page
// Exports: Radar, Pyramid, Icon
const { useState, useEffect, useRef } = React;
// ============ RADAR ============
function Radar({ pings = true }) {
const [angle, setAngle] = useState(0);
const rafRef = useRef(null);
useEffect(() => {
if (!pings) return;
let last = performance.now();
const tick = (t) => {
const dt = (t - last) / 1000;
last = t;
setAngle((a) => (a + dt * 60) % 360); // 60deg/s
rafRef.current = requestAnimationFrame(tick);
};
rafRef.current = requestAnimationFrame(tick);
return () => cancelAnimationFrame(rafRef.current);
}, [pings]);
// fixed blip positions (so they don't jump on re-render)
const blips = [
{ r: 0.30, theta: 30, label: "Vision" },
{ r: 0.50, theta: 90, label: "Strategy" },
{ r: 0.62, theta: 160, label: "Brand" },
{ r: 0.42, theta: 215, label: "Systems" },
{ r: 0.68, theta: 285, label: "Sales" },
{ r: 0.25, theta: 335, label: "Self" },
];
return (
);
}
// ============ PYRAMID ============
function Pyramid({ tiers, activeIdx, onSelect }) {
// tiers ordered top -> bottom
const total = tiers.length;
const baseWidth = 100; // %
const topWidth = 28;
return (
);
}
// ============ Icon ============
function Icon({ name, size = 22 }) {
const props = {
width: size, height: size, viewBox: "0 0 24 24",
fill: "none", stroke: "currentColor", strokeWidth: "1.5",
strokeLinecap: "round", strokeLinejoin: "round",
};
switch (name) {
case "saas":
return ();
case "ecom":
return ();
case "founder":
return ();
case "arrow":
return ();
case "play":
return ();
default: return null;
}
}
Object.assign(window, { Radar, Pyramid, Icon });