"use client"; import React, { useState, useEffect, useRef } from 'react'; import { VendorDirectoryIcon, OpenSourceIcon, CommunityHubIcon, VendorsIcon, CommunityIcon, CompareIcon, } from './icons-stub'; import { Sun, Moon, CheckCircle, Github, PlusCircle } from 'lucide-react'; // Map lucide icons const SunIcon = Sun; const MoonIcon = Moon; const CheckCircleIcon = CheckCircle; const GitHubIcon = Github; const PlusCircleIcon = PlusCircle; const OpenmspLogo = () =>
Logo
; interface IconsBlockProps { /** * When true, always render the loading placeholder bar regardless of whether the grid is ready. * Default behaviour renders placeholder only until the grid is generated. */ loading?: boolean; } // Available icons array - moved outside component to prevent recreating on each render const availableIcons = [ VendorDirectoryIcon, OpenSourceIcon, CommunityHubIcon, VendorsIcon, CommunityIcon, CompareIcon, SunIcon, MoonIcon, CheckCircleIcon, GitHubIcon, PlusCircleIcon, OpenmspLogo ]; export function ResponsiveIconsBlock({ loading = false }: IconsBlockProps) { const [columns, setColumns] = useState(24); const [iconGrid, setIconGrid] = useState>>>([]); const [iconsLoaded, setIconsLoaded] = useState(false); const randomSeedRef = useRef(0); useEffect(() => { function calculateColumns() { const cols = Math.ceil(window.innerWidth / 56) + 4; setColumns(cols); } calculateColumns(); window.addEventListener('resize', calculateColumns); setIconsLoaded(true); return () => window.removeEventListener('resize', calculateColumns); }, []); // Generate icon grid only on client side useEffect(() => { if (randomSeedRef.current === 0) { randomSeedRef.current = Date.now(); } const grid: any[][] = []; const totalCells = columns * 2; for (let idx = 0; idx < totalCells; idx++) { const col = idx % columns; const row = Math.floor(idx / columns); // Initialize row if needed if (!grid[row]) grid[row] = []; // Get adjacent icons to avoid const adjacentIcons = new Set(); // Check left neighbor (same row, previous column) if (col > 0 && grid[row][col - 1]) { adjacentIcons.add(grid[row][col - 1]); } // Check top neighbor (previous row, same column) if (row > 0 && grid[row - 1] && grid[row - 1][col]) { adjacentIcons.add(grid[row - 1][col]); } // Filter available icons to exclude adjacent ones const availableOptions = availableIcons.filter(icon => !adjacentIcons.has(icon)); // Generate random selection from available options using the stable seed const seed = randomSeedRef.current + idx; const pseudoRandom = (seed * 9301 + 49297) % 233280; const normalized = pseudoRandom / 233280; const iconIndex = Math.floor(normalized * availableOptions.length); // Assign selected icon to grid grid[row][col] = availableOptions[iconIndex] || availableIcons[0]; // Fallback to first icon } setIconGrid(grid); }, [columns]); const displayColumns = columns; // Get icon for specific position from pre-generated grid const getIconForIndex = (index: number) => { const col = index % displayColumns; const row = Math.floor(index / displayColumns); return iconGrid[row]?.[col] || availableIcons[0]; }; // When explicit loading prop true OR grid not ready → show placeholder if (loading || iconGrid.length === 0) { return (