stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
118 lines (104 loc) • 3.33 kB
text/typescript
import {
type EntryAnimationsValues,
type ExitAnimationsValues,
type LayoutAnimation,
withTiming,
} from 'react-native-reanimated';
export type BoundedZoomDirection = 'bottom' | 'left' | 'right' | 'top';
type CreateBoundedZoomTransitionParams = {
duration: number;
};
const getInitialOffset = (direction: BoundedZoomDirection, values: EntryAnimationsValues) => {
'worklet';
switch (direction) {
case 'bottom':
return { translateX: 0, translateY: values.targetHeight / 2 };
case 'left':
return { translateX: -values.targetWidth / 2, translateY: 0 };
case 'right':
return { translateX: values.targetWidth / 2, translateY: 0 };
case 'top':
return { translateX: 0, translateY: -values.targetHeight / 2 };
default:
return { translateX: 0, translateY: 0 };
}
};
const getTargetOffset = (direction: BoundedZoomDirection, values: ExitAnimationsValues) => {
'worklet';
switch (direction) {
case 'bottom':
return { translateX: 0, translateY: values.currentHeight / 2 };
case 'left':
return { translateX: -values.currentWidth / 2, translateY: 0 };
case 'right':
return { translateX: values.currentWidth / 2, translateY: 0 };
case 'top':
return { translateX: 0, translateY: -values.currentHeight / 2 };
default:
return { translateX: 0, translateY: 0 };
}
};
export const createBoundedZoomTransition = ({ duration }: CreateBoundedZoomTransitionParams) => {
const createBoundedZoomIn =
(direction: BoundedZoomDirection) =>
(values: EntryAnimationsValues): LayoutAnimation => {
'worklet';
const initialOffset = getInitialOffset(direction, values);
return {
animations: {
transform: [
{ translateX: withTiming(0, { duration }) },
{ translateY: withTiming(0, { duration }) },
{ scale: withTiming(1, { duration }) },
],
},
initialValues: {
transform: [
{ translateX: initialOffset.translateX },
{ translateY: initialOffset.translateY },
{ scale: 0 },
],
},
};
};
const createBoundedZoomOut =
(direction: BoundedZoomDirection) =>
(values: ExitAnimationsValues): LayoutAnimation => {
'worklet';
const targetOffset = getTargetOffset(direction, values);
return {
animations: {
transform: [
{
translateX: withTiming(targetOffset.translateX, {
duration,
}),
},
{
translateY: withTiming(targetOffset.translateY, {
duration,
}),
},
{ scale: withTiming(0, { duration }) },
],
},
initialValues: {
transform: [{ translateX: 0 }, { translateY: 0 }, { scale: 1 }],
},
};
};
return {
boundedZoomIn: {
bottom: createBoundedZoomIn('bottom'),
left: createBoundedZoomIn('left'),
right: createBoundedZoomIn('right'),
top: createBoundedZoomIn('top'),
},
boundedZoomOut: {
bottom: createBoundedZoomOut('bottom'),
left: createBoundedZoomOut('left'),
right: createBoundedZoomOut('right'),
top: createBoundedZoomOut('top'),
},
} as const;
};