// Shared UI primitives: Button, IconButton, Pill, Badge, Card, Modal, Toggle, TextInput, Textarea, Avatar.
// Export to window.UI.
const { useState, useEffect, useRef, useMemo, useCallback } = React;
function classnames(...args) {
return args.filter(Boolean).join(' ');
}
function Button({ variant = 'primary', size = 'md', children, className = '', icon = null, iconRight = null, full = false, disabled = false, onClick, type = 'button', ...rest }) {
const sizes = {
sm: 'h-8 px-3 text-[13px] gap-1.5',
md: 'h-10 px-4 text-[14px] gap-2',
lg: 'h-12 px-5 text-[15px] gap-2',
};
const variants = {
primary: 'bg-ink-900 text-white hover:bg-ink-800 active:bg-ink-700 shadow-soft',
accent: 'bg-violet text-white hover:opacity-90 active:opacity-100 shadow-soft',
ghost: 'bg-transparent text-ink-800 hover:bg-ink-100 active:bg-ink-200',
outline: 'bg-white text-ink-900 border border-ink-200 hover:bg-ink-50 active:bg-ink-100',
danger: 'bg-white text-red-700 border border-red-200 hover:bg-red-50',
soft: 'bg-ink-100 text-ink-900 hover:bg-ink-200',
};
return (
);
}
function IconButton({ children, className = '', onClick, title, variant = 'ghost', size = 'md', ...rest }) {
const sizes = { sm: 'h-8 w-8', md: 'h-9 w-9', lg: 'h-10 w-10' };
const variants = {
ghost: 'hover:bg-ink-100 text-ink-700',
outline: 'border border-ink-200 bg-white hover:bg-ink-50',
solid: 'bg-ink-900 text-white hover:bg-ink-800',
};
return (
);
}
function Pill({ children, active = false, onClick, className = '' }) {
return (
);
}
function Badge({ children, variant = 'default', className = '' }) {
const variants = {
default: 'bg-ink-100 text-ink-700',
ready: 'bg-emerald-50 text-emerald-700 border border-emerald-100',
draft: 'bg-ink-100 text-ink-700',
sent: 'bg-violet-soft text-violet-ink',
accent: 'bg-violet text-white',
};
return {children};
}
function Card({ children, className = '', as: As = 'div', ...rest }) {
return
{sub}
}