import React from 'react'; import { ArrowRight, Heart, Infinity as InfinityIcon, X } from 'lucide-react'; import { useTranslation } from '../../i18n/TranslationContext.js'; import type { SystemNoticeDTO } from '../../store/systemNoticeStore.js'; import { ReleaseFeatureVisual } from './ReleaseNoticeVisuals.js'; import './releaseNotice.css'; interface Props { notice: SystemNoticeDTO; visible: boolean; onDismiss: () => void; onCTA: () => void; onSecondaryCTA: () => void; } /** Lucide's coffee cup, drawn here so its three steam strokes can drift up in waves. */ function SteamingCoffee() { return ( ); } /** Splits a translated block into paragraphs the way the notice bodies are written. */ function paragraphs(text: string): string[] { return text.split('\n\n').map(p => p.trim()).filter(Boolean); } /** * The release modal: what shipped on the left, a note from the maintainer on * the right. Rendered instead of the generic notice body whenever a notice * carries `release`. Every string comes from that block, so a later release * only edits the registry entry and its keys. * * Desktop only (the notice carrying it sets `desktopOnly`), and it keeps the * generic modal's behaviour: the host hook still owns ESC, the scroll lock and * the dismissal, this component only draws. */ export function ReleaseNoticeModal({ notice, visible, onDismiss, onCTA, onSecondaryCTA }: Props) { const { t } = useTranslation(); const release = notice.release; if (!release) return null; const titleId = `notice-title-${notice.id}`; const bodyId = `notice-body-${notice.id}`; return (
{ if (e.target === e.currentTarget) onDismiss() } : undefined} >
{/* A child of the panel, not the note: stacked, the panel scrolls and the note is its second screen, so the button sticks to the panel's edge. */} {notice.dismissible && ( )} {/* ── Left: the release ─────────────────────────────────────────── */}
); }