5e155f9cee
Co-authored-by: Kandev Agent <agent@kandev.dev>
80 lines
2.0 KiB
TypeScript
80 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { Button } from "@kandev/ui/button";
|
|
import { IconArrowBackUp, IconLoader2 } from "@tabler/icons-react";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
interface HunkActionBarProps {
|
|
changeBlockId: string;
|
|
onRevert: () => Promise<void> | void;
|
|
onMouseEnter: () => void;
|
|
onMouseLeave: () => void;
|
|
}
|
|
|
|
export function HunkActionBar({
|
|
changeBlockId,
|
|
onRevert,
|
|
onMouseEnter,
|
|
onMouseLeave,
|
|
}: HunkActionBarProps) {
|
|
const { t } = useTranslation();
|
|
const [loading, setLoading] = useState(false);
|
|
const mountedRef = useRef(true);
|
|
|
|
useEffect(
|
|
() => () => {
|
|
mountedRef.current = false;
|
|
},
|
|
[],
|
|
);
|
|
|
|
const handleClick = async () => {
|
|
setLoading(true);
|
|
try {
|
|
await onRevert();
|
|
} catch {
|
|
// Revert failures are surfaced by the caller; keep this overlay from
|
|
// turning a failed async action into an unhandled event rejection.
|
|
} finally {
|
|
if (!mountedRef.current) return;
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
data-cb={changeBlockId}
|
|
style={{
|
|
position: "relative",
|
|
zIndex: 10,
|
|
width: "100%",
|
|
overflow: "visible",
|
|
}}
|
|
>
|
|
<div
|
|
data-undo-btn=""
|
|
style={{ opacity: 0, pointerEvents: "none", transition: "opacity 150ms" }}
|
|
className="absolute top-1 right-2"
|
|
onMouseEnter={onMouseEnter}
|
|
onMouseLeave={onMouseLeave}
|
|
>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
disabled={loading}
|
|
className="h-6 gap-1 px-2 text-xs cursor-pointer rounded border border-border/60 bg-background text-muted-foreground shadow-sm hover:text-red-500 hover:bg-red-500/10 hover:border-red-500/30"
|
|
onClick={handleClick}
|
|
>
|
|
{loading ? (
|
|
<IconLoader2 className="h-3.5 w-3.5 animate-spin" />
|
|
) : (
|
|
<IconArrowBackUp className="h-3.5 w-3.5" />
|
|
)}
|
|
{t("diff:undo")}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|