Skip to content

Commit fad14e9

Browse files
Added Deck Swiper component + example in example app (#581)
* Added deck swiper component Changes from #580 Copying changes manually - easier than rebasing * Small change to comment to trigger rebuild * Added export for DeckSwiper in ui package * Moved ui package export above deprecated comment * Minor edit to comment * Fixed issue where border radius of theme is undefined * Removed default border radius from theme * Added layout to mapping --------- Co-authored-by: Brian Luerssen <[email protected]>
1 parent 2f4517a commit fad14e9

File tree

11 files changed

+326
-3
lines changed

11 files changed

+326
-3
lines changed

example/src/App.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ import LinearGradientExample from "./LinearGradientExample";
7171

7272
import SurfaceExample from "./SurfaceExample";
7373

74+
import DeckSwiperExample from "./DeckSwiperExample";
75+
7476
const ROUTES = {
7577
AudioPlayer: AudioPlayerExample,
7678
Layout: LayoutExample,
@@ -115,6 +117,7 @@ const ROUTES = {
115117
TextInput: TextInputExample,
116118
NumberInput: NumberInputExample,
117119
WebView: WebViewExample,
120+
DeckSwiper: DeckSwiperExample,
118121
};
119122

120123
let customFonts = {

example/src/DeckSwiperExample.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from "react";
2+
import { Image, Text } from "react-native";
3+
import Section, { Container } from "./Section";
4+
import { DeckSwiper, DeckSwiperCard } from "@draftbit/core";
5+
6+
const DeckSwiperExample: React.FC = () => {
7+
return (
8+
<Container style={{}}>
9+
<Section title="Simple swiper with text" style={{ paddingBottom: 30 }}>
10+
<DeckSwiper visibleCardCount={3}>
11+
<DeckSwiperCard>
12+
<Text>Card 1</Text>
13+
</DeckSwiperCard>
14+
<DeckSwiperCard>
15+
<Text>Card 2</Text>
16+
</DeckSwiperCard>
17+
<DeckSwiperCard>
18+
<Text>Card 3</Text>
19+
</DeckSwiperCard>
20+
<DeckSwiperCard>
21+
<Text>Card 4</Text>
22+
</DeckSwiperCard>
23+
</DeckSwiper>
24+
</Section>
25+
26+
<Section title="Infinite swiper with images" style={{}}>
27+
<DeckSwiper infiniteSwiping visibleCardCount={2}>
28+
<DeckSwiperCard>
29+
<Image
30+
style={{ width: "100%", height: 300 }}
31+
source={{ uri: "https://picsum.photos/id/141/1125" }}
32+
/>
33+
</DeckSwiperCard>
34+
<DeckSwiperCard>
35+
<Image
36+
style={{ width: "100%", height: 300 }}
37+
source={{ uri: "https://picsum.photos/id/141/1125" }}
38+
/>
39+
</DeckSwiperCard>
40+
<DeckSwiperCard>
41+
<Image
42+
style={{ width: "100%", height: 300 }}
43+
source={{ uri: "https://picsum.photos/id/141/1125" }}
44+
/>
45+
</DeckSwiperCard>
46+
</DeckSwiper>
47+
</Section>
48+
</Container>
49+
);
50+
};
51+
52+
export default DeckSwiperExample;

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"lodash.isnumber": "^3.0.3",
5454
"lodash.omit": "^4.5.0",
5555
"lodash.tonumber": "^4.0.3",
56+
"react-native-deck-swiper": "^2.0.12",
5657
"react-native-modal-datetime-picker": "^13.0.0",
5758
"react-native-svg": "12.3.0",
5859
"react-native-typography": "^1.4.1",
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React from "react";
2+
import { StyleProp, ViewStyle, StyleSheet, View } from "react-native";
3+
import DeckSwiperComponent from "react-native-deck-swiper";
4+
5+
export interface DeckSwiperProps {
6+
onIndexChanged?: (index: number) => void;
7+
onEndReached?: () => void;
8+
startCardIndex?: number;
9+
infiniteSwiping?: boolean;
10+
verticalEnabled?: boolean;
11+
horizontalEnabled?: boolean;
12+
visibleCardCount?: number;
13+
style?: StyleProp<ViewStyle>;
14+
}
15+
16+
const DeckSwiper: React.FC<React.PropsWithChildren<DeckSwiperProps>> = ({
17+
onIndexChanged,
18+
onEndReached,
19+
startCardIndex = 0,
20+
infiniteSwiping = false,
21+
verticalEnabled = true,
22+
horizontalEnabled = true,
23+
visibleCardCount = 1,
24+
style,
25+
children,
26+
}) => {
27+
const childrenArray = React.useMemo(
28+
() => React.Children.toArray(children),
29+
[children]
30+
);
31+
32+
// an array of indices based on children count
33+
const cardsFillerData = React.useMemo(
34+
() => Array.from(Array(childrenArray.length).keys()),
35+
[childrenArray]
36+
);
37+
38+
/**
39+
* By default react-native-deck-swiper positions everything with absolute position.
40+
* To overcome this, it is wrapped in a View to be able to add the component in any layout structure.
41+
*
42+
*
43+
* Since all children of that View are absolutley positioned, the View does not have a height and still looks and behaves weird.
44+
* To fix/mitage this without setting a static height, the first card is rendered in invisible state to take up space.
45+
* This effectivley makes the default height of the container be the height of the first card.
46+
*/
47+
48+
return (
49+
<View>
50+
<View style={styles.containerHeightFiller}>
51+
{childrenArray.length && childrenArray[0]}
52+
</View>
53+
<DeckSwiperComponent
54+
cards={cardsFillerData}
55+
renderCard={(_, i) => <>{childrenArray[i]}</>}
56+
keyExtractor={(card) => card?.toString()}
57+
containerStyle={
58+
StyleSheet.flatten([styles.cardsContainer, style]) as
59+
| object
60+
| undefined
61+
}
62+
cardStyle={styles.card as object | undefined}
63+
onSwiped={onIndexChanged}
64+
onSwipedAll={onEndReached}
65+
cardIndex={startCardIndex}
66+
infinite={infiniteSwiping}
67+
verticalSwipe={verticalEnabled}
68+
horizontalSwipe={horizontalEnabled}
69+
showSecondCard={visibleCardCount > 1}
70+
stackSize={visibleCardCount}
71+
backgroundColor="transparent"
72+
cardVerticalMargin={0}
73+
cardHorizontalMargin={0}
74+
/>
75+
</View>
76+
);
77+
};
78+
79+
const styles = StyleSheet.create({
80+
cardsContainer: {
81+
width: "100%",
82+
},
83+
card: {
84+
left: 0,
85+
right: 0,
86+
width: "auto",
87+
height: "auto",
88+
},
89+
containerHeightFiller: {
90+
opacity: 0.0,
91+
},
92+
});
93+
94+
export default DeckSwiper;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from "react";
2+
import { View, StyleSheet, StyleProp, ViewStyle } from "react-native";
3+
import type { Theme } from "../../styles/DefaultTheme";
4+
import { withTheme } from "../../theming";
5+
6+
export interface DeckSwiperCardProps {
7+
style?: StyleProp<ViewStyle>;
8+
children: React.ReactNode;
9+
theme: Theme;
10+
}
11+
12+
const DeckSwiperCard: React.FC<DeckSwiperCardProps> = ({
13+
style,
14+
children,
15+
theme,
16+
}) => (
17+
<View
18+
style={[
19+
styles.card,
20+
{
21+
backgroundColor: theme.colors.background,
22+
borderColor: theme.colors.divider,
23+
},
24+
style,
25+
]}
26+
>
27+
{children}
28+
</View>
29+
);
30+
31+
const styles = StyleSheet.create({
32+
card: {
33+
flex: 1,
34+
alignItems: "center",
35+
justifyContent: "center",
36+
padding: 20,
37+
borderWidth: 2,
38+
},
39+
});
40+
41+
export default withTheme(DeckSwiperCard);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as DeckSwiper } from "./DeckSwiper";
2+
export { default as DeckSwiperCard } from "./DeckSwiperCard";

packages/core/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export {
5151
RadioButtonFieldGroup,
5252
} from "./components/RadioButton/index";
5353

54+
export { DeckSwiper, DeckSwiperCard } from "./components/DeckSwiper";
55+
5456
/* Deprecated: Fix or Delete! */
5557
export { default as DatePicker } from "./components/DatePicker/DatePicker";
5658
export { default as Picker } from "./components/Picker/Picker";
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {
2+
COMPONENT_TYPES,
3+
Triggers,
4+
createActionProp,
5+
createStaticNumberProp,
6+
createStaticBoolProp,
7+
BLOCK_STYLES_SECTIONS,
8+
} from "@draftbit/types";
9+
10+
export const SEED_DATA = {
11+
name: "Deck Swiper",
12+
tag: "DeckSwiper",
13+
description: "Deck swiper container",
14+
category: COMPONENT_TYPES.swiper,
15+
stylesPanelSections: BLOCK_STYLES_SECTIONS,
16+
layout: {
17+
width: "100%",
18+
},
19+
triggers: [Triggers.OnIndexChanged, Triggers.OnEndReached],
20+
props: {
21+
onIndexChanged: createActionProp({
22+
label: "On index changed",
23+
description: "Action to execute when swipe to new index",
24+
}),
25+
onEndReached: createActionProp({
26+
label: "On end reached",
27+
description: "Action to execute when end of swiping reached",
28+
}),
29+
startCardIndex: createStaticNumberProp({
30+
label: "Start card index",
31+
description: "Index of card to start swiping from",
32+
defaultValue: 0,
33+
}),
34+
infiniteSwiping: createStaticBoolProp({
35+
label: "Infinite swiping",
36+
description: "Whether to infinitley loop through cards or not",
37+
}),
38+
verticalEnabled: createStaticBoolProp({
39+
label: "Vertical swipe enabled",
40+
description: "Whether cards should be swipeable vertically or not",
41+
defaultValue: true,
42+
}),
43+
horizontalEnabled: createStaticBoolProp({
44+
label: "Horizontal swipe enabled",
45+
description: "Whether cards should be swipeable horizontally or not",
46+
defaultValue: true,
47+
}),
48+
visibleCardCount: createStaticNumberProp({
49+
label: "Visible card count",
50+
description:
51+
"Number of cards visible behind (and including) the current card",
52+
defaultValue: 1,
53+
min: 1,
54+
step: 1,
55+
}),
56+
},
57+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
COMPONENT_TYPES,
3+
CONTAINER_COMPONENT_STYLES_SECTIONS,
4+
} from "@draftbit/types";
5+
6+
export const SEED_DATA = {
7+
name: "Deck Swiper Card",
8+
tag: "DeckSwiperCard",
9+
description: "Single Deck Swiper Card item to be used in DeckSwiper",
10+
category: COMPONENT_TYPES.swiper,
11+
stylesPanelSections: CONTAINER_COMPONENT_STYLES_SECTIONS,
12+
layout: {
13+
flex: 1,
14+
alignItems: "center",
15+
justifyContent: "center",
16+
padding: 20,
17+
borderWidth: 2,
18+
},
19+
props: {},
20+
};

packages/ui/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export {
2828
Pressable,
2929
withTheme,
3030
useAuthState,
31+
DeckSwiper,
32+
DeckSwiperCard,
3133
/* Deprecated, needs fixing */
3234
ProgressBar,
3335
ProgressCircle,

0 commit comments

Comments
 (0)