import { type ReactNode } from "react"; import { closestCenter, DndContext, PointerSensor, useSensor, useSensors, type DragEndEvent, } from "@dnd-kit/core"; import { arrayMove, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; import type { PanelLayout } from "../lib/panelLayout"; import PanelGroup from "./PanelGroup"; export type PanelItem = { id: string; title: string; body: ReactNode }; // Renders a panel's islands in the user's saved order, with drag-to-reorder + hide + per-group // collapse driven by `layout` (see lib/panelLayout). `items` holds only the currently AVAILABLE // groups (a caller drops facet-gated / empty ones); the layout order is filtered to them so a // stored order that references a now-absent group is tolerated. Reordering/hiding is active only // in `editing` mode. Shared by all three side panels. export default function PanelGroups({ items, layout, setLayout, editing, }: { items: PanelItem[]; layout: PanelLayout; setLayout: (l: PanelLayout) => void; editing: boolean; }) { const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } })); const byId = new Map(items.map((it) => [it.id, it])); const orderedAvailable = layout.order.filter((id) => byId.has(id)); // Append any available id missing from the stored order (e.g. a group that became available // after the layout was saved) so it never silently disappears. for (const it of items) if (!orderedAvailable.includes(it.id)) orderedAvailable.push(it.id); const renderedIds = editing ? orderedAvailable : orderedAvailable.filter((id) => !layout.hidden[id]); function toggleCollapse(id: string) { setLayout({ ...layout, collapsed: { ...layout.collapsed, [id]: !layout.collapsed[id] } }); } function toggleHidden(id: string) { setLayout({ ...layout, hidden: { ...layout.hidden, [id]: !layout.hidden[id] } }); } function onDragEnd(e: DragEndEvent) { const { active, over } = e; if (!over || active.id === over.id) return; const from = layout.order.indexOf(active.id as string); const to = layout.order.indexOf(over.id as string); if (from < 0 || to < 0) return; setLayout({ ...layout, order: arrayMove(layout.order, from, to) }); } return (
{renderedIds.map((id) => ( ))}
); }