1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
"use client";
import Link from "next/link";
import { Button } from "./ui/button";
import { ChevronLeft, Download } from "lucide-react";
import { useTimelineStore } from "@/stores/timeline-store";
import { HeaderBase } from "./header-base";
import { formatTimeCode } from "@/lib/time";
import { useProjectStore } from "@/stores/project-store";
import { KeyboardShortcutsHelp } from "./keyboard-shortcuts-help";
import { useState, useRef, useEffect } from "react";
import { Input } from "@/components/ui/input";
export function EditorHeader() {
const { getTotalDuration } = useTimelineStore();
const { activeProject, renameProject } = useProjectStore();
// State for edit mode and project name input
const [isEditing, setIsEditing] = useState(false);
const [newName, setNewName] = useState(activeProject?.name || "");
// Ref for focusing/selecting the input
const inputRef = useRef<HTMLInputElement>(null);
const handleExport = () => {
// TODO: Implement export functionality
console.log("Export project");
};
// When user clicks the project name, enter edit mode
const handleNameClick = () => {
if (!activeProject) return;
setNewName(activeProject.name);
setIsEditing(true);
};
// Focus/select input when entering edit mode
useEffect(() => {
if (isEditing && inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
}
}, [isEditing]);
// Save the new name if changed, exit edit mode
const handleNameSave = async () => {
if (activeProject && newName.trim() && newName !== activeProject.name) {
await renameProject(activeProject.id, newName.trim());
}
setIsEditing(false);
};
// Handle Enter (save) and Escape (cancel) in the input
const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") handleNameSave();
else if (e.key === "Escape") setIsEditing(false);
};
// Project name in header: editable input or span
const leftContent = (
<div className="flex items-center gap-2">
<Link
href="/projects"
className="font-medium tracking-tight flex items-center gap-2 hover:opacity-80 transition-opacity"
>
<ChevronLeft className="h-4 w-4" />
</Link>
<div className="w-[14rem] h-9 flex items-center">
{isEditing ? (
// Editable input for project name using standard Input component
<Input
ref={inputRef}
className="text-sm font-medium px-2 py-1 h-7 truncate"
value={newName}
onChange={e => setNewName(e.target.value)}
onBlur={handleNameSave}
onKeyDown={handleInputKeyDown}
maxLength={64}
aria-label="Project name"
autoFocus
/>
) : (
// Display project name as span, click to edit
<span
className="text-sm font-medium cursor-pointer hover:underline"
title="Click to rename"
role="button"
tabIndex={0}
onClick={handleNameClick}
onKeyDown={e => e.key === 'Enter' && handleNameClick()}
><div className="truncate text-ellipsis overflow-clip w-40">{activeProject?.name}</div>
</span>
)}
</div>
</div>
);
const centerContent = (
<div className="flex items-center gap-2 text-xs">
<span>
{formatTimeCode(
getTotalDuration(),
"HH:MM:SS:FF",
activeProject?.fps || 30
)}
</span>
</div>
);
const rightContent = (
<nav className="flex items-center gap-2">
<KeyboardShortcutsHelp />
<Button
size="sm"
variant="primary"
className="h-7 text-xs"
onClick={handleExport}
>
<Download className="h-4 w-4" />
<span className="text-sm">Export</span>
</Button>
</nav>
);
return (
<HeaderBase
leftContent={leftContent}
centerContent={centerContent}
rightContent={rightContent}
className="bg-background h-[3.2rem] px-4 items-center"
/>
);
}
|