"use client" import React, { useCallback, useMemo } from 'react'; import { Input, Textarea } from '@djangocfg/ui-core/components'; import { cn } from '@djangocfg/ui-core/lib'; import { WidgetProps } from '@rjsf/utils'; import { useWidgetEnv } from './_useWidgetEnv'; /** * Text input widget for JSON Schema Form. * * Handles `string` fields. Switches to a multiline `Textarea` when * `options.widget === 'textarea'` (see `TextareaWidget`). Maps the * schema `format` to a native input type (`email`, `url`, `tel`, * `password`, `date`, `datetime-local`, `time`). Honors `density` * and `ui:disabledWhen` via `useWidgetEnv`. */ /** Maps JSON Schema `format` values to native `` values. */ const FORMAT_INPUT_TYPE: Record = { email: 'email', uri: 'url', url: 'url', tel: 'tel', phone: 'tel', password: 'password', date: 'date', 'date-time': 'datetime-local', datetime: 'datetime-local', time: 'time', }; export function TextWidget(props: WidgetProps) { const { id, placeholder, required, autofocus, value, onChange, onBlur, onFocus, options, schema, rawErrors, } = props; const { disabled, compact, tooltipText } = useWidgetEnv(props); // Memoize widget configuration const config = useMemo(() => ({ isTextarea: options?.widget === 'textarea', rows: typeof options?.rows === 'number' ? options.rows : 3, emptyValue: options?.emptyValue, inputType: (typeof schema.format === 'string' && FORMAT_INPUT_TYPE[schema.format]) || 'text', }), [options, schema.format]); // Ensure value is always a string const safeValue = useMemo(() => { if (value === null || value === undefined) return ''; return String(value); }, [value]); const hasError = useMemo(() => { return Boolean(rawErrors && rawErrors.length > 0); }, [rawErrors]); const handleChange = useCallback((event: React.ChangeEvent) => { const newValue = event.target.value; onChange(newValue === '' ? config.emptyValue : newValue); }, [onChange, config.emptyValue]); const handleBlur = useCallback((event: React.FocusEvent) => { onBlur(id, event.target.value); }, [id, onBlur]); const handleFocus = useCallback((event: React.FocusEvent) => { onFocus(id, event.target.value); }, [id, onFocus]); if (config.isTextarea) { return (