"use client";
import { useState, useEffect } from "react";
const FILTER_CATEGORIES = [
{ id: "All", name: "Todos", color: "#64748b" },
{ id: "Ground", name: "Terra (GND)", color: "#64748b" },
{ id: "Power", name: "Alimentação", color: "#ef4444" },
{ id: "RTC", name: "RTC", color: "#f59e0b" },
{ id: "GPIO", name: "GPIO", color: "#22c55e" },
{ id: "ADC", name: "ADC", color: "#ec4899" },
{ id: "DAC", name: "DAC", color: "#a855f7" },
{ id: "Touch", name: "Touch", color: "#06b6d4" },
{ id: "UART", name: "UART", color: "#3b82f6" },
{ id: "SPI", name: "SPI", color: "#ef4444" },
{ id: "I2C", name: "I2C", color: "#10b981" },
{ id: "PWM", name: "PWM", color: "#f97316" },
{ id: "USB", name: "USB", color: "#8b5cf6" },
{ id: "Clock", name: "Clock", color: "#eab308" },
{ id: "JTAG", name: "JTAG", color: "#8b5cf6" },
{ id: "Strapping", name: "Inicialização", color: "#dc2626" },
];
export default function ConnectionsDiagram({ connections, color }) {
const [activeFilter, setActiveFilter] = useState("All");
const [selectedConnection, setSelectedConnection] = useState(null);
const [hoveredConnection, setHoveredConnection] = useState(null);
const isConnectionVisible = (connection) => {
if (activeFilter === "All") return true;
return connection.categorias.includes(activeFilter);
};
const getCategoryColor = (category) => {
const filter = FILTER_CATEGORIES.find((f) => f.id === category);
return filter?.color || "#64748b";
};
useEffect(() => {
const handleEscape = (e) => {
if (e.key === "Escape") setSelectedConnection(null);
};
if (selectedConnection) {
document.addEventListener("keydown", handleEscape);
document.body.style.overflow = "hidden";
}
return () => {
document.removeEventListener("keydown", handleEscape);
document.body.style.overflow = "unset";
};
}, [selectedConnection]);
if (!connections || connections.length === 0) {
return (
Diagrama de conexões indisponível
Este modelo ainda não possui dados de conexão
);
}
return (
📍
Diagrama de Conexões Interativo
Clique em qualquer conexão para ver informações detalhadas ou use filtros para destacar funções específicas.
Filtre por Função
{activeFilter !== "All" && (
{connections.filter(isConnectionVisible).length} de {connections.length} conexões
)}
{FILTER_CATEGORIES.map((filter) => {
const isActive = activeFilter === filter.id;
return (
setActiveFilter(filter.id)}
aria-pressed={isActive}
aria-label={`Filter by ${filter.name}`}
className={`px-5 py-2.5 rounded-xl text-sm font-semibold transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 ${
isActive
? "shadow-lg transform scale-105 text-white"
: "bg-gray-50 text-gray-700 hover:bg-gray-100 hover:shadow-md"
}`}
style={{
backgroundColor: isActive ? filter.color : undefined,
focusRingColor: filter.color,
}}
>
{filter.name}
);
})}
{connections.map((connection, index) => {
const visible = isConnectionVisible(connection);
const isHovered = hoveredConnection === index;
return (
visible && setSelectedConnection(connection)}
onMouseEnter={() => visible && setHoveredConnection(index)}
onMouseLeave={() => setHoveredConnection(null)}
disabled={!visible}
aria-label={`Connection ${connection.nome}, number ${connection.numero}`}
className={`relative flex flex-col items-center justify-center p-2 rounded-2xl border-2 transition-all duration-300 ${
visible
? "opacity-100 hover:scale-110 hover:shadow-2xl hover:z-10 cursor-pointer active:scale-95"
: "opacity-15 cursor-not-allowed grayscale"
}`}
style={{
backgroundColor: visible ? connection.cor + "15" : "#f3f4f615",
borderColor: visible ? (isHovered ? connection.cor : connection.cor + "60") : "#d1d5db",
transform: isHovered ? "translateY(-2px)" : undefined,
}}
>
{typeof connection.numero === "number"
? connection.numero
: connection.numero.substring(0, 4)}
{connection.nome}
{connection.restricoes && (
)}
);
})}
{connections.some(c => c.restricoes) && (
Informações Importantes
•
Conexões com ícones de aviso possuem restrições de uso. Clique para mais detalhes.
•
Sempre consulte o datasheet oficial antes de usar conexões com funções especiais.
)}
{selectedConnection && (
setSelectedConnection(null)}
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
e.stopPropagation()}
>
{typeof selectedConnection.numero === "number"
? selectedConnection.numero
: selectedConnection.numero.substring(0, 4)}
{selectedConnection.nome}
Conexão {selectedConnection.numero}
setSelectedConnection(null)}
aria-label="Close modal"
className="text-gray-400 hover:text-gray-600 transition-colors p-2 hover:bg-gray-100 rounded-xl shrink-0"
>
Categorias
{selectedConnection.categorias.map((cat) => (
{cat}
))}
Funções da Conexão
{selectedConnection.funcoes.map((func, index) => (
{func}
))}
{selectedConnection.restricoes && (
Alertas Importantes
{selectedConnection.restricoes}
)}
setSelectedConnection(null)}
className="w-full py-4 rounded-2xl font-bold text-white shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 active:translate-y-0 transition-all duration-200 focus:outline-none focus:ring-4 focus:ring-offset-2"
style={{ backgroundColor: color }}
aria-label="Close modal"
>
Close
)}
Sobre a Matriz de Conexões Flexível
O ESP32 possui uma matriz de conexões flexível que permite mapear diversas funções para múltiplos pinos.
Isso significa que muitas conexões podem ser configuradas para desempenhar diferentes papéis, dependendo das necessidades do seu projeto.
Consulte a documentação oficial para entender como aproveitar ao máximo essa flexibilidade.
);
}