import { useEffect, useRef, useState, type ReactNode, type CSSProperties } from 'react'; import './devtool.css'; interface CrosshairProps { children: ReactNode; /** Optionales Label, das vor den Dimensionen angezeigt wird, z. B. "Header" */ label?: string; /** Beliebige CSS-Farbe für Rahmen/Kreuz, überschreibt --crosshair-color */ color?: string; /** Schraffur-Hintergrund aktivieren (.hatch Utility) */ hatch?: boolean; /** Größe der Schraffur in px, überschreibt --hatch-size */ hatchSize?: number; /** Live-Breite/Höhe oben links einblenden (per ResizeObserver) */ showDimensions?: boolean; className?: string; } export function Crosshair({ children, label, color, hatch = false, hatchSize, showDimensions = true, className = '', }: CrosshairProps) { const ref = useRef(null); const [size, setSize] = useState({ w: 0, h: 0 }); useEffect(() => { const el = ref.current; if (!el || !showDimensions) return; const ro = new ResizeObserver(([entry]) => { const { width, height } = entry.contentRect; setSize({ w: Math.round(width), h: Math.round(height) }); }); ro.observe(el); return () => ro.disconnect(); }, [showDimensions]); const style: CSSProperties = { ...(color ? { ['--crosshair-color' as string]: color } : {}), ...(hatchSize ? { ['--hatch-size' as string]: `${hatchSize}px` } : {}), }; return (
{showDimensions && ( {label ? `${label} · ` : ''} {size.w}×{size.h} )} {children}
); } /** Zeigt den berechneten z-index eines Elements als Badge oben rechts an. */ export function ZIndexBadge({ children, className = '', }: { children: ReactNode; className?: string; }) { const ref = useRef(null); const [z, setZ] = useState('auto'); useEffect(() => { const el = ref.current; if (!el) return; setZ(getComputedStyle(el).zIndex); }, []); return (
z: {z} {children}
); } /** * Definiert die SVG-Filter für die colorblind-* Utilities aus dev-utilities.css. * Einmal im App-Root rendern (z. B. direkt unter /) — erzeugt selbst * kein sichtbares Element, nur die -Definitionen im DOM. */ export function ColorblindFilters() { return ( ); }