create-expo-stack 2.7.0-next.997d3bf → 2.7.0-next.a1c3bd8

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 (32) hide show
  1. package/README.md +9 -9
  2. package/build/templates/base/app.json.ejs +5 -1
  3. package/build/templates/base/package.json.ejs +29 -2
  4. package/build/templates/packages/nativewindui/app/_layout.tsx.ejs +21 -15
  5. package/build/templates/packages/nativewindui/app/index.tsx.ejs +616 -26
  6. package/build/templates/packages/nativewindui/app/modal.tsx.ejs +20 -19
  7. package/build/templates/packages/nativewindui/components/nativewind-ui/ActivityIndicator.tsx.ejs +10 -0
  8. package/build/templates/packages/nativewindui/components/nativewind-ui/Avatar.tsx.ejs +139 -0
  9. package/build/templates/packages/nativewindui/components/nativewind-ui/DatePicker.android.tsx.ejs +66 -0
  10. package/build/templates/packages/nativewindui/components/nativewind-ui/DatePicker.tsx.ejs +10 -0
  11. package/build/templates/packages/nativewindui/components/nativewind-ui/Picker.tsx.ejs +39 -0
  12. package/build/templates/packages/nativewindui/components/nativewind-ui/ProgressIndicator.tsx.ejs +95 -0
  13. package/build/templates/packages/nativewindui/components/nativewind-ui/SegmentedControl.tsx.ejs +22 -0
  14. package/build/templates/packages/nativewindui/components/nativewind-ui/Sheet.tsx.ejs +59 -0
  15. package/build/templates/packages/nativewindui/components/nativewind-ui/Slider.tsx.ejs +28 -0
  16. package/build/templates/packages/nativewindui/components/nativewind-ui/Text.tsx.ejs +25 -1
  17. package/build/templates/packages/nativewindui/components/{ThemeToggle.tsx.ejs → nativewind-ui/ThemeToggle.tsx.ejs} +3 -5
  18. package/build/templates/packages/nativewindui/components/nativewind-ui/Toggle.tsx.ejs +17 -0
  19. package/build/templates/packages/nativewindui/global.css.ejs +2 -2
  20. package/build/types/types.d.ts +2 -0
  21. package/build/utilities/configureProjectFiles.js +41 -11
  22. package/build/utilities/runCLI.js +80 -26
  23. package/package.json +1 -1
  24. package/build/templates/packages/nativewindui/app/bottom-tabs/_layout.tsx.ejs +0 -34
  25. package/build/templates/packages/nativewindui/app/bottom-tabs/index.tsx.ejs +0 -11
  26. package/build/templates/packages/nativewindui/app/bottom-tabs/profile.tsx.ejs +0 -11
  27. package/build/templates/packages/nativewindui/app/drawer/_layout.tsx.ejs +0 -29
  28. package/build/templates/packages/nativewindui/app/drawer/index.tsx.ejs +0 -11
  29. package/build/templates/packages/nativewindui/app/top-tabs/_layout.tsx.ejs +0 -71
  30. package/build/templates/packages/nativewindui/app/top-tabs/following.tsx.ejs +0 -13
  31. package/build/templates/packages/nativewindui/app/top-tabs/index.tsx.ejs +0 -13
  32. package/build/templates/packages/nativewindui/app/top-tabs/my-group.tsx.ejs +0 -13
@@ -1,12 +1,71 @@
1
+ import { useHeaderHeight } from '@react-navigation/elements';
1
2
  import { FlashList } from '@shopify/flash-list';
2
3
  import { cssInterop } from 'nativewind';
3
4
  import * as React from 'react';
4
- import { Button as RNButton, ButtonProps, Linking, View } from 'react-native';
5
+ import {
6
+ <% if (props.stylingPackage?.options.selectedComponents.includes('alert')) { %>
7
+ Alert,
8
+ <% } %>
9
+ Button as RNButton,
10
+ ButtonProps,
11
+ Linking,
12
+ Platform,
13
+ <% if (props.stylingPackage?.options.selectedComponents.includes('dropdown-menu')) { %>
14
+ Pressable,
15
+ <% } %>
16
+ <% if (props.stylingPackage?.options.selectedComponents.includes('activity-view')) { %>
17
+ Share,
18
+ <% } %>
19
+ useWindowDimensions,
20
+ View,
21
+ } from 'react-native';
22
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
23
+ <% if (props.stylingPackage?.options.selectedComponents.includes('action-sheet')) { %>
24
+ import { useActionSheet } from '@expo/react-native-action-sheet';
25
+ <% } %>
26
+ import { Icon } from '@roninoss/icons';
27
+ <% if (props.stylingPackage?.options.selectedComponents.includes('ratings-indicator')) { %>
28
+ import * as StoreReview from 'expo-store-review';
29
+ <% } %>
30
+ <% if (props.stylingPackage?.options.selectedComponents.includes('context-menu')) { %>
31
+ import * as ContextMenu from 'zeego/context-menu';
32
+ <% } %>
33
+ <% if (props.stylingPackage?.options.selectedComponents.includes('dropdown-menu')) { %>
34
+ import * as DropdownMenu from 'zeego/dropdown-menu';
35
+ <% } %>
5
36
 
37
+ <% if (props.stylingPackage?.options.selectedComponents.includes('activity-indicator')) { %>
38
+ import { ActivityIndicator } from '~/components/nativewind-ui/ActivityIndicator';
39
+ <% } %>
40
+ <% if (props.stylingPackage?.options.selectedComponents.includes('avatar')) { %>
41
+ import { Avatar, AvatarFallback, AvatarImage } from '~/components/nativewind-ui/Avatar';
42
+ <% } %>
43
+ <% if (props.stylingPackage?.options.selectedComponents.includes('date-picker')) { %>
44
+ import { DatePicker } from '~/components/nativewind-ui/DatePicker';
45
+ <% } %>
46
+ <% if (props.stylingPackage?.options.selectedComponents.includes('picker')) { %>
47
+ import { Picker, PickerItem } from '~/components/nativewind-ui/Picker';
48
+ <% } %>
49
+ <% if (props.stylingPackage?.options.selectedComponents.includes('progress-indicator')) { %>
50
+ import { ProgressIndicator } from '~/components/nativewind-ui/ProgressIndicator';
51
+ <% } %>
52
+ <% if (props.stylingPackage?.options.selectedComponents.includes('segmented-control')) { %>
53
+ import { SegmentedControl } from '~/components/nativewind-ui/SegmentedControl';
54
+ <% } %>
55
+ <% if (props.stylingPackage?.options.selectedComponents.includes('bottom-sheet')) { %>
56
+ import { Sheet, useSheetRef } from '~/components/nativewind-ui/Sheet';
57
+ <% } %>
58
+ <% if (props.stylingPackage?.options.selectedComponents.includes('slider')) { %>
59
+ import { Slider } from '~/components/nativewind-ui/Slider';
60
+ <% } %>
6
61
  import { Text } from '~/components/nativewind-ui/Text';
62
+ <% if (props.stylingPackage?.options.selectedComponents.includes('toggle')) { %>
63
+ import { Toggle } from '~/components/nativewind-ui/Toggle';
64
+ <% } %>
7
65
  import { useColorScheme } from '~/lib/useColorScheme';
8
66
  import { useHeaderSearchBar } from '~/lib/useHeaderSearchBar';
9
67
 
68
+
10
69
  cssInterop(FlashList, {
11
70
  className: 'style',
12
71
  contentContainerClassName: 'contentContainerStyle',
@@ -18,32 +77,12 @@ function DefaultButton({ color, ...props }: ButtonProps) {
18
77
  }
19
78
 
20
79
  export default function Screen() {
21
- const searchValue = useHeaderSearchBar();
80
+ const searchValue = useHeaderSearchBar({ hideWhenScrolling: COMPONENTS.length === 0 });
22
81
 
23
82
  const data = searchValue
24
83
  ? COMPONENTS.filter((c) => c.name.toLowerCase().includes(searchValue.toLowerCase()))
25
84
  : COMPONENTS;
26
85
 
27
- if (data.length === 0) {
28
- return (
29
- <View className='flex-1 justify-center items-center px-4'>
30
- <Text variant='title3' className='text-center font-bold pb-1'>
31
- {searchValue.length === 0
32
- ? 'No Components Installed'
33
- : 'No Components Found'}
34
- </Text>
35
- <Text color='tertiary' variant='body' className='text-center pb-4'>
36
- You can install any of the free components from the NativeWindUI
37
- website.
38
- </Text>
39
- <DefaultButton
40
- title='Open NativeWindUI'
41
- onPress={() => Linking.openURL('https://nativewindui.com')}
42
- />
43
- </View>
44
- );
45
- }
46
-
47
86
  return (
48
87
  <FlashList
49
88
  contentInsetAdjustmentBehavior="automatic"
@@ -52,22 +91,53 @@ export default function Screen() {
52
91
  estimatedItemSize={200}
53
92
  contentContainerClassName="py-4"
54
93
  extraData={searchValue}
94
+ <% if (props.stylingPackage?.options.selectedComponents.includes('selectable-text')) { %>
55
95
  removeClippedSubviews={false} // used for selecting text on android
96
+ <% } %>
56
97
  keyExtractor={keyExtractor}
57
98
  ItemSeparatorComponent={renderItemSeparator}
58
99
  renderItem={renderItem}
100
+ ListEmptyComponent={COMPONENTS.length === 0 ? ListEmptyComponent : undefined}
59
101
  />
60
102
  );
61
103
  }
62
104
 
63
- type ComponentItem = { name: string; component: () => React.JSX.Element };
105
+ function ListEmptyComponent() {
106
+ const insets = useSafeAreaInsets();
107
+ const dimensions = useWindowDimensions();
108
+ const headerHeight = useHeaderHeight();
109
+ const { colors } = useColorScheme();
110
+ const height = dimensions.height - headerHeight - insets.bottom - insets.top;
111
+
112
+ return (
113
+ <View style={{ height }} className="flex-1 items-center justify-center gap-1 px-12">
114
+ <Icon name="file-plus-outline" size={42} color={colors.grey} />
115
+ <Text variant='title3' className='pb-1 text-center font-semibold'>
116
+ No Components Installed
117
+ </Text>
118
+ <Text color='tertiary' variant='subhead' className='pb-4 text-center'>
119
+ You can install any of the free components from the{' '}
120
+ <Text
121
+ onPress={() => Linking.openURL('https://nativewindui.com')}
122
+ variant='subhead'
123
+ className='text-primary'
124
+ >
125
+ NativeWindUI
126
+ </Text>
127
+ {' website.'}
128
+ </Text>
129
+ </View>
130
+ );
131
+ }
132
+
133
+ type ComponentItem = { name: string; component: React.FC };
64
134
 
65
135
  function keyExtractor(item: ComponentItem) {
66
136
  return item.name;
67
137
  }
68
138
 
69
139
  function renderItemSeparator() {
70
- return <View className='p-2' />;
140
+ return <View className="p-2" />;
71
141
  }
72
142
 
73
143
  function renderItem({ item }: { item: ComponentItem }) {
@@ -81,7 +151,7 @@ function renderItem({ item }: { item: ComponentItem }) {
81
151
  function Card({ children, title }: { children: React.ReactNode; title: string }) {
82
152
  return (
83
153
  <View className="px-4">
84
- <View className="bg-card border-border gap-4 rounded-xl border p-4 pb-6 shadow-sm shadow-black/10 dark:shadow-none">
154
+ <View className="gap-4 rounded-xl border border-border bg-card p-4 pb-6 shadow-sm shadow-black/10 dark:shadow-none">
85
155
  <Text className="text-center text-sm font-medium tracking-wider opacity-60">{title}</Text>
86
156
  {children}
87
157
  </View>
@@ -89,5 +159,525 @@ function Card({ children, title }: { children: React.ReactNode; title: string })
89
159
  );
90
160
  }
91
161
 
92
- const COMPONENTS: ComponentItem[] = [];
162
+ const COMPONENTS: ComponentItem[] = [
163
+ <% if (props.stylingPackage?.options.selectedComponents.includes('picker')) { %>
164
+ {
165
+ name: 'Picker',
166
+ component: function PickerExample() {
167
+ const { colors } = useColorScheme();
168
+ const [picker, setPicker] = React.useState('blue');
169
+ return (
170
+ <Picker
171
+ selectedValue={picker}
172
+ onValueChange={(itemValue) => setPicker(itemValue)}
173
+ >
174
+ <PickerItem
175
+ label='Red'
176
+ value='red'
177
+ color={colors.foreground}
178
+ style={{
179
+ backgroundColor: colors.root,
180
+ }}
181
+ />
182
+ <PickerItem
183
+ label='Blue'
184
+ value='blue'
185
+ color={colors.foreground}
186
+ style={{
187
+ backgroundColor: colors.root,
188
+ }}
189
+ />
190
+ <PickerItem
191
+ label='Green'
192
+ value='green'
193
+ color={colors.foreground}
194
+ style={{
195
+ backgroundColor: colors.root,
196
+ }}
197
+ />
198
+ </Picker>
199
+ );
200
+ },
201
+ },
202
+ <% } %>
203
+ <% if (props.stylingPackage?.options.selectedComponents.includes('date-picker')) { %>
204
+ {
205
+ name: 'Date Picker',
206
+ component: function DatePickerExample() {
207
+ const [date, setDate] = React.useState(new Date());
208
+ return (
209
+ <View className='items-center'>
210
+ <DatePicker
211
+ value={date}
212
+ mode='datetime'
213
+ onChange={(ev) => {
214
+ setDate(new Date(ev.nativeEvent.timestamp));
215
+ }}
216
+ />
217
+ </View>
218
+ );
219
+ },
220
+ },
221
+ <% } %>
222
+ <% if (props.stylingPackage?.options.selectedComponents.includes('segmented-control')) { %>
223
+ {
224
+ name: 'Segmented Controls',
225
+ component: function SegmentedControlsExample() {
226
+ const [segment, setSegment] = React.useState(0);
227
+ return (
228
+ <SegmentedControl
229
+ values={['red', 'green', 'blue']}
230
+ selectedIndex={segment}
231
+ onChange={(event) => {
232
+ setSegment(event.nativeEvent.selectedSegmentIndex);
233
+ }}
234
+ />
235
+ );
236
+ },
237
+ },
238
+ <% } %>
239
+ <% if (props.stylingPackage?.options.selectedComponents.includes('slider')) { %>
240
+ {
241
+ name: 'Slider',
242
+ component: function SliderExample() {
243
+ const [sliderValue, setSliderValue] = React.useState(0.5);
244
+ return <Slider value={sliderValue} onValueChange={setSliderValue} />;
245
+ },
246
+ },
247
+ <% } %>
248
+ <% if (props.stylingPackage?.options.selectedComponents.includes('toggle')) { %>
249
+ {
250
+ name: 'Toggle',
251
+ component: function ToggleExample() {
252
+ const [switchValue, setSwitchValue] = React.useState(true);
253
+ return (
254
+ <View className='items-center'>
255
+ <Toggle value={switchValue} onValueChange={setSwitchValue} />
256
+ </View>
257
+ );
258
+ }
259
+ },
260
+ <% } %>
261
+ <% if (props.stylingPackage?.options.selectedComponents.includes('context-menu')) { %>
262
+ {
263
+ name: 'Context Menu',
264
+ component: function ContextMenuExample() {
265
+ const [isChecked, setIsChecked] = React.useState(true);
266
+ return (
267
+ <View>
268
+ <ContextMenu.Root style={{ borderRadius: 12 }}>
269
+ <ContextMenu.Trigger>
270
+ <View className='w-full h-36 rounded-xl border border-foreground border-dashed justify-center items-center'>
271
+ <Text>Press and hold me</Text>
272
+ </View>
273
+ </ContextMenu.Trigger>
274
+ <ContextMenu.Content>
275
+ <ContextMenu.Label children='Label 1' />
276
+ <ContextMenu.Item key='item-1'>
277
+ <ContextMenu.ItemTitle>Item 1</ContextMenu.ItemTitle>
278
+ </ContextMenu.Item>
279
+ <ContextMenu.Group>
280
+ <ContextMenu.Item key='item-2'>
281
+ <ContextMenu.ItemTitle>Item 2</ContextMenu.ItemTitle>
282
+ </ContextMenu.Item>
283
+ <ContextMenu.CheckboxItem
284
+ key='checkbox-example'
285
+ value={isChecked}
286
+ onValueChange={(val) => {
287
+ setIsChecked(val === 'on');
288
+ }}
289
+ >
290
+ <ContextMenu.ItemTitle>Item 3</ContextMenu.ItemTitle>
291
+ <ContextMenu.ItemIndicator />
292
+ </ContextMenu.CheckboxItem>
293
+ </ContextMenu.Group>
294
+ <ContextMenu.Separator />
295
+ </ContextMenu.Content>
296
+ </ContextMenu.Root>
297
+ </View>
298
+ );
299
+ },
300
+ },
301
+ <% } %>
302
+ <% if (props.stylingPackage?.options.selectedComponents.includes('dropdown-menu')) { %>
303
+ {
304
+ name: 'Dropdown Menu',
305
+ component: function DropdownMenuExample() {
306
+ const { colors } = useColorScheme();
307
+ const [menu, setMenu] = React.useState<'primary' | 'destructive'>('primary');
308
+
309
+ return (
310
+ <View className='items-center'>
311
+ <DropdownMenu.Root>
312
+ <DropdownMenu.Trigger>
313
+ <Pressable className='flex-row items-center gap-1.5 android:gap-3'>
314
+ <Text>
315
+ Selected: <Text style={{ color: colors[menu] }}>{menu}</Text>
316
+ </Text>
317
+ <View className='pl-0.5 opacity-70'>
318
+ <Icon
319
+ name='chevron-down'
320
+ color={colors.foreground}
321
+ size={21}
322
+ />
323
+ </View>
324
+ </Pressable>
325
+ </DropdownMenu.Trigger>
326
+ <DropdownMenu.Content>
327
+ <DropdownMenu.CheckboxItem
328
+ key='destructive'
329
+ value={menu === 'destructive'}
330
+ onValueChange={() => {
331
+ setMenu('destructive');
332
+ }}
333
+ >
334
+ <DropdownMenu.ItemIndicator />
335
+ <DropdownMenu.ItemTitle children='destructive' />
336
+ </DropdownMenu.CheckboxItem>
337
+ <DropdownMenu.CheckboxItem
338
+ key='primary'
339
+ value={menu === 'primary'}
340
+ onValueChange={() => {
341
+ setMenu('primary');
342
+ }}
343
+ >
344
+ <DropdownMenu.ItemIndicator />
345
+ <DropdownMenu.ItemTitle children='primary' />
346
+ </DropdownMenu.CheckboxItem>
347
+ </DropdownMenu.Content>
348
+ </DropdownMenu.Root>
349
+ </View>
350
+ );
351
+ },
352
+ },
353
+ <% } %>
354
+ <% if (props.stylingPackage?.options.selectedComponents.includes('progress-indicator')) { %>
355
+ {
356
+ name: 'Progress Indicator',
357
+ component: function ProgressIndicatorExample() {
358
+ const [progress, setProgress] = React.useState(13);
359
+ let id: ReturnType<typeof setInterval> | null = null;
360
+ React.useEffect(() => {
361
+ if (!id) {
362
+ id = setInterval(() => {
363
+ setProgress((prev) => (prev >= 99 ? 0 : prev + 5));
364
+ }, Math.random() * 3000);
365
+ }
366
+ return () => {
367
+ if (id) clearInterval(id);
368
+ };
369
+ }, []);
370
+ return (
371
+ <View className='p-4'>
372
+ <ProgressIndicator value={progress} />
373
+ </View>
374
+ );
375
+ },
376
+ },
377
+ <% } %>
378
+ <% if (props.stylingPackage?.options.selectedComponents.includes('activity-indicator')) { %>
379
+ {
380
+ name: 'Activity Indicator',
381
+ component: function ActivityIndicatorExample() {
382
+ return (
383
+ <View className='p-4 items-center'>
384
+ <ActivityIndicator />
385
+ </View>
386
+ );
387
+ },
388
+ },
389
+ <% } %>
390
+ <% if (props.stylingPackage?.options.selectedComponents.includes('alert')) { %>
391
+ {
392
+ name: 'Alert',
393
+ component: function AlertExample() {
394
+ const { colors } = useColorScheme();
395
+ return (
396
+ <View className='items-center'>
397
+ <DefaultButton
398
+ color={colors.destructive}
399
+ onPress={() => {
400
+ if (Platform.OS === 'ios') {
401
+ Alert.prompt(
402
+ 'Delete account?',
403
+ 'Enter your password to delete your account.',
404
+ [
405
+ {
406
+ text: 'Cancel',
407
+ onPress: () => console.log('Cancel Pressed'),
408
+ style: 'cancel',
409
+ },
410
+ {
411
+ text: 'Delete',
412
+ style: 'destructive',
413
+ onPress: () => console.log('Delete Pressed'),
414
+ },
415
+ ],
416
+ 'secure-text',
417
+ '',
418
+ 'default'
419
+ );
420
+ } else {
421
+ Alert.alert(
422
+ 'Delete account?',
423
+ 'Enter your password to delete your account.',
424
+ [
425
+ {
426
+ text: 'Cancel',
427
+ onPress: () => console.log('Cancel Pressed'),
428
+ style: 'cancel',
429
+ },
430
+ {
431
+ text: 'Delete',
432
+ style: 'destructive',
433
+ onPress: () => console.log('Delete Pressed'),
434
+ },
435
+ ]
436
+ );
437
+ }
438
+ }}
439
+ title='Delete account'
440
+ />
441
+ </View>
442
+ );
443
+ },
444
+ },
445
+ <% } %>
446
+ <% if (props.stylingPackage?.options.selectedComponents.includes('action-sheet')) { %>
447
+ {
448
+ name: 'Action Sheet',
449
+ component: function ActionSheetExample() {
450
+ const { colorScheme, colors } = useColorScheme();
451
+ const { showActionSheetWithOptions } = useActionSheet();
452
+ return (
453
+ <View className='items-center'>
454
+ <DefaultButton
455
+ color={'grey'}
456
+ onPress={async () => {
457
+ const options = ['Delete', 'Save', 'Cancel'];
458
+ const destructiveButtonIndex = 0;
459
+ const cancelButtonIndex = 2;
460
+
461
+ showActionSheetWithOptions(
462
+ {
463
+ options,
464
+ cancelButtonIndex,
465
+ destructiveButtonIndex,
466
+ containerStyle: {
467
+ backgroundColor: colorScheme === 'dark' ? 'black' : 'white',
468
+ },
469
+ textStyle: {
470
+ color: colors.foreground,
471
+ },
472
+ },
473
+ (selectedIndex) => {
474
+ switch (selectedIndex) {
475
+ case 1:
476
+ // Save
477
+ break;
478
+
479
+ case destructiveButtonIndex:
480
+ // Delete
481
+ break;
482
+
483
+ case cancelButtonIndex:
484
+ // Canceled
485
+ }
486
+ }
487
+ );
488
+ }}
489
+ title='Open action sheet'
490
+ />
491
+ </View>
492
+ );
493
+ },
494
+ },
495
+ <% } %>
496
+ <% if (props.stylingPackage?.options.selectedComponents.includes('text')) { %>
497
+ {
498
+ name: 'Text',
499
+ component: function TextExample() {
500
+ return (
501
+ <View className='gap-2'>
502
+ <Text variant='largeTitle' className='text-center'>
503
+ Large Title
504
+ </Text>
505
+ <Text variant='title1' className='text-center'>
506
+ Title 1
507
+ </Text>
508
+ <Text variant='title2' className='text-center'>
509
+ Title 2
510
+ </Text>
511
+ <Text variant='title3' className='text-center'>
512
+ Title 3
513
+ </Text>
514
+ <Text variant='heading' className='text-center'>
515
+ Heading
516
+ </Text>
517
+ <Text variant='body' className='text-center'>
518
+ Body
519
+ </Text>
520
+ <Text variant='callout' className='text-center'>
521
+ Callout
522
+ </Text>
523
+ <Text variant='subhead' className='text-center'>
524
+ Subhead
525
+ </Text>
526
+ <Text variant='footnote' className='text-center'>
527
+ Footnote
528
+ </Text>
529
+ <Text variant='caption1' className='text-center'>
530
+ Caption 1
531
+ </Text>
532
+ <Text variant='caption2' className='text-center'>
533
+ Caption 2
534
+ </Text>
535
+ </View>
536
+ );
537
+ },
538
+ },
539
+ <% } %>
540
+ <% if (props.stylingPackage?.options.selectedComponents.includes('selectable-text')) { %>
541
+ {
542
+ name: 'Selectable Text',
543
+ component: function SelectableTextExample() {
544
+ return (
545
+ <Text uiTextView selectable>
546
+ Long press or double press this text
547
+ </Text>
548
+ );
549
+ },
550
+ },
551
+ <% } %>
552
+ <% if (props.stylingPackage?.options.selectedComponents.includes('ratings-indicator')) { %>
553
+ {
554
+ name: 'Ratings Indicator',
555
+ component: function RatingsIndicatorExample() {
556
+ React.useEffect(() => {
557
+ const wasAskedRef = React.useRef(false);
558
+ async function showRequestReview() {
559
+ if (await StoreReview.hasAction()) {
560
+ StoreReview.requestReview();
561
+ }
562
+ }
563
+ const timeout = setTimeout(() => {
564
+ showRequestReview();
565
+ wasAskedRef.current = true;
566
+ }, 1000);
567
+
568
+ return () => clearTimeout(timeout);
569
+ }, []);
570
+
571
+ return (
572
+ <View className="gap-3">
573
+ <Text className="pb-2 text-center font-semibold">Please follow the guidelines.</Text>
574
+ <View className="flex-row">
575
+ <Text className="w-6 text-center text-muted-foreground">·</Text>
576
+ <View className="flex-1">
577
+ <Text variant="caption1" className="text-muted-foreground">
578
+ Don't call StoreReview.requestReview() from a button
579
+ </Text>
580
+ </View>
581
+ </View>
582
+ <View className="flex-row">
583
+ <Text className="w-6 text-center text-muted-foreground">·</Text>
584
+ <View className="flex-1">
585
+ <Text variant="caption1" className="text-muted-foreground">
586
+ Don't request a review when the user is doing something time sensitive.
587
+ </Text>
588
+ </View>
589
+ </View>
590
+ <View className="flex-row">
591
+ <Text className="w-6 text-center text-muted-foreground">·</Text>
592
+ <View className="flex-1">
593
+ <Text variant="caption1" className="text-muted-foreground">
594
+ Don't ask the user any questions before or while presenting the rating button or
595
+ card.
596
+ </Text>
597
+ </View>
598
+ </View>
599
+ </View>
600
+ );
601
+ },
602
+ },
603
+ <% } %>
604
+ <% if (props.stylingPackage?.options.selectedComponents.includes('activity-view')) { %>
605
+ {
606
+ name: 'Activity View',
607
+ component: function ActivityViewExample() {
608
+ return (
609
+ <View className='items-center'>
610
+ <DefaultButton
611
+ onPress={async () => {
612
+ try {
613
+ const result = await Share.share({
614
+ message: 'NativeWindUI | Familiar interface, native feel.',
615
+ });
616
+ if (result.action === Share.sharedAction) {
617
+ if (result.activityType) {
618
+ // shared with activity type of result.activityType
619
+ } else {
620
+ // shared
621
+ }
622
+ } else if (result.action === Share.dismissedAction) {
623
+ // dismissed
624
+ }
625
+ } catch (error: any) {
626
+ Alert.alert(error.message);
627
+ }
628
+ }}
629
+ title='Share a message'
630
+ />
631
+ </View>
632
+ );
633
+ },
634
+ },
635
+ <% } %>
636
+ <% if (props.stylingPackage?.options.selectedComponents.includes('bottom-sheet')) { %>
637
+ {
638
+ name: 'Bottom Sheet',
639
+ component: function BottomSheetExample() {
640
+ const { colorScheme } = useColorScheme();
641
+ const bottomSheetModalRef = useSheetRef();
642
+
643
+ return (
644
+ <View className='items-center'>
645
+ <DefaultButton
646
+ color={
647
+ colorScheme === 'dark' && Platform.OS === 'ios'
648
+ ? 'white'
649
+ : 'black'
650
+ }
651
+ title='Open Bottom Sheet'
652
+ onPress={() => bottomSheetModalRef.current?.present()}
653
+ />
654
+ <Sheet ref={bottomSheetModalRef} snapPoints={[200]}>
655
+ <View className='flex-1 justify-center items-center pb-8'>
656
+ <Text>@gorhom/bottom-sheet 🎉</Text>
657
+ </View>
658
+ </Sheet>
659
+ </View>
660
+ );
661
+ },
662
+ },
663
+ <% } %>
664
+ <% if (props.stylingPackage?.options.selectedComponents.includes('avatar')) { %>
665
+ {
666
+ name: 'Avatar',
667
+ component: function AvatarExample() {
668
+ const GITHUB_AVATAR_URI = 'https://github.com/mrzachnugent.png';
669
+ return (
670
+ <View className='items-center'>
671
+ <Avatar alt="Zach Nugent's Avatar">
672
+ <AvatarImage source={{ uri: GITHUB_AVATAR_URI }} />
673
+ <AvatarFallback>
674
+ <Text>ZN</Text>
675
+ </AvatarFallback>
676
+ </Avatar>
677
+ </View>
678
+ );
679
+ },
680
+ },
681
+ <% } %>
682
+ ];
93
683