Files
fusion/packages/dashboard/app/hooks/usePoppedOutTasks.ts
gsxdsm f6f9e822f5 refactor(dashboard): extract task-detail, board-scroll, popped-out hooks
Extract three AppInner state clusters into hooks:
- useMainPanelTaskDetail: the main-panel task-detail snapshot + initial tab;
  setTask accepts the SetStateAction updater form so the embedded detail can
  patch the snapshot on task updates.
- useBoardScrollRestore: the board scroll snapshot refs, capture, and the
  double-requestAnimationFrame restore effect keyed on taskView; exposes
  requestRestore for App to schedule a restore on detail close.
- usePoppedOutTasks: the popped-out task-detail windows (dedupe-by-id popOut,
  close-by-id).

App keeps the navigation-history composition (openTaskDetailInMainPanel /
closeTaskDetailMainPanel) and now consumes the hooks' primitives.
Behavior-preserving; App.test.tsx identical (5 pre-existing failures, none
introduced). Verified by typecheck, eslint, and 5 renderHook tests.

Completes U6 (App.tsx module-breakup plan).
2026-06-23 21:09:36 -07:00

28 lines
1.0 KiB
TypeScript

/*
FNXC:FloatingWindow 2026-06-24-00:00:
Popped-out task-detail windows — movable, resizable, non-blocking FloatingWindows. Each entry is a task snapshot; several can be open at once. Snapshots survive a tasks revalidation (rendering prefers the live row by id). Pop-out dedupes by task id. Extracted from AppInner.
*/
import { useCallback, useState } from "react";
import type { Task, TaskDetail } from "@fusion/core";
export interface UsePoppedOutTasksResult {
tasks: Array<Task | TaskDetail>;
popOut: (task: Task | TaskDetail) => void;
close: (taskId: string) => void;
}
export function usePoppedOutTasks(): UsePoppedOutTasksResult {
const [tasks, setTasks] = useState<Array<Task | TaskDetail>>([]);
const popOut = useCallback((task: Task | TaskDetail) => {
setTasks((current) => (current.some((entry) => entry.id === task.id) ? current : [...current, task]));
}, []);
const close = useCallback((taskId: string) => {
setTasks((current) => current.filter((entry) => entry.id !== taskId));
}, []);
return { tasks, popOut, close };
}