/* global React */ /* =========================================================== VOLTLAB · CONVERSOR DE UNIDADES Conversões úteis para engenharia elétrica: Potência · Tensão · Corrente · Comprimento · Seção (AWG↔mm²) 100% no padrão visual VoltLab (reutiliza classes app.css). =========================================================== */ const { useState, useEffect, useMemo, useRef } = React; /* ---------- persistência segura ---------- */ const useCvPersist = (k, v) => (window.useLocalStorage ? window.useLocalStorage(k, v) : useState(v)); /* ---------- ícones (mesmo traço dos demais módulos) ---------- */ const CvIcon = ({ name, size = 16 }) => { const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" }; const d = { swap: <>, bolt: , wave: , current:<>, ruler: <>, cable: <>, check: , info: <>, copy: <>, }; return {d[name] || null}; }; /* ---------- dropdown idêntico ao do app (.vl-dd) ---------- */ const CvDropdown = ({ value, onChange, options }) => { const [open, setOpen] = useState(false); const ref = useRef(null); useEffect(() => { if (!open) return; const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }; document.addEventListener("mousedown", h); return () => document.removeEventListener("mousedown", h); }, [open]); const cur = options.find(o => o.value === value) || options[0]; return (
{open && (
{options.map(o => (
{ onChange(o.value); setOpen(false); }}> {o.label}
))}
)}
); }; /* ---------- formatação de números ---------- */ function fmtNum(n) { if (!isFinite(n)) return "—"; if (n === 0) return "0"; const abs = Math.abs(n); let s; if (abs >= 1e6 || abs < 1e-4) s = n.toExponential(4); else s = n.toPrecision(7); // limpa zeros à direita if (s.indexOf("e") === -1 && s.indexOf(".") !== -1) s = s.replace(/\.?0+$/, ""); return s; } /* =========================================================== DEFINIÇÃO DAS GRANDEZAS LINEARES (fator → unidade base SI) =========================================================== */ const CATS = { potencia: { label: "Potência", icon: "bolt", base: "W", baseName: "watt", units: [ { u: "W", f: 1, n: "Watt" }, { u: "kW", f: 1e3, n: "Quilowatt" }, { u: "MW", f: 1e6, n: "Megawatt" }, { u: "cv", f: 735.49875, n: "Cavalo-vapor (métrico)" }, { u: "HP", f: 745.699872, n: "Horsepower (mecânico)" }, ], }, tensao: { label: "Tensão", icon: "wave", base: "V", baseName: "volt", units: [ { u: "mV", f: 1e-3, n: "Milivolt" }, { u: "V", f: 1, n: "Volt" }, { u: "kV", f: 1e3, n: "Quilovolt" }, ], }, corrente: { label: "Corrente", icon: "current", base: "A", baseName: "ampère", units: [ { u: "mA", f: 1e-3, n: "Miliampère" }, { u: "A", f: 1, n: "Ampère" }, { u: "kA", f: 1e3, n: "Quiloampère" }, ], }, comprimento: { label: "Comprimento", icon: "ruler", base: "m", baseName: "metro", units: [ { u: "mm", f: 1e-3, n: "Milímetro" }, { u: "cm", f: 1e-2, n: "Centímetro" }, { u: "m", f: 1, n: "Metro" }, { u: "km", f: 1e3, n: "Quilômetro" }, ], }, }; /* =========================================================== TABELA AWG (gerada pela fórmula da bitola americana) d(mm) = 0.127 · 92^((36 - n)/39) · área = π/4 · d² =========================================================== */ const IEC_SECOES = [0.5,0.75,1,1.5,2.5,4,6,10,16,25,35,50,70,95,120,150,185,240,300,400,500]; function buildAWG() { // n: 0000(-3) … 24 ; rotulamos os 1/0..4/0 const rows = []; const defs = [ { n: -3, label: "4/0 (0000)" }, { n: -2, label: "3/0 (000)" }, { n: -1, label: "2/0 (00)" }, { n: 0, label: "1/0 (0)" }, ]; for (let i = 1; i <= 24; i++) defs.push({ n: i, label: String(i) }); defs.forEach(({ n, label }) => { const d_mm = 0.127 * Math.pow(92, (36 - n) / 39); const area = Math.PI / 4 * d_mm * d_mm; const cmil = area / 5.067e-4; // 1 cmil = 5.067e-4 mm² rows.push({ awg: label, key: label, d_mm, area, cmil }); }); return rows; } const AWG_ROWS = buildAWG(); function nearestIEC(area) { // menor seção comercial que comporta a área (próximo valor ≥) return IEC_SECOES.find(s => s >= area - 1e-9) || IEC_SECOES[IEC_SECOES.length - 1]; } function nearestAWG(area) { // AWG cuja seção é a mais próxima da área informada let best = AWG_ROWS[0], diff = Infinity; AWG_ROWS.forEach(r => { const dd = Math.abs(r.area - area); if (dd < diff) { diff = dd; best = r; } }); return best; } /* ---------- átomos visuais (classes do app.css) ---------- */ const Field = ({ label, hint, children }) => (
{children}
); const NumInput = ({ value, onChange, suffix }) => (
onChange(e.target.value)} step="any"/> {suffix && {suffix}}
); const Banner = ({ kind, children }) => (
{children}
); const Metric = ({ label, value, unit }) => (
{label}
{value}{unit && {unit}}
); /* =========================================================== COMPONENTE PRINCIPAL =========================================================== */ const Conversor = () => { const [cat, setCat] = useCvPersist("vl_conv_cat", "potencia"); // estado linear const [val, setVal] = useCvPersist("vl_conv_val", "1"); const [from, setFrom] = useCvPersist("vl_conv_from", "kW"); const [to, setTo] = useCvPersist("vl_conv_to", "cv"); // estado AWG const [awgDir, setAwgDir] = useCvPersist("vl_conv_awgdir", "a2m"); // a2m | m2a const [awgSel, setAwgSel] = useCvPersist("vl_conv_awg", "10"); const [mmVal, setMmVal] = useCvPersist("vl_conv_mm", "6"); const isAWG = cat === "secao"; const def = CATS[cat]; // garante que from/to pertencem à categoria atual useEffect(() => { if (isAWG) return; const us = def.units.map(u => u.u); if (!us.includes(from)) setFrom(us[0]); if (!us.includes(to)) setTo(us[Math.min(1, us.length - 1)]); }, [cat]); // eslint-disable-line /* -------- cálculo linear -------- */ const linear = useMemo(() => { if (isAWG) return null; const v = parseFloat(val); const fU = def.units.find(u => u.u === from) || def.units[0]; const tU = def.units.find(u => u.u === to) || def.units[0]; if (!isFinite(v)) return { invalid: true, fU, tU }; const base = v * fU.f; // em unidade SI const out = base / tU.f; // na unidade destino const factor = fU.f / tU.f; // multiplicador direto const table = def.units.map(u => ({ ...u, conv: base / u.f })); return { v, fU, tU, base, out, factor, table }; }, [cat, val, from, to, isAWG]); /* -------- cálculo AWG -------- */ const awg = useMemo(() => { if (!isAWG) return null; if (awgDir === "a2m") { const row = AWG_ROWS.find(r => r.key === awgSel) || AWG_ROWS[0]; return { mode: "a2m", row, iec: nearestIEC(row.area) }; } else { const a = parseFloat(mmVal); if (!isFinite(a) || a <= 0) return { mode: "m2a", invalid: true }; const row = nearestAWG(a); return { mode: "m2a", area: a, row, iec: nearestIEC(a) }; } }, [isAWG, awgDir, awgSel, mmVal]); const swap = () => { const a = from; setFrom(to); setTo(a); }; /* ========================================================= RENDER ========================================================= */ return (
{/* ---------- ENTRADA ---------- */}
CONVERSÃO DE UNIDADES

Selecione a grandeza e converta

TEMPO REAL
{/* categorias */}
{Object.entries(CATS).map(([id, c]) => ( ))}
{!isAWG ? ( <>
({ value: u.u, label: `${u.u} · ${u.n}` }))}/>
({ value: u.u, label: `${u.u} · ${u.n}` }))}/>
Grandeza{def.label}
Base SI{def.base}
Fator direto×{linear && !linear.invalid ? fmtNum(linear.factor) : "—"}
) : ( <>
{awgDir === "a2m" ? ( ({ value: r.key, label: `AWG ${r.awg}` }))}/> ) : ( )}
PadrãoAWG ⇄ IEC
Referência25,4 mm/in
1 cmil5,067e-4 mm²
)}
{/* ---------- RESULTADO ---------- */}
{/* ---------- TABELA DE REFERÊNCIA ---------- */} {!isAWG ? (
TABELA DE EQUIVALÊNCIA

{linear && !linear.invalid ? `${fmtNum(linear.v)} ${from}` : "Valor de entrada"} em todas as unidades de {def.label}

Base: 1 {def.base} ({def.baseName})
UNIDADE NOME VALOR EQUIVALENTE FATOR P/ {def.base}
{(linear?.table || def.units.map(u => ({ ...u, conv: NaN }))).map(u => { const sel = u.u === to; return (
{u.u} {u.n} {isFinite(u.conv) ? fmtNum(u.conv) : "—"} {u.u} ×{fmtNum(u.f)}
); })}
) : (
TABELA DE REFERÊNCIA · AWG ⇄ mm²

Bitolas americanas e seções comerciais IEC

d = 0,127 · 92^((36−n)/39)
AWG Ø (mm) SEÇÃO (mm²) CIRCULAR MILS COMERCIAL IEC
{AWG_ROWS.map(r => { const sel = awg && !awg.invalid && awg.row.key === r.key; return (
{r.awg} {r.d_mm.toFixed(2)} {fmtNum(r.area)} {Math.round(r.cmil).toLocaleString("pt-BR")} {fmtNum(nearestIEC(r.area))} mm²
); })}
)}
); }; window.VL_Conversores = Conversor;