import { useCallback, useRef, useMemo } from "react" import type { MediaAsset } from "@/api/template-editor" interface UseAssetSelectionOptions { filteredAssets: MediaAsset[] selectedIds: string[] onSelectionChange?: (ids: string[]) => void } interface UseAssetSelectionReturn { selectedSet: Set toggleSelect: (asset: MediaAsset, idx: number, shiftKey: boolean) => void clearSelection: () => void } /** * 素材选择 Hook —— 单选/多选/Shift 连选 */ const useAssetSelection = ({ filteredAssets, selectedIds, onSelectionChange, }: UseAssetSelectionOptions): UseAssetSelectionReturn => { const lastClickedIdx = useRef(null) const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds]) const toggleSelect = useCallback( (asset: MediaAsset, idx: number, shiftKey: boolean) => { if (!onSelectionChange) return if (shiftKey && lastClickedIdx.current !== null) { // Shift 连选 const start = Math.min(lastClickedIdx.current, idx) const end = Math.max(lastClickedIdx.current, idx) const rangeIds = filteredAssets.slice(start, end + 1).map((a) => a.id) const newSet = new Set(selectedIds) rangeIds.forEach((id) => newSet.add(id)) onSelectionChange(Array.from(newSet)) } else { const newSet = new Set(selectedIds) if (newSet.has(asset.id)) { newSet.delete(asset.id) } else { newSet.add(asset.id) } onSelectionChange(Array.from(newSet)) } lastClickedIdx.current = idx }, [onSelectionChange, selectedIds, filteredAssets], ) const clearSelection = useCallback(() => { onSelectionChange?.([]) }, [onSelectionChange]) return { selectedSet, toggleSelect, clearSelection, } } export default useAssetSelection