Skip to content

Commit e6116ad

Browse files
committed
chore(sort): revert to measureLayout, only sort on children ids
1 parent 564a48d commit e6116ad

File tree

12 files changed

+153
-155
lines changed

12 files changed

+153
-155
lines changed

example/src/pages/DraggableStackExample.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const data = items.map((letter, index) => ({
1616
value: letter,
1717
id: `${index}-${letter}`,
1818
})) satisfies ObjectWithId[];
19+
let id = items.length;
1920

2021
export const DraggableStackExample: FunctionComponent = () => {
2122
const [items, setItems] = useState(data);
@@ -62,9 +63,10 @@ export const DraggableStackExample: FunctionComponent = () => {
6263
onPress={() => {
6364
setItems(prevItems => {
6465
const randomIndex = 2; //Math.floor(Math.random() * prevItems.length);
66+
id++;
6567
prevItems.splice(randomIndex, 0, {
6668
value: '🤪',
67-
id: `${prevItems.length}-🤪`,
69+
id: `${id}-🤪`,
6870
});
6971
return prevItems.slice();
7072
});
@@ -109,13 +111,22 @@ export const DraggableStackExample: FunctionComponent = () => {
109111
const styles = StyleSheet.create({
110112
container: {
111113
flexGrow: 1,
112-
alignItems: 'center',
113-
justifyContent: 'center',
114+
// alignItems: 'stretch',
115+
// justifyContent: 'st',
116+
flexDirection: 'column',
117+
},
118+
view: {
119+
flexDirection: 'row',
120+
justifyContent: 'space-around',
121+
alignItems: 'flex-end',
122+
backgroundColor: 'rgba(255,0,255,0.1)',
123+
flexGrow: 1,
114124
},
115125
stack: {
116126
backgroundColor: 'rgba(0,0,0,0.1)',
117127
alignItems: 'center',
118-
justifyContent: 'flex-start',
128+
justifyContent: 'center',
129+
// flexGrow: 1,
119130
padding: 32,
120131
borderRadius: 32,
121132
},

src/DndContext.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ export type DraggableState = "resting" | "pending" | "dragging" | "dropping" | "
1515
export type DraggableStates = Record<UniqueIdentifier, SharedValue<DraggableState>>;
1616

1717
export type DndContextValue = {
18-
containerRef: RefObject<View>;
19-
draggableIds: SharedValue<UniqueIdentifier[]>;
20-
droppableIds: SharedValue<UniqueIdentifier[]>;
18+
containerRef: RefObject<View>; // AnimatedRef<Component>;
2119
draggableLayouts: SharedValue<Layouts>;
2220
droppableLayouts: SharedValue<Layouts>;
2321
draggableOptions: SharedValue<DraggableOptions>;

src/DndProvider.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr
9494
ref,
9595
) {
9696
const containerRef = useRef<View | null>(null);
97-
const draggableIds = useSharedValue<UniqueIdentifier[]>([]);
98-
const droppableIds = useSharedValue<UniqueIdentifier[]>([]);
9997
const draggableLayouts = useSharedValue<Layouts>({});
10098
const droppableLayouts = useSharedValue<Layouts>({});
10199
const draggableOptions = useSharedValue<DraggableOptions>({});
@@ -113,8 +111,6 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr
113111

114112
const contextValue = useRef<DndContextValue>({
115113
containerRef,
116-
draggableIds,
117-
droppableIds,
118114
draggableLayouts,
119115
droppableLayouts,
120116
draggableOptions,
@@ -216,7 +212,7 @@ export const DndProvider = forwardRef<DndProviderHandle, PropsWithChildren<DndPr
216212

217213
const panGesture = Gesture.Pan()
218214
.onBegin((event) => {
219-
const { state, absoluteX: x, absoluteY: y } = event;
215+
const { state, x, y } = event;
220216
debug && console.log("begin", { state, x, y });
221217
// Gesture is globally disabled
222218
if (disabled) {

src/components/Draggable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const Draggable: FunctionComponent<PropsWithChildren<DraggableProps>> = (
4343
animatedStyleWorklet,
4444
...otherProps
4545
}) => {
46-
const { animatedRef, setNodeLayout, offset, state } = useDraggable({
46+
const { props, offset, state } = useDraggable({
4747
id,
4848
data,
4949
disabled,
@@ -83,7 +83,7 @@ export const Draggable: FunctionComponent<PropsWithChildren<DraggableProps>> = (
8383
}, [id, state, activeOpacity]);
8484

8585
return (
86-
<Animated.View ref={animatedRef} onLayout={setNodeLayout} style={[style, animatedStyle]} {...otherProps}>
86+
<Animated.View {...props} style={[style, animatedStyle]} {...otherProps}>
8787
{children}
8888
</Animated.View>
8989
);

src/components/Droppable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const Droppable: FunctionComponent<PropsWithChildren<DroppableProps>> = (
3838
animatedStyleWorklet,
3939
...otherProps
4040
}) => {
41-
const { animatedRef, setNodeLayout, activeId } = useDroppable({
41+
const { props, activeId } = useDroppable({
4242
id,
4343
disabled,
4444
data,
@@ -56,7 +56,7 @@ export const Droppable: FunctionComponent<PropsWithChildren<DroppableProps>> = (
5656
}, [id, activeOpacity]);
5757

5858
return (
59-
<Animated.View ref={animatedRef} onLayout={setNodeLayout} style={[style, animatedStyle]} {...otherProps}>
59+
<Animated.View {...props} style={[style, animatedStyle]} {...otherProps}>
6060
{children}
6161
</Animated.View>
6262
);

src/features/sort/components/DraggableStack.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const DraggableStack = forwardRef<DraggableStackHandle, PropsWithChildren
3232
},
3333
ref,
3434
) {
35-
const initialOrder = useChildrenIds(children);
35+
const childrenIds = useChildrenIds(children);
3636

3737
const style = useMemo(
3838
() =>
@@ -51,7 +51,7 @@ export const DraggableStack = forwardRef<DraggableStackHandle, PropsWithChildren
5151
const { refreshOffsets } = useDraggableStack({
5252
gap: style.gap,
5353
horizontal,
54-
initialOrder,
54+
childrenIds,
5555
onOrderChange,
5656
onOrderUpdate,
5757
shouldSwapWorklet,
@@ -66,7 +66,7 @@ export const DraggableStack = forwardRef<DraggableStackHandle, PropsWithChildren
6666
useEffect(() => {
6767
// Refresh offsets when children change
6868
runOnUI(refreshOffsets)();
69-
}, [initialOrder, refreshOffsets]);
69+
}, [childrenIds, refreshOffsets]);
7070

7171
return <Animated.View style={style}>{children}</Animated.View>;
7272
},

src/features/sort/hooks/useDraggableGrid.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import { useDraggableSort, type UseDraggableSortOptions } from "./useDraggableSo
66

77
export type UseDraggableGridOptions = Pick<
88
UseDraggableSortOptions,
9-
"initialOrder" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
9+
"childrenIds" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
1010
> & {
1111
gap?: number;
1212
size: number;
1313
direction: FlexStyle["flexDirection"];
1414
};
1515

1616
export const useDraggableGrid = ({
17-
initialOrder,
17+
childrenIds,
1818
onOrderChange,
1919
onOrderUpdate,
2020
gap = 0,
@@ -27,7 +27,7 @@ export const useDraggableGrid = ({
2727

2828
const { draggablePlaceholderIndex, draggableSortOrder } = useDraggableSort({
2929
horizontal,
30-
initialOrder,
30+
childrenIds,
3131
onOrderChange,
3232
onOrderUpdate,
3333
shouldSwapWorklet,

src/features/sort/hooks/useDraggableSort.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect } from "react";
12
import { LayoutRectangle } from "react-native";
23
import { runOnJS, useAnimatedReaction, useSharedValue } from "react-native-reanimated";
34
import { useDndContext } from "../../../DndContext";
@@ -18,7 +19,7 @@ export type ShouldSwapWorklet = (
1819
) => boolean;
1920

2021
export type UseDraggableSortOptions = {
21-
initialOrder: UniqueIdentifier[];
22+
childrenIds: UniqueIdentifier[];
2223
horizontal?: boolean;
2324
onOrderChange?: (order: UniqueIdentifier[]) => void;
2425
onOrderUpdate?: (nextOrder: UniqueIdentifier[], prevOrder: UniqueIdentifier[]) => void;
@@ -27,18 +28,17 @@ export type UseDraggableSortOptions = {
2728

2829
export const useDraggableSort = ({
2930
horizontal = false,
30-
initialOrder,
31+
childrenIds,
3132
onOrderChange,
3233
onOrderUpdate,
3334
shouldSwapWorklet = doesOverlapOnAxis,
3435
}: UseDraggableSortOptions) => {
35-
const { draggableIds, draggableActiveId, draggableActiveLayout, draggableOffsets, draggableLayouts } =
36-
useDndContext();
36+
const { draggableActiveId, draggableActiveLayout, draggableOffsets, draggableLayouts } = useDndContext();
3737
const direction = horizontal ? "horizontal" : "vertical";
3838

3939
const draggablePlaceholderIndex = useSharedValue(-1);
40-
const draggableLastOrder = useSharedValue<UniqueIdentifier[]>(initialOrder);
41-
const draggableSortOrder = useSharedValue<UniqueIdentifier[]>(initialOrder);
40+
const draggableLastOrder = useSharedValue<UniqueIdentifier[]>(childrenIds);
41+
const draggableSortOrder = useSharedValue<UniqueIdentifier[]>(childrenIds);
4242

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

7878
// Track added/removed draggable items and update the sort order
7979
useAnimatedReaction(
80-
() => draggableIds.value,
80+
() => childrenIds,
8181
(next, prev) => {
8282
if (prev === null || prev.length === 0) {
8383
return;
@@ -131,11 +131,15 @@ export const useDraggableSort = ({
131131
draggablePlaceholderIndex.value = -1;
132132
return;
133133
}
134+
// Only track our own children
135+
if (!childrenIds.includes(nextActiveId)) {
136+
return;
137+
}
134138
// const axis = direction === "row" ? "x" : "y";
135139
// const delta = prevActiveLayout !== null ? nextActiveLayout[axis] - prevActiveLayout[axis] : 0;
136140
draggablePlaceholderIndex.value = findPlaceholderIndex(nextActiveLayout);
137141
},
138-
[],
142+
[childrenIds],
139143
);
140144

141145
// Track placeholder index changes and update the sort order

src/features/sort/hooks/useDraggableStack.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,27 @@ import { useDraggableSort, type UseDraggableSortOptions } from "./useDraggableSo
77

88
export type UseDraggableStackOptions = Pick<
99
UseDraggableSortOptions,
10-
"initialOrder" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
10+
"childrenIds" | "onOrderChange" | "onOrderUpdate" | "shouldSwapWorklet"
1111
> & {
1212
gap?: number;
1313
horizontal?: boolean;
1414
};
1515
export const useDraggableStack = ({
16-
initialOrder,
16+
childrenIds,
1717
onOrderChange,
1818
onOrderUpdate,
1919
gap = 0,
2020
horizontal = false,
2121
shouldSwapWorklet = doesOverlapOnAxis,
2222
}: UseDraggableStackOptions) => {
23-
const {
24-
draggableIds,
25-
draggableStates,
26-
draggableActiveId,
27-
draggableOffsets,
28-
draggableRestingOffsets,
29-
draggableLayouts,
30-
} = useDndContext();
23+
const { draggableStates, draggableActiveId, draggableOffsets, draggableRestingOffsets, draggableLayouts } =
24+
useDndContext();
3125
const axis = horizontal ? "x" : "y";
3226
const size = horizontal ? "width" : "height";
3327

3428
const { draggablePlaceholderIndex, draggableSortOrder } = useDraggableSort({
3529
horizontal,
36-
initialOrder,
30+
childrenIds,
3731
onOrderChange,
3832
onOrderUpdate,
3933
shouldSwapWorklet,
@@ -47,7 +41,7 @@ export const useDraggableStack = ({
4741
const { value: sortOrder } = draggableSortOrder;
4842

4943
const nextIndex = sortOrder.findIndex((itemId) => itemId === id);
50-
const prevIndex = initialOrder.findIndex((itemId) => itemId === id);
44+
const prevIndex = childrenIds.findIndex((itemId) => itemId === id);
5145

5246
let offset = 0;
5347
// Accumulate the directional offset for the current item accross its siblings in the stack
@@ -62,7 +56,7 @@ export const useDraggableStack = ({
6256
// Can happen if some items are being removed from the stack
6357
continue;
6458
}
65-
const prevSiblingIndex = initialOrder.findIndex((itemId) => itemId === siblingId);
59+
const prevSiblingIndex = childrenIds.findIndex((itemId) => itemId === siblingId);
6660
// Accummulate the directional offset for the active item
6761
if (nextSiblingIndex < nextIndex && prevSiblingIndex > prevIndex) {
6862
// console.log(
@@ -78,7 +72,7 @@ export const useDraggableStack = ({
7872
}
7973
return offset;
8074
},
81-
[draggableLayouts, draggableSortOrder, gap, horizontal, initialOrder],
75+
[draggableLayouts, draggableSortOrder, gap, horizontal, childrenIds],
8276
);
8377

8478
const refreshOffsets = useCallback(() => {
@@ -121,7 +115,7 @@ export const useDraggableStack = ({
121115

122116
// Track items being added or removed from the stack
123117
useAnimatedReaction(
124-
() => draggableIds.value,
118+
() => childrenIds,
125119
(next, prev) => {
126120
// Ignore initial reaction
127121
if (prev === null) {
@@ -133,7 +127,7 @@ export const useDraggableStack = ({
133127
// Refresh all offsets
134128
refreshOffsets();
135129
},
136-
[initialOrder],
130+
[childrenIds],
137131
);
138132

139133
// Track sort order changes and update the offsets

0 commit comments

Comments
 (0)