( +Control: React.ComponentType
, +opts: WithExperimentOpts +): React.ComponentType
void; probat?: { trackClick: () => void } }> { +const { proposalId, registry } = opts; + +function Wrapped(props: P) { + const [choice, setChoice] = React.useState<{ experiment_id: string; label: string } | null>(null); + + React.useEffect(() => { + let alive = true; + + const cached = readChoice(proposalId); + if (cached) { + setChoice({ experiment_id: cached.experiment_id, label: cached.label }); + } + + if (!cached) { + (async () => { + try { + const { experiment_id, label } = await fetchDecision(ENV_BASE, proposalId); + if (!alive) return; + setChoice({ experiment_id, label }); + } catch (e) { + if (!alive) return; + setChoice({ experiment_id: `exp_${proposalId}`, label: "control" }); + } + })(); + } + + return () => { alive = false; }; + }, [proposalId]); + + const trackClick = React.useCallback(() => { + const exp = choice?.experiment_id; + const lbl = choice?.label ?? "control"; + void sendClickMetric(ENV_BASE, proposalId, exp, lbl); + }, [proposalId, choice?.experiment_id, choice?.label]); + + const label = choice?.label ?? "control"; + const Variant = registry[label] || Control; + + const key = `${proposalId}:${label}`; + return ( +