Add Rust logo pipeline: trim, metrics, knockout and Branding settings

Logos (PNG, JPEG, WebP) are decoded, trimmed to their ink box, downscaled
to 1200 px and re-encoded as a content-addressed print PNG plus a white
knockout variant when the logo has alpha; aspect, ink density, mean colour
and kind (wordmark, mark, tall) are stored with the settings and frozen in
the issue snapshot. Legacy logos are derived at startup. The Arun P logo
PDF shrinks from 334 KB to 92 KB. Settings gains a Branding section with
white and dark previews and a business-name toggle (migration M5).
This commit is contained in:
2026-10-04 06:31:30 +05:30
parent afd07071c3
commit 74ba04e17f
27 changed files with 1615 additions and 37 deletions
+14 -8
View File
@@ -19,6 +19,7 @@ import {
TableRow,
TextArea,
TextInput,
Tile,
Toggle,
} from "@carbon/react";
import { Add, Save, TrashCan } from "@carbon/icons-react";
@@ -33,6 +34,7 @@ import {
} from "../lib/types";
import { emailError, ifscError, panError, phoneError, vendorGstinError } from "../lib/validators";
import { ImagePicker } from "../components/ImagePicker";
import { LogoBranding } from "../components/LogoBranding";
import DiagnosticsPanel from "../components/DiagnosticsPanel";
const blankBank = (): BankAccount => ({
@@ -264,14 +266,6 @@ export default function AppSettings({
onChange={(e) => set("signatoryDesignation", e.target.value)}
/>
</Column>
<Column sm={4} md={8} lg={8}>
<ImagePicker
kind="logo"
label="Vendor logo"
value={form.logoPath}
onChange={(path) => set("logoPath", path)}
/>
</Column>
<Column sm={4} md={8} lg={8}>
<ImagePicker
kind="signature"
@@ -283,6 +277,18 @@ export default function AppSettings({
</Grid>
</section>
<section className="voiced-stack" style={{ marginBottom: "2.5rem" }}>
<h3>Branding</h3>
<Tile>
<LogoBranding
idPrefix="s"
value={form}
onChange={(patch) => setForm((prev) => ({ ...prev, ...patch }))}
disabled={busy}
/>
</Tile>
</section>
<section className="voiced-stack" style={{ marginBottom: "2.5rem" }}>
<h3>Defaults</h3>
<Grid narrow>