@butternutbox/pawprint-native 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +14 -0
  3. package/dist/index.cjs +1012 -173
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +252 -5
  6. package/dist/index.d.ts +252 -5
  7. package/dist/index.js +1007 -173
  8. package/dist/index.js.map +1 -1
  9. package/package.json +2 -1
  10. package/src/components/atoms/Hint/Hint.tsx +1 -2
  11. package/src/components/atoms/Input/InputField.tsx +7 -1
  12. package/src/components/molecules/Animated/Animated.tsx +12 -3
  13. package/src/components/molecules/Countdown/Countdown.stories.tsx +218 -0
  14. package/src/components/molecules/Countdown/Countdown.tsx +315 -0
  15. package/src/components/molecules/Countdown/index.ts +2 -0
  16. package/src/components/molecules/NumberField/NumberFieldInput.tsx +14 -24
  17. package/src/components/molecules/ProductDisplayCard/ProductDisplayCard.stories.tsx +275 -0
  18. package/src/components/molecules/ProductDisplayCard/ProductDisplayCard.test.tsx +198 -0
  19. package/src/components/molecules/ProductDisplayCard/ProductDisplayCard.tsx +292 -0
  20. package/src/components/molecules/ProductDisplayCard/index.ts +5 -0
  21. package/src/components/molecules/ProductListingCard/Badge.tsx +65 -0
  22. package/src/components/molecules/ProductListingCard/Grid.tsx +59 -0
  23. package/src/components/molecules/ProductListingCard/ProductListingCard.stories.tsx +209 -0
  24. package/src/components/molecules/ProductListingCard/ProductListingCard.tsx +235 -0
  25. package/src/components/molecules/ProductListingCard/index.ts +2 -0
  26. package/src/components/molecules/TabNavigation/TabNavigation.stories.tsx +183 -0
  27. package/src/components/molecules/TabNavigation/TabNavigation.tsx +354 -0
  28. package/src/components/molecules/TabNavigation/index.ts +7 -0
  29. package/src/components/molecules/index.ts +4 -0
  30. package/src/utils/index.ts +1 -0
  31. package/src/utils/token.ts +1 -0
@@ -0,0 +1,292 @@
1
+ import React from "react"
2
+ import { View, ViewProps, Image } from "react-native"
3
+ import styled from "@emotion/native"
4
+ import { Typography } from "../../atoms/Typography"
5
+ import { NumberField } from "../../molecules/NumberField"
6
+ import { Notification } from "../Notification"
7
+ import { parseTokenValue } from "../../../utils"
8
+
9
+ export type ProductDisplayCardDevice = "desktop" | "mobile"
10
+
11
+ export type ProductDisplayCardProps = ViewProps & {
12
+ device?: ProductDisplayCardDevice
13
+ title: string
14
+ subtext?: string | React.ReactNode
15
+ showSubtext?: boolean
16
+ quantity?: number
17
+ onQuantityChange?: (quantity: number) => void
18
+ showQuantityPicker?: boolean
19
+ disableQuantityButtons?: boolean
20
+ hideQuantityButtons?: boolean
21
+ showIncrementButton?: boolean
22
+ showDecrementButton?: boolean
23
+ incrementDisabled?: boolean
24
+ decrementDisabled?: boolean
25
+ image?: string | React.ReactNode
26
+ imageBackgroundColor?: string
27
+ showImageQuantityBadge?: boolean
28
+ banner?: React.ReactNode
29
+ showBanner?: boolean
30
+ bannerType?: "error" | "success" | "warning" | "info"
31
+ showBannerIcon?: boolean
32
+ }
33
+
34
+ const StyledCardContainer = styled(View)<{
35
+ cardDevice: ProductDisplayCardDevice
36
+ }>(({ theme }) => {
37
+ const { spacing, borderRadius } = theme.tokens.semantics.dimensions
38
+ const { colour } = theme.tokens.semantics
39
+ const spacingMd = parseTokenValue(spacing.md)
40
+ const spacingXl = parseTokenValue(spacing.xl)
41
+ return {
42
+ flexDirection: "row",
43
+ width: "100%",
44
+ height: "100%",
45
+ maxHeight: spacingXl * 6 + spacingMd,
46
+ backgroundColor: colour.background.surface.default,
47
+ borderWidth: 1,
48
+ borderColor: colour.border.default,
49
+ borderRadius: parseTokenValue(borderRadius.md),
50
+ overflow: "hidden",
51
+ shadowColor: "#522a10",
52
+ shadowOffset: { width: 0, height: spacingMd / 4 },
53
+ shadowOpacity: 0.05,
54
+ shadowRadius: spacingXl - 4,
55
+ elevation: 5,
56
+ zIndex: 1
57
+ }
58
+ })
59
+
60
+ const StyledImage = styled(View)<{ imageBackgroundColor?: string }>(
61
+ ({ theme, imageBackgroundColor }) => ({
62
+ flexShrink: 0,
63
+ backgroundColor:
64
+ imageBackgroundColor ||
65
+ theme.tokens.semantics.colour.background.container.secondary,
66
+ overflow: "hidden",
67
+ aspectRatio: "1 / 1",
68
+ height: "100%",
69
+ position: "relative"
70
+ })
71
+ )
72
+
73
+ const StyledQuantityBadge = styled(View)(({ theme }) => {
74
+ const spacing = theme.tokens.semantics.dimensions.spacing
75
+ const borderRadius = theme.tokens.semantics.dimensions.borderRadius
76
+ const { colour } = theme.tokens.semantics
77
+
78
+ return {
79
+ position: "absolute",
80
+ top: parseTokenValue(spacing["2xs"]),
81
+ right: parseTokenValue(spacing["2xs"]),
82
+ backgroundColor: colour.background.container.brand,
83
+ borderRadius: parseTokenValue(borderRadius.xs),
84
+ paddingHorizontal: parseTokenValue(spacing.sm),
85
+ height: parseTokenValue(spacing["2xl"]),
86
+ minWidth: parseTokenValue(spacing["2xl"]),
87
+ alignItems: "center",
88
+ justifyContent: "center",
89
+ zIndex: 2
90
+ }
91
+ })
92
+
93
+ const StyledContentArea = styled(View)<{
94
+ contentDevice: ProductDisplayCardDevice
95
+ }>(({ theme }) => {
96
+ const { spacing } = theme.tokens.semantics.dimensions
97
+ return {
98
+ flex: 1,
99
+ paddingHorizontal: parseTokenValue(spacing.md),
100
+ paddingVertical: parseTokenValue(spacing.md),
101
+ gap: parseTokenValue(spacing.xs),
102
+ justifyContent: "space-between"
103
+ }
104
+ })
105
+
106
+ const StyledTextContainer = styled(View)(() => ({
107
+ gap: 2
108
+ }))
109
+
110
+ const StyledBannerWrapper = styled(View)(() => ({
111
+ width: "100%",
112
+ marginTop: -48,
113
+ paddingTop: 24,
114
+ paddingBottom: 16
115
+ }))
116
+
117
+ const StyledRootWrapper = styled(View)(() => {
118
+ return {
119
+ flexDirection: "column",
120
+ width: "100%",
121
+ height: "100%"
122
+ }
123
+ })
124
+
125
+ const StyledNotification = styled(Notification as any)(({ theme }) => {
126
+ const { spacing } = theme.tokens.semantics.dimensions
127
+ return {
128
+ top: parseTokenValue(spacing.md),
129
+ paddingHorizontal: parseTokenValue(spacing.xl),
130
+ paddingVertical: parseTokenValue(spacing.md)
131
+ }
132
+ })
133
+
134
+ /**
135
+ * Product Display Card component for showing product information with optional quantity picker.
136
+ *
137
+ * @example
138
+ * ```tsx
139
+ * import { ProductDisplayCard } from "@butternutbox/pawprint-native"
140
+ *
141
+ * <ProductDisplayCard
142
+ * device="mobile"
143
+ * title="Premium Recipe"
144
+ * subtext="+£0.00/pouch"
145
+ * quantity={1}
146
+ * showQuantityPicker
147
+ * />
148
+ * ```
149
+ *
150
+ * @param device - *(optional)* Device variant: "desktop" or "mobile" (default)
151
+ * @param title - Product title
152
+ * @param subtext - *(optional)* Subtitle text or JSX element (e.g. price)
153
+ * @param showSubtext - *(optional)* Show/hide subtext
154
+ * @param quantity - *(optional)* Current quantity value
155
+ * @param onQuantityChange - *(optional)* Callback when quantity changes
156
+ * @param showQuantityPicker - *(optional)* Show/hide quantity picker
157
+ * @param image - *(optional)* Image URL string or React element/JSX content
158
+ * @param imageBackgroundColor - *(optional)* Background color for image container (default: theme background.container.secondary)
159
+ * @param showImageQuantityBadge - *(optional)* Show/hide quantity badge overlay on image
160
+ * @param banner - *(optional)* Banner content to show below card
161
+ * @param showBanner - *(optional)* Show/hide banner
162
+ * @param bannerType - *(optional)* Banner notification type: "error", "success", "warning", or "info" (default)
163
+ * @param showBannerIcon - *(optional)* Show/hide banner notification icon
164
+ */
165
+ export const ProductDisplayCard = React.forwardRef<
166
+ View,
167
+ ProductDisplayCardProps
168
+ >(
169
+ (
170
+ {
171
+ device = "mobile",
172
+ title,
173
+ subtext,
174
+ showSubtext = true,
175
+ quantity = 1,
176
+ onQuantityChange,
177
+ showQuantityPicker = false,
178
+ disableQuantityButtons = false,
179
+ hideQuantityButtons = false,
180
+ showIncrementButton,
181
+ showDecrementButton,
182
+ incrementDisabled = false,
183
+ decrementDisabled = false,
184
+ image,
185
+ imageBackgroundColor,
186
+ showImageQuantityBadge = false,
187
+ banner,
188
+ showBanner = false,
189
+ bannerType = "info",
190
+ showBannerIcon = false,
191
+ ...rest
192
+ },
193
+ ref
194
+ ) => {
195
+ const handleQuantityChange = (newQuantity: number) => {
196
+ if (newQuantity >= 1) {
197
+ onQuantityChange?.(newQuantity)
198
+ }
199
+ }
200
+
201
+ const cardContent = (
202
+ <StyledCardContainer ref={ref} cardDevice={device} {...rest}>
203
+ {image && (
204
+ <StyledImage imageBackgroundColor={imageBackgroundColor}>
205
+ {typeof image === "string" ? (
206
+ <Image
207
+ source={{ uri: image }}
208
+ style={{ width: "100%", height: "100%" }}
209
+ />
210
+ ) : (
211
+ image
212
+ )}
213
+ {showImageQuantityBadge && quantity && (
214
+ <StyledQuantityBadge>
215
+ <Typography variant="body" size="sm" weight="bold">
216
+ {quantity}
217
+ </Typography>
218
+ </StyledQuantityBadge>
219
+ )}
220
+ </StyledImage>
221
+ )}
222
+
223
+ <StyledContentArea contentDevice={device}>
224
+ <StyledTextContainer>
225
+ <Typography variant="heading" size="xs" color="primary">
226
+ {title}
227
+ </Typography>
228
+
229
+ {showSubtext && subtext && (
230
+ <Typography variant="body" size="sm" color="secondary">
231
+ {subtext}
232
+ </Typography>
233
+ )}
234
+ </StyledTextContainer>
235
+
236
+ {showQuantityPicker && (
237
+ <View style={{ marginLeft: "auto" }}>
238
+ <NumberField
239
+ size="sm"
240
+ value={String(quantity)}
241
+ onChangeText={(text) => {
242
+ const value = parseInt(text, 10)
243
+ if (!isNaN(value)) {
244
+ handleQuantityChange(value)
245
+ }
246
+ }}
247
+ onIncrement={() => handleQuantityChange(quantity + 1)}
248
+ onDecrement={() => handleQuantityChange(quantity - 1)}
249
+ min={1}
250
+ accessible
251
+ accessibilityLabel={`Quantity: ${quantity}`}
252
+ showIncrementButton={
253
+ showIncrementButton !== undefined
254
+ ? showIncrementButton
255
+ : !hideQuantityButtons
256
+ }
257
+ showDecrementButton={
258
+ showDecrementButton !== undefined
259
+ ? showDecrementButton
260
+ : !hideQuantityButtons
261
+ }
262
+ incrementDisabled={incrementDisabled || disableQuantityButtons}
263
+ decrementDisabled={decrementDisabled || disableQuantityButtons}
264
+ />
265
+ </View>
266
+ )}
267
+ </StyledContentArea>
268
+ </StyledCardContainer>
269
+ )
270
+
271
+ if (showBanner && banner) {
272
+ return (
273
+ <StyledRootWrapper>
274
+ {cardContent}
275
+ <StyledBannerWrapper>
276
+ <StyledNotification
277
+ variant="inline"
278
+ type={bannerType}
279
+ showIcon={showBannerIcon}
280
+ >
281
+ {banner}
282
+ </StyledNotification>
283
+ </StyledBannerWrapper>
284
+ </StyledRootWrapper>
285
+ )
286
+ }
287
+
288
+ return cardContent
289
+ }
290
+ )
291
+
292
+ ProductDisplayCard.displayName = "ProductDisplayCard"
@@ -0,0 +1,5 @@
1
+ export { ProductDisplayCard } from "./ProductDisplayCard"
2
+ export type {
3
+ ProductDisplayCardProps,
4
+ ProductDisplayCardDevice
5
+ } from "./ProductDisplayCard"
@@ -0,0 +1,65 @@
1
+ import React from "react"
2
+ import { View, ViewProps } from "react-native"
3
+ import styled from "@emotion/native"
4
+ import { Typography } from "../../atoms/Typography"
5
+
6
+ const parseTokenValue = (value: string | number): number => {
7
+ if (typeof value === "number") return value
8
+ return parseFloat(value)
9
+ }
10
+
11
+ type BadgeOwnProps = {
12
+ icon?: React.ReactNode
13
+ text: React.ReactNode
14
+ }
15
+
16
+ export type BadgeProps = BadgeOwnProps & Omit<ViewProps, keyof BadgeOwnProps>
17
+
18
+ const BadgeContainer = styled(View)(({ theme }) => {
19
+ const spacing = theme.tokens.semantics.dimensions.spacing
20
+ const { sizing, borderRadius } = theme.tokens.semantics.dimensions
21
+ const { colour } = theme.tokens.semantics
22
+
23
+ return {
24
+ display: "flex",
25
+ flexDirection: "row",
26
+ gap: parseTokenValue(spacing["2xs"]),
27
+ alignItems: "center",
28
+ justifyContent: "center",
29
+ height: parseTokenValue(sizing["2xl"]),
30
+ paddingRight: parseTokenValue(spacing.sm),
31
+ backgroundColor: colour.background.container.alt,
32
+ borderTopRightRadius: parseTokenValue(borderRadius.xs),
33
+ borderBottomRightRadius: parseTokenValue(borderRadius.xs)
34
+ }
35
+ })
36
+
37
+ const BadgeIcon = styled(View)(({ theme }) => {
38
+ const spacing = theme.tokens.semantics.dimensions.spacing
39
+ const sizing = theme.tokens.semantics.dimensions.sizing
40
+
41
+ return {
42
+ display: "flex",
43
+ alignItems: "center",
44
+ justifyContent: "center",
45
+ width: parseTokenValue(sizing.md),
46
+ height: parseTokenValue(sizing.md),
47
+ marginLeft: parseTokenValue(spacing.xs),
48
+ flexShrink: 0
49
+ }
50
+ })
51
+
52
+ export const Badge = React.forwardRef<View, BadgeProps>(
53
+ ({ icon, text, ...rest }, ref) => {
54
+ return (
55
+ <BadgeContainer ref={ref} {...rest}>
56
+ {icon && <BadgeIcon>{icon}</BadgeIcon>}
57
+ <Typography variant="body" size="sm" weight="bold">
58
+ {text}
59
+ </Typography>
60
+ </BadgeContainer>
61
+ )
62
+ }
63
+ )
64
+
65
+ Badge.displayName = "ProductListingCard.Badge"
@@ -0,0 +1,59 @@
1
+ import React from "react"
2
+ import { View, ViewProps, useWindowDimensions } from "react-native"
3
+ import styled from "@emotion/native"
4
+ import { DEFAULT_THEME_OPTIONS } from "@butternutbox/pawprint-tokens"
5
+
6
+ type ProductListingCardGridOwnProps = {
7
+ children: React.ReactNode
8
+ xs?: number
9
+ md?: number
10
+ lg?: number
11
+ }
12
+
13
+ export type ProductListingCardGridProps = ProductListingCardGridOwnProps &
14
+ Omit<ViewProps, keyof ProductListingCardGridOwnProps>
15
+
16
+ const StyledGrid = styled(View)(({ theme }) => {
17
+ const spacing = theme.tokens.semantics.dimensions.spacing
18
+
19
+ return {
20
+ display: "grid",
21
+ "grid-column-gap": spacing.sm,
22
+ "grid-row-gap": spacing.xl
23
+ } as any
24
+ })
25
+
26
+ export const Grid = React.forwardRef<View, ProductListingCardGridProps>(
27
+ ({ children, xs = 1, md = 2, lg = 3, ...rest }, ref) => {
28
+ const { width } = useWindowDimensions()
29
+
30
+ const breakpoints =
31
+ DEFAULT_THEME_OPTIONS.tokens.semantics.dimensions.breakpoints.spacing
32
+ const SM_BREAKPOINT = parseFloat(String(breakpoints.sm))
33
+ const MD_BREAKPOINT = parseFloat(String(breakpoints.md))
34
+
35
+ const getItemsPerRow = () => {
36
+ if (width >= MD_BREAKPOINT) return lg
37
+ if (width >= SM_BREAKPOINT) return md
38
+ return xs
39
+ }
40
+
41
+ const itemsPerRow = getItemsPerRow()
42
+
43
+ return (
44
+ <StyledGrid
45
+ ref={ref}
46
+ style={
47
+ {
48
+ gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`
49
+ } as any
50
+ }
51
+ {...rest}
52
+ >
53
+ {children}
54
+ </StyledGrid>
55
+ )
56
+ }
57
+ )
58
+
59
+ Grid.displayName = "ProductListingCard.Grid"
@@ -0,0 +1,209 @@
1
+ import React from "react"
2
+ import { View } from "react-native"
3
+ import { ProductListingCard } from "./ProductListingCard"
4
+ import { Badge } from "./Badge"
5
+ import { ThumbsUpFilledPrimary } from "@butternutbox/pawprint-icons/marketing"
6
+
7
+ const defaultBadge = (
8
+ <Badge icon={<ThumbsUpFilledPrimary />} text="New & improved" />
9
+ )
10
+
11
+ const placeholderImage = {
12
+ uri: "https://placehold.co/232x232"
13
+ }
14
+
15
+ export default {
16
+ title: "Molecules/ProductListingCard",
17
+ component: ProductListingCard,
18
+ argTypes: {
19
+ image: {
20
+ description: "Product image source"
21
+ },
22
+ imageAlt: {
23
+ control: "text",
24
+ description: "Alt text for the product image"
25
+ },
26
+ badge: {
27
+ description: "Badge content to display in the top-left corner"
28
+ },
29
+ category: {
30
+ description: "Product category Typography element(s)"
31
+ },
32
+ title: {
33
+ description: "Product name/title Typography element(s)"
34
+ },
35
+ size: {
36
+ description: "Product size or variant Typography element(s)"
37
+ },
38
+ price: {
39
+ description: "Price content Typography element(s)"
40
+ },
41
+ showBadge: {
42
+ control: "boolean",
43
+ description: "Toggle badge visibility"
44
+ },
45
+ showCategory: {
46
+ control: "boolean",
47
+ description: "Toggle category visibility"
48
+ },
49
+ showTitle: {
50
+ control: "boolean",
51
+ description: "Toggle product title visibility"
52
+ },
53
+ showSize: {
54
+ control: "boolean",
55
+ description: "Toggle product size visibility"
56
+ },
57
+ showPrice: {
58
+ control: "boolean",
59
+ description: "Toggle price visibility"
60
+ }
61
+ }
62
+ }
63
+
64
+ export const Default = {
65
+ render: () => (
66
+ <View style={{ width: 232, alignSelf: "flex-start" }}>
67
+ <ProductListingCard
68
+ image={placeholderImage}
69
+ imageAlt="Fish Oil Product"
70
+ badge={defaultBadge}
71
+ category="Daily supplements"
72
+ title="Fish Oil"
73
+ size="200ml"
74
+ price="From £7.49"
75
+ showBadge={true}
76
+ showCategory={true}
77
+ showTitle={true}
78
+ showSize={true}
79
+ showPrice={true}
80
+ />
81
+ </View>
82
+ )
83
+ }
84
+
85
+ export const WithoutBadge = {
86
+ render: () => (
87
+ <View style={{ width: 232, alignSelf: "flex-start" }}>
88
+ <ProductListingCard
89
+ image={placeholderImage}
90
+ imageAlt="Fish Oil Product"
91
+ category="Daily supplements"
92
+ title="Fish Oil"
93
+ size="200ml"
94
+ price="From £7.49"
95
+ showBadge={false}
96
+ showCategory={true}
97
+ showTitle={true}
98
+ showSize={true}
99
+ showPrice={true}
100
+ />
101
+ </View>
102
+ )
103
+ }
104
+
105
+ export const MinimalInfo = {
106
+ render: () => (
107
+ <View style={{ width: 232, alignSelf: "flex-start" }}>
108
+ <ProductListingCard
109
+ image={{ uri: "https://placeholder.co/232x232" }}
110
+ imageAlt="Product"
111
+ title="Product Name"
112
+ price="£9.99"
113
+ showBadge={false}
114
+ showCategory={false}
115
+ showSize={false}
116
+ />
117
+ </View>
118
+ )
119
+ }
120
+
121
+ export const FullyCustomized = {
122
+ render: () => (
123
+ <View style={{ width: 232, alignSelf: "flex-start" }}>
124
+ <ProductListingCard
125
+ image={{ uri: "https://placehold.co/232x232" }}
126
+ imageAlt="Premium Item"
127
+ badge={<Badge icon="⭐" text="Premium" />}
128
+ category="Premium Collection"
129
+ title="Deluxe Supplement Pack"
130
+ size="500ml x 3 bottles"
131
+ price="From £24.99"
132
+ showBadge={true}
133
+ showCategory={true}
134
+ showTitle={true}
135
+ showSize={true}
136
+ showPrice={true}
137
+ />
138
+ </View>
139
+ )
140
+ }
141
+
142
+ export const Grid = {
143
+ render: () => (
144
+ <View style={{ width: "100%", padding: 16 }}>
145
+ <ProductListingCard.Grid xs={1} md={2} lg={3}>
146
+ {Array.from({ length: 6 }).map((_, i) => (
147
+ <ProductListingCard
148
+ key={i}
149
+ image={placeholderImage}
150
+ imageAlt="Fish Oil Product"
151
+ badge={defaultBadge}
152
+ category="Daily supplements"
153
+ title="Fish Oil"
154
+ size="200ml"
155
+ price="From £7.49"
156
+ showBadge={true}
157
+ showCategory={true}
158
+ showTitle={true}
159
+ showSize={true}
160
+ showPrice={true}
161
+ />
162
+ ))}
163
+ </ProductListingCard.Grid>
164
+ </View>
165
+ )
166
+ }
167
+
168
+ export const Playground = {
169
+ render: () => (
170
+ <View style={{ width: 232, alignSelf: "flex-start" }}>
171
+ <ProductListingCard
172
+ image={placeholderImage}
173
+ imageAlt="Fish Oil Product"
174
+ badge={defaultBadge}
175
+ category="Daily supplements"
176
+ title="Fish Oil"
177
+ size="200ml"
178
+ price="From £7.49"
179
+ showBadge={true}
180
+ showCategory={true}
181
+ showTitle={true}
182
+ showSize={true}
183
+ showPrice={true}
184
+ />
185
+ </View>
186
+ )
187
+ }
188
+
189
+ export const WithWasPrice = {
190
+ render: () => (
191
+ <View style={{ width: 232, alignSelf: "flex-start" }}>
192
+ <ProductListingCard
193
+ image={placeholderImage}
194
+ imageAlt="Fish Oil Product"
195
+ badge={defaultBadge}
196
+ category="Daily supplements"
197
+ title="Fish Oil"
198
+ size="200ml"
199
+ price="From £7.49"
200
+ wasPrice="£12.50"
201
+ showBadge={true}
202
+ showCategory={true}
203
+ showTitle={true}
204
+ showSize={true}
205
+ showPrice={true}
206
+ />
207
+ </View>
208
+ )
209
+ }