Create monorepo from known-good production state
This commit is contained in:
commit
c034824338
651 changed files with 120469 additions and 0 deletions
113
app/components/utilities/laser-toolkit/dpi-lpi-dpcm/page.tsx
Normal file
113
app/components/utilities/laser-toolkit/dpi-lpi-dpcm/page.tsx
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
"use client";
|
||||
|
||||
import { useState, useEffect } 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;
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
const [dpi, setDpi] = useState("300");
|
||||
const [lpi, setLpi] = useState("300");
|
||||
const [dpcm, setDpcm] = useState("118.11");
|
||||
|
||||
const [active, setActive] = useState<"dpi" | "lpi" | "dpcm">("dpi");
|
||||
|
||||
// keep all three in sync based on the most recently edited field
|
||||
useEffect(() => {
|
||||
const D = num(dpi), L = num(lpi), C = num(dpcm);
|
||||
if (active === "dpi") {
|
||||
const d = Math.max(1e-9, D);
|
||||
setDpcm((d / 2.54).toFixed(5));
|
||||
setLpi(D.toFixed(2)); // LPI≈DPI for raster row spacing (workflow convention)
|
||||
} else if (active === "lpi") {
|
||||
const l = Math.max(1e-9, L);
|
||||
setDpi(L.toFixed(2));
|
||||
setDpcm((L / 2.54).toFixed(5));
|
||||
} else {
|
||||
const c = Math.max(1e-9, C);
|
||||
setDpi((c * 2.54).toFixed(2));
|
||||
setLpi((c * 2.54).toFixed(2));
|
||||
}
|
||||
}, [dpi, lpi, dpcm, active]);
|
||||
|
||||
const gapFromDpiMm = 25.4 / Math.max(1e-9, num(dpi));
|
||||
const gapFromLpiMm = 25.4 / Math.max(1e-9, num(lpi));
|
||||
|
||||
return (
|
||||
<ToolShell title="DPI / LPI / DPCM Converter">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Values</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-3 sm:grid-cols-3">
|
||||
<label className="text-[11px] sm:text-xs">
|
||||
<div className="mb-1 text-muted-foreground">DPI</div>
|
||||
<Input
|
||||
inputMode="decimal"
|
||||
value={dpi}
|
||||
onChange={(e) => {
|
||||
setActive("dpi");
|
||||
setDpi(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="text-[11px] sm:text-xs">
|
||||
<div className="mb-1 text-muted-foreground">LPI</div>
|
||||
<Input
|
||||
inputMode="decimal"
|
||||
value={lpi}
|
||||
onChange={(e) => {
|
||||
setActive("lpi");
|
||||
setLpi(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="text-[11px] sm:text-xs">
|
||||
<div className="mb-1 text-muted-foreground">DPCM</div>
|
||||
<Input
|
||||
inputMode="decimal"
|
||||
value={dpcm}
|
||||
onChange={(e) => {
|
||||
setActive("dpcm");
|
||||
setDpcm(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="mt-4">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Derived spacing</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-3 sm:grid-cols-3">
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground">Pixel/line gap from DPI</div>
|
||||
<div className="text-lg">{gapFromDpiMm.toFixed(4)} mm</div>
|
||||
<div className="text-xs text-muted-foreground">{(gapFromDpiMm * 1000).toFixed(1)} µm</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground">Line gap from LPI</div>
|
||||
<div className="text-lg">{gapFromLpiMm.toFixed(4)} mm</div>
|
||||
<div className="text-xs text-muted-foreground">{(gapFromLpiMm * 1000).toFixed(1)} µm</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm text-muted-foreground">Pixels/cm from DPCM</div>
|
||||
<div className="text-lg">{num(dpcm).toFixed(2)} px/cm</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{(num(dpcm) * 2.54).toFixed(2)} px/in
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ToolShell>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue