'use client' import { useState, useCallback, useEffect, useRef } from 'react' import { UseSelectionReturn } from '../types' interface UseSelectionProps { currentPageData: any[] totalCount: number getRowId: (row: any) => string onSelectionChange?: (ids: Set) => void onSelectAllPages?: (enabled: boolean) => void // External controlled state externalSelectedIds?: Set externalSelectAllPages?: boolean } export function useSelection({ currentPageData, totalCount, getRowId, onSelectionChange, onSelectAllPages, externalSelectedIds, externalSelectAllPages, }: UseSelectionProps): UseSelectionReturn { const [internalSelectedIds, setInternalSelectedIds] = useState>(new Set()) const [internalSelectAllPages, setInternalSelectAllPages] = useState(false) // Track if we're in controlled mode const isControlled = externalSelectedIds !== undefined // Use external state if provided, otherwise internal const selectedIds = isControlled ? externalSelectedIds : internalSelectedIds const selectAllPages = externalSelectAllPages ?? internalSelectAllPages // Store callbacks in refs to avoid stale closures const onSelectionChangeRef = useRef(onSelectionChange) const onSelectAllPagesRef = useRef(onSelectAllPages) useEffect(() => { onSelectionChangeRef.current = onSelectionChange onSelectAllPagesRef.current = onSelectAllPages }, [onSelectionChange, onSelectAllPages]) // Sync external state to internal when in controlled mode const prevExternalIdsRef = useRef | undefined>(undefined) useEffect(() => { if (externalSelectedIds !== undefined && externalSelectedIds !== prevExternalIdsRef.current) { setInternalSelectedIds(new Set(externalSelectedIds)) prevExternalIdsRef.current = externalSelectedIds } }, [externalSelectedIds]) useEffect(() => { if (externalSelectAllPages !== undefined) { setInternalSelectAllPages(externalSelectAllPages) } }, [externalSelectAllPages]) const toggleRow = useCallback((id: string) => { setInternalSelectedIds(prev => { const next = new Set(prev) if (next.has(id)) { next.delete(id) } else { next.add(id) } // Notify parent after state update onSelectionChangeRef.current?.(next) return next }) // If we're toggling individual rows, turn off select all pages setInternalSelectAllPages(prev => { if (prev) { onSelectAllPagesRef.current?.(false) return false } return prev }) }, []) const toggleAll = useCallback(() => { const currentPageIds = currentPageData.map(getRowId) setInternalSelectedIds(prev => { const allSelected = currentPageIds.every(id => prev.has(id)) let next: Set if (allSelected) { // Deselect all on current page next = new Set(prev) currentPageIds.forEach(id => next.delete(id)) } else { // Select all on current page next = new Set(prev) currentPageIds.forEach(id => next.add(id)) } // Notify parent onSelectionChangeRef.current?.(next) return next }) // Turn off select all pages if toggling individual page setInternalSelectAllPages(prev => { if (prev) { onSelectAllPagesRef.current?.(false) return false } return prev }) }, [currentPageData, getRowId]) const selectAllPagesToggle = useCallback(() => { setInternalSelectAllPages(prev => { const next = !prev // Notify parent onSelectAllPagesRef.current?.(next) if (next) { // When selecting all pages, clear individual selections setInternalSelectedIds(new Set()) onSelectionChangeRef.current?.(new Set()) } return next }) }, []) const clearSelection = useCallback(() => { // Update internal state setInternalSelectedIds(new Set()) setInternalSelectAllPages(false) // Notify parent onSelectionChangeRef.current?.(new Set()) onSelectAllPagesRef.current?.(false) }, []) const getSelectedCount = useCallback(() => { if (selectAllPages) { return totalCount } return selectedIds.size }, [selectAllPages, selectedIds, totalCount]) return { selectedIds, selectAllPages, toggleRow, toggleAll, selectAllPagesToggle, clearSelection, getSelectedCount, } }