import type React from 'react'; import { forwardRef, useState, useRef, useEffect, useCallback } from 'react'; import { IconEdit1, Button, useUIKit } from '@tencentcloud/uikit-base-component-react'; import cs from 'classnames'; import { View } from 'tuikit-atomicx-react/chat'; import classes from './SettingItem.module.scss'; // Base props shared by all types interface BaseSettingItemProps { label: string; disabled?: boolean; className?: string; } // Switch type props interface SwitchSettingItemProps extends BaseSettingItemProps { type: 'switch'; value: boolean; onChange: (checked: boolean) => void; } // Input type props interface InputSettingItemProps extends BaseSettingItemProps { type: 'input'; value?: string; placeholder?: string; editable?: boolean; onConfirm?: (value: string) => void; validator?: (value: string, originalValue?: string) => string | null; } // Textarea type props interface TextareaSettingItemProps extends BaseSettingItemProps { type: 'textarea'; value?: string; placeholder?: string; editable?: boolean; rows?: number; onConfirm?: (value: string) => void; validator?: (value: string, originalValue?: string) => string | null; } // Display type props (read-only) interface DisplaySettingItemProps extends BaseSettingItemProps { type: 'display'; value?: string; placeholder?: string; isWrap?: boolean; } // Union type for all setting item props type SettingItemProps = | SwitchSettingItemProps | InputSettingItemProps | TextareaSettingItemProps | DisplaySettingItemProps; const SettingItem = forwardRef((props, ref) => { const { type, label, disabled = false, className } = props; const { t } = useUIKit(); // Edit state management const [isEditing, setIsEditing] = useState(false); const [editValue, setEditValue] = useState(''); const [errorMessage, setErrorMessage] = useState(null); const inputRef = useRef(null); const textareaRef = useRef(null); // Focus input/textarea when entering edit mode useEffect(() => { if (isEditing) { if (type === 'input' && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } else if (type === 'textarea' && textareaRef.current) { textareaRef.current.focus(); textareaRef.current.select(); } } }, [isEditing, type]); // Validate input value const validateValue = useCallback((value: string) => { if (type === 'input' || type === 'textarea') { const { validator, value: originalValue } = props as InputSettingItemProps | TextareaSettingItemProps; if (validator) { return validator(value, originalValue); } } return null; }, [type, props]); // Handle value change with validation const handleValueChange = useCallback((value: string) => { setEditValue(value); const error = validateValue(value); setErrorMessage(error); }, [validateValue]); // Start editing const startEdit = useCallback(() => { if (disabled || (type !== 'input' && type !== 'textarea')) { return; } const currentValue = (props as InputSettingItemProps | TextareaSettingItemProps).value || ''; setEditValue(currentValue); setIsEditing(true); }, [disabled, type, props, validateValue]); // Cancel editing const cancelEdit = useCallback(() => { setIsEditing(false); setEditValue(''); setErrorMessage(null); }, []); // Confirm editing const confirmEdit = useCallback(() => { if (type === 'input' || type === 'textarea') { const { onConfirm } = props as InputSettingItemProps | TextareaSettingItemProps; if (onConfirm && !errorMessage) { onConfirm(editValue); } } setIsEditing(false); setEditValue(''); setErrorMessage(null); }, [type, props, editValue, errorMessage]); // Handle key press const handleKeyPress = useCallback((e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey && type === 'input') { e.preventDefault(); if (!errorMessage) { confirmEdit(); } } else if (e.key === 'Escape') { e.preventDefault(); cancelEdit(); } }, [type, confirmEdit, cancelEdit, errorMessage]); // Handle switch change const handleSwitchChange = useCallback((event: React.ChangeEvent) => { if (type === 'switch') { const { onChange } = props as SwitchSettingItemProps; onChange(event.target.checked); } }, [type, props]); // Render content based on type const renderContent = () => { switch (type) { case 'switch': { const { value } = props as SwitchSettingItemProps; return ( ); } case 'input': { const { value, placeholder, editable = true } = props as InputSettingItemProps; if (isEditing && editable) { return (
handleValueChange(e.target.value)} onKeyDown={handleKeyPress} className={cs( classes['setting-item__input'], { [classes['setting-item__input--error']]: !!errorMessage }, )} /> {errorMessage && (
{errorMessage}
)}
); } return (
{value || ( {placeholder || t('ChatSetting.not_set')} )} {editable && ( )}
); } case 'textarea': { const { value, placeholder, editable = true, rows = 3 } = props as TextareaSettingItemProps; if (isEditing && editable) { return (