@shopify/shop-minis-cli 0.0.35

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 (152) hide show
  1. package/README.md +8 -0
  2. package/build/commands/create-mini/index.d.ts +2 -0
  3. package/build/commands/create-mini/index.js +116 -0
  4. package/build/commands/create-mini/index.js.map +1 -0
  5. package/build/commands/create-mini/utils/template-app.d.ts +1 -0
  6. package/build/commands/create-mini/utils/template-app.js +44 -0
  7. package/build/commands/create-mini/utils/template-app.js.map +1 -0
  8. package/build/commands/dev/index.d.ts +6 -0
  9. package/build/commands/dev/index.js +31 -0
  10. package/build/commands/dev/index.js.map +1 -0
  11. package/build/commands/dev/utils/android.d.ts +16 -0
  12. package/build/commands/dev/utils/android.js +165 -0
  13. package/build/commands/dev/utils/android.js.map +1 -0
  14. package/build/commands/dev/utils/binaries.d.ts +83 -0
  15. package/build/commands/dev/utils/binaries.js +173 -0
  16. package/build/commands/dev/utils/binaries.js.map +1 -0
  17. package/build/commands/dev/utils/binaries.test.d.ts +1 -0
  18. package/build/commands/dev/utils/binaries.test.js +275 -0
  19. package/build/commands/dev/utils/binaries.test.js.map +1 -0
  20. package/build/commands/dev/utils/deeplink.d.ts +3 -0
  21. package/build/commands/dev/utils/deeplink.js +30 -0
  22. package/build/commands/dev/utils/deeplink.js.map +1 -0
  23. package/build/commands/dev/utils/interactive-terminal.d.ts +23 -0
  24. package/build/commands/dev/utils/interactive-terminal.js +252 -0
  25. package/build/commands/dev/utils/interactive-terminal.js.map +1 -0
  26. package/build/commands/dev/utils/metro/metro-config.d.ts +2 -0
  27. package/build/commands/dev/utils/metro/metro-config.js +31 -0
  28. package/build/commands/dev/utils/metro/metro-config.js.map +1 -0
  29. package/build/commands/dev/utils/metro/metro-reporter.d.ts +14 -0
  30. package/build/commands/dev/utils/metro/metro-reporter.js +34 -0
  31. package/build/commands/dev/utils/metro/metro-reporter.js.map +1 -0
  32. package/build/commands/dev/utils/metro/metro-server-middleware.d.ts +6 -0
  33. package/build/commands/dev/utils/metro/metro-server-middleware.js +45 -0
  34. package/build/commands/dev/utils/metro/metro-server-middleware.js.map +1 -0
  35. package/build/commands/dev/utils/metro/metro-server.d.ts +2 -0
  36. package/build/commands/dev/utils/metro/metro-server.js +24 -0
  37. package/build/commands/dev/utils/metro/metro-server.js.map +1 -0
  38. package/build/commands/dev/utils/minis-manifest.d.ts +1 -0
  39. package/build/commands/dev/utils/minis-manifest.js +24 -0
  40. package/build/commands/dev/utils/minis-manifest.js.map +1 -0
  41. package/build/commands/dev/utils/qr-code.d.ts +1 -0
  42. package/build/commands/dev/utils/qr-code.js +12 -0
  43. package/build/commands/dev/utils/qr-code.js.map +1 -0
  44. package/build/commands/dev/utils/simulator.d.ts +19 -0
  45. package/build/commands/dev/utils/simulator.js +89 -0
  46. package/build/commands/dev/utils/simulator.js.map +1 -0
  47. package/build/commands/dev/utils/with-retries.d.ts +4 -0
  48. package/build/commands/dev/utils/with-retries.js +28 -0
  49. package/build/commands/dev/utils/with-retries.js.map +1 -0
  50. package/build/commands/generate-graphql-types/index.d.ts +5 -0
  51. package/build/commands/generate-graphql-types/index.js +90 -0
  52. package/build/commands/generate-graphql-types/index.js.map +1 -0
  53. package/build/commands/utils/exec-async-child-process.d.ts +18 -0
  54. package/build/commands/utils/exec-async-child-process.js +48 -0
  55. package/build/commands/utils/exec-async-child-process.js.map +1 -0
  56. package/build/commands/utils/wrap-with-loading-indicator.d.ts +9 -0
  57. package/build/commands/utils/wrap-with-loading-indicator.js +23 -0
  58. package/build/commands/utils/wrap-with-loading-indicator.js.map +1 -0
  59. package/build/dev-panel/images/bottomsheet.png +0 -0
  60. package/build/dev-panel/images/checkmark.svg +3 -0
  61. package/build/dev-panel/images/chevron.svg +3 -0
  62. package/build/dev-panel/images/copy.svg +4 -0
  63. package/build/dev-panel/images/get-started.svg +3 -0
  64. package/build/dev-panel/images/how-to.svg +3 -0
  65. package/build/dev-panel/images/navigation.png +0 -0
  66. package/build/dev-panel/images/references.svg +3 -0
  67. package/build/dev-panel/images/shop-minis-logo-inverse.svg +5 -0
  68. package/build/dev-panel/images/shop-minis-logo.svg +5 -0
  69. package/build/dev-panel/images/stories.png +0 -0
  70. package/build/dev-panel/images/topics.svg +3 -0
  71. package/build/dev-panel/index.html +302 -0
  72. package/build/dev-panel/middleware.d.ts +4 -0
  73. package/build/dev-panel/middleware.js +11 -0
  74. package/build/dev-panel/middleware.js.map +1 -0
  75. package/build/dev-panel/middleware.ts +6 -0
  76. package/build/dev-panel/styles.css +507 -0
  77. package/build/index.d.ts +2 -0
  78. package/build/index.js +26 -0
  79. package/build/index.js.map +1 -0
  80. package/package.json +83 -0
  81. package/templates/__template_blank/src/custom.d.ts +4 -0
  82. package/templates/__template_blank/src/index.tsx +9 -0
  83. package/templates/__template_blank/src/screens/HomeScreen.tsx +12 -0
  84. package/templates/__template_blank/src/types.ts +5 -0
  85. package/templates/__template_common/.eslintignore +1 -0
  86. package/templates/__template_common/.eslintrc.json +132 -0
  87. package/templates/__template_common/.prettierrc.json +8 -0
  88. package/templates/__template_common/babel.config.js +19 -0
  89. package/templates/__template_common/gitignore +3 -0
  90. package/templates/__template_common/index.tsx +43 -0
  91. package/templates/__template_common/metro.config.js +31 -0
  92. package/templates/__template_common/package.json +68 -0
  93. package/templates/__template_common/patches/react-native+0.68.5.patch +173 -0
  94. package/templates/__template_common/src/manifest.json +29 -0
  95. package/templates/__template_common/tsconfig.json +36 -0
  96. package/templates/__template_hello_world/src/assets/Modal-component-thumbnail.png +0 -0
  97. package/templates/__template_hello_world/src/assets/ProductCard-component-thumbnail.png +0 -0
  98. package/templates/__template_hello_world/src/assets/ProductLink-component-thumbnail.png +0 -0
  99. package/templates/__template_hello_world/src/assets/assets.d.ts +4 -0
  100. package/templates/__template_hello_world/src/assets/figma-logo.svg +14 -0
  101. package/templates/__template_hello_world/src/assets/shop-minis-logo.svg +7 -0
  102. package/templates/__template_hello_world/src/components/ButtonCTA.tsx +31 -0
  103. package/templates/__template_hello_world/src/components/ComponentLink.ts +70 -0
  104. package/templates/__template_hello_world/src/components/ComponentListItem.tsx +38 -0
  105. package/templates/__template_hello_world/src/components/FeaturedComponents.tsx +108 -0
  106. package/templates/__template_hello_world/src/components/Header.tsx +40 -0
  107. package/templates/__template_hello_world/src/data/Test.graphql +33 -0
  108. package/templates/__template_hello_world/src/data/Test.graphql.d.ts +114 -0
  109. package/templates/__template_hello_world/src/data/TestProducts.graphql +34 -0
  110. package/templates/__template_hello_world/src/data/TestProducts.graphql.d.ts +119 -0
  111. package/templates/__template_hello_world/src/index.tsx +9 -0
  112. package/templates/__template_hello_world/src/routes.tsx +107 -0
  113. package/templates/__template_hello_world/src/screens/AvatarScreen.tsx +95 -0
  114. package/templates/__template_hello_world/src/screens/BottomSheetScreen.tsx +711 -0
  115. package/templates/__template_hello_world/src/screens/ButtonsScreen.tsx +90 -0
  116. package/templates/__template_hello_world/src/screens/GridScreen.tsx +74 -0
  117. package/templates/__template_hello_world/src/screens/HomeScreen.tsx +70 -0
  118. package/templates/__template_hello_world/src/screens/IconsScreen.tsx +181 -0
  119. package/templates/__template_hello_world/src/screens/MediaScreen.tsx +130 -0
  120. package/templates/__template_hello_world/src/screens/ModalScreen.tsx +379 -0
  121. package/templates/__template_hello_world/src/screens/ProductCardGridScreen.tsx +68 -0
  122. package/templates/__template_hello_world/src/screens/ProductCardScreen.tsx +62 -0
  123. package/templates/__template_hello_world/src/screens/ProductLinkScreen.tsx +215 -0
  124. package/templates/__template_hello_world/src/screens/ProgressIndicatorScreen.tsx +77 -0
  125. package/templates/__template_hello_world/src/screens/QuantityPickerScreen.tsx +76 -0
  126. package/templates/__template_hello_world/src/screens/SpinnerScreen.tsx +63 -0
  127. package/templates/__template_hello_world/src/screens/TypographyScreen.tsx +274 -0
  128. package/templates/__template_hello_world/src/screens/WebViewScreen.tsx +42 -0
  129. package/templates/__template_hello_world/src/types.ts +25 -0
  130. package/templates/__template_snowboardz/src/assets/assets.d.ts +4 -0
  131. package/templates/__template_snowboardz/src/assets/circle-blue.svg +9 -0
  132. package/templates/__template_snowboardz/src/assets/circle-green.svg +9 -0
  133. package/templates/__template_snowboardz/src/assets/circle-purple.svg +9 -0
  134. package/templates/__template_snowboardz/src/assets/circle-rainbow.svg +34 -0
  135. package/templates/__template_snowboardz/src/assets/circle-red.svg +9 -0
  136. package/templates/__template_snowboardz/src/assets/circle-yellow.svg +9 -0
  137. package/templates/__template_snowboardz/src/assets/skill-level-icon-advanced.svg +3 -0
  138. package/templates/__template_snowboardz/src/assets/skill-level-icon-beginner.svg +3 -0
  139. package/templates/__template_snowboardz/src/assets/skill-level-icon-intermediate.svg +3 -0
  140. package/templates/__template_snowboardz/src/components/ColorButton.tsx +79 -0
  141. package/templates/__template_snowboardz/src/components/ColorPicker.tsx +40 -0
  142. package/templates/__template_snowboardz/src/components/EmptyResult.tsx +52 -0
  143. package/templates/__template_snowboardz/src/components/SkillLevelIcon.tsx +44 -0
  144. package/templates/__template_snowboardz/src/components/SkillLevelPicker.tsx +86 -0
  145. package/templates/__template_snowboardz/src/data/TestProducts.graphql +34 -0
  146. package/templates/__template_snowboardz/src/data/TestProducts.graphql.d.ts +108 -0
  147. package/templates/__template_snowboardz/src/hooks/useSnowboardData.tsx +37 -0
  148. package/templates/__template_snowboardz/src/index.tsx +9 -0
  149. package/templates/__template_snowboardz/src/routes.tsx +17 -0
  150. package/templates/__template_snowboardz/src/screens/HomeScreen.tsx +126 -0
  151. package/templates/__template_snowboardz/src/types.ts +12 -0
  152. package/templates/__template_snowboardz/src/utils.ts +17 -0
@@ -0,0 +1,711 @@
1
+ import {ComponentProps, useCallback, useState} from 'react'
2
+ import {SafeAreaView, ScrollView, TouchableOpacity} from 'react-native'
3
+ import Animated from 'react-native-reanimated'
4
+ import {
5
+ Button,
6
+ Box,
7
+ Text,
8
+ FlatListBottomSheet,
9
+ ProductCardGridBottomSheet,
10
+ ScrollViewBottomSheet,
11
+ SectionListBottomSheet,
12
+ useTheme,
13
+ useMinisQuery,
14
+ TouchableProduct,
15
+ ProductCard,
16
+ Avatar,
17
+ useBottomSheet,
18
+ GridBottomSheet,
19
+ useScrollViewBottomSheet,
20
+ useGridBottomSheet,
21
+ useFlatListBottomSheet,
22
+ useProductCardGridBottomSheet,
23
+ useSectionListBottomSheet,
24
+ } from '@shopify/shop-minis-platform-sdk'
25
+
26
+ import {Header} from '../components/Header'
27
+ import TestProductsQuery from '../data/TestProducts.graphql'
28
+
29
+ const SHOP_GID = 'gid://shopify/Shop/68822335510'
30
+ const PRODUCT_GIDS = [
31
+ 'gid://shopify/Product/7982542651414',
32
+ 'gid://shopify/Product/7982528397334',
33
+ 'gid://shopify/Product/7982535704598',
34
+ 'gid://shopify/Product/7982577352726',
35
+ 'gid://shopify/Product/7982564245526',
36
+ 'gid://shopify/Product/7982547763222',
37
+ 'gid://shopify/Product/7982499495958',
38
+ 'gid://shopify/Product/7982540521494',
39
+ 'gid://shopify/Product/7982554710038',
40
+ 'gid://shopify/Product/7982557200406',
41
+ 'gid://shopify/Product/7982571257878',
42
+ 'gid://shopify/Product/7982372388886',
43
+ ]
44
+
45
+ const DemoContent = ({length = 50}: {length?: number}) => (
46
+ <>
47
+ {Array.from({length}, (_, index) => (
48
+ <Box key={`item-${index}`} marginBottom="s" marginHorizontal="gutter">
49
+ <Text>item {index + 1}</Text>
50
+ </Box>
51
+ ))}
52
+ </>
53
+ )
54
+
55
+ const ExampleFlatList = ({
56
+ onDismiss,
57
+ }: {
58
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
59
+ }) => {
60
+ return (
61
+ <FlatListBottomSheet
62
+ onDismiss={onDismiss}
63
+ data={Array.from({length: 50}, (_, index) => ({
64
+ key: index,
65
+ title: `Thing ${index + 1}`,
66
+ }))}
67
+ renderItem={({item}) => {
68
+ return (
69
+ <Box key={item.key} marginBottom="s" marginHorizontal="gutter">
70
+ <Text>{item.title}</Text>
71
+ </Box>
72
+ )
73
+ }}
74
+ />
75
+ )
76
+ }
77
+
78
+ const ExampleGrid = ({
79
+ onDismiss,
80
+ }: {
81
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
82
+ }) => {
83
+ const theme = useTheme()
84
+ const data = Array.from({length: 50}, (_, index) => ({
85
+ text: `Item ${index + 1}`,
86
+ }))
87
+
88
+ return (
89
+ <GridBottomSheet
90
+ onDismiss={onDismiss}
91
+ data={data}
92
+ renderItem={({item}) => (
93
+ <Box
94
+ minHeight={200}
95
+ backgroundColor="backgrounds-success"
96
+ justifyContent="center"
97
+ alignItems="center"
98
+ >
99
+ <Text>{item.text}</Text>
100
+ </Box>
101
+ )}
102
+ contentContainerStyle={{
103
+ paddingHorizontal: theme.spacing.gutter,
104
+ paddingBottom: theme.spacing.m,
105
+ }}
106
+ />
107
+ )
108
+ }
109
+
110
+ const ExampleProductCardGrid = ({
111
+ onDismiss,
112
+ }: {
113
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
114
+ }) => {
115
+ const theme = useTheme()
116
+
117
+ const {loading, data} = useMinisQuery(TestProductsQuery, {
118
+ variables: {
119
+ shopId: SHOP_GID,
120
+ productIds: PRODUCT_GIDS,
121
+ },
122
+ })
123
+
124
+ const products = data?.shop?.productsByIds ?? []
125
+
126
+ // TODO: It would be nice to handle this inside the bottomsheet with a spinner
127
+ if (loading || !data) return null
128
+
129
+ return (
130
+ <ProductCardGridBottomSheet
131
+ onDismiss={onDismiss}
132
+ products={products}
133
+ renderItem={({product}) => (
134
+ <TouchableProduct product={product} key={product.id}>
135
+ <ProductCard shopId={SHOP_GID} product={product} />
136
+ </TouchableProduct>
137
+ )}
138
+ contentContainerStyle={{
139
+ paddingHorizontal: theme.spacing.gutter,
140
+ paddingBottom: theme.spacing.m,
141
+ }}
142
+ />
143
+ )
144
+ }
145
+
146
+ const ExampleScrollView1 = ({
147
+ onDismiss,
148
+ }: {
149
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
150
+ }) => {
151
+ return (
152
+ <ScrollViewBottomSheet onDismiss={onDismiss}>
153
+ <DemoContent />
154
+ </ScrollViewBottomSheet>
155
+ )
156
+ }
157
+
158
+ const ExampleScrollView2 = ({
159
+ onDismiss,
160
+ }: {
161
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
162
+ }) => {
163
+ const [answer, setAnswer] = useState<number | null>(null)
164
+
165
+ return (
166
+ <ScrollViewBottomSheet
167
+ onDismiss={onDismiss}
168
+ variant="header"
169
+ headerText="Poll"
170
+ >
171
+ <Box marginBottom="m" marginHorizontal="gutter">
172
+ <Avatar
173
+ color="foregrounds-regular"
174
+ title="Mother Goose"
175
+ source={{uri: 'https://picsum.photos/150/150'}}
176
+ />
177
+ </Box>
178
+
179
+ <Box marginBottom="m" marginHorizontal="gutter">
180
+ <Text>
181
+ How much wood could a woodchuck chuck if a woodchuck could chuck wood?
182
+ </Text>
183
+ </Box>
184
+
185
+ <Box marginBottom="s" marginHorizontal="gutter">
186
+ <Button
187
+ text="5"
188
+ variant={answer === 5 ? 'primary' : 'outlined'}
189
+ onPress={() => setAnswer(5)}
190
+ />
191
+ </Box>
192
+ <Box marginBottom="s" marginHorizontal="gutter">
193
+ <Button
194
+ text="10"
195
+ variant={answer === 10 ? 'primary' : 'outlined'}
196
+ onPress={() => setAnswer(10)}
197
+ />
198
+ </Box>
199
+ <Box marginBottom="s" marginHorizontal="gutter">
200
+ <Button
201
+ text="500"
202
+ variant={answer === 500 ? 'primary' : 'outlined'}
203
+ onPress={() => setAnswer(500)}
204
+ />
205
+ </Box>
206
+ <Box marginBottom="s" marginHorizontal="gutter">
207
+ <Button
208
+ text="10000"
209
+ variant={answer === 10000 ? 'primary' : 'outlined'}
210
+ onPress={() => setAnswer(10000)}
211
+ />
212
+ </Box>
213
+ </ScrollViewBottomSheet>
214
+ )
215
+ }
216
+
217
+ const ExampleSectionList = ({
218
+ onDismiss,
219
+ }: {
220
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
221
+ }) => {
222
+ return (
223
+ <SectionListBottomSheet
224
+ onDismiss={onDismiss}
225
+ sections={Array.from({length: 50}, (_, index) => ({
226
+ title: `Section ${index + 1}`,
227
+ data: ['1', '2', '3', '4', '5'],
228
+ }))}
229
+ renderSectionHeader={({section: {title}}) => (
230
+ <Box padding="s" backgroundColor="backgrounds-success">
231
+ <Text variant="heroBold">{title}</Text>
232
+ </Box>
233
+ )}
234
+ renderItem={({item}) => (
235
+ <Box padding="s">
236
+ <Text>{item}</Text>
237
+ </Box>
238
+ )}
239
+ />
240
+ )
241
+ }
242
+
243
+ const ExampleSnapPoints = ({
244
+ onDismiss,
245
+ }: {
246
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
247
+ }) => {
248
+ return (
249
+ <FlatListBottomSheet
250
+ onDismiss={onDismiss}
251
+ snapPoints={{
252
+ positionOne: 200,
253
+ positionTwo: 500,
254
+ }}
255
+ data={Array.from({length: 50}, (_, index) => ({
256
+ key: index,
257
+ title: `Thing ${index + 1}`,
258
+ }))}
259
+ renderItem={({item}) => {
260
+ return (
261
+ <Box key={item.key} marginBottom="s" marginHorizontal="gutter">
262
+ <Text>{item.title}</Text>
263
+ </Box>
264
+ )
265
+ }}
266
+ />
267
+ )
268
+ }
269
+
270
+ const ExampleVariants = ({
271
+ onDismiss,
272
+ }: {
273
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
274
+ }) => {
275
+ return (
276
+ <FlatListBottomSheet
277
+ onDismiss={onDismiss}
278
+ variant="handle"
279
+ data={Array.from({length: 50}, (_, index) => ({
280
+ key: index,
281
+ title: `Thing ${index + 1}`,
282
+ }))}
283
+ renderItem={({item}) => {
284
+ return (
285
+ <Box key={item.key} paddingBottom="s" paddingHorizontal="m">
286
+ <Text>{item.title}</Text>
287
+ </Box>
288
+ )
289
+ }}
290
+ />
291
+ )
292
+ }
293
+
294
+ const ExampleUseBottomSheet = ({
295
+ onDismiss,
296
+ }: {
297
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
298
+ }) => {
299
+ const theme = useTheme()
300
+
301
+ const scrollToTop = useCallback((ref?: Animated.ScrollView) => {
302
+ ref?.scrollTo({y: 0, animated: false})
303
+ }, [])
304
+
305
+ const {BottomSheet, scrollRef, onScroll, dismissBottomSheet} =
306
+ useBottomSheet<Animated.ScrollView>({
307
+ onDismiss,
308
+ scrollToTop,
309
+ })
310
+
311
+ return (
312
+ <BottomSheet>
313
+ <Animated.ScrollView
314
+ ref={scrollRef}
315
+ style={[
316
+ {
317
+ flex: 1,
318
+ elevation: 10,
319
+ backgroundColor: theme.colors['backgrounds-regular'],
320
+ },
321
+ ]}
322
+ indicatorStyle={theme.type === 'dark' ? 'white' : 'black'}
323
+ onScrollBeginDrag={onScroll}
324
+ onScroll={onScroll}
325
+ scrollEventThrottle={1}
326
+ >
327
+ <Box marginBottom="s" marginHorizontal="gutter">
328
+ <Text>
329
+ When using useBottomSheet directly you can programmatically close
330
+ the bottomsheet
331
+ </Text>
332
+ </Box>
333
+
334
+ <Box marginBottom="s" marginHorizontal="gutter">
335
+ <Button text="Close" onPress={dismissBottomSheet} />
336
+ </Box>
337
+
338
+ <DemoContent />
339
+ </Animated.ScrollView>
340
+ </BottomSheet>
341
+ )
342
+ }
343
+
344
+ const ExampleUseScrollViewBottomSheet = ({
345
+ onDismiss,
346
+ }: {
347
+ onDismiss: ComponentProps<typeof ScrollViewBottomSheet>['onDismiss']
348
+ }) => {
349
+ // Aliasing because we already have `ScrollViewBottomSheet` imported
350
+ const {
351
+ ScrollViewBottomSheet: ScrollViewBottomSheetComponent,
352
+ dismissBottomSheet,
353
+ } = useScrollViewBottomSheet({
354
+ onDismiss,
355
+ })
356
+
357
+ return (
358
+ <ScrollViewBottomSheetComponent>
359
+ <Box marginBottom="s" marginHorizontal="gutter">
360
+ <Text>
361
+ When using useScrollViewBottomSheet directly you can programmatically
362
+ close the bottomsheet
363
+ </Text>
364
+ </Box>
365
+
366
+ <Box marginBottom="s" marginHorizontal="gutter">
367
+ <Button text="Close" onPress={dismissBottomSheet} />
368
+ </Box>
369
+
370
+ <DemoContent />
371
+ </ScrollViewBottomSheetComponent>
372
+ )
373
+ }
374
+
375
+ const ExampleUseGridBottomSheet = ({
376
+ onDismiss,
377
+ }: {
378
+ onDismiss: ComponentProps<typeof GridBottomSheet>['onDismiss']
379
+ }) => {
380
+ const theme = useTheme()
381
+
382
+ // Aliasing because we already have `GridBottomSheet` imported
383
+ const {GridBottomSheet: GridBottomSheetComponent, dismissBottomSheet} =
384
+ useGridBottomSheet({
385
+ onDismiss,
386
+ })
387
+
388
+ const data = Array.from({length: 50}, (_, index) => ({
389
+ text: `Item ${index + 1}`,
390
+ }))
391
+
392
+ return (
393
+ <GridBottomSheetComponent
394
+ data={data}
395
+ renderItem={({item}) => (
396
+ <TouchableOpacity onPress={dismissBottomSheet}>
397
+ <Box
398
+ minHeight={200}
399
+ backgroundColor="backgrounds-subdued"
400
+ justifyContent="center"
401
+ alignItems="center"
402
+ >
403
+ <Text>{item.text}</Text>
404
+ <Text>Press to close</Text>
405
+ </Box>
406
+ </TouchableOpacity>
407
+ )}
408
+ contentContainerStyle={{
409
+ paddingHorizontal: theme.spacing.gutter,
410
+ paddingBottom: theme.spacing.m,
411
+ }}
412
+ />
413
+ )
414
+ }
415
+
416
+ const ExampleUseProductCardGridBottomSheet = ({
417
+ onDismiss,
418
+ }: {
419
+ onDismiss: ComponentProps<typeof ProductCardGridBottomSheet>['onDismiss']
420
+ }) => {
421
+ const theme = useTheme()
422
+
423
+ // Aliasing because we already have `ProductCardGridBottomSheet` imported
424
+ const {
425
+ ProductCardGridBottomSheet: ProductCardGridBottomSheetComponent,
426
+ dismissBottomSheet,
427
+ } = useProductCardGridBottomSheet({
428
+ onDismiss,
429
+ })
430
+
431
+ const {loading, data} = useMinisQuery(TestProductsQuery, {
432
+ variables: {
433
+ shopId: SHOP_GID,
434
+ productIds: PRODUCT_GIDS,
435
+ },
436
+ })
437
+
438
+ const products = data?.shop?.productsByIds ?? []
439
+
440
+ // TODO: It would be nice to handle this inside the bottomsheet with a spinner
441
+ if (loading || !data) return null
442
+
443
+ return (
444
+ <ProductCardGridBottomSheetComponent
445
+ products={products}
446
+ ListHeaderComponent={
447
+ <Box paddingBottom="s" paddingHorizontal="gutter">
448
+ <Button text="Close" onPress={dismissBottomSheet} />
449
+ </Box>
450
+ }
451
+ renderItem={({product}) => (
452
+ <TouchableProduct product={product} key={product.id}>
453
+ <ProductCard shopId={SHOP_GID} product={product} />
454
+ </TouchableProduct>
455
+ )}
456
+ contentContainerStyle={{
457
+ paddingHorizontal: theme.spacing.gutter,
458
+ paddingBottom: theme.spacing.m,
459
+ }}
460
+ />
461
+ )
462
+ }
463
+
464
+ const ExampleUseFlatListBottomSheet = ({
465
+ onDismiss,
466
+ }: {
467
+ onDismiss: ComponentProps<typeof FlatListBottomSheet>['onDismiss']
468
+ }) => {
469
+ // Aliasing because we already have `FlatListBottomSheet` imported
470
+ const {
471
+ FlatListBottomSheet: FlatListBottomSheetComponent,
472
+ dismissBottomSheet,
473
+ } = useFlatListBottomSheet({
474
+ onDismiss,
475
+ })
476
+
477
+ return (
478
+ <FlatListBottomSheetComponent
479
+ data={Array.from({length: 50}, (_, index) => ({
480
+ key: index,
481
+ title: `Thing ${index + 1}`,
482
+ }))}
483
+ renderItem={({item}) => {
484
+ return (
485
+ <TouchableOpacity onPress={dismissBottomSheet}>
486
+ <Box
487
+ key={item.key}
488
+ marginBottom="s"
489
+ padding="s"
490
+ marginHorizontal="gutter"
491
+ backgroundColor="backgrounds-dangerous"
492
+ >
493
+ <Text>{item.title}</Text>
494
+ <Text>Touch to close</Text>
495
+ </Box>
496
+ </TouchableOpacity>
497
+ )
498
+ }}
499
+ />
500
+ )
501
+ }
502
+
503
+ const ExampleUseSectionListBottomSheet = ({
504
+ onDismiss,
505
+ }: {
506
+ onDismiss: ComponentProps<typeof SectionListBottomSheet>['onDismiss']
507
+ }) => {
508
+ // Aliasing because we already have `SectionListBottomSheet` imported
509
+ const {
510
+ SectionListBottomSheet: SectionListBottomSheetComponent,
511
+ dismissBottomSheet,
512
+ } = useSectionListBottomSheet({
513
+ onDismiss,
514
+ })
515
+
516
+ return (
517
+ <SectionListBottomSheetComponent
518
+ sections={Array.from({length: 50}, (_, index) => ({
519
+ title: `Section ${index + 1}`,
520
+ data: ['1', '2', '3', '4', '5'],
521
+ }))}
522
+ renderSectionHeader={({section: {title}}) => (
523
+ <Box padding="s" backgroundColor="foregrounds-primary">
524
+ <Text variant="heroBold" color="foregrounds-contrasting">
525
+ {title}
526
+ </Text>
527
+ </Box>
528
+ )}
529
+ renderItem={({item}) => (
530
+ <Box padding="s">
531
+ <Text>{item}</Text>
532
+ </Box>
533
+ )}
534
+ ListHeaderComponent={
535
+ <Box paddingBottom="s" paddingHorizontal="gutter">
536
+ <Button text="Close" onPress={dismissBottomSheet} />
537
+ </Box>
538
+ }
539
+ />
540
+ )
541
+ }
542
+
543
+ export const BottomSheetScreen = () => {
544
+ const theme = useTheme()
545
+ const [examples, setExamples] = useState([
546
+ {
547
+ Component: ExampleScrollView1,
548
+ title: 'ScrollView',
549
+ description:
550
+ 'The simplest bottomsheet. This is a good starting point although for a large amount of content it will be best to use one of the more optimised options such as the FlatList',
551
+ cta: 'scrolling example',
552
+ isVisible: false,
553
+ },
554
+ {
555
+ Component: ExampleScrollView2,
556
+ cta: 'non-scrolling example',
557
+ isVisible: false,
558
+ },
559
+ {
560
+ Component: ExampleFlatList,
561
+ title: 'FlatList',
562
+ isVisible: false,
563
+ },
564
+ {
565
+ Component: ExampleGrid,
566
+ title: 'Grid',
567
+ isVisible: false,
568
+ },
569
+ {
570
+ Component: ExampleProductCardGrid,
571
+ title: 'ProductCardGrid',
572
+ isVisible: false,
573
+ },
574
+ {
575
+ Component: ExampleSectionList,
576
+ title: 'SectionList',
577
+ isVisible: false,
578
+ },
579
+ {
580
+ Component: ExampleSnapPoints,
581
+ title: 'Configuring snapPoints',
582
+ description:
583
+ 'You can configure snap points for all of the bottomsheets. This allows you to control the initial, smaller, point ' +
584
+ ' (positionTwo) as well as the top-most position (positionOne). These are measurements in screen units from the top ' +
585
+ 'of the container.',
586
+ isVisible: false,
587
+ },
588
+ {
589
+ Component: ExampleVariants,
590
+ title: 'Header Variants',
591
+ description:
592
+ "There's a variant called handle that replaces the top of the bottomsheet with an iOS-style handle",
593
+ isVisible: false,
594
+ },
595
+ {
596
+ Component: ExampleUseScrollViewBottomSheet,
597
+ title: 'hooks',
598
+ description:
599
+ 'If you need to programmatically close the bottomsheet or want low-level control of the bottomsheet you can one of the hooks such as useScrollViewBottomSheet directly',
600
+ cta: 'with useScrollViewBottomSheet',
601
+ isVisible: false,
602
+ },
603
+ {
604
+ Component: ExampleUseGridBottomSheet,
605
+ title: 'useGridBottomSheet hook',
606
+ isVisible: false,
607
+ },
608
+ {
609
+ Component: ExampleUseProductCardGridBottomSheet,
610
+ title: 'useProductCardGridBottomSheet hook',
611
+ isVisible: false,
612
+ },
613
+ {
614
+ Component: ExampleUseFlatListBottomSheet,
615
+ title: 'useFlatListBottomSheet hook',
616
+ isVisible: false,
617
+ },
618
+ {
619
+ Component: ExampleUseSectionListBottomSheet,
620
+ title: 'useSectionListBottomSheet hook',
621
+ isVisible: false,
622
+ },
623
+ {
624
+ Component: ExampleUseBottomSheet,
625
+ description:
626
+ 'If you have an advanced use-case you can use useBottomSheet directly but you will need to wire up the scroll handlers manually',
627
+ cta: 'with useBottomSheet',
628
+ isVisible: false,
629
+ },
630
+ ])
631
+
632
+ const openExample = useCallback((index: number) => {
633
+ setExamples(existingExamples =>
634
+ existingExamples.map((existingExample, i) => {
635
+ if (i !== index) return existingExample
636
+
637
+ return {
638
+ ...existingExample,
639
+ isVisible: true,
640
+ }
641
+ })
642
+ )
643
+ }, [])
644
+
645
+ const closeExample = useCallback((index: number) => {
646
+ setExamples(existingExamples =>
647
+ existingExamples.map((existingExample, i) => {
648
+ if (i !== index) return existingExample
649
+
650
+ return {
651
+ ...existingExample,
652
+ isVisible: false,
653
+ }
654
+ })
655
+ )
656
+ }, [])
657
+
658
+ return (
659
+ <>
660
+ <SafeAreaView
661
+ style={{flex: 1, backgroundColor: theme.colors['backgrounds-regular']}}
662
+ >
663
+ <ScrollView
664
+ style={{
665
+ flex: 1,
666
+ backgroundColor: theme.colors['backgrounds-regular'],
667
+ }}
668
+ >
669
+ <Header />
670
+ <Box px="gutter">
671
+ <Box marginBottom="m">
672
+ <Text variant="headerBold">BottomSheet</Text>
673
+ </Box>
674
+
675
+ {examples.map(({title, cta, isVisible, description}, i) => (
676
+ <Box key={title || cta} marginBottom="s">
677
+ {title ? (
678
+ <Box marginBottom="xs">
679
+ <Text variant="label" style={{textTransform: 'none'}}>
680
+ {title}
681
+ </Text>
682
+ </Box>
683
+ ) : null}
684
+
685
+ {description ? (
686
+ <Box marginBottom="s">
687
+ <Text>{description}</Text>
688
+ </Box>
689
+ ) : null}
690
+
691
+ <Button
692
+ text={`Launch ${cta ?? 'example'}`}
693
+ disabled={isVisible}
694
+ onPress={() => openExample(i)}
695
+ />
696
+ </Box>
697
+ ))}
698
+ </Box>
699
+ </ScrollView>
700
+ </SafeAreaView>
701
+
702
+ {/* Notice that the bottomsheet component itself lives outside the SafeAreaView */}
703
+
704
+ {examples.map(({Component, title, isVisible}, i) => {
705
+ if (!isVisible) return null
706
+
707
+ return <Component key={title} onDismiss={() => closeExample(i)} />
708
+ })}
709
+ </>
710
+ )
711
+ }