react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
78 lines (75 loc) • 3.1 kB
JavaScript
;
import { measure, useAnimatedReaction } from 'react-native-reanimated';
import { useDebugContext } from '../../../debug';
import { useAnimatableValue, useMutableValue } from '../../../integrations/reanimated';
import { useCommonValuesContext } from '../CommonValuesProvider';
import { handleMeasurementsHorizontal, handleMeasurementsVertical } from './utils';
export default function useTargetScrollOffset(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
scrollableRef, enabled, horizontal, autoScrollActivationOffset, maxScrollToOverflowOffset, dragStartScrollOffset) {
const {
containerRef,
touchPosition
} = useCommonValuesContext();
const debugContext = useDebugContext();
const debugRects = debugContext?.useDebugRects(['start', 'end']);
const debugLine = debugContext?.useDebugLine();
const targetScrollOffset = useMutableValue(null);
const startContainerPagePosition = useMutableValue(null);
const offsetThreshold = useAnimatableValue(autoScrollActivationOffset, v => {
'worklet';
return typeof v === 'number' ? [v, v] : v;
});
const maxOverScrollOffset = useAnimatableValue(maxScrollToOverflowOffset, v => {
'worklet';
return typeof v === 'number' ? [v, v] : v;
});
const handleMeasurements = horizontal ? handleMeasurementsHorizontal : handleMeasurementsVertical;
useAnimatedReaction(() => {
if (!enabled.value || !touchPosition.value) {
startContainerPagePosition.value = null;
targetScrollOffset.value = null;
return null;
}
return {
threshold: offsetThreshold.value,
touchOffset: touchPosition.value?.[horizontal ? 'x' : 'y']
};
}, props => {
const hideDebugViews = () => {
debugRects?.start?.hide();
debugRects?.end?.hide();
debugLine?.hide();
};
if (!props) {
hideDebugViews();
return;
}
const scrollableMeasurements = measure(scrollableRef);
const containerMeasurements = measure(containerRef);
if (!scrollableMeasurements || !containerMeasurements || dragStartScrollOffset.value === null) {
hideDebugViews();
return;
}
const {
containerPosition,
endDistance,
endOverflow,
startDistance,
startOverflow
} = handleMeasurements(props.threshold, maxOverScrollOffset.value, props.touchOffset, scrollableMeasurements, containerMeasurements, debugRects, debugLine);
startContainerPagePosition.value ??= containerPosition;
const offsetDelta = startContainerPagePosition.value - containerPosition;
const currentOffset = dragStartScrollOffset.value + offsetDelta;
// Scroll up (vertical) / left (horizontal)
if (startDistance > 0 && startOverflow > 0) {
targetScrollOffset.value = currentOffset - Math.min(startOverflow, startDistance);
}
// Scroll down (vertical) / right (horizontal)
else if (endDistance > 0 && endOverflow > 0) {
targetScrollOffset.value = currentOffset + Math.min(endOverflow, endDistance);
}
});
return targetScrollOffset;
}
//# sourceMappingURL=useTargetScrollOffset.js.map