"use client"; import { useState, useRef, useCallback } from "react"; import { createPortal } from "react-dom"; import { AlertTriangle } from "lucide-react"; import type { DriverData } from "@/lib/types"; interface Props { drivers: DriverData } function fmt(v: number | null, dec: number, unit = "") { if (v === null) return "—"; return `${v.toLocaleString("fr-FR", { minimumFractionDigits: dec, maximumFractionDigits: dec })}${unit}`; } interface TooltipState { x: number; y: number } function D({ label, value, dec = 2, unit = "", delta, deltaPct, deltaDec, tooltip }: { label: string; value: number | null; dec?: number; unit?: string; delta?: number | null; deltaPct?: boolean; deltaDec?: number; tooltip?: string; }) { const [tip, setTip] = useState(null); const ref = useRef(null); const show = useCallback(() => { if (!ref.current) return; const r = ref.current.getBoundingClientRect(); setTip({ x: r.left + r.width / 2, y: r.top }); }, []); const hide = useCallback(() => setTip(null), []); const pos = delta != null && delta > 0; const neg = delta != null && delta < 0; const dColor = pos ? "text-emerald-400" : neg ? "text-red-400" : "text-slate-500"; const dArrow = pos ? "▲" : neg ? "▼" : ""; const dFmt = delta != null ? `${Math.abs(delta).toFixed(deltaDec ?? dec)}${deltaPct ? "%" : ""}` : null; return ( <>
{label} {fmt(value, dec, unit)} {dFmt && ( {dArrow}{dFmt} )} {tooltip && ( i )}
{tip && typeof document !== "undefined" && createPortal(
{tooltip}
, document.body, )} ); } function VSep() { return
; } export default function DriversBar({ drivers }: Props) { const { vix, vixDelta, sp500, sp500ChangePct, btc, btcChange24h, hySpread, igSpread, us10y, us2y, curveSlope, gold, goldDelta, silver, silverDelta, brent, brentDelta, wti, wtiDelta, } = drivers; const dxy = (drivers as DriverData & { dxy?: number | null }).dxy ?? null; const dxyDelta = (drivers as DriverData & { dxyDelta?: number | null }).dxyDelta ?? null; const riskOff = (vix ?? 0) > 25 || (hySpread ?? 0) > 500; return (
DRIVERS GLOBAUX {riskOff && (
Risk-Off
)} {/* Sentiment / Risk-On */} {/* Crédit */} {/* Taux & FX */} {/* Commodités */}
); }