import { forwardRef, useId, type ButtonHTMLAttributes, type InputHTMLAttributes, type SelectHTMLAttributes, type TextareaHTMLAttributes, type ReactNode, } from "react"; import { Dialog as HeadlessDialog, DialogPanel, DialogTitle, Menu, MenuButton, MenuItems, MenuItem, } from "@headlessui/react"; export interface ButtonProps extends ButtonHTMLAttributes { variant?: "primary" | "secondary" | "ghost" | "danger"; loading?: boolean; } export const Button = forwardRef( function Button( { variant = "primary", loading = false, disabled, children, className = "", type = "button", ...props }, ref, ) { return ( ); }, ); export interface LinkAction { label: string; href: string; } export function ActionLink({ label, href, variant = "primary", }: LinkAction & { variant?: ButtonProps["variant"] }) { return ( {label} ); } export type Tone = "neutral" | "success" | "warning" | "danger"; export function Badge({ children, tone = "neutral", }: { children: ReactNode; tone?: Tone; }) { return {children}; } interface FieldDescription { label: string; hint?: string; error?: string; } export interface InputProps extends InputHTMLAttributes, FieldDescription { prefix?: string; suffix?: string; } export const Input = forwardRef(function Input( { label, hint, error, id, prefix, suffix, className = "", ...props }, ref, ) { const generated = useId(), fieldId = id || generated, messageId = fieldId + "-message"; return (
{prefix && {prefix}} {suffix && {suffix}}
{(error || hint) && (

{error || hint}

)}
); }); export function Select({ label, options, id, hint, error, ...props }: SelectHTMLAttributes & FieldDescription & { options: { value: string; label: string }[] }) { const generated = useId(), fieldId = id || generated, listbox = !!props.multiple || (props.size || 0) > 1; return (
{!listbox && ( )}
{(hint || error) && (

{error || hint}

)}
); } export function TextArea({ label, id, hint, error, ...props }: TextareaHTMLAttributes & FieldDescription) { const generated = useId(), fieldId = id || generated; return (