makearmy-app/app/laser-toolkit/beam-spot-size/page.tsx
2025-09-22 10:37:53 -04:00

88 lines
3.3 KiB
TypeScript

"use client";
import { useMemo, useState } from "react";
import ToolShell from "@/components/toolkit/ToolShell";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
function num(v: string) {
const n = parseFloat(v);
return Number.isFinite(n) ? n : 0;
}
// Spot diameter (µm) ≈ 1.27 * M² * λ(µm) * f(mm) / D(mm)
export default function Page() {
const [lambdaNm, setLambdaNm] = useState("1064"); // nm (default fiber)
const [focalMm, setFocalMm] = useState("160"); // mm
const [beamDm, setBeamDm] = useState("6"); // mm (input beam diameter at lens)
const [m2, setM2] = useState("1.3");
const dUm = useMemo(() => {
const lamUm = num(lambdaNm) / 1000; // convert nm -> µm
const f = num(focalMm);
const D = num(beamDm);
const M2 = Math.max(1, num(m2));
if (lamUm <= 0 || f <= 0 || D <= 0) return 0;
return 1.27 * M2 * lamUm * (f / D);
}, [lambdaNm, focalMm, beamDm, m2]);
const dMm = dUm / 1000;
return (
<ToolShell title="Beam Spot Size">
<Card>
<CardHeader>
<CardTitle className="text-base">Inputs</CardTitle>
</CardHeader>
<CardContent className="grid gap-3 sm:grid-cols-4">
<label className="text-[11px] sm:text-xs">
<div className="mb-1 text-muted-foreground">Wavelength (nm)</div>
<Input value={lambdaNm} onChange={(e) => setLambdaNm(e.target.value)} />
<div className="mt-1 text-[11px] text-muted-foreground space-x-2">
<button type="button" className="underline" onClick={() => setLambdaNm("1064")}>
Fiber (1064 nm)
</button>
<button type="button" className="underline" onClick={() => setLambdaNm("10600")}>
CO (10600 nm)
</button>
</div>
</label>
<label className="text-[11px] sm:text-xs">
<div className="mb-1 text-muted-foreground">Focal length (mm)</div>
<Input value={focalMm} onChange={(e) => setFocalMm(e.target.value)} />
</label>
<label className="text-[11px] sm:text-xs">
<div className="mb-1 text-muted-foreground">Beam Ø @ lens (mm)</div>
<Input value={beamDm} onChange={(e) => setBeamDm(e.target.value)} />
</label>
<label className="text-[11px] sm:text-xs">
<div className="mb-1 text-muted-foreground">M²</div>
<Input value={m2} onChange={(e) => setM2(e.target.value)} />
</label>
</CardContent>
</Card>
<Card className="mt-4">
<CardHeader>
<CardTitle className="text-base">Result</CardTitle>
</CardHeader>
<CardContent className="grid gap-3 sm:grid-cols-2">
<div>
<div className="text-sm text-muted-foreground">Spot diameter</div>
<div className="text-lg">{dMm.toFixed(4)} mm</div>
<div className="text-xs text-muted-foreground">{dUm.toFixed(2)} µm</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Spot radius</div>
<div className="text-lg">{(dMm / 2).toFixed(4)} mm</div>
<div className="text-xs text-muted-foreground">{(dUm / 2).toFixed(2)} µm</div>
</div>
</CardContent>
</Card>
</ToolShell>
);
}