({
id,
editingValue,
setEditingValue,
isFolder,
onSaveAndExit,
onCancelAndExit,
onGenerateItemName
}: TreeViewEditInputProps)
| 199 | } |
| 200 | |
| 201 | function TreeViewEditInput({ |
| 202 | id, |
| 203 | editingValue, |
| 204 | setEditingValue, |
| 205 | isFolder, |
| 206 | onSaveAndExit, |
| 207 | onCancelAndExit, |
| 208 | onGenerateItemName |
| 209 | }: TreeViewEditInputProps): React.JSX.Element { |
| 210 | const [popoverOpen, setPopoverOpen] = useState(false) |
| 211 | const containerRef = useRef<HTMLDivElement>(null) |
| 212 | const exitModeRef = useRef<'idle' | 'save' | 'cancel'>('idle') |
| 213 | |
| 214 | const handleSaveAndExit = useCallback(() => { |
| 215 | if (exitModeRef.current !== 'idle') { |
| 216 | return |
| 217 | } |
| 218 | |
| 219 | exitModeRef.current = 'save' |
| 220 | onSaveAndExit() |
| 221 | }, [onSaveAndExit]) |
| 222 | |
| 223 | const handleCancelAndExit = useCallback(() => { |
| 224 | if (exitModeRef.current !== 'idle') { |
| 225 | return |
| 226 | } |
| 227 | |
| 228 | exitModeRef.current = 'cancel' |
| 229 | onCancelAndExit() |
| 230 | }, [onCancelAndExit]) |
| 231 | |
| 232 | const handleGenerate = async (options: GenerateOptions): Promise<void> => { |
| 233 | if (onGenerateItemName) { |
| 234 | await onGenerateItemName(id, options) |
| 235 | handleCancelAndExit() |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | useEffect(() => { |
| 240 | const handlePointerDownOutside = (event: PointerEvent): void => { |
| 241 | const target = event.target |
| 242 | if (!(target instanceof HTMLElement)) { |
| 243 | return |
| 244 | } |
| 245 | |
| 246 | if (containerRef.current?.contains(target)) { |
| 247 | return |
| 248 | } |
| 249 | |
| 250 | if ( |
| 251 | target.closest('.rename-input__ai-btn') || |
| 252 | target.closest('.ai-generate-popover__content') |
| 253 | ) { |
| 254 | return |
| 255 | } |
| 256 | |
| 257 | if (!popoverOpen) { |
| 258 | handleSaveAndExit() |
nothing calls this directly
no outgoing calls
no test coverage detected