import type { ReactNode } from "react"; import { t, tf } from "../../i18n"; import { useThemeColors } from "../../theme/theme-context"; import { Box, Text } from "../../ui"; import { Spinner } from "./loading"; import { ButtonActionScope } from "./action-scope"; export interface EmptyStateProps { title: string; message?: string; hint?: string; actions?: ReactNode; status?: "empty" | "error"; } export function EmptyState({ title, message, hint, actions, status = "empty" }: EmptyStateProps) { const colors = useThemeColors(); // Provider messages must wrap at narrow pane widths rather than lose their tail. return ( {t(title)} {message && {t(message)}} {hint && {t(hint)}} {actions && {actions}} ); } export interface NoticeProps { children: ReactNode; tone?: "muted" | "positive" | "warning" | "negative"; } /** Inline feedback leaves existing content visible, including stale data after a refresh failure. */ export function Notice({ children, tone = "warning" }: NoticeProps) { const colors = useThemeColors(); return ( {children} ); } /** The one loading phrasing: "Loading ..." with three dots, never the ellipsis glyph. */ export function loadingText(thing?: string): string { return thing ? tf("Loading {thing}...", { thing }) : t("Loading..."); } /** The one failure phrasing: " unavailable." */ export function unavailableText(thing: string): string { return tf("{thing} unavailable.", { thing }); } export interface PaneStatusBodyProps { loading?: boolean; error?: string | null; /** True when there is nothing to show and nothing is in flight. */ empty?: boolean; subject?: string; loadingLabel?: string; errorTitle?: string; emptyTitle?: string; emptyMessage?: string; actions?: ReactNode; align?: "start" | "center"; width?: number; height?: number; children?: ReactNode; } /** State precedence remains explicit at the caller: pass loading/error only when replacing the body. */ export function PaneStatusBody({ loading = false, error, empty = false, subject, loadingLabel, errorTitle, emptyTitle, emptyMessage, actions, align = "start", width, height, children, }: PaneStatusBodyProps) { const status = error ? "error" : loading ? "loading" : empty ? "empty" : null; if (!status) return <>{children}; return ( {status === "loading" ? : ( )} ); }