Backend (nvcurve/): - hal/fans.py, hal/limits.py, hal/gpu.py: replace conditional pynvml imports with the established 'pynvml: Any = _pynvml_import' pattern (fixes ~50 'possibly unbound' errors); type the result dicts; guard query_interface() results; explicit uuid/pci-bus parsing (int, hex convention documented); modernize Optional[T] -> T | None - cli.py: fix 'curve_state' possibly-unbound and snap_path None handling in cmd_setup; wrap unchecked int()/open()/makedirs() calls in try/except with clean CLI errors; add module logger for silent except-pass blocks; raise ... from exc; fix unused loop vars and set-comprehension - hal/snapshot.py: filepath: str | None; wrap all file ops; sorted imports; remove unused CT_POINTS import - daemon.py: extract 0o666 to _SOCKET_MODE constant (intentional for /run sockets) with nosemgrep - server.py: nosemgrep for Python 3.7-compat false positive (project requires >= 3.12); log previously-swallowed exception - profiles/native.py, profiles/apply.py: wrap file ops and int(k) profile-key parsing; sorted imports; modernize typing Frontend (frontend/src): - Add .js extensions to all relative imports (standard TS-ESM; Vite resolves .js -> .ts) - React.FormEvent (deprecated in React 19 types) -> React.SubmitEvent - catch (e: any) -> catch (e: unknown) + instanceof Error narrowing - React-hooks: move ref writes from render into effects; convert viewport reset to render-phase state adjustment; split selectPoint(index, multi) into selectPoint + togglePoint (no flag argument); remove non-null assertion - Static inline styles -> Tailwind classes (dynamic positioning/cursor styles kept) - Remove non-standard 'container' option from scrollIntoView (browsers ignore unknown options) which had orphaned a @ts-expect-error - Object.fromEntries for Map -> Record conversion Tooling: - .gitignore: ignore .codegraph/ local tool data Verified: tsc --noEmit, vite production build, python imports, and full LSP scan (0 errors/warnings in both projects).
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
interface Props {
|
|
message: string;
|
|
detail?: string;
|
|
confirmLabel?: string;
|
|
isDestructive?: boolean;
|
|
onConfirm: () => void;
|
|
onCancel: () => void;
|
|
}
|
|
|
|
export function ConfirmDialog({
|
|
message,
|
|
detail,
|
|
confirmLabel = "Confirm",
|
|
isDestructive = false,
|
|
onConfirm,
|
|
onCancel,
|
|
}: Props) {
|
|
return (
|
|
<div
|
|
className="fixed inset-0 z-50 flex items-center justify-center bg-black/70"
|
|
onMouseDown={(e) => {
|
|
if (e.target === e.currentTarget) onCancel();
|
|
}}
|
|
>
|
|
<div className="bg-zinc-900 border border-zinc-700 rounded-xl shadow-2xl p-6 w-96 max-w-[90vw]">
|
|
<h2 className="text-zinc-100 font-semibold text-sm mb-1">{message}</h2>
|
|
{detail && <p className="text-zinc-400 text-xs mb-4">{detail}</p>}
|
|
{!detail && <div className="mb-4" />}
|
|
<div className="flex justify-end gap-2">
|
|
<button
|
|
onClick={onCancel}
|
|
className="px-3 py-1.5 rounded bg-zinc-800 hover:bg-zinc-700 text-zinc-300 text-xs transition-colors"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
onClick={onConfirm}
|
|
className={[
|
|
"px-3 py-1.5 rounded text-xs font-semibold transition-colors",
|
|
isDestructive
|
|
? "bg-red-600 hover:bg-red-500 text-white"
|
|
: "bg-emerald-600 hover:bg-emerald-500 text-white",
|
|
].join(" ")}
|
|
>
|
|
{confirmLabel}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|