import * as React from "react" import { AlertTriangleIcon, CheckCircle2Icon, InfoIcon, Loader2Icon, SearchXIcon, XIcon, } from "lucide-react" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" export type StateViewStatus = "idle" | "loading" | "empty" | "error" | "success" | "info" export type StateViewTone = "default" | "muted" | "success" | "warning" | "danger" | "info" export type StateViewVariant = "card" | "plain" | "inline" export type StateViewSize = "compact" | "default" | "page" export type StateViewProps = Omit, "title"> & { status?: StateViewStatus tone?: StateViewTone variant?: StateViewVariant size?: StateViewSize align?: "start" | "center" title?: React.ReactNode description?: React.ReactNode icon?: React.ReactNode badge?: React.ReactNode actions?: React.ReactNode footer?: React.ReactNode query?: React.ReactNode retryLabel?: React.ReactNode onRetry?: () => void clearLabel?: React.ReactNode onClear?: () => void loadingVariant?: "spinner" | "skeleton" | "progress" progress?: number slot?: string } const defaults: Record = { idle: { title: "Ready", description: "No action has started yet.", icon: }, loading: { title: "Loading", description: "Please wait while data is being prepared.", icon: }, empty: { title: "No data", description: "There is nothing to show yet.", icon: }, error: { title: "Something went wrong", description: "Try again or check the request.", icon: }, success: { title: "Ready", description: "Data loaded successfully.", icon: }, info: { title: "Information", description: "Review the information below.", icon: }, } const toneClassName: Record = { default: "text-muted-foreground", muted: "text-muted-foreground", success: "text-[color:var(--aui-success,var(--primary))]", warning: "text-[color:var(--aui-warning,var(--primary))]", danger: "text-destructive", info: "text-[color:var(--aui-info,var(--primary))]", } function StateView({ status = "empty", tone, variant = "card", size = "default", align = "center", title, description, icon, badge, actions, footer, query, retryLabel = "Retry", onRetry, clearLabel = "Clear", onClear, loadingVariant = "spinner", progress, slot = "state-view", className, children, ...props }: StateViewProps) { const content = defaults[status] const resolvedTone = tone ?? (status === "error" ? "danger" : status === "success" ? "success" : status === "info" ? "info" : "default") const compact = size === "compact" || variant === "inline" const page = size === "page" const skeleton = status === "loading" && loadingVariant === "skeleton" const resolvedProgress = typeof progress === "number" ? Math.min(Math.max(progress, 0), 100) : undefined return (
{skeleton ? (