Files
kandev/apps/web/components/task/inline-file-input.tsx
T
2026-09-10 18:14:05 +01:00

65 lines
1.7 KiB
TypeScript

"use client";
import { useRef, useEffect, useCallback } from "react";
import { Input } from "@kandev/ui/input";
import { FileIcon } from "@/components/ui/file-icon";
import { useTranslation } from "react-i18next";
type InlineFileInputProps = {
depth: number;
onSubmit: (name: string) => void;
onCancel: () => void;
};
export function InlineFileInput({ depth, onSubmit, onCancel }: InlineFileInputProps) {
const { t } = useTranslation();
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
// Focus on next tick to ensure the element is rendered
requestAnimationFrame(() => inputRef.current?.focus());
}, []);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
const value = inputRef.current?.value.trim();
if (value) onSubmit(value);
else onCancel();
} else if (e.key === "Escape") {
onCancel();
}
},
[onSubmit, onCancel],
);
const handleBlur = useCallback(() => {
const value = inputRef.current?.value.trim();
if (value) onSubmit(value);
else onCancel();
}, [onSubmit, onCancel]);
return (
<div
className="flex items-center gap-1 px-2 py-0.5"
style={{ paddingLeft: `${depth * 12 + 8 + 20}px` }}
>
<FileIcon
fileName="file"
filePath=""
className="flex-shrink-0"
style={{ width: "14px", height: "14px", opacity: 0.7 }}
/>
<Input
ref={inputRef}
type="text"
controlSize="none"
className="h-5 text-xs px-1 py-0 border-muted-foreground/30"
placeholder={t("task:filename")}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
/>
</div>
);
}