dify/web/features/agent-v2/roster/components/agent-form-fields.tsx
盐粒 Yanli f4fdbeba76
feat(agent-v2): sync nightly updates to main (2026-06-22) (#37651)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-06-23 08:05:16 +00:00

123 lines
4.0 KiB
TypeScript

import type { AgentIconSelection } from './agent-form'
import { FieldControl, FieldError, FieldLabel, FieldRoot } from '@langgenius/dify-ui/field'
import { Textarea } from '@langgenius/dify-ui/textarea'
import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
type AgentFormFieldsProps = {
description: string
icon: AgentIconSelection
iconAriaLabel: string
name: string
onDescriptionChange: (description: string) => void
onIconClick: () => void
onNameChange: (name: string) => void
onRoleChange: (role: string) => void
role: string
}
export function AgentFormFields({
description,
icon,
iconAriaLabel,
name,
onDescriptionChange,
onIconClick,
onNameChange,
onRoleChange,
role,
}: AgentFormFieldsProps) {
const { t } = useTranslation('agentV2')
return (
<div className="space-y-5 px-6 py-3">
<div className="flex items-end gap-4 pb-2">
<button
type="button"
aria-label={iconAriaLabel}
className="shrink-0 rounded-full outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid"
onClick={onIconClick}
>
<AppIcon
size="xxl"
rounded
className="size-16 cursor-pointer"
iconType={icon.type === 'link' ? 'image' : icon.type}
icon={icon.type === 'emoji' ? icon.icon : undefined}
background={icon.type === 'emoji' ? icon.background : undefined}
imageUrl={icon.type === 'emoji' ? undefined : icon.url}
/>
</button>
<div className="flex min-w-0 flex-1 gap-3 pb-1">
<FieldRoot
name="name"
className="relative min-w-0 flex-1"
validate={(value) => {
if (typeof value === 'string' && value.length > 0 && !value.trim())
return t('roster.createForm.nameRequired')
return null
}}
>
<FieldLabel>
{t('roster.createForm.nameLabel')}
</FieldLabel>
<FieldControl
autoComplete="off"
// eslint-disable-next-line jsx-a11y/no-autofocus -- Agent roster dialogs open from explicit commands, and the name field is the primary editable control.
autoFocus
maxLength={255}
onValueChange={onNameChange}
placeholder={t('roster.createForm.namePlaceholder')}
required
value={name}
/>
<div className="absolute top-full left-0 mt-1">
<FieldError match="valueMissing">{t('roster.createForm.nameRequired')}</FieldError>
<FieldError match="customError" />
</div>
</FieldRoot>
<FieldRoot
name="role"
className="relative min-w-0 flex-1"
validate={(value) => {
if (typeof value === 'string' && value.length > 0 && !value.trim())
return t('roster.createForm.roleRequired')
return null
}}
>
<FieldLabel>
{t('roster.createForm.roleLabel')}
</FieldLabel>
<FieldControl
autoComplete="off"
maxLength={255}
onValueChange={onRoleChange}
placeholder={t('roster.createForm.rolePlaceholder')}
required
value={role}
/>
<div className="absolute top-full left-0 mt-1">
<FieldError match="valueMissing">{t('roster.createForm.roleRequired')}</FieldError>
<FieldError match="customError" />
</div>
</FieldRoot>
</div>
</div>
<FieldRoot name="description">
<FieldLabel>
{t('roster.createForm.descriptionLabel')}
</FieldLabel>
<Textarea
autoComplete="off"
className="h-20 resize-none"
onValueChange={onDescriptionChange}
placeholder={t('roster.createForm.descriptionPlaceholder')}
value={description}
/>
</FieldRoot>
</div>
)
}