react-native-reanimated#useCode TypeScript Examples
The following examples show how to use
react-native-reanimated#useCode.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: layoutUtil.ts From react-native-template with MIT License | 6 votes |
useDebug = (values: { [key: string]: Animated.Node<number> }) => {
const keys = Object.keys(values)
const nodes = Object.values(values)
useCode(
() =>
call(nodes, (arrayOfNodes) => {
keys.map((key, i) => console.log(key + " " + arrayOfNodes[i]))
}),
[keys]
)
}
Example #2
Source File: CardModal.tsx From react-native-template with MIT License | 5 votes |
CardModal = ({
children,
visible,
cardHeight = layoutUtil.height,
almostTuckedIn = false,
cardStyle,
}: Props) => {
const animation = useValue(0)
const heightValue = useMemo(() => multiply(-cardHeight, HEIGHT_OFFSET), [
cardHeight,
])
const isTuckedIn = bin(visible)
const isAlmostTuckedIn = bin(almostTuckedIn)
useCode(
() => [
cond(
// down animation
or(not(isTuckedIn), isAlmostTuckedIn),
set(
animation,
spring({
to: cond(isAlmostTuckedIn, TUCK_IN_HEIGHT, 0),
from: animation,
config: {
damping: new Value(20),
mass: 0.6,
},
})
),
cond(or(isTuckedIn, not(isAlmostTuckedIn)), [
// up animation
set(
animation,
spring({
to: heightValue,
from: animation,
config: {
damping: new Value(20),
mass: 0.8,
},
})
),
])
),
],
[visible, heightValue, almostTuckedIn]
)
return (
<>
<Animated.View
style={[
styles.card,
{
height: cardHeight * HEIGHT_OFFSET,
bottom: -cardHeight * HEIGHT_OFFSET,
transform: [{ translateY: animation }],
},
cardStyle,
]}
>
{children}
</Animated.View>
</>
)
}
Example #3
Source File: PaperOnboarding.tsx From react-native-paper-onboarding with MIT License | 4 votes |
PaperOnboardingComponent = forwardRef<
PaperOnboarding,
PaperOnboardingProps
>(
(
{
data,
safeInsets: _safeInsets,
direction = DEFAULT_DIRECTION,
// indicator config
indicatorSize = DEFAULT_INDICATOR_SIZE,
indicatorBackgroundColor = DEFAULT_INDICATOR_BACKGROUND_COLOR,
indicatorBorderColor = DEFAULT_INDICATOR_BORDER_COLOR,
// override styles
titleStyle,
descriptionStyle,
// close button config
closeButton,
closeButtonTextStyle,
closeButtonText = DEFAULT_CLOSE_BUTTON_TEXT,
onCloseButtonPress = DEFAULT_CLOSE_BUTTON_CALLBACK,
onIndexChange,
},
ref
) => {
// state
const [dimensions, setDimensions] =
useState<PaperOnboardingScreenDimensions>({
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
});
// refs
const indexRef = useRef<number>(0);
const pagesRef = useRef<Array<Animated.View | null>>(data.map(() => null));
//#region variables
const safeInsets = useMemo<Required<Insets>>(() => {
return {
top: _safeInsets?.top ?? DEFAULT_SAFE_INSET,
bottom: _safeInsets?.bottom ?? DEFAULT_SAFE_INSET,
left: _safeInsets?.left ?? DEFAULT_SAFE_INSET,
right: _safeInsets?.right ?? DEFAULT_SAFE_INSET,
};
}, [_safeInsets]);
const indicatorsContainerLeftPadding = useMemo(() => {
const containerLeftPadding = dimensions.width / 2 - indicatorSize / 2;
return I18nManager.isRTL
? -containerLeftPadding + indicatorSize * (data.length - 1)
: containerLeftPadding;
}, [dimensions.width, indicatorSize, data.length]);
//#endregion
//#region animated variables
const { gestureHandler, state, translation, velocity } =
usePanGestureHandler();
const animatedStaticIndex = useValue<number>(0);
const animatedOverrideIndex = useValue<number>(0);
const animatedIndex = useTiming({
animatedStaticIndex,
animatedOverrideIndex,
value: direction === 'horizontal' ? translation.x : translation.y,
velocity: direction === 'horizontal' ? velocity.x : velocity.y,
state: state,
size: data.length,
screenWidth: dimensions.width,
});
const indicatorsContainerPosition = useMemo(
() => data.map((_, index) => index * indicatorSize * -1),
[data, indicatorSize]
);
const animatedIndicatorsContainerPosition = useMemo(
() =>
add(
interpolate(animatedIndex, {
inputRange: data.map((_, index) => index),
outputRange: I18nManager.isRTL
? indicatorsContainerPosition.reverse()
: indicatorsContainerPosition,
extrapolate: Animated.Extrapolate.CLAMP,
}),
indicatorsContainerLeftPadding
),
[
data,
animatedIndex,
indicatorsContainerLeftPadding,
indicatorsContainerPosition,
]
);
//#endregion
//#region callbacks
const handlePageRef = useCallback((pageRef, index) => {
pagesRef.current[index] = pageRef;
}, []);
const handleOnLayout = useCallback(
({
nativeEvent: {
layout: { width, height },
},
}: LayoutChangeEvent) => {
setDimensions({
width,
height,
});
},
[]
);
//#endregion
//#region public methods
const handleNavigateToNextPage = useCallback(() => {
const currentIndex = indexRef.current;
if (currentIndex === data.length - 1) {
return;
}
animatedOverrideIndex.setValue(currentIndex + 1);
}, [data, animatedOverrideIndex]);
const handleNavigateToPreviousPage = useCallback(() => {
const currentIndex = indexRef.current;
if (currentIndex === 0) {
return;
}
animatedOverrideIndex.setValue(currentIndex - 1);
}, [animatedOverrideIndex]);
useImperativeHandle(
ref,
() => ({
next: handleNavigateToNextPage,
previous: handleNavigateToPreviousPage,
}),
[handleNavigateToNextPage, handleNavigateToPreviousPage]
);
//#endregion
//#region effects
useCode(
() =>
onChange(
animatedStaticIndex,
call([animatedStaticIndex], args => {
indexRef.current = args[0];
/**
* @DEV
* here we directly manipulate pages native props by setting `pointerEvents`
* to `auto` for current page and `none` for others.
*/
pagesRef.current.map((pageRef, _index) => {
// @ts-ignore
pageRef.setNativeProps({
pointerEvents: _index === args[0] ? 'auto' : 'none',
});
});
if (onIndexChange) {
onIndexChange(args[0]);
}
})
),
[]
);
//#endregion
// renders
return (
<PanGestureHandler {...gestureHandler}>
<Animated.View onLayout={handleOnLayout} style={styles.container}>
<Background
animatedIndex={animatedIndex}
data={data}
safeInsets={safeInsets}
screenDimensions={dimensions}
indicatorSize={indicatorSize}
animatedIndicatorsContainerPosition={
animatedIndicatorsContainerPosition
}
/>
{data.map((item, index) => (
<Page
key={`page-${index}`}
index={index}
item={item}
animatedIndex={animatedIndex}
indicatorSize={indicatorSize}
titleStyle={titleStyle}
descriptionStyle={descriptionStyle}
safeInsets={safeInsets}
screenDimensions={dimensions}
handleRef={handlePageRef}
/>
))}
<IndicatorsContainer
data={data}
animatedIndex={animatedIndex}
animatedIndicatorsContainerPosition={
animatedIndicatorsContainerPosition
}
indicatorSize={indicatorSize}
indicatorBackgroundColor={indicatorBackgroundColor}
indicatorBorderColor={indicatorBorderColor}
safeInsets={safeInsets}
/>
<CloseButton
data={data}
animatedIndex={animatedIndex}
safeInsets={safeInsets}
closeButtonText={closeButtonText}
closeButtonTextStyle={closeButtonTextStyle}
closeButton={closeButton}
onCloseButtonPress={onCloseButtonPress}
/>
</Animated.View>
</PanGestureHandler>
);
}
)
Example #4
Source File: StickyItemFlatList.tsx From react-native-sticky-item with MIT License | 4 votes |
StickyItemFlatList = forwardRef( <T extends {}>(props: StickyItemFlatListProps<T>, ref: Ref<FlatList<T>>) => { const { initialScrollIndex = 0, decelerationRate = DEFAULT_DECELERATION_RATE, itemWidth, itemHeight, separatorSize = DEFAULT_SEPARATOR_SIZE, borderRadius = DEFAULT_BORDER_RADIUS, stickyItemActiveOpacity = DEFAULT_STICKY_ITEM_ACTIVE_OPACITY, stickyItemWidth, stickyItemHeight, stickyItemBackgroundColors, stickyItemContent, onStickyItemPress, isRTL = DEFAULT_IS_RTL, ItemSeparatorComponent = Separator, ...rest } = props; // refs const flatListRef = useRef<FlatList<T>>(null); const tapRef = useRef<TapGestureHandler>(null); //#region variables const itemWidthWithSeparator = useMemo( () => itemWidth + separatorSize, [itemWidth, separatorSize] ); const separatorProps = useMemo( () => ({ size: separatorSize, }), [separatorSize] ); //#endregion //#region styles const contentContainerStyle = useMemo( () => [ rest.contentContainerStyle, { paddingLeft: itemWidth + separatorSize * 2, paddingRight: separatorSize, }, ], [rest.contentContainerStyle, itemWidth, separatorSize] ); //#endregion //#region methods const getHitSlop = useCallback( isMinimized => { const verticalPosition = isMinimized ? -((itemHeight - stickyItemHeight) / 2) : 0; const startPosition = isMinimized ? 0 : -separatorSize; const endPosition = isMinimized ? -(SCREEN_WIDTH - stickyItemWidth) : -(SCREEN_WIDTH - separatorSize - itemWidth); return { top: verticalPosition, right: isRTL ? startPosition : endPosition, left: isRTL ? endPosition : startPosition, bottom: verticalPosition, }; }, [ itemWidth, itemHeight, stickyItemWidth, stickyItemHeight, separatorSize, isRTL, ] ); const getItemLayout = useCallback( (_, index) => { return { length: itemWidthWithSeparator, // sticky item + previous items width offset: itemWidthWithSeparator + itemWidthWithSeparator * index, index, }; }, [itemWidthWithSeparator] ); //#endregion //#region gesture const x = useValue(0); const tapState = useValue(State.UNDETERMINED); const tapGestures = useGestureHandler({ state: tapState }); const onScroll = event([ { nativeEvent: { contentOffset: { x, }, }, }, ]); const onScrollEnd = event([ { nativeEvent: { contentOffset: { x, }, }, }, ]); //#endregion //#region effects //@ts-ignore useImperativeHandle(ref, () => flatListRef.current!.getNode()); useCode( () => cond(eq(tapState, State.END), [ call([tapState], () => { if (onStickyItemPress) { onStickyItemPress(); } }), set(tapState, State.UNDETERMINED), ]), [tapState] ); useCode( () => onChange( x, call([x], args => { if (tapRef.current) { const isMinimized = args[0] > 0; // @ts-ignore tapRef.current.setNativeProps({ hitSlop: getHitSlop(isMinimized), }); } }) ), [ x, itemWidth, itemHeight, stickyItemWidth, stickyItemWidth, separatorSize, ] ); useEffect(() => { /** * @DEV * to fix stick item position with fast refresh */ x.setValue(0); if (tapRef.current) { // @ts-ignore tapRef.current.setNativeProps({ hitSlop: getHitSlop(initialScrollIndex !== 0), }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [getHitSlop]); //#endregion // render const renderSeparator = useCallback(() => { if (typeof ItemSeparatorComponent === 'function') { // @ts-ignore return ItemSeparatorComponent(separatorProps); } else { // @ts-ignore return <ItemSeparatorComponent size={separatorProps.size} />; } }, [ItemSeparatorComponent, separatorProps]); return ( <TapGestureHandler ref={tapRef} waitFor={flatListRef} shouldCancelWhenOutside={true} {...tapGestures} > <Animated.View> <AnimatedFlatList {...rest} ref={flatListRef} initialScrollIndex={initialScrollIndex} inverted={isRTL} ItemSeparatorComponent={renderSeparator} contentContainerStyle={contentContainerStyle} horizontal={true} showsHorizontalScrollIndicator={false} scrollEventThrottle={1} pagingEnabled={true} decelerationRate={decelerationRate} snapToAlignment={'start'} snapToInterval={itemWidth + separatorSize} onScroll={onScroll} onScrollAnimationEnd={onScrollEnd} getItemLayout={getItemLayout} /> <StickyItem x={x} tapState={tapState} itemWidth={itemWidth} itemHeight={itemHeight} separatorSize={separatorSize} borderRadius={borderRadius} stickyItemActiveOpacity={stickyItemActiveOpacity} stickyItemWidth={stickyItemWidth} stickyItemHeight={stickyItemHeight} stickyItemBackgroundColors={stickyItemBackgroundColors} stickyItemContent={stickyItemContent} isRTL={isRTL} /> </Animated.View> </TapGestureHandler> ); } )
Example #5
Source File: Snackbar.tsx From react-native-template with MIT License | 4 votes |
Snackbar = ({
visible,
message,
onDismiss,
btnTitle,
onPress,
unsafeView,
}: SnackbarProps) => {
const timeoutRef = useRef(-1)
const insets = useSafeArea()
const safeArea = !unsafeView
? insets
: { top: 0, bottom: 0, left: 0, right: 0 }
const snackbarHeight =
SNACKBAR_HEIGHT + safeArea.bottom + safeArea.bottom / 2 + 10
const translateY = useValue(snackbarHeight)
const opacity = useMemo(
() =>
timing({
to: 1,
from: 0.2,
duration: 200,
}),
// eslint-disable-next-line
[message]
)
useCode(
() => [
cond(
bin(visible),
set(
translateY,
timing({
from: translateY,
to: 0,
duration: 250,
})
),
cond(
neq(translateY, snackbarHeight),
set(
translateY,
timing({
from: translateY,
to: snackbarHeight,
duration: 150,
})
)
)
),
],
[visible, snackbarHeight, translateY]
)
useEffect(() => {
if (visible) {
timeoutRef.current = setTimeout(() => {
onDismiss()
}, 3000)
}
return clearTimeoutRef
}, [onDismiss, visible])
const clearTimeoutRef = () => clearTimeout(timeoutRef.current)
const handleOnPress = () => {
onDismiss()
clearTimeout(timeoutRef.current)
setTimeout(() => {
onPress!()
}, 150)
}
return (
<View style={styles.container}>
<Animated.View
style={[
styles.snackbar,
{
transform: [{ translateY }],
height: snackbarHeight,
backgroundColor: "#1D2226",
},
]}
>
<Animated.Text
style={[
styles.text,
{
marginBottom: safeArea.bottom,
opacity,
},
]}
>
{message}
</Animated.Text>
{onPress && (
<TouchableOpacity
onPress={handleOnPress}
style={styles.touchable}
activeOpacity={0.6}
>
<Text
style={[
styles.dismissText,
{
marginBottom: safeArea.bottom,
color: "#15AAE1",
},
]}
>
{btnTitle}
</Text>
</TouchableOpacity>
)}
<TouchableOpacity
onPress={onDismiss}
style={styles.touchable}
activeOpacity={0.6}
>
<Text
style={[
styles.dismissText,
{
marginBottom: safeArea.bottom,
color: "#2E97C8",
},
]}
>
Dismiss
</Text>
</TouchableOpacity>
</Animated.View>
</View>
)
}