Skip to content

Commit

Permalink
chore(sort): revert to measureLayout, only sort on children ids
Browse files Browse the repository at this point in the history
  • Loading branch information
mgcrea committed Dec 12, 2024
1 parent 564a48d commit e6116ad
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 155 deletions.
19 changes: 15 additions & 4 deletions example/src/pages/DraggableStackExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const data = items.map((letter, index) => ({
value: letter,
id: `${index}-${letter}`,
})) satisfies ObjectWithId[];
let id = items.length;

export const DraggableStackExample: FunctionComponent = () => {
const [items, setItems] = useState(data);
Expand Down Expand Up @@ -62,9 +63,10 @@ export const DraggableStackExample: FunctionComponent = () => {
onPress={() => {
setItems(prevItems => {
const randomIndex = 2; //Math.floor(Math.random() * prevItems.length);
id++;
prevItems.splice(randomIndex, 0, {
value: '🤪',
id: `${prevItems.length}-🤪`,
id: `${id}-🤪`,
});
return prevItems.slice();
});
Expand Down Expand Up @@ -109,13 +111,22 @@ export const DraggableStackExample: FunctionComponent = () => {
const styles = StyleSheet.create({
container: {
flexGrow: 1,
alignItems: 'center',
justifyContent: 'center',
// alignItems: 'stretch',
// justifyContent: 'st',
flexDirection: 'column',
},
view: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'flex-end',
backgroundColor: 'rgba(255,0,255,0.1)',
flexGrow: 1,
},
stack: {
backgroundColor: 'rgba(0,0,0,0.1)',
alignItems: 'center',
justifyContent: 'flex-start',
justifyContent: 'center',
// flexGrow: 1,
padding: 32,
borderRadius: 32,
},
Expand Down
4 changes: 1 addition & 3 deletions src/DndContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ export type DraggableState = "resting" | "pending" | "dragging" | "dropping" | "
export type DraggableStates = Record<UniqueIdentifier, SharedValue<DraggableState>>;

export type DndContextValue = {
containerRef: RefObject<View>;
draggableIds: SharedValue<UniqueIdentifier[]>;
droppableIds: SharedValue<UniqueIdentifier[]>;
containerRef: RefObject<View>; // AnimatedRef<Component>;
draggableLayouts: SharedValue<Layouts>;
droppableLayouts: SharedValue<Layouts>;
draggableOptions: SharedValue<DraggableOptions>;
Expand Down
6 changes: 1 addition & 5 deletions src/DndProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr
ref,
) {
const containerRef = useRef<View | null>(null);
const draggableIds = useSharedValue<UniqueIdentifier[]>([]);
const droppableIds = useSharedValue<UniqueIdentifier[]>([]);
const draggableLayouts = useSharedValue<Layouts>({});
const droppableLayouts = useSharedValue<Layouts>({});
const draggableOptions = useSharedValue<DraggableOptions>({});
Expand All @@ -113,8 +111,6 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr

const contextValue = useRef<DndContextValue>({
containerRef,
draggableIds,
droppableIds,
draggableLayouts,
droppableLayouts,
draggableOptions,
Expand Down Expand Up @@ -216,7 +212,7 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr

const panGesture = Gesture.Pan()
.onBegin((event) => {
const { state, absoluteX: x, absoluteY: y } = event;
const { state, x, y } = event;
debug && console.log("begin", { state, x, y });
// Gesture is globally disabled
if (disabled) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const Draggable: FunctionComponent<PropsWithChildren<DraggableProps>> = (
animatedStyleWorklet,
...otherProps
}) => {
const { animatedRef, setNodeLayout, offset, state } = useDraggable({
const { props, offset, state } = useDraggable({
id,
data,
disabled,
Expand Down Expand Up @@ -83,7 +83,7 @@ export const Draggable: FunctionComponent<PropsWithChildren<DraggableProps>> = (
}, [id, state, activeOpacity]);

return (
<Animated.View ref={animatedRef} onLayout={setNodeLayout} style={[style, animatedStyle]} {...otherProps}>
<Animated.View {...props} style={[style, animatedStyle]} {...otherProps}>
{children}
</Animated.View>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/Droppable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const Droppable: FunctionComponent<PropsWithChildren<DroppableProps>> = (
animatedStyleWorklet,
...otherProps
}) => {
const { animatedRef, setNodeLayout, activeId } = useDroppable({
const { props, activeId } = useDroppable({
id,
disabled,
data,
Expand All @@ -56,7 +56,7 @@ export const Droppable: FunctionComponent<PropsWithChildren<DroppableProps>> = (
}, [id, activeOpacity]);

return (
<Animated.View ref={animatedRef} onLayout={setNodeLayout} style={[style, animatedStyle]} {...otherProps}>
<Animated.View {...props} style={[style, animatedStyle]} {...otherProps}>
{children}
</Animated.View>
);
Expand Down
6 changes: 3 additions & 3 deletions src/features/sort/components/DraggableStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const DraggableStack = forwardRef<DraggableStackHandle, PropsWithChildren
},
ref,
) {
const initialOrder = useChildrenIds(children);
const childrenIds = useChildrenIds(children);

const style = useMemo(
() =>
Expand All @@ -51,7 +51,7 @@ export const DraggableStack = forwardRef<DraggableStackHandle, PropsWithChildren
const { refreshOffsets } = useDraggableStack({
gap: style.gap,
horizontal,
initialOrder,
childrenIds,
onOrderChange,
onOrderUpdate,
shouldSwapWorklet,
Expand All @@ -66,7 +66,7 @@ export const DraggableStack = forwardRef<DraggableStackHandle, PropsWithChildren
useEffect(() => {
// Refresh offsets when children change
runOnUI(refreshOffsets)();
}, [initialOrder, refreshOffsets]);
}, [childrenIds, refreshOffsets]);

return <Animated.View style={style}>{children}</Animated.View>;
},
Expand Down
6 changes: 3 additions & 3 deletions src/features/sort/hooks/useDraggableGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { useDraggableSort, type UseDraggableSortOptions } from "./useDraggableSo

export type UseDraggableGridOptions = Pick<
UseDraggableSortOptions,
"initialOrder" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
"childrenIds" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
> & {
gap?: number;
size: number;
direction: FlexStyle["flexDirection"];
};

export const useDraggableGrid = ({
initialOrder,
childrenIds,
onOrderChange,
onOrderUpdate,
gap = 0,
Expand All @@ -27,7 +27,7 @@ export const useDraggableGrid = ({

const { draggablePlaceholderIndex, draggableSortOrder } = useDraggableSort({
horizontal,
initialOrder,
childrenIds,
onOrderChange,
onOrderUpdate,
shouldSwapWorklet,
Expand Down
20 changes: 12 additions & 8 deletions src/features/sort/hooks/useDraggableSort.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect } from "react";

Check warning on line 1 in src/features/sort/hooks/useDraggableSort.ts

View workflow job for this annotation

GitHub Actions / Test on node@vlts/-1

'useEffect' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 1 in src/features/sort/hooks/useDraggableSort.ts

View workflow job for this annotation

GitHub Actions / Test on node@vlts/*

'useEffect' is defined but never used. Allowed unused vars must match /^_/u
import { LayoutRectangle } from "react-native";
import { runOnJS, useAnimatedReaction, useSharedValue } from "react-native-reanimated";
import { useDndContext } from "../../../DndContext";
Expand All @@ -18,7 +19,7 @@ export type ShouldSwapWorklet = (
) => boolean;

export type UseDraggableSortOptions = {
initialOrder: UniqueIdentifier[];
childrenIds: UniqueIdentifier[];
horizontal?: boolean;
onOrderChange?: (order: UniqueIdentifier[]) => void;
onOrderUpdate?: (nextOrder: UniqueIdentifier[], prevOrder: UniqueIdentifier[]) => void;
Expand All @@ -27,18 +28,17 @@ export type UseDraggableSortOptions = {

export const useDraggableSort = ({
horizontal = false,
initialOrder,
childrenIds,
onOrderChange,
onOrderUpdate,
shouldSwapWorklet = doesOverlapOnAxis,
}: UseDraggableSortOptions) => {
const { draggableIds, draggableActiveId, draggableActiveLayout, draggableOffsets, draggableLayouts } =
useDndContext();
const { draggableActiveId, draggableActiveLayout, draggableOffsets, draggableLayouts } = useDndContext();
const direction = horizontal ? "horizontal" : "vertical";

const draggablePlaceholderIndex = useSharedValue(-1);
const draggableLastOrder = useSharedValue<UniqueIdentifier[]>(initialOrder);
const draggableSortOrder = useSharedValue<UniqueIdentifier[]>(initialOrder);
const draggableLastOrder = useSharedValue<UniqueIdentifier[]>(childrenIds);
const draggableSortOrder = useSharedValue<UniqueIdentifier[]>(childrenIds);

// Core placeholder index logic
const findPlaceholderIndex = (activeLayout: LayoutRectangle): number => {
Expand Down Expand Up @@ -77,7 +77,7 @@ export const useDraggableSort = ({

// Track added/removed draggable items and update the sort order
useAnimatedReaction(
() => draggableIds.value,
() => childrenIds,
(next, prev) => {
if (prev === null || prev.length === 0) {
return;
Expand Down Expand Up @@ -131,11 +131,15 @@ export const useDraggableSort = ({
draggablePlaceholderIndex.value = -1;
return;
}
// Only track our own children
if (!childrenIds.includes(nextActiveId)) {
return;
}
// const axis = direction === "row" ? "x" : "y";
// const delta = prevActiveLayout !== null ? nextActiveLayout[axis] - prevActiveLayout[axis] : 0;
draggablePlaceholderIndex.value = findPlaceholderIndex(nextActiveLayout);
},
[],
[childrenIds],
);

// Track placeholder index changes and update the sort order
Expand Down
26 changes: 10 additions & 16 deletions src/features/sort/hooks/useDraggableStack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,27 @@ import { useDraggableSort, type UseDraggableSortOptions } from "./useDraggableSo

export type UseDraggableStackOptions = Pick<
UseDraggableSortOptions,
"initialOrder" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
"childrenIds" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
> & {
gap?: number;
horizontal?: boolean;
};
export const useDraggableStack = ({
initialOrder,
childrenIds,
onOrderChange,
onOrderUpdate,
gap = 0,
horizontal = false,
shouldSwapWorklet = doesOverlapOnAxis,
}: UseDraggableStackOptions) => {
const {
draggableIds,
draggableStates,
draggableActiveId,
draggableOffsets,
draggableRestingOffsets,
draggableLayouts,
} = useDndContext();
const { draggableStates, draggableActiveId, draggableOffsets, draggableRestingOffsets, draggableLayouts } =
useDndContext();
const axis = horizontal ? "x" : "y";
const size = horizontal ? "width" : "height";

const { draggablePlaceholderIndex, draggableSortOrder } = useDraggableSort({
horizontal,
initialOrder,
childrenIds,
onOrderChange,
onOrderUpdate,
shouldSwapWorklet,
Expand All @@ -47,7 +41,7 @@ export const useDraggableStack = ({
const { value: sortOrder } = draggableSortOrder;

const nextIndex = sortOrder.findIndex((itemId) => itemId === id);
const prevIndex = initialOrder.findIndex((itemId) => itemId === id);
const prevIndex = childrenIds.findIndex((itemId) => itemId === id);

let offset = 0;
// Accumulate the directional offset for the current item accross its siblings in the stack
Expand All @@ -62,7 +56,7 @@ export const useDraggableStack = ({
// Can happen if some items are being removed from the stack
continue;
}
const prevSiblingIndex = initialOrder.findIndex((itemId) => itemId === siblingId);
const prevSiblingIndex = childrenIds.findIndex((itemId) => itemId === siblingId);
// Accummulate the directional offset for the active item
if (nextSiblingIndex < nextIndex && prevSiblingIndex > prevIndex) {
// console.log(
Expand All @@ -78,7 +72,7 @@ export const useDraggableStack = ({
}
return offset;
},
[draggableLayouts, draggableSortOrder, gap, horizontal, initialOrder],
[draggableLayouts, draggableSortOrder, gap, horizontal, childrenIds],
);

const refreshOffsets = useCallback(() => {
Expand Down Expand Up @@ -121,7 +115,7 @@ export const useDraggableStack = ({

// Track items being added or removed from the stack
useAnimatedReaction(
() => draggableIds.value,
() => childrenIds,
(next, prev) => {
// Ignore initial reaction
if (prev === null) {
Expand All @@ -133,7 +127,7 @@ export const useDraggableStack = ({
// Refresh all offsets
refreshOffsets();
},
[initialOrder],
[childrenIds],
);

// Track sort order changes and update the offsets
Expand Down
Loading

0 comments on commit e6116ad

Please sign in to comment.