Skip to content

Commit

Permalink
add Masonic/Multi Column support
Browse files Browse the repository at this point in the history
  • Loading branch information
Andres Garcia committed Jun 15, 2021
1 parent d9bad02 commit a53deb4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 25 deletions.
70 changes: 48 additions & 22 deletions src/DraxList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ import {
import { defaultListItemLongPressDelay } from './params';

interface Shift {
targetValue: number;
animatedValue: Animated.Value;
targetValue: Position;
animatedValue: Animated.ValueXY;
}

interface ListItemPayload {
Expand Down Expand Up @@ -137,8 +137,8 @@ export const DraxList = <T extends unknown>(
itemMeasurements.push(undefined);
registrations.push(undefined);
shifts.push({
targetValue: 0,
animatedValue: new Animated.Value(0),
targetValue: { x: 0, y: 0 },
animatedValue: new Animated.ValueXY({ x: 0, y: 0 }),
});
}
}
Expand Down Expand Up @@ -171,14 +171,15 @@ export const DraxList = <T extends unknown>(
);

// Get shift transform for list item at index.
const getShiftTransform = useCallback(
const getShiftTransformStyle = useCallback(
(index: number) => {
const shift = shiftsRef.current[index]?.animatedValue ?? 0;
return horizontal
? [{ translateX: shift }]
: [{ translateY: shift }];
const shift = shiftsRef.current[index]?.animatedValue;
const transform = shift
? [{ translateX: shift.x }, { translateY: shift.y }]
: [];
return { transform };
},
[horizontal],
[],
);

// Set the currently dragged list item.
Expand Down Expand Up @@ -210,7 +211,7 @@ export const DraxList = <T extends unknown>(
} = itemStyles ?? {};
return (
<DraxView
style={[itemStyle, { transform: getShiftTransform(originalIndex) }]}
style={[itemStyle, getShiftTransformStyle(originalIndex)]}
draggingStyle={draggingStyle}
dragReleasedStyle={dragReleasedStyle}
{...otherStyleProps}
Expand Down Expand Up @@ -243,7 +244,7 @@ export const DraxList = <T extends unknown>(
originalIndexes,
itemStyles,
viewPropsExtractor,
getShiftTransform,
getShiftTransformStyle,
resetDraggedItem,
itemsDraggable,
renderItemContent,
Expand Down Expand Up @@ -368,8 +369,8 @@ export const DraxList = <T extends unknown>(
() => {
shiftsRef.current.forEach((shift) => {
// eslint-disable-next-line no-param-reassign
shift.targetValue = 0;
shift.animatedValue.setValue(0);
shift.targetValue = { x: 0, y: 0 };
shift.animatedValue.setValue({ x: 0, y: 0 });
});
},
[],
Expand All @@ -380,18 +381,36 @@ export const DraxList = <T extends unknown>(
(
{ index: fromIndex, originalIndex: fromOriginalIndex }: ListItemPayload,
{ index: toIndex }: ListItemPayload,
horizontalShift: boolean
) => {
const contentSize = contentSizeRef.current;
const { width = 50, height = 50 } = itemMeasurementsRef.current[fromOriginalIndex] ?? {};
const offset = horizontal ? width : height;
const posOffset = horizontalShift && contentSize && width < contentSize.x
? { x: width, y: 0 }
: { x: 0, y: height };
const negOffset = {
x: posOffset.x * -1,
y: posOffset.y * -1,
};
originalIndexes.forEach((originalIndex, index) => {
const { width: itemWidth = 0, height: itemHeight = 0 } = itemMeasurementsRef.current[originalIndex] ?? {};
const shift = shiftsRef.current[originalIndex];
let newTargetValue = 0;
if (!shift) {
return;
}
let newTargetValue = { x: 0, y: 0 };
if (index > fromIndex && index <= toIndex) {
newTargetValue = -offset;
newTargetValue = negOffset;
} else if (index < fromIndex && index >= toIndex) {
newTargetValue = offset;
newTargetValue = posOffset;
}
if (shift.targetValue !== newTargetValue) {
// Keep from shifting full width items horizontally
if (contentSize && itemWidth >= contentSize.x) {
if (!itemHeight) return;
newTargetValue.x = 0;
}
if (itemHeight && (shift.targetValue.x !== newTargetValue.x
|| shift.targetValue.y !== newTargetValue.y)) {
shift.targetValue = newTargetValue;
Animated.timing(shift.animatedValue, {
duration: 200,
Expand All @@ -401,7 +420,7 @@ export const DraxList = <T extends unknown>(
}
});
},
[originalIndexes, horizontal],
[originalIndexes],
);

// Calculate absolute position of list item for snapback.
Expand Down Expand Up @@ -573,7 +592,12 @@ export const DraxList = <T extends unknown>(
// Monitor drags to react with item shifts and auto-scrolling.
const onMonitorDragOver = useCallback(
(eventData: DraxMonitorEventData) => {
const { dragged, receiver, monitorOffsetRatio } = eventData;
const {
dragTranslation,
dragged,
receiver,
monitorOffsetRatio
} = eventData;
// First, check if we need to shift items.
if (reorderable && dragged.parentId === id) {
// One of our list items is being dragged.
Expand All @@ -597,8 +621,10 @@ export const DraxList = <T extends unknown>(
draggedToIndex.current = toIndex;
}

const horizontalShift = (Math.abs(dragTranslation.x) > Math.abs(dragTranslation.y))

// Update shift transforms for items in the list.
updateShifts(fromPayload, toPayload ?? fromPayload);
updateShifts(fromPayload, toPayload ?? fromPayload, horizontalShift);
}

// Next, see if we need to auto-scroll.
Expand Down
6 changes: 3 additions & 3 deletions src/DraxProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from './types';
import { getRelativePosition } from './math';

export const DraxProvider: FunctionComponent<DraxProviderProps> = ({ debug = false, children }) => {
export const DraxProvider: FunctionComponent<DraxProviderProps> = ({ debug = false, multicolumn = false, children }) => {
const {
getViewState,
getTrackingStatus,
Expand Down Expand Up @@ -387,10 +387,10 @@ export const DraxProvider: FunctionComponent<DraxProviderProps> = ({ debug = fal
* NOTE: if view is transformed, these will be wrong.
*/
const dragAbsolutePosition = {
x: absoluteX + grabX,
x: multicolumn ? absoluteX : absoluteX + grabX,
y: absoluteY + grabY,
};
const grabOffset = { x: grabX, y: grabY };
const grabOffset = { x: multicolumn ? 0 : grabX, y: grabY };
const grabOffsetRatio = {
x: grabX / width,
y: grabY / height,
Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
StyleProp,
ScrollViewProps,
ListRenderItemInfo,
NativeScrollEvent,
} from 'react-native';
import {
LongPressGestureHandlerStateChangeEvent,
Expand Down Expand Up @@ -583,6 +584,7 @@ export interface DraxContextValue {
/** Optional props that can be passed to a DraxProvider to modify its behavior */
export interface DraxProviderProps {
debug?: boolean;
multicolumn?: boolean;
}

/** Props that are passed to a DraxSubprovider, used internally for nesting views */
Expand Down Expand Up @@ -878,6 +880,9 @@ export interface DraxListProps<TItem> extends Omit<FlatListProps<TItem>, 'render
/** Callback handler for when a list item is moved within the list, reordering the list */
onItemReorder?: DraxListOnItemReorder<TItem>;

/** Callback handler for when list is scrolled */
onScrollProp?: (scrollEvent: NativeScrollEvent) => void;

/** Can the list be reordered by dragging items? Defaults to true if onItemReorder is set. */
reorderable?: boolean;

Expand Down

0 comments on commit a53deb4

Please sign in to comment.