- Fix: ProjectSelector dropdown now scrolls (max-height + overflow-y) when project list exceeds visible area, with scrollIntoView on keyboard navigation - Feat: Always-visible search input with type-ahead filtering, HighlightMatch text highlighting, exact match detection + auto-select on Enter - Feat: Project bookmarking via localStorage (useProjectBookmarks hook), star toggle on each item, bookmarked section shown at top of dropdown - Refactor: Header.tsx now imports standalone ProjectSelector instead of using an inline copy that lacked these features - Tests: 131 tests passing across ProjectSelector + useProjectBookmarks
53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
import { useCallback, useState, useEffect } from "react";
|
|
|
|
const STORAGE_KEY = "fusion_project_bookmarks";
|
|
|
|
/**
|
|
* Manages project bookmark IDs persisted in localStorage.
|
|
* Bookmarks are stored as a JSON array of project ID strings.
|
|
*/
|
|
export function useProjectBookmarks() {
|
|
const [bookmarkedIds, setBookmarkedIds] = useState<Set<string>>(() => {
|
|
try {
|
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
if (raw) {
|
|
const parsed = JSON.parse(raw);
|
|
if (Array.isArray(parsed)) {
|
|
return new Set(parsed.filter((id: unknown) => typeof id === "string"));
|
|
}
|
|
}
|
|
} catch {
|
|
// Corrupted or missing — start empty
|
|
}
|
|
return new Set<string>();
|
|
});
|
|
|
|
// Sync to localStorage whenever the set changes
|
|
useEffect(() => {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify([...bookmarkedIds]));
|
|
} catch {
|
|
// localStorage full or unavailable — non-critical, ignore
|
|
}
|
|
}, [bookmarkedIds]);
|
|
|
|
const toggleBookmark = useCallback((projectId: string) => {
|
|
setBookmarkedIds((prev) => {
|
|
const next = new Set(prev);
|
|
if (next.has(projectId)) {
|
|
next.delete(projectId);
|
|
} else {
|
|
next.add(projectId);
|
|
}
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
const isBookmarked = useCallback(
|
|
(projectId: string) => bookmarkedIds.has(projectId),
|
|
[bookmarkedIds],
|
|
);
|
|
|
|
return { bookmarkedIds, toggleBookmark, isBookmarked };
|
|
}
|