'use client'; import { useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import { useTranslations } from 'next-intl'; interface PictureFrameLightboxProps { src: string; caption?: string; onClose: () => void; } /** * Grossansicht des Bilderrahmen-Widgets (quick-260921-pi9). * * Aufbau wie widget-catalog-modal.tsx: Hintergrund als echte, benannte * Schaltflaeche (schliesst), Dialog `role="dialog" aria-modal` mit * `tabIndex={-1}` und Fokus beim Einhaengen, Escape-Listener mit Aufraeumung, * Schliessen-Knopf oben rechts. Die Fokus-RUECKGABE an den Bild-Knopf macht * das Widget selbst (es kennt den Ausloeser), nicht diese Komponente. * * `referrerPolicy="no-referrer"` auch hier (T-PI9-09): ein Fremdhost erfaehrt * die Tessera-Adresse nicht. Die Unterschrift ist ein React-Textknoten, * kein HTML (T-PI9-06). * * Gerendert per `createPortal` in `document.body` (wie der Kalender-Tooltip): * die Kachel liegt in einem `react-grid-item` mit CSS-`transform`, und ein * transformierter Vorfahr macht sich fuer `position: fixed` zum Bezugsrahmen — * ohne Portal waere die Grossansicht auf die Kachelflaeche beschraenkt * (im Browser-Rundgang am 21.09.2026 so gesehen: Dialog 531x216 statt Viewport). */ export function PictureFrameLightbox({ src, caption, onClose }: PictureFrameLightboxProps) { const t = useTranslations('widgets'); const tCommon = useTranslations('common'); const dialogRef = useRef(null); useEffect(() => { function handleKeyDown(e: KeyboardEvent) { if (e.key === 'Escape') { onClose(); } } document.addEventListener('keydown', handleKeyDown); dialogRef.current?.focus(); return () => document.removeEventListener('keydown', handleKeyDown); }, [onClose]); if (typeof document === 'undefined') return null; return createPortal(
{caption {caption && (

{caption}

)}
, document.body, ); }