import { useDrag, useDrop } from 'react-dnd'; import { motion } from 'framer-motion'; import { classNames } from '~/utils/classNames'; import type { TabVisibilityConfig } from '~/components/settings/settings.types'; import { TAB_LABELS } from '~/components/settings/settings.types'; import { Switch } from '~/components/ui/Switch'; interface DraggableTabListProps { tabs: TabVisibilityConfig[]; onReorder: (tabs: TabVisibilityConfig[]) => void; onWindowChange?: (tab: TabVisibilityConfig, window: 'user' | 'developer') => void; onVisibilityChange?: (tab: TabVisibilityConfig, visible: boolean) => void; showControls?: boolean; } interface DraggableTabItemProps { tab: TabVisibilityConfig; index: number; moveTab: (dragIndex: number, hoverIndex: number) => void; showControls?: boolean; onWindowChange?: (tab: TabVisibilityConfig, window: 'user' | 'developer') => void; onVisibilityChange?: (tab: TabVisibilityConfig, visible: boolean) => void; } interface DragItem { type: string; index: number; id: string; } const DraggableTabItem = ({ tab, index, moveTab, showControls, onWindowChange, onVisibilityChange, }: DraggableTabItemProps) => { const [{ isDragging }, dragRef] = useDrag({ type: 'tab', item: { type: 'tab', index, id: tab.id }, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), }); const [, dropRef] = useDrop({ accept: 'tab', hover: (item: DragItem, monitor) => { if (!monitor.isOver({ shallow: true })) { return; } if (item.index === index) { return; } if (item.id === tab.id) { return; } moveTab(item.index, index); item.index = index; }, }); const ref = (node: HTMLDivElement | null) => { dragRef(node); dropRef(node); }; return (
{TAB_LABELS[tab.id]}
{showControls && (
Order: {tab.order}, Window: {tab.window}
)}
{showControls && !tab.locked && (
onVisibilityChange?.(tab, checked)} className="data-[state=checked]:bg-purple-500" aria-label={`Toggle ${TAB_LABELS[tab.id]} visibility`} />
onWindowChange?.(tab, checked ? 'developer' : 'user')} className="data-[state=checked]:bg-purple-500" aria-label={`Toggle ${TAB_LABELS[tab.id]} window assignment`} />
)} ); }; export const DraggableTabList = ({ tabs, onReorder, onWindowChange, onVisibilityChange, showControls = false, }: DraggableTabListProps) => { const moveTab = (dragIndex: number, hoverIndex: number) => { const items = Array.from(tabs); const [reorderedItem] = items.splice(dragIndex, 1); items.splice(hoverIndex, 0, reorderedItem); // Update order numbers based on position const reorderedTabs = items.map((tab, index) => ({ ...tab, order: index + 1, })); onReorder(reorderedTabs); }; return (
{tabs.map((tab, index) => ( ))}
); };