UNPKG

react-native-skeleton-component

Version:

A skeleton component for react-native and react-native-web.

81 lines 3.82 kB
import * as React from "react"; import { Animated, View, StyleSheet, Easing, useWindowDimensions, } from "react-native"; import MaskedView from "@react-native-masked-view/masked-view"; import { SkeletonContainer as SkeletonContainerWeb, SkeletonContext, defaultProps, } from "./SkeletonContainerBase"; export * from "./SkeletonContainerBase"; export const SkeletonContainer = (props) => { if (props.animation === "wave") { return <Wave {...props}/>; } else { return <SkeletonContainerWeb {...props}/>; } }; SkeletonContainer.defaultProps = defaultProps; export default SkeletonContainer; // WAVE ANIMATION const waveDefaultProps = { speed: 800, }; const Wave = (props) => { const { children, backgroundColor, speed, highlightColor } = props; const SCREEN_WIDTH = useWindowDimensions().width; const SCREEN_HEIGHT = useWindowDimensions().height; const [context, setContext] = React.useState({ backgroundColor }); const [layout, setLayout] = React.useState(); const animatedValue = React.useMemo(() => new Animated.Value(0), []); const translateX = React.useMemo(() => { var _a; const width = (_a = layout === null || layout === void 0 ? void 0 : layout.width) !== null && _a !== void 0 ? _a : SCREEN_WIDTH; return animatedValue.interpolate({ inputRange: [0, 1], outputRange: [-width, width], }); }, [animatedValue, layout === null || layout === void 0 ? void 0 : layout.width, SCREEN_WIDTH]); const loop = Animated.loop(Animated.timing(animatedValue, { toValue: 1, duration: speed, easing: Easing.ease, useNativeDriver: true, })); React.useEffect(() => { loop.stop(); animatedValue.setValue(0); if ((layout === null || layout === void 0 ? void 0 : layout.width) && (layout === null || layout === void 0 ? void 0 : layout.height)) { loop.start(); } return () => loop.stop(); }, [animatedValue, speed, layout === null || layout === void 0 ? void 0 : layout.width, SCREEN_WIDTH]); const onLayout = (e) => { const newLayout = e.nativeEvent.layout; if (newLayout.width !== (layout === null || layout === void 0 ? void 0 : layout.width)) { setLayout(newLayout); } }; React.useEffect(() => { setContext({ backgroundColor }); }, [backgroundColor]); const absoluteTranslateStyle = React.useMemo(() => (Object.assign(Object.assign({}, StyleSheet.absoluteFillObject), { transform: [{ translateX }] })), [translateX]); return (<SkeletonContext.Provider value={context}> <View onLayout={onLayout}> {(layout === null || layout === void 0 ? void 0 : layout.width) && (layout === null || layout === void 0 ? void 0 : layout.height) ? (<MaskedView style={{ maxHeight: SCREEN_HEIGHT, height: layout.height, width: layout.width }} maskElement={<View>{children}</View>}> <View style={{ flexGrow: 1, backgroundColor }}/> <Animated.View style={[{ flexDirection: "row" }, absoluteTranslateStyle]}> {Array.from({ length: layout.width }).map((_, index) => { const opacity = new Animated.Value(index); return (<Animated.View key={index} style={{ width: 1, backgroundColor: highlightColor, opacity: opacity.interpolate({ inputRange: [0, layout.width / 2, layout.width], outputRange: [0, 1, 0], }), }}/>); })} </Animated.View> </MaskedView>) : (children)} </View> </SkeletonContext.Provider>); }; Wave.defaultProps = waveDefaultProps; //# sourceMappingURL=SkeletonContainer.native.js.map