Skip to content

Commit f122a06

Browse files
authored
add loading component (#909)
* add activity indicator component * add loading example * adjust from loading to activity indicator * update spinner color * update base on comments feedback
1 parent 61e1fef commit f122a06

File tree

7 files changed

+255
-0
lines changed

7 files changed

+255
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import * as React from "react";
2+
import { View, StyleSheet, Text } from "react-native";
3+
import { ActivityIndicator, withTheme } from "@draftbit/ui";
4+
import Section, { Container } from "./Section";
5+
import { ActivityIndicatorType } from "@draftbit/core/lib/typescript/src/components/ActivityIndicator";
6+
7+
interface WrapperProps {
8+
label: string;
9+
children: React.ReactNode;
10+
}
11+
12+
const Wrapper: React.FC<WrapperProps> = ({ label, children }) => {
13+
return (
14+
<View style={styles.wrapper}>
15+
<View style={styles.boxLabel}>
16+
<Text>{label}</Text>
17+
</View>
18+
<View>{children}</View>
19+
</View>
20+
);
21+
};
22+
23+
const ActivityIndicatorExample: React.FC = () => {
24+
return (
25+
<Container style={{}}>
26+
<Section style={{}} title="Default">
27+
<View style={{ flexDirection: "row" }}>
28+
<Wrapper label="Small">
29+
<ActivityIndicator size="small" />
30+
</Wrapper>
31+
<Wrapper label="Large">
32+
<ActivityIndicator size="large" />
33+
</Wrapper>
34+
<Wrapper label="Size">
35+
<ActivityIndicator size={80} />
36+
</Wrapper>
37+
</View>
38+
</Section>
39+
<Section style={{}} title="Loading">
40+
<View style={{ flexDirection: "row" }}>
41+
<Wrapper label="Default">
42+
<ActivityIndicator />
43+
</Wrapper>
44+
<Wrapper label="Plane">
45+
<ActivityIndicator type={ActivityIndicatorType.plane} />
46+
</Wrapper>
47+
<Wrapper label="Chase">
48+
<ActivityIndicator type={ActivityIndicatorType.chase} />
49+
</Wrapper>
50+
<Wrapper label="Bounce">
51+
<ActivityIndicator type={ActivityIndicatorType.bounce} />
52+
</Wrapper>
53+
<Wrapper label="Wave">
54+
<ActivityIndicator type={ActivityIndicatorType.wave} />
55+
</Wrapper>
56+
<Wrapper label="Pulse">
57+
<ActivityIndicator type={ActivityIndicatorType.pulse} />
58+
</Wrapper>
59+
</View>
60+
</Section>
61+
<Section style={{}} title="Loading">
62+
<View style={{ flexDirection: "row" }}>
63+
<Wrapper label="Flow">
64+
<ActivityIndicator type={ActivityIndicatorType.flow} />
65+
</Wrapper>
66+
<Wrapper label="Swing">
67+
<ActivityIndicator type={ActivityIndicatorType.swing} />
68+
</Wrapper>
69+
<Wrapper label="Circle">
70+
<ActivityIndicator type={ActivityIndicatorType.circle} />
71+
</Wrapper>
72+
<Wrapper label="Circle Fade">
73+
<ActivityIndicator type={ActivityIndicatorType.circleFade} />
74+
</Wrapper>
75+
<Wrapper label="Grid">
76+
<ActivityIndicator type={ActivityIndicatorType.grid} />
77+
</Wrapper>
78+
<Wrapper label="Fold">
79+
<ActivityIndicator type={ActivityIndicatorType.fold} />
80+
</Wrapper>
81+
<Wrapper label="Wander">
82+
<ActivityIndicator type={ActivityIndicatorType.wander} />
83+
</Wrapper>
84+
</View>
85+
</Section>
86+
</Container>
87+
);
88+
};
89+
90+
const styles = StyleSheet.create({
91+
wrapper: {
92+
flex: 1,
93+
display: "flex",
94+
flexDirection: "column",
95+
flexWrap: "wrap",
96+
justifyContent: "center",
97+
alignItems: "center",
98+
},
99+
boxLabel: {
100+
margin: 10,
101+
flex: 1,
102+
},
103+
});
104+
105+
export default withTheme(ActivityIndicatorExample);

example/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@ import VideoPlayerExample from "./VideoPlayerExample";
7373
import PinInputExample from "./PinInputExample";
7474
import KeyboardAvoidingViewExample from "./KeyboardAvoidingViewExample";
7575
import ThemeExample from "./ThemeExample";
76+
import ActivityIndicatorExample from "./ActivityIndicatorExample";
7677

7778
const ROUTES = {
79+
ActivityIndicator: ActivityIndicatorExample,
7880
Theme: ThemeExample,
7981
AudioPlayer: AudioPlayerExample,
8082
Layout: LayoutExample,

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"lodash.isnumber": "^3.0.3",
5858
"lodash.omit": "^4.5.0",
5959
"lodash.tonumber": "^4.0.3",
60+
"react-native-animated-spinkit": "1.5.2",
6061
"react-native-confirmation-code-field": "^7.3.1",
6162
"react-native-deck-swiper": "^2.0.12",
6263
"react-native-dropdown-picker": "^5.4.7-beta.1",
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import * as React from "react";
2+
import {
3+
StyleProp,
4+
ViewStyle,
5+
ActivityIndicator as ActivityIndicatorRN,
6+
View,
7+
Platform,
8+
} from "react-native";
9+
import { withTheme } from "@draftbit/theme";
10+
import type { ReadTheme } from "@draftbit/theme";
11+
import {
12+
Bounce,
13+
Chase,
14+
Circle,
15+
CircleFade,
16+
Flow,
17+
Fold,
18+
Grid,
19+
Plane,
20+
Pulse,
21+
Swing,
22+
Wander,
23+
Wave,
24+
} from "react-native-animated-spinkit";
25+
26+
export enum ActivityIndicatorType {
27+
default = "default",
28+
plane = "plane",
29+
chase = "chase",
30+
bounce = "bounce",
31+
wave = "wave",
32+
pulse = "pulse",
33+
flow = "flow",
34+
swing = "swing",
35+
circle = "circle",
36+
circleFade = "circleFade",
37+
grid = "grid",
38+
fold = "fold",
39+
wander = "wander",
40+
}
41+
42+
type Props = {
43+
style?: StyleProp<ViewStyle>;
44+
color?: string;
45+
theme: ReadTheme;
46+
type?: ActivityIndicatorType;
47+
size?: number | "small" | "large";
48+
};
49+
50+
const SPINNER_COMPONENTS = {
51+
[ActivityIndicatorType.plane]: Plane,
52+
[ActivityIndicatorType.chase]: Chase,
53+
[ActivityIndicatorType.bounce]: Bounce,
54+
[ActivityIndicatorType.wave]: Wave,
55+
[ActivityIndicatorType.pulse]: Pulse,
56+
[ActivityIndicatorType.flow]: Flow,
57+
[ActivityIndicatorType.swing]: Swing,
58+
[ActivityIndicatorType.circle]: Circle,
59+
[ActivityIndicatorType.circleFade]: CircleFade,
60+
[ActivityIndicatorType.grid]: Grid,
61+
[ActivityIndicatorType.fold]: Fold,
62+
[ActivityIndicatorType.wander]: Wander,
63+
};
64+
65+
const smallActivityIndicatorSize = 20;
66+
const largeActivityIndicatorSize = 40;
67+
68+
const getLoadingSizeNumber = (size?: number | "small" | "large"): number => {
69+
if (typeof size === "number") return size;
70+
return size === "large"
71+
? largeActivityIndicatorSize
72+
: smallActivityIndicatorSize;
73+
};
74+
75+
const getScaleLevel = (size?: number | "small" | "large"): number => {
76+
if (typeof size === "number") return size / smallActivityIndicatorSize;
77+
return size === "large" ? 2 : 1;
78+
};
79+
80+
const ActivityIndicator: React.FC<React.PropsWithChildren<Props>> = ({
81+
theme,
82+
color = theme.colors.branding.primary,
83+
type = ActivityIndicatorType.default,
84+
size = "small",
85+
style,
86+
...rest
87+
}) => {
88+
const sizeNumber = getLoadingSizeNumber(size);
89+
const spinnerColor = color ?? theme.colors.branding.primary;
90+
91+
// Handle display spinner type
92+
if (type !== ActivityIndicatorType.default) {
93+
if (type && SPINNER_COMPONENTS[type]) {
94+
const SpinnerComponent = SPINNER_COMPONENTS[type];
95+
return (
96+
<SpinnerComponent
97+
size={sizeNumber}
98+
color={spinnerColor}
99+
style={style}
100+
/>
101+
);
102+
}
103+
}
104+
105+
// This is due to limitations with iOS UIActivityIndicator
106+
// Refer: https://github.com/facebook/react-native/issues/12250
107+
const scaleLevel = getScaleLevel(size);
108+
if (Platform.OS === "ios") {
109+
return (
110+
<View
111+
style={[
112+
style,
113+
{
114+
transform: [{ scale: scaleLevel }],
115+
},
116+
]}
117+
>
118+
<ActivityIndicatorRN
119+
animating={true}
120+
hidesWhenStopped={true}
121+
size={"small"}
122+
color={spinnerColor}
123+
{...rest}
124+
/>
125+
</View>
126+
);
127+
}
128+
return (
129+
<ActivityIndicatorRN
130+
animating={true}
131+
hidesWhenStopped={true}
132+
size={size}
133+
color={spinnerColor}
134+
style={style}
135+
{...rest}
136+
/>
137+
);
138+
};
139+
140+
export default withTheme(ActivityIndicator);

packages/core/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export { default as SimpleStyleMasonryFlashList } from "./components/SimpleStyle
7979
export { default as SimpleStyleScrollView } from "./components/SimpleStyleScrollables/SimpleStyleScrollView";
8080
export { default as SimpleStyleSectionList } from "./components/SimpleStyleScrollables/SimpleStyleSectionList";
8181
export { default as SimpleStyleSwipeableList } from "./components/SimpleStyleScrollables/SimpleStyleSwipeableList";
82+
export { default as ActivityIndicator } from "./components/ActivityIndicator";
8283

8384
/* Deprecated: Fix or Delete! */
8485
export { default as AccordionItem } from "./deprecated-components/AccordionItem";

packages/ui/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export {
7575
SimpleStyleScrollView,
7676
SimpleStyleSectionList,
7777
SimpleStyleSwipeableList,
78+
ActivityIndicator,
7879
} from "@draftbit/core";
7980

8081
export {

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12910,6 +12910,11 @@ react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0:
1291012910
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
1291112911
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
1291212912

12913+
12914+
version "1.5.2"
12915+
resolved "https://registry.yarnpkg.com/react-native-animated-spinkit/-/react-native-animated-spinkit-1.5.2.tgz#b1c00ecbadf48634273e6a843f8dfbcb7c006186"
12916+
integrity sha512-YCQGR3HzEQvyaAnepiyf/hv88Sta3UIZ2CFZPtFqwu+VbFJfMgjJZniOx4157TuR5AAYajEJP9Fgy+JLIU3jzQ==
12917+
1291312918
react-native-avoid-softinput@^4.0.1:
1291412919
version "4.0.2"
1291512920
resolved "https://registry.yarnpkg.com/react-native-avoid-softinput/-/react-native-avoid-softinput-4.0.2.tgz#30825e7666b530c5d3e555a7778bd50f1431d0c3"

0 commit comments

Comments
 (0)