import { Input } from '@affine/admin/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@affine/admin/components/ui/select'; import { Switch } from '@affine/admin/components/ui/switch'; import { cn } from '@affine/admin/utils'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Textarea } from '../../components/ui/textarea'; export type ConfigInputProps = { field: string; desc: string; defaultValue: any; onChange: (field: string, value: any) => void; error?: string; onErrorChange?: (field: string, error?: string) => void; } & ( | { type: 'String' | 'Number' | 'Boolean' | 'JSON'; } | { type: 'Enum'; options: string[]; } ); const Inputs: Record< ConfigInputProps['type'], React.ComponentType<{ defaultValue: any; onChange: (value?: any) => void; options?: string[]; error?: string; onValidationChange?: (error?: string) => void; }> > = { Boolean: function SwitchInput({ defaultValue, onChange }) { const handleSwitchChange = (checked: boolean) => { onChange(checked); }; return ( ); }, String: function StringInput({ defaultValue, onChange }) { const handleInputChange = (e: React.ChangeEvent) => { onChange(e.target.value); }; return ( ); }, Number: function NumberInput({ defaultValue, onChange }) { const handleInputChange = (e: React.ChangeEvent) => { const next = e.target.value; onChange(next === '' ? undefined : parseInt(next, 10)); }; return ( ); }, JSON: function ObjectInput({ defaultValue, onChange, error, onValidationChange, }) { const fallbackText = useMemo( () => typeof defaultValue === 'string' ? defaultValue : JSON.stringify(defaultValue ?? null), [defaultValue] ); const [text, setText] = useState(fallbackText); useEffect(() => { setText(fallbackText); }, [fallbackText]); const handleInputChange = (e: React.ChangeEvent) => { const nextText = e.target.value; setText(nextText); try { const value = JSON.parse(nextText); onValidationChange?.(undefined); onChange(value); } catch { onValidationChange?.('Invalid JSON format'); // Keep the draft "dirty" even when JSON is temporarily invalid // so Save/Cancel state can reflect real editing progress. onChange(nextText); } }; return (