summaryrefslogtreecommitdiff
path: root/apps/web/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components')
-rw-r--r--apps/web/src/components/editor-header.tsx17
-rw-r--r--apps/web/src/components/editor/project-name-editor.tsx110
2 files changed, 120 insertions, 7 deletions
diff --git a/apps/web/src/components/editor-header.tsx b/apps/web/src/components/editor-header.tsx
index c6cecbe8..6f9f0b2f 100644
--- a/apps/web/src/components/editor-header.tsx
+++ b/apps/web/src/components/editor-header.tsx
@@ -6,6 +6,7 @@ import { ChevronLeft, Download } from "lucide-react";
import { useProjectStore } from "@/stores/project-store";
import { useTimelineStore } from "@/stores/timeline-store";
import { HeaderBase } from "./header-base";
+import { ProjectNameEditor } from "./editor/project-name-editor";
export function EditorHeader() {
const { activeProject } = useProjectStore();
@@ -24,13 +25,15 @@ export function EditorHeader() {
};
const leftContent = (
- <Link
- href="/"
- className="font-medium tracking-tight flex items-center gap-2 hover:opacity-80 transition-opacity"
- >
- <ChevronLeft className="h-4 w-4" />
- <span className="text-sm">{activeProject?.name || "Loading..."}</span>
- </Link>
+ <div className="flex items-center gap-2">
+ <Link
+ href="/"
+ className="font-medium tracking-tight flex items-center gap-2 hover:opacity-80 transition-opacity"
+ >
+ <ChevronLeft className="h-4 w-4" />
+ </Link>
+ <ProjectNameEditor />
+ </div>
);
const centerContent = (
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