import { X } from 'lucide-react'; import { DndContext, PointerSensor, useSensor, useSensors, closestCenter, type DragEndEvent, } from '@dnd-kit/core'; import { SortableContext, horizontalListSortingStrategy, useSortable, } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { useFileStore, type OpenTab } from '@/stores/file-store'; import { cn } from '@/lib/utils'; function SortableTab({ tab, isActive, onSelect, onClose, }: { tab: OpenTab; isActive: boolean; onSelect: (id: string) => void; onClose: (id: string) => void; }) { const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: tab.id, }); const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1, }; return (
onSelect(tab.id)} > {tab.dirty && ( )} {tab.title}
); } export function TabBar() { const openTabs = useFileStore((s) => s.openTabs); const activeTabId = useFileStore((s) => s.activeTabId); const setActiveTab = useFileStore((s) => s.setActiveTab); const closeTab = useFileStore((s) => s.closeTab); const reorderTabs = useFileStore((s) => s.reorderTabs); // Require a small drag distance before activating — so a click on the tab // body still triggers `onClick` (dnd-kit's PointerSensor default is 0). const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } })); if (openTabs.length === 0) { return (
No files open
); } function handleDragEnd(e: DragEndEvent) { const { active, over } = e; if (!over || active.id === over.id) return; const fromIndex = openTabs.findIndex((t) => t.id === active.id); const toIndex = openTabs.findIndex((t) => t.id === over.id); if (fromIndex === -1 || toIndex === -1) return; reorderTabs(fromIndex, toIndex); } return (
t.id)} strategy={horizontalListSortingStrategy}>
{openTabs.map((tab) => ( ))}
); }