"use client"; import { useRef } from "react"; import { useGSAP } from "@gsap/react"; import gsap from "gsap"; import { Check, LoaderCircle, X } from "lucide-react"; import { cn } from "@/lib/utils"; import type { AccessDecision, AccessRequestEntry, } from "./access-request-state"; gsap.registerPlugin(useGSAP); interface AccessRequestRowProps { entry: AccessRequestEntry; expanded: boolean; disabled: boolean; reduced: boolean; onDecision: (decision: AccessDecision) => void; onExit: () => void; } const actionClass = "relative flex min-h-7 w-16 min-w-16 cursor-pointer items-center justify-center gap-1 rounded-full border px-2 text-[11px] leading-4 font-medium outline-none focus-visible:ring-2 focus-visible:ring-current focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-wait disabled:opacity-50 pointer-coarse:min-h-10 dark:focus-visible:ring-offset-[#171717]"; export function AccessRequestRow({ entry, expanded, disabled, reduced, onDecision, onExit, }: AccessRequestRowProps) { const rowRef = useRef(null); const callbacksRef = useRef(onExit); const { person, phase, decision, error } = entry; const leaving = phase === "decided" || phase === "removing"; const busy = phase === "pending"; useGSAP( () => { callbacksRef.current = onExit; }, { dependencies: [onExit] }, ); useGSAP( () => { const face = rowRef.current?.querySelector("[data-request-face]"); if (!face) return; const duration = reduced ? 0 : 0.18; if (leaving) { const timeline = gsap.timeline({ onComplete: () => callbacksRef.current(), }); timeline.to( face, { x: reduced ? 0 : decision === "approved" ? 10 : -10, autoAlpha: 0, scale: reduced ? 1 : 0.98, duration: expanded ? duration : 0, ease: "power2.in", }, expanded && phase === "decided" && !reduced ? 0.25 : 0, ); return; } gsap.to(face, { x: 0, autoAlpha: 1, scale: 1, duration, overwrite: "auto", }); if (busy && expanded && !reduced) gsap.to("[data-request-spinner]", { rotation: 360, duration: 0.8, repeat: -1, ease: "none", }); }, { dependencies: [phase, decision, expanded, reduced], scope: rowRef, revertOnUpdate: true, }, ); return (
  • ); }