react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
100 lines (96 loc) • 3.02 kB
JavaScript
;
import { useMemo } from 'react';
import { StyleSheet } from 'react-native';
import { interpolate, measure, useAnimatedReaction, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
import { useCommonValuesContext } from '../CommonValuesProvider';
import { usePortalOutletContext } from '../PortalOutletProvider';
import { usePortalContext } from '../PortalProvider';
import useItemZIndex from './useItemZIndex';
export default function useTeleportedItemStyles(key, isActive, activationAnimationProgress) {
const {
activeItemAbsolutePosition
} = usePortalContext();
const {
portalOutletRef
} = usePortalOutletContext();
const {
activeItemKey,
containerRef,
itemPositions
} = useCommonValuesContext();
const zIndex = useItemZIndex(key, activationAnimationProgress);
const dropStartTranslation = useSharedValue(null);
const absoluteX = useSharedValue(null);
const absoluteY = useSharedValue(null);
// Inactive item updater (for drop animation)
useAnimatedReaction(() => ({
activationProgress: activationAnimationProgress.value,
active: isActive.value,
position: itemPositions.value[key]
}), ({
activationProgress,
active,
position
}) => {
if (active || !position || !activationProgress || absoluteX.value === null || absoluteY.value === null) {
dropStartTranslation.value = null;
return;
}
const containerMeasurements = measure(containerRef);
if (!containerMeasurements) {
return;
}
// Drop animation
dropStartTranslation.value ??= {
x: absoluteX.value,
y: absoluteY.value
};
const animate = (from, to) => interpolate(activationProgress, [1, 0], [from, to]);
const {
x,
y
} = dropStartTranslation.value;
absoluteX.value = animate(x, containerMeasurements.pageX + position.x);
absoluteY.value = animate(y, containerMeasurements.pageY + position.y);
});
// Active item updater
useAnimatedReaction(() => ({
active: activeItemKey.value === key,
position: activeItemAbsolutePosition.value
}), ({
active,
position
}) => {
if (!active || !position) {
return;
}
absoluteX.value = position.x;
absoluteY.value = position.y;
});
const animatedStyle = useAnimatedStyle(() => {
const portalOutletMeasurements = measure(portalOutletRef);
if (absoluteX.value === null || absoluteY.value === null || !portalOutletMeasurements) {
return {
opacity: 0
};
}
const dX = portalOutletMeasurements.pageX;
const dY = portalOutletMeasurements.pageY;
return {
opacity: 1,
transform: [{
translateX: absoluteX.value - dX
}, {
translateY: absoluteY.value - dY
}],
zIndex: zIndex.value
};
});
return useMemo(() => [styles.container, animatedStyle], [animatedStyle]);
}
const styles = StyleSheet.create({
container: {
position: 'absolute'
}
});
//# sourceMappingURL=useTeleportedItemStyles.js.map