/
skeleton.tsx
111 lines (101 loc) · 2.45 KB
/
skeleton.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import React from "react";
import Box, { BoxProps } from "../box/box";
import { ResponsiveValue, PaletteColors } from "../../../theme";
import { pearl } from "../../../pearl";
import { BoxStyleProps } from "../../../theme/src/style-functions";
import { View } from "react-native";
import { useTheme } from "../../../hooks";
type BaseSkeletonProps = BoxProps & {
/**
* The color at the animation start
*/
startColor?: ResponsiveValue<PaletteColors>;
/**
* The color at the animation end
*/
endColor?: ResponsiveValue<PaletteColors>;
/**
* If `true`, it'll render its children with a fade transition
*
* @default false
*/
isLoaded?: boolean;
/**
* The animation speed in milliseconds
*
* @default 800
*/
speed?: number;
/**
* The fadeIn duration in milliseconds. Requires `isLoaded` toggled to `true` in order to see the transition.
*
* @default 200
*/
fadeDuration?: number;
};
const BaseSkeleton = React.memo(
React.forwardRef(
(
{
startColor,
endColor,
isLoaded = false,
speed = 800,
fadeDuration = 200,
...rest
}: BaseSkeletonProps,
ref: any
) => {
const { colorMode } = useTheme();
const key = React.useMemo(
() => `${colorMode}-${Math.random()}`,
[isLoaded, colorMode, startColor, endColor, speed, fadeDuration, rest]
);
if (isLoaded) {
return (
<Box
key={key}
ref={ref}
from={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
duration: fadeDuration,
}}
>
{rest.children}
</Box>
);
}
rest.children = <View style={{ opacity: 0 }}>{rest.children}</View>;
return (
<Box
key={key}
{...rest}
ref={ref}
from={{ bgColor: startColor }}
animate={{ bgColor: endColor }}
transition={{
loop: true,
repeatReverse: true,
duration: speed,
}}
/>
);
}
)
);
/**
* A Skeleton component that is used to show placeholders is a loading state
*/
const Skeleton = pearl<
BaseSkeletonProps,
"atom",
Record<string, any>,
BoxStyleProps
>(BaseSkeleton, {
componentName: "Skeleton",
type: "atom",
});
export type SkeletonProps = React.ComponentProps<typeof Skeleton>;
Skeleton.displayName = "Skeleton";
export default Skeleton;