Files
dify/web/app/components/workflow/skill/file-tree/tree/tree-edit-input.tsx

100 lines
2.5 KiB
TypeScript

'use client'
import type { NodeApi } from 'react-arborist'
import type { TreeNodeData } from '../../type'
import * as React from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
type TreeEditInputProps = {
node: NodeApi<TreeNodeData>
}
const TreeEditInput = ({ node }: TreeEditInputProps) => {
const { t } = useTranslation('workflow')
const inputRef = useRef<HTMLInputElement>(null)
const isMountedRef = useRef(true)
const submitLockRef = useRef(false)
const [isSubmitting, setIsSubmitting] = useState(false)
const isFolder = node.data.node_type === 'folder'
const placeholder = isFolder
? t('skillSidebar.folderNamePlaceholder')
: t('skillSidebar.fileNamePlaceholder')
useEffect(() => {
const input = inputRef.current
if (!input)
return
input.focus()
const name = input.value
const dotIndex = isFolder ? -1 : name.lastIndexOf('.')
if (dotIndex > 0)
input.setSelectionRange(0, dotIndex)
else
input.select()
}, [isFolder])
useEffect(() => {
return () => {
isMountedRef.current = false
}
}, [])
const handleSubmit = useCallback(async () => {
if (submitLockRef.current)
return
submitLockRef.current = true
setIsSubmitting(true)
try {
await node.tree.submit(node, inputRef.current?.value || '')
}
finally {
submitLockRef.current = false
if (isMountedRef.current)
setIsSubmitting(false)
}
}, [node])
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
e.stopPropagation()
if (e.key === 'Escape') {
if (submitLockRef.current)
return
node.reset()
}
else if (e.key === 'Enter') {
e.preventDefault()
void handleSubmit()
}
}
const handleBlur = () => {
if (submitLockRef.current)
return
node.reset()
}
const ariaLabel = isFolder
? t('skillSidebar.renameFolderInput')
: t('skillSidebar.renameFileInput')
return (
<input
ref={inputRef}
type="text"
defaultValue={node.data.name}
placeholder={placeholder}
aria-label={ariaLabel}
disabled={isSubmitting}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
onClick={e => e.stopPropagation()}
className="min-w-0 flex-1 rounded border border-components-input-border-active bg-transparent px-1 text-[13px] font-normal leading-4 text-text-primary outline-none placeholder:text-text-placeholder"
/>
)
}
export default React.memo(TreeEditInput)