diff --git a/packages/web/src/hooks/useDragManager.ts b/packages/web/src/hooks/useDragManager.ts new file mode 100644 index 00000000..1b227731 --- /dev/null +++ b/packages/web/src/hooks/useDragManager.ts @@ -0,0 +1,54 @@ +import { useState, useCallback, useEffect, type RefObject } from 'react'; + +export type DragType = 'channel' | 'category' | 'voiceUser'; + +export interface DragState { + type: DragType; + dragId: string; + sourceId?: string; // only for voiceUser — originating channelId +} + +export interface DropTarget { + targetId: string; + position: 'before' | 'after'; + targetType: 'channel' | 'category'; +} + +interface UseDragManagerOpts { + scrollContainerRef: RefObject; + canManage: boolean; + canMoveMembers: boolean; + onChannelDrop: (dragId: string, target: DropTarget) => void; + onCategoryDrop: (dragId: string, target: DropTarget) => void; + onVoiceUserDrop: (userId: string, fromChannelId: string, toChannelId: string) => void; +} + +export function useDragManager(opts: UseDragManagerOpts) { + const { scrollContainerRef, canManage, canMoveMembers, onChannelDrop, onCategoryDrop, onVoiceUserDrop } = opts; + + const [activeDrag, setActiveDrag] = useState(null); + const [dropTarget, setDropTarget] = useState(null); + const [voiceHoverChannelId, setVoiceHoverChannelId] = useState(null); + + const clearState = useCallback(() => { + setActiveDrag(null); + setDropTarget(null); + setVoiceHoverChannelId(null); + }, []); + + // Handler factories added in subsequent stages... + + // Suppress unused variable warnings for incremental build + void scrollContainerRef; + void canManage; + void canMoveMembers; + void onChannelDrop; + void onCategoryDrop; + void onVoiceUserDrop; + void clearState; + + return { + activeDrag, + dropTarget, + }; +}