"use client"; import { useState, useMemo } from "react"; import { usePathname } from "next/navigation"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import PageHero from "@/components/PageHero"; import SectionHead from "@/components/SectionHead"; import * as componentesPt from "@/lib/componentRegistryData"; import * as componentesEn from "@/lib/data/en/componentes"; import { ArrowUpRight, Box, Brain, Check, CircuitBoard, Cloud, Copy, Cpu, Download, HelpCircle, Home, Layers, Monitor, Plus, Search, ShieldCheck, Terminal, Trash2, Wrench, X, } from "lucide-react"; const ICONES_CATEGORIA = { ui_display: Monitor, cloud_conectividade: Cloud, audio_voz_ia: Brain, smart_home_mesh: Home, drivers_perifericos: Cpu, bsp_placas: CircuitBoard, sistema_utilitarios: Wrench, }; export default function ComponentRegistryPage() { const pathname = usePathname(); const isEn = pathname?.startsWith("/en"); const { CATEGORIAS_COMPONENTES, COMPONENTES_REGISTRY, GUIA_COMPONENT_MANAGER } = isEn ? componentesEn : componentesPt; const [busca, setBusca] = useState(""); const [categoriaAtiva, setCategoriaAtiva] = useState("todos"); const [chipFiltro, setChipFiltro] = useState("todos"); const [copiadoId, setCopiadoId] = useState(null); const [manifestoCopiado, setManifestoCopiado] = useState(false); // Componentes selecionados no construtor de idf_component.yml const [componentesSelecionados, setComponentesSelecionados] = useState([ "espressif-esp_lvgl_port", "espressif-led_indicator" ]); // Lista de chips únicos para filtro const chipsDisponiveis = ["todos", "ESP32", "ESP32-S3", "ESP32-C6", "ESP32-P4", "ESP32-H2", "ESP32-C3"]; // Filtragem dos componentes const componentesFiltrados = useMemo(() => { return COMPONENTES_REGISTRY.filter((comp) => { const matchCategoria = categoriaAtiva === "todos" || comp.categoria === categoriaAtiva; const matchChip = chipFiltro === "todos" || (comp.chips && comp.chips.includes(chipFiltro)); const matchBusca = busca.trim() === "" || comp.name.toLowerCase().includes(busca.toLowerCase()) || comp.namespace.toLowerCase().includes(busca.toLowerCase()) || comp.titulo.toLowerCase().includes(busca.toLowerCase()) || comp.descricao.toLowerCase().includes(busca.toLowerCase()) || comp.tags.some((t) => t.toLowerCase().includes(busca.toLowerCase())); return matchCategoria && matchChip && matchBusca; }); }, [busca, categoriaAtiva, chipFiltro, COMPONENTES_REGISTRY]); // Manipuladores de cópia const copiarComando = (id, comando) => { navigator.clipboard.writeText(comando); setCopiadoId(id); setTimeout(() => setCopiadoId(null), 2000); }; const toggleSelecaoManifesto = (id) => { setComponentesSelecionados((prev) => prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id] ); }; // Geração dinâmica do manifesto YAML const manifestoYaml = useMemo(() => { const selecionados = COMPONENTES_REGISTRY.filter((c) => componentesSelecionados.includes(c.id) ); if (selecionados.length === 0) { return isEn ? `# No components selected.\n# Click "+ Add to Manifest" on the cards below.` : `# Nenhum componente selecionado.\n# Clique em "+ Adicionar ao Manifesto" nos cards abaixo.`; } let yaml = isEn ? `# main/idf_component.yml\n# Generated via ESPDocs Component Hub (https://espdocs.cienciaembarcada.com.br/en/components)\n\ndependencies:\n` : `# main/idf_component.yml\n# Gerado via ESPDocs Component Hub (https://espdocs.cienciaembarcada.com.br/componentes)\n\ndependencies:\n`; selecionados.forEach((c) => { yaml += ` ${c.namespace}/${c.name}: "${c.versao}"\n`; }); return yaml; }, [componentesSelecionados, COMPONENTES_REGISTRY, isEn]); const copiarManifesto = () => { navigator.clipboard.writeText(manifestoYaml); setManifestoCopiado(true); setTimeout(() => setManifestoCopiado(false), 2000); }; const baixarManifesto = () => { const blob = new Blob([manifestoYaml], { type: "text/yaml;charset=utf-8" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = "idf_component.yml"; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }; const limparFiltros = () => { setBusca(""); setCategoriaAtiva("todos"); setChipFiltro("todos"); }; const totalFiltros = (busca.trim() ? 1 : 0) + (categoriaAtiva !== "todos" ? 1 : 0) + (chipFiltro !== "todos" ? 1 : 0); return (
{isEn ? "Open official registry" : "Abrir o registro oficial"} {isEn ? "Generate idf_component.yml" : "Gerar idf_component.yml"}

{isEn ? "Category" : "Categoria"}

{CATEGORIAS_COMPONENTES.map((cat) => { const Icone = ICONES_CATEGORIA[cat.id] ?? Layers; const contagem = cat.id === "todos" ? COMPONENTES_REGISTRY.length : COMPONENTES_REGISTRY.filter((c) => c.categoria === cat.id).length; return ( ); })}

{isEn ? "Compatible chip" : "Chip compatível"}

{chipsDisponiveis.map((chip) => ( ))}

{componentesFiltrados.length} {componentesFiltrados.length === 1 ? (isEn ? "component" : "componente") : (isEn ? "components" : "componentes")}

{componentesFiltrados.length === 0 ? (
) : (
{componentesFiltrados.map((comp) => { const selecionado = componentesSelecionados.includes(comp.id); const cliCmd = `idf.py add-dependency "${comp.namespace}/${comp.name}${comp.versao}"`; const foiCopiado = copiadoId === comp.id; return (

{comp.namespace}/ {comp.oficial && ( )}

{comp.name}

{comp.titulo}

{comp.versao}

{comp.descricao}

    {comp.tags.map((tag) => (
  • {tag}
  • ))}

{foiCopiado ? (isEn ? "Command copied" : "Comando copiado") : ""}

Chips: {comp.chips.join(", ")}

); })}
)}

{isEn ? "Manifest generator" : "Gerador de manifesto"}

{isEn ? "Your idf_component.yml" : "Seu idf_component.yml"}

{isEn ? ( <>Save this file in your project's main/ folder and ESP-IDF will download all dependencies during build. ) : ( <>Salve o arquivo na pasta main/ do projeto e o ESP-IDF baixa todas as bibliotecas na compilação. )}

{componentesSelecionados.length > 0 && ( )}
{manifestoYaml}
{componentesSelecionados.length > 0 && (
    {componentesSelecionados.map((id) => { const c = COMPONENTES_REGISTRY.find((item) => item.id === id); if (!c) return null; return (
  • {c.name}
  • ); })}
)}
    {GUIA_COMPONENT_MANAGER.vantagens.map((v) => (
  • {v.titulo}

    {v.descricao}

  • ))}

    {GUIA_COMPONENT_MANAGER.comandosCli.map((cmd, i) => (
  • $ {cmd.exemplo}

    {cmd.explicacao}

  • ))}

    {isEn ? ( <>
  • ^1.2.0: accepts minor updates and bug fixes (1.2.1, 1.3.0), but blocks breaking API changes (2.0.0). Recommended.
  • ~1.2.0: accepts patch releases only (1.2.1, 1.2.5).
  • 1.2.0: locks to this exact version.
  • *: accepts any version. Avoid in production.
  • ) : ( <>
  • ^1.2.0: aceita atualizações menores e correções (1.2.1, 1.3.0), mas bloqueia mudanças grandes de API (2.0.0). Recomendado.
  • ~1.2.0: aceita só correções de bugs (1.2.1, 1.2.5).
  • 1.2.0: trava na versão exata.
  • *: aceita qualquer versão. Evite em produção.
  • )}
); }