import { type JSX, For, Show, createSignal } from 'solid-js'; import { cn } from '../utils/cn'; import { Textarea } from '../ui/textarea'; import { Input, FIELD_BASE as inputBase } from '../ui/input'; import { Star } from 'lucide-solid'; import type { FormField } from './form'; /** The shared prop shape every leaf widget receives from FieldRow. */ export interface WidgetProps { id: string; value: unknown; field: FormField; disabled: boolean; placeholder?: string; required: boolean; invalid: boolean; describedBy?: string; label: string; onInput: (value: unknown) => void; onBlur: () => void; } function ariaProps(p: WidgetProps) { return { 'aria-required': p.required || undefined, 'aria-invalid': p.invalid || undefined, 'aria-describedby': p.describedBy, }; } /** text / email / url / date / datetime / time / password — all variants. */ export function TextWidget( props: WidgetProps & { variant: 'text' | 'email' | 'url' | 'date' | 'datetime' | 'time' | 'password' }, ): JSX.Element { const inputType = () => { switch (props.variant) { case 'email': return 'email'; case 'url': return 'url'; case 'date': return 'date'; case 'datetime': return 'datetime-local'; case 'time': return 'time'; case 'password': return 'password'; default: return 'text'; } }; // Render the bare `Input` control (no label/hint/error): `kai-form`'s FieldRow // already supplies the label, description, and inline error around the widget. // `Input` owns the field styling (its `FIELD_BASE` is the former `inputBase`), // so the rendered input is byte-identical to the old raw ``. return ( props.onInput(value)} onValueChange={() => props.onBlur()} /> ); } export function TextareaWidget(props: WidgetProps): JSX.Element { const len = () => ((props.value as string) ?? '').length; return (