feat: refactor sidebar to nested draggable lists with long-press gesture arbitration

This commit is contained in:
Mohamed Boudra
2026-03-04 10:27:01 +07:00
parent bf1cded8a1
commit 3c066f5dd9
14 changed files with 830 additions and 327 deletions
@@ -1,6 +1,7 @@
import { RefreshControl } from "react-native";
import { useCallback, useState } from "react";
import DraggableFlatList, {
NestableDraggableFlatList,
type RenderItemParams,
} from "react-native-draggable-flatlist";
import { useUnistyles } from "react-native-unistyles";
@@ -32,6 +33,7 @@ export function DraggableList<T>({
simultaneousGestureRef,
waitFor,
onDragBegin: onDragBeginProp,
nestable = false,
}: DraggableListProps<T>) {
const { theme } = useUnistyles();
const [isDragging, setIsDragging] = useState(false);
@@ -75,9 +77,13 @@ export function DraggableList<T>({
const showRefreshControl = Boolean(onRefresh) && (!isDragging || Boolean(refreshing));
const resolvedContainerStyle =
containerStyle ?? (scrollEnabled ? { flex: 1 } : undefined);
const ListComponent: typeof DraggableFlatList = (nestable
? (NestableDraggableFlatList as any)
: DraggableFlatList) as any;
const shouldShowRefreshControl = showRefreshControl && !nestable;
return (
<DraggableFlatList
<ListComponent
testID={testID}
data={data}
keyExtractor={keyExtractor}
@@ -99,7 +105,7 @@ export function DraggableList<T>({
// @ts-expect-error - waitFor is supported by RNGH FlatList but not typed in DraggableFlatList
waitFor={waitFor}
refreshControl={
showRefreshControl ? (
shouldShowRefreshControl ? (
<RefreshControl
refreshing={refreshing ?? false}
onRefresh={onRefresh}
@@ -52,4 +52,9 @@ export interface DraggableListProps<T> {
waitFor?: MutableRefObject<GestureType | undefined> | MutableRefObject<GestureType | undefined>[];
/** Called when a drag gesture begins (before items are reordered) */
onDragBegin?: () => void;
/**
* Native-only: use the nestable draggable-flatlist variant for nested drag
* lists coordinated by a shared NestableScrollContainer.
*/
nestable?: boolean;
}
@@ -136,6 +136,7 @@ export function DraggableList<T>({
useDragHandle = false,
// simultaneousGestureRef is native-only, ignored on web
onDragBegin,
nestable: _nestable = false,
}: DraggableListProps<T>) {
const [activeId, setActiveId] = useState<string | null>(null);
const [items, setItems] = useState(data);
File diff suppressed because it is too large Load Diff