import React, { useCallback, useEffect, useMemo, useState } from "react"; import Sortable from "react-native-sortables"; import { Text, View, ViewStyle } from "react-native"; import Animated, { useAnimatedRef } from "react-native-reanimated"; const DEFAULT_HEADERS: any[] = []; const DEFAULT_SORTABLE_DATA: any[] = []; const renderHeaderComponent = (component: any) => { if (!component) return null; if (React.isValidElement(component)) return component; if (typeof component === "function") { const HeaderComponent = component; return ; } return null; }; const SortableListHeader = ({ title, style, }: { title?: string; style?: ViewStyle; }) => { const displayTitle = typeof title === "string" ? title : String(title ?? ""); return ( {displayTitle ? {displayTitle} : null} ); }; export type SortableListProps = { scrollViewStyle?: ViewStyle; contentContainerStyle?: ViewStyle; itemStyle?: ViewStyle; headerStyle?: ViewStyle; columns?: number; rowGap?: number; columnGap?: number; spacing?: number; keyExtractor?: (item: any, index?: number) => string; renderItem: ({ item, index, renderHandle, }: { item: any; index: number; renderHandle: (children: React.ReactElement) => React.ReactElement; }) => React.ReactNode; sortableData?: any[]; headers?: { index: number; title?: string; component: any }[]; onDragEnd?: (params: { fromIndex?: number; toIndex?: number; from?: number; to?: number; data: any[]; }) => void; }; const defaultKeyExtractor = (item, index) => `sortable-item-${item?.id ?? item?.title ?? index}`; export const SortableList = ({ scrollViewStyle, contentContainerStyle, itemStyle, headerStyle, columns = 1, rowGap = 0, columnGap = 0, keyExtractor = defaultKeyExtractor, renderItem, sortableData = DEFAULT_SORTABLE_DATA, headers = DEFAULT_HEADERS, onDragEnd, }: SortableListProps) => { const scrollableRef = useAnimatedRef(); const [localData, setLocalData] = useState(sortableData); useEffect(() => { setLocalData((localData) => localData !== sortableData ? sortableData : localData ); }, [sortableData]); const handleDragEnd = useCallback( (params: any) => { if (params?.data) { setLocalData(params.data); } if (onDragEnd) { onDragEnd(params); } }, [onDragEnd] ); const _renderItem = useCallback( ({ item, index }) => ( {renderItem({ item, index, renderHandle: (children) => ( {children} ), })} ), [itemStyle, keyExtractor, renderItem] ); const renderHeader = useMemo( () => (headers || []).map((header, idx) => ( {header.title ? ( ) : ( renderHeaderComponent(header.component) )} )), [headers, headerStyle] ); return ( {renderHeader} ); };