|
import { |
|
memo, |
|
useCallback, |
|
useState, |
|
} from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import { RiArrowDownSLine } from '@remixicon/react' |
|
import { capitalize } from 'lodash-es' |
|
import { useBoolean } from 'ahooks' |
|
import { VarType as NumberVarType } from '../../tool/types' |
|
import VariableTag from '../../_base/components/variable-tag' |
|
import { |
|
PortalToFollowElem, |
|
PortalToFollowElemContent, |
|
PortalToFollowElemTrigger, |
|
} from '@/app/components/base/portal-to-follow-elem' |
|
import Button from '@/app/components/base/button' |
|
import cn from '@/utils/classnames' |
|
import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars' |
|
import type { |
|
NodeOutPutVar, |
|
ValueSelector, |
|
} from '@/app/components/workflow/types' |
|
import { VarType } from '@/app/components/workflow/types' |
|
import { variableTransformer } from '@/app/components/workflow/utils' |
|
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' |
|
|
|
const options = [ |
|
NumberVarType.variable, |
|
NumberVarType.constant, |
|
] |
|
|
|
type ConditionNumberInputProps = { |
|
numberVarType?: NumberVarType |
|
onNumberVarTypeChange: (v: NumberVarType) => void |
|
value: string |
|
onValueChange: (v: string) => void |
|
variables: NodeOutPutVar[] |
|
isShort?: boolean |
|
unit?: string |
|
} |
|
const ConditionNumberInput = ({ |
|
numberVarType = NumberVarType.constant, |
|
onNumberVarTypeChange, |
|
value, |
|
onValueChange, |
|
variables, |
|
isShort, |
|
unit, |
|
}: ConditionNumberInputProps) => { |
|
const { t } = useTranslation() |
|
const [numberVarTypeVisible, setNumberVarTypeVisible] = useState(false) |
|
const [variableSelectorVisible, setVariableSelectorVisible] = useState(false) |
|
const [isFocus, { |
|
setTrue: setFocus, |
|
setFalse: setBlur, |
|
}] = useBoolean() |
|
|
|
const handleSelectVariable = useCallback((valueSelector: ValueSelector) => { |
|
onValueChange(variableTransformer(valueSelector) as string) |
|
setVariableSelectorVisible(false) |
|
}, [onValueChange]) |
|
|
|
return ( |
|
<div className='flex items-center cursor-pointer'> |
|
<PortalToFollowElem |
|
open={numberVarTypeVisible} |
|
onOpenChange={setNumberVarTypeVisible} |
|
placement='bottom-start' |
|
offset={{ mainAxis: 2, crossAxis: 0 }} |
|
> |
|
<PortalToFollowElemTrigger onClick={() => setNumberVarTypeVisible(v => !v)}> |
|
<Button |
|
className='shrink-0' |
|
variant='ghost' |
|
size='small' |
|
> |
|
{capitalize(numberVarType)} |
|
<RiArrowDownSLine className='ml-[1px] w-3.5 h-3.5' /> |
|
</Button> |
|
</PortalToFollowElemTrigger> |
|
<PortalToFollowElemContent className='z-[1000]'> |
|
<div className='p-1 w-[112px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'> |
|
{ |
|
options.map(option => ( |
|
<div |
|
key={option} |
|
className={cn( |
|
'flex items-center px-3 h-7 rounded-md hover:bg-state-base-hover cursor-pointer', |
|
'text-[13px] font-medium text-text-secondary', |
|
numberVarType === option && 'bg-state-base-hover', |
|
)} |
|
onClick={() => { |
|
onNumberVarTypeChange(option) |
|
setNumberVarTypeVisible(false) |
|
}} |
|
> |
|
{capitalize(option)} |
|
</div> |
|
)) |
|
} |
|
</div> |
|
</PortalToFollowElemContent> |
|
</PortalToFollowElem> |
|
<div className='mx-1 w-[1px] h-4 bg-divider-regular'></div> |
|
<div className='grow w-0 ml-0.5'> |
|
{ |
|
numberVarType === NumberVarType.variable && ( |
|
<PortalToFollowElem |
|
open={variableSelectorVisible} |
|
onOpenChange={setVariableSelectorVisible} |
|
placement='bottom-start' |
|
offset={{ mainAxis: 2, crossAxis: 0 }} |
|
> |
|
<PortalToFollowElemTrigger |
|
className='w-full' |
|
onClick={() => setVariableSelectorVisible(v => !v)}> |
|
{ |
|
value && ( |
|
<VariableTag |
|
valueSelector={variableTransformer(value) as string[]} |
|
varType={VarType.number} |
|
isShort={isShort} |
|
/> |
|
) |
|
} |
|
{ |
|
!value && ( |
|
<div className='flex items-center p-1 h-6 text-components-input-text-placeholder text-[13px]'> |
|
<Variable02 className='shrink-0 mr-1 w-4 h-4' /> |
|
<div className='w-0 grow truncate'>{t('workflow.nodes.ifElse.selectVariable')}</div> |
|
</div> |
|
) |
|
} |
|
</PortalToFollowElemTrigger> |
|
<PortalToFollowElemContent className='z-[1000]'> |
|
<div className={cn('w-[296px] pt-1 bg-components-panel-bg-blur rounded-lg border-[0.5px] border-components-panel-border shadow-lg', isShort && 'w-[200px]')}> |
|
<VarReferenceVars |
|
vars={variables} |
|
onChange={handleSelectVariable} |
|
/> |
|
</div> |
|
</PortalToFollowElemContent> |
|
</PortalToFollowElem> |
|
) |
|
} |
|
{ |
|
numberVarType === NumberVarType.constant && ( |
|
<div className=' relative'> |
|
<input |
|
className={cn('block w-full px-2 text-[13px] text-components-input-text-filled placeholder:text-components-input-text-placeholder outline-none appearance-none bg-transparent', unit && 'pr-6')} |
|
type='number' |
|
value={value} |
|
onChange={e => onValueChange(e.target.value)} |
|
placeholder={t('workflow.nodes.ifElse.enterValue') || ''} |
|
onFocus={setFocus} |
|
onBlur={setBlur} |
|
/> |
|
{!isFocus && unit && <div className='absolute right-2 top-[50%] translate-y-[-50%] text-text-tertiary system-sm-regular'>{unit}</div>} |
|
</div> |
|
) |
|
} |
|
</div> |
|
</div> |
|
) |
|
} |
|
|
|
export default memo(ConditionNumberInput) |
|
|