import type { CSSProperties } from "react"; type RetroLedMarqueeProps = { text: string; className?: string; }; const MATRIX_ROWS = 7; const MATRIX_COLUMNS = 56; const REPEAT_GAP_COLUMNS = 12; const GLYPHS: Record = { A: ["01110", "10001", "10001", "11111", "10001", "10001", "10001"], B: ["11110", "10001", "10001", "11110", "10001", "10001", "11110"], D: ["11110", "10001", "10001", "10001", "10001", "10001", "11110"], E: ["11111", "10000", "10000", "11110", "10000", "10000", "11111"], G: ["01111", "10000", "10000", "10111", "10001", "10001", "01111"], H: ["10001", "10001", "10001", "11111", "10001", "10001", "10001"], I: ["11111", "00100", "00100", "00100", "00100", "00100", "11111"], M: ["10001", "11011", "10101", "10101", "10001", "10001", "10001"], N: ["10001", "11001", "10101", "10011", "10001", "10001", "10001"], O: ["01110", "10001", "10001", "10001", "10001", "10001", "01110"], R: ["11110", "10001", "10001", "11110", "10100", "10010", "10001"], T: ["11111", "00100", "00100", "00100", "00100", "00100", "00100"], Y: ["10001", "10001", "01010", "00100", "00100", "00100", "00100"], " ": ["000", "000", "000", "000", "000", "000", "000"], }; function getGlyph(character: string) { return GLYPHS[character] ?? GLYPHS[" "]; } function getMessageColumns(text: string) { return text .toUpperCase() .split("") .reduce((total, character, index, characters) => { const glyph = getGlyph(character); const glyphWidth = glyph[0]?.length ?? 0; const spacer = index === characters.length - 1 ? 0 : 1; return total + glyphWidth + spacer; }, 0); } function buildLitDots(text: string) { const dots: Array<{ key: string; row: number; column: number }> = []; let columnOffset = 0; text .toUpperCase() .split("") .forEach((character, characterIndex, characters) => { const glyph = getGlyph(character); const glyphWidth = glyph[0]?.length ?? 0; glyph.forEach((row, rowIndex) => { row.split("").forEach((cell, columnIndex) => { if (cell !== "1") { return; } dots.push({ key: `${characterIndex}-${rowIndex}-${columnIndex}`, row: rowIndex + 1, column: columnOffset + columnIndex + 1, }); }); }); columnOffset += glyphWidth; if (characterIndex < characters.length - 1) { columnOffset += 1; } }); return dots; } function RetroLedMessage({ text, hidden = false }: { text: string; hidden?: boolean }) { const litDots = buildLitDots(text); return (
{litDots.map((dot) => ( ))}
); } export function RetroLedMarquee({ text, className }: RetroLedMarqueeProps) { const backgroundDots = Array.from({ length: MATRIX_COLUMNS * MATRIX_ROWS }, (_, index) => index); const messageColumns = getMessageColumns(text); return (
); }