summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor
diff options
context:
space:
mode:
authorPulkit Garg <pulkitgargbnl@gmail.com>2025-06-25 10:26:29 +0530
committerPulkit Garg <pulkitgargbnl@gmail.com>2025-06-25 10:26:29 +0530
commit411a9a5f1cdb4b52c65f4a1344c9be7694d130d7 (patch)
tree217923d57528feaacdfe359ff3501b317f0d5483 /apps/web/src/components/editor
parent7461b763b1e434a763c1d02e9fa750dce1c153a8 (diff)
downloadopencut-411a9a5f1cdb4b52c65f4a1344c9be7694d130d7.tar.gz
feature: add project name editing functionality
Diffstat (limited to 'apps/web/src/components/editor')
-rw-r--r--apps/web/src/components/editor/project-name-editor.tsx110
1 files changed, 110 insertions, 0 deletions
diff --git a/apps/web/src/components/editor/project-name-editor.tsx b/apps/web/src/components/editor/project-name-editor.tsx
new file mode 100644
index 00000000..aa0141ae
--- /dev/null
+++ b/apps/web/src/components/editor/project-name-editor.tsx
@@ -0,0 +1,110 @@
+"use client";
+
+import { useState, useRef, useEffect } from "react";
+import { Input } from "../ui/input";
+import { useProjectStore } from "@/stores/project-store";
+import { Edit2, Check, X } from "lucide-react";
+import { Button } from "../ui/button";
+
+interface ProjectNameEditorProps {
+ className?: string;
+}
+
+export function ProjectNameEditor({ className }: ProjectNameEditorProps) {
+ const { activeProject, updateProjectName } = useProjectStore();
+ const [isEditing, setIsEditing] = useState(false);
+ const [editValue, setEditValue] = useState("");
+ const inputRef = useRef<HTMLInputElement>(null);
+
+ useEffect(() => {
+ if (activeProject) {
+ setEditValue(activeProject.name);
+ }
+ }, [activeProject]);
+
+ useEffect(() => {
+ if (isEditing && inputRef.current) {
+ inputRef.current.focus();
+ inputRef.current.select();
+ }
+ }, [isEditing]);
+
+ const handleStartEdit = () => {
+ if (activeProject) {
+ setEditValue(activeProject.name);
+ setIsEditing(true);
+ }
+ };
+
+ const handleSave = () => {
+ if (editValue.trim()) {
+ updateProjectName(editValue.trim());
+ setIsEditing(false);
+ }
+ };
+
+ const handleCancel = () => {
+ if (activeProject) {
+ setEditValue(activeProject.name);
+ }
+ setIsEditing(false);
+ };
+
+ const handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === "Enter") {
+ handleSave();
+ } else if (e.key === "Escape") {
+ handleCancel();
+ }
+ };
+
+ if (!activeProject) {
+ return <span className="text-sm text-muted-foreground">Loading...</span>;
+ }
+
+ if (isEditing) {
+ return (
+ <div className="flex items-center gap-1">
+ <Input
+ ref={inputRef}
+ value={editValue}
+ onChange={(e) => setEditValue(e.target.value)}
+ onKeyDown={handleKeyDown}
+ className="h-7 text-sm px-3 py-1 min-w-[200px]"
+ size={1}
+ />
+ <Button
+ size="sm"
+ variant="text"
+ onClick={handleSave}
+ className="h-7 w-7 p-0"
+ disabled={!editValue.trim()}
+ >
+ <Check className="h-3 w-3" />
+ </Button>
+ <Button
+ size="sm"
+ variant="text"
+ onClick={handleCancel}
+ className="h-7 w-7 p-0"
+ >
+ <X className="h-3 w-3" />
+ </Button>
+ </div>
+ );
+ }
+
+ return (
+ <div className="flex items-center gap-1 group">
+ <span className="text-sm font-medium">{activeProject.name}</span>
+ <Button
+ size="sm"
+ variant="text"
+ onClick={handleStartEdit}
+ className="h-6 w-6 p-0 opacity-0 group-hover:opacity-100 transition-opacity"
+ >
+ <Edit2 className="h-3 w-3" />
+ </Button>
+ </div>
+ );
+} \ No newline at end of file