/**
* GeneratingPanel — reusable enterprise-grade waiting overlay
* used across Interactive surfaces.
*
* Mirrors the pattern Animate uses on its video-card processing
* overlay (see Animate.tsx — bg-black/50 backdrop-blur-sm,
* Loader2 size=32 animate-spin, text-white/90 sm font-medium
* label, optional pill under it for extra context) so the two
* features feel like siblings under the HomePilot brand.
*
* Two modes:
* - `variant="overlay"` fills its positioned parent (use inside
* a ``relative`` container; the form beneath stays in the DOM
* and the overlay sits above it).
* - `variant="panel"` renders a self-contained block for places
* that don't have a host to overlay.
*
* Two progress styles (mixable):
* - `steps[]` — vertical checklist; promotes each stage
* "pending → running → done" as activeStep
* advances. Best for a small fixed set of
* phases (plan → graph → ready).
* - `progress` + `progressLabel` — linear gradient progress bar
* with text below. Best for long-running
* batch ops (render scene 5 / 12).
*
* ``spinnerSize="large"`` switches the 32px Loader2 for a 64px
* dual-ring spinner (outer static ring + rotating inner arc),
* matching the visual weight of a full-screen creation modal.
* ``iconOverride`` swaps the central Sparkles for per-phase icons
* (e.g. ImageIcon while rendering stills, Film while rendering
* clips) so the user sees what phase we're in at a glance.
*/
import React from "react";
import { Check, Loader2, Sparkles } from "lucide-react";
export interface GeneratingStep {
label: string;
}
export interface GeneratingPanelProps {
/** Big heading above the spinner, e.g. "Generating project". */
title: string;
/** One-line hint below the title. Optional. */
description?: React.ReactNode;
/** Variant picks full-parent overlay vs self-contained block. */
variant?: "overlay" | "panel";
/** Ordered stages the caller walks through. */
steps?: GeneratingStep[];
/** Which step is currently running. Earlier ones render as done;
* later ones render as pending. Default 0. */
activeStep?: number;
/** 0–100 linear progress. Renders the gradient bar + label
* under the title. Omit for spinner-only indeterminate mode. */
progress?: number;
/** Small text under the progress bar (e.g. "5 / 12 scenes"). */
progressLabel?: React.ReactNode;
/** Tint color for the spinner + running-step indicator. Accepts
* a Tailwind arbitrary-value color class (e.g. "text-[#3ea6ff]"
* or "text-purple-400"). Default matches Animate (purple). */
accentClassName?: string;
/** "small" = 32px Loader2 (default, legacy look).
* "large" = 64px dual-ring spinner (Studio-style modal). */
spinnerSize?: "small" | "large";
/** Replace the decorative Sparkles with a phase-specific icon
* (ImageIcon, Film, Gamepad2…). Sits centered inside the
* dual-ring when spinnerSize='large', or next to the 32px
* loader when 'small'. */
iconOverride?: React.ReactNode;
/** Footer pill copy. Default: "AI is working — this usually
* takes a few seconds." Pass null to hide the pill entirely. */
footerHint?: React.ReactNode | null;
}
export function GeneratingPanel({
title,
description,
variant = "overlay",
steps,
activeStep = 0,
progress,
progressLabel,
accentClassName = "text-purple-400",
spinnerSize = "small",
iconOverride,
footerHint,
}: GeneratingPanelProps) {
const clamped = typeof progress === "number"
? Math.max(0, Math.min(100, progress))
: undefined;
const hasProgress = clamped !== undefined;
const spinner = spinnerSize === "large"
?