import { useEffect, useState } from "react"; import { Button, InlineLoading, InlineNotification, RadioButton, RadioButtonGroup } from "@carbon/react"; import { TrashCan, Upload } from "@carbon/icons-react"; import { open } from "@tauri-apps/plugin-dialog"; import { api } from "../lib/api"; import { loadLogoImages, logoFacts, logoIncludesName, parseLogoMeta, type LogoAsset, type LogoImages, type LogoIncludesName, type LogoSettings, } from "../lib/logo"; import type { Settings } from "../lib/types"; type LogoPatch = Pick; interface LogoBrandingProps { /** Id prefix, so two instances on a page never share control ids. */ idPrefix: string; value: LogoSettings; onChange: (patch: Partial) => void; disabled?: boolean; } /** * Logo upload with the pipeline's result: the trimmed logo on a white and on a dark surface, what * was measured, and whether the logo already contains the business name. */ export function LogoBranding({ idPrefix, value, onChange, disabled }: LogoBrandingProps) { const [images, setImages] = useState(null); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); useEffect(() => { let active = true; if (!value.logoPath) { setImages(null); return; } loadLogoImages(value, api.readAssetDataUri) .then((loaded) => active && setImages(loaded)) .catch(() => active && setImages(null)); return () => { active = false; }; }, [value.logoPath, value.logoKnockoutPath]); const pick = async () => { setError(null); try { const selected = await open({ multiple: false, directory: false, filters: [{ name: "Images", extensions: ["png", "jpg", "jpeg", "webp"] }], }); if (typeof selected !== "string") return; setBusy(true); const asset: LogoAsset = await api.importLogo(selected); onChange({ logoPath: asset.printPath, logoOriginalPath: asset.originalPath, logoKnockoutPath: asset.knockoutPath, logoMeta: JSON.stringify(asset.metrics), }); } catch (e) { setError(String(e)); } finally { setBusy(false); } }; const remove = async () => { setError(null); try { await api.removeLogo(); onChange({ logoPath: null, logoOriginalPath: null, logoKnockoutPath: null, logoMeta: "", logoIncludesName: "auto" }); } catch (e) { setError(String(e)); } }; const meta = parseLogoMeta(value.logoMeta); const automaticYes = logoIncludesName("auto", meta?.kind ?? null); return (
Vendor logo (PNG, JPEG or WebP). A transparent PNG works best.
{value.logoPath ? (
{images ? Logo on a white background : }
On white
{images ? ( images.knockoutUri ? ( White logo on a dark background ) : ( Logo on a white chip over a dark background ) ) : ( )}
{images && !images.knockoutUri ? "On dark (white chip)" : "On dark"}
) : (
{busy ? : "No logo selected"}
)} {meta ?
{logoFacts(meta)}
: null} {meta?.opaqueBackground ? ( ) : null}
{value.logoPath ? ( ) : null} {busy && value.logoPath ? : null}
{error ? : null} {value.logoPath ? ( onChange({ logoIncludesName: next as LogoIncludesName })} > ) : null}
); }