import type { ReactNode } from 'react' import { useTranslation } from 'react-i18next' import { formatUnits } from 'viem' import { fmtAmount, sanitizeAmountInput } from '../lib/format' export function Btn(props: { onClick?: () => void disabled?: boolean tone?: 'default' | 'danger' | 'ghost' | 'amber' big?: boolean busy?: boolean title?: string children: ReactNode }) { const cls = ['btn', props.tone === 'default' ? '' : props.tone, props.big ? 'big' : ''] .filter(Boolean) .join(' ') return ( ) } export function Badge(props: { tone?: 'green' | 'amber' | 'red' | 'cyan' | 'dim'; children: ReactNode }) { return {props.children} } export function Stat(props: { k: string; v: ReactNode; sub?: ReactNode }) { return (
{props.k}
{props.v}
{props.sub !== undefined &&
{props.sub}
}
) } /** amount input row: label + NumInput + wallet balance + MAX chip */ export function AmountRow(props: { sym: string value: string onChange: (v: string) => void bal?: bigint dec: number onMax: (v: string) => void disabled?: boolean note?: string }) { const { t } = useTranslation() return (
{props.sym} {props.bal !== undefined && ( <> {t('common.bal')} {fmtAmount(props.bal, props.dec)} )} {props.note && {props.note}}
) } /** numeric text input that only accepts decimal strings */ export function NumInput(props: { value: string onChange: (v: string) => void placeholder?: string disabled?: boolean width?: number invalid?: boolean /** clamp typed fraction digits (token precision); 18 = EVM max */ decimals?: number }) { return ( { const v = sanitizeAmountInput(e.target.value, props.decimals ?? 18) if (v !== null) props.onChange(v) }} /> ) }