import type { FC } from 'react' import { useEffect, useRef, useState } from 'react' import type { ModelParameterRule } from '../declarations' import { useLanguage } from '../hooks' import { isNullOrUndefined } from '../utils' import cn from '@/utils/classnames' import Switch from '@/app/components/base/switch' import Tooltip from '@/app/components/base/tooltip' import Slider from '@/app/components/base/slider' import Radio from '@/app/components/base/radio' import { SimpleSelect } from '@/app/components/base/select' import TagInput from '@/app/components/base/tag-input' export type ParameterValue = number | string | string[] | boolean | undefined type ParameterItemProps = { parameterRule: ModelParameterRule value?: ParameterValue onChange?: (value: ParameterValue) => void className?: string onSwitch?: (checked: boolean, assignValue: ParameterValue) => void isInWorkflow?: boolean } const ParameterItem: FC = ({ parameterRule, value, onChange, className, onSwitch, isInWorkflow, }) => { const language = useLanguage() const [localValue, setLocalValue] = useState(value) const numberInputRef = useRef(null) const getDefaultValue = () => { let defaultValue: ParameterValue if (parameterRule.type === 'int' || parameterRule.type === 'float') defaultValue = isNullOrUndefined(parameterRule.default) ? (parameterRule.min || 0) : parameterRule.default else if (parameterRule.type === 'string' || parameterRule.type === 'text') defaultValue = parameterRule.options?.length ? (parameterRule.default || '') : (parameterRule.default || '') else if (parameterRule.type === 'boolean') defaultValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : false else if (parameterRule.type === 'tag') defaultValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : [] return defaultValue } const renderValue = value ?? localValue ?? getDefaultValue() const handleInputChange = (newValue: ParameterValue) => { setLocalValue(newValue) if (onChange && (parameterRule.name === 'stop' || !isNullOrUndefined(value) || parameterRule.required)) onChange(newValue) } const handleNumberInputChange = (e: React.ChangeEvent) => { let num = +e.target.value if (!isNullOrUndefined(parameterRule.max) && num > parameterRule.max!) { num = parameterRule.max as number numberInputRef.current!.value = `${num}` } if (!isNullOrUndefined(parameterRule.min) && num < parameterRule.min!) num = parameterRule.min as number handleInputChange(num) } const handleNumberInputBlur = () => { if (numberInputRef.current) numberInputRef.current.value = renderValue as string } const handleSlideChange = (num: number) => { if (!isNullOrUndefined(parameterRule.max) && num > parameterRule.max!) { handleInputChange(parameterRule.max) numberInputRef.current!.value = `${parameterRule.max}` return } if (!isNullOrUndefined(parameterRule.min) && num < parameterRule.min!) { handleInputChange(parameterRule.min) numberInputRef.current!.value = `${parameterRule.min}` return } handleInputChange(num) numberInputRef.current!.value = `${num}` } const handleRadioChange = (v: number) => { handleInputChange(v === 1) } const handleStringInputChange = (e: React.ChangeEvent) => { handleInputChange(e.target.value) } const handleSelect = (option: { value: string | number; name: string }) => { handleInputChange(option.value) } const handleTagChange = (newSequences: string[]) => { handleInputChange(newSequences) } const handleSwitch = (checked: boolean) => { if (onSwitch) { const assignValue: ParameterValue = localValue || getDefaultValue() onSwitch(checked, assignValue) } } useEffect(() => { if ((parameterRule.type === 'int' || parameterRule.type === 'float') && numberInputRef.current) numberInputRef.current.value = `${renderValue}` }, [value]) const renderInput = () => { const numberInputWithSlide = (parameterRule.type === 'int' || parameterRule.type === 'float') && !isNullOrUndefined(parameterRule.min) && !isNullOrUndefined(parameterRule.max) if (parameterRule.type === 'int') { let step = 100 if (parameterRule.max) { if (parameterRule.max < 100) step = 1 else if (parameterRule.max < 1000) step = 10 else if (parameterRule.max < 10000) step = 100 } return ( <> {numberInputWithSlide && } ) } if (parameterRule.type === 'float') { return ( <> {numberInputWithSlide && } ) } if (parameterRule.type === 'boolean') { return ( True False ) } if (parameterRule.type === 'string' && !parameterRule.options?.length) { return ( ) } if (parameterRule.type === 'text') { return (