create-expo-stack 2.7.0-next.54eb637 → 2.7.0-next.6619334

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 (38) 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 +30 -2
  4. package/build/templates/base/tsconfig.json.ejs +1 -1
  5. package/build/templates/packages/nativewindui/app/+not-found.tsx.ejs +1 -1
  6. package/build/templates/packages/nativewindui/app/_layout.tsx.ejs +25 -19
  7. package/build/templates/packages/nativewindui/app/index.tsx.ejs +644 -45
  8. package/build/templates/packages/nativewindui/app/modal.tsx.ejs +20 -19
  9. package/build/templates/packages/nativewindui/components/nativewind-ui/ActivityIndicator.tsx.ejs +10 -0
  10. package/build/templates/packages/nativewindui/components/nativewind-ui/Avatar.tsx.ejs +139 -0
  11. package/build/templates/packages/nativewindui/components/nativewind-ui/DatePicker.android.tsx.ejs +66 -0
  12. package/build/templates/packages/nativewindui/components/nativewind-ui/DatePicker.tsx.ejs +10 -0
  13. package/build/templates/packages/nativewindui/components/nativewind-ui/Picker.tsx.ejs +39 -0
  14. package/build/templates/packages/nativewindui/components/nativewind-ui/ProgressIndicator.tsx.ejs +95 -0
  15. package/build/templates/packages/nativewindui/components/nativewind-ui/SegmentedControl.tsx.ejs +22 -0
  16. package/build/templates/packages/nativewindui/components/nativewind-ui/Sheet.tsx.ejs +59 -0
  17. package/build/templates/packages/nativewindui/components/nativewind-ui/Slider.tsx.ejs +28 -0
  18. package/build/templates/packages/nativewindui/components/nativewind-ui/Text.tsx.ejs +26 -2
  19. package/build/templates/packages/nativewindui/components/{ThemeToggle.tsx.ejs → nativewind-ui/ThemeToggle.tsx.ejs} +6 -8
  20. package/build/templates/packages/nativewindui/components/nativewind-ui/Toggle.tsx.ejs +17 -0
  21. package/build/templates/packages/nativewindui/global.css.ejs +2 -2
  22. package/build/templates/packages/nativewindui/lib/useColorScheme.tsx.ejs +1 -1
  23. package/build/templates/packages/nativewindui/lib/useHeaderSearchBar.tsx.ejs +2 -2
  24. package/build/templates/packages/nativewindui/theme/colors.ts.ejs +8 -8
  25. package/build/templates/packages/nativewindui/theme/index.ts.ejs +4 -4
  26. package/build/types/types.d.ts +2 -0
  27. package/build/utilities/configureProjectFiles.js +41 -12
  28. package/build/utilities/runCLI.js +80 -26
  29. package/package.json +1 -1
  30. package/build/templates/packages/nativewindui/app/bottom-tabs/_layout.tsx.ejs +0 -34
  31. package/build/templates/packages/nativewindui/app/bottom-tabs/index.tsx.ejs +0 -11
  32. package/build/templates/packages/nativewindui/app/bottom-tabs/profile.tsx.ejs +0 -11
  33. package/build/templates/packages/nativewindui/app/drawer/_layout.tsx.ejs +0 -29
  34. package/build/templates/packages/nativewindui/app/drawer/index.tsx.ejs +0 -11
  35. package/build/templates/packages/nativewindui/app/top-tabs/_layout.tsx.ejs +0 -71
  36. package/build/templates/packages/nativewindui/app/top-tabs/following.tsx.ejs +0 -13
  37. package/build/templates/packages/nativewindui/app/top-tabs/index.tsx.ejs +0 -13
  38. package/build/templates/packages/nativewindui/app/top-tabs/my-group.tsx.ejs +0 -13
@@ -1,63 +1,157 @@
1
+ import { useHeaderHeight } from '@react-navigation/elements';
2
+ import { FlashList } from '@shopify/flash-list';
3
+ import { cssInterop } from 'nativewind';
1
4
  import * as React from 'react';
2
- import { Button as RNButton, ButtonProps, FlatList, 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
+ <% } %>
3
36
 
4
- import { Text } from '@/components/nativewind-ui/Text';
5
- import { useColorScheme } from '@/lib/useColorScheme';
6
- import { useHeaderSearchBar } from '@/lib/useHeaderSearchBar';
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
+ <% } %>
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
+ <% } %>
65
+ import { useColorScheme } from '~/lib/useColorScheme';
66
+ import { useHeaderSearchBar } from '~/lib/useHeaderSearchBar';
67
+
68
+
69
+ cssInterop(FlashList, {
70
+ className: 'style',
71
+ contentContainerClassName: 'contentContainerStyle',
72
+ });
7
73
 
8
74
  function DefaultButton({ color, ...props }: ButtonProps) {
9
75
  const { colors } = useColorScheme();
10
- return <RNButton color={color ?? colors.blue} {...props} />;
76
+ return <RNButton color={color ?? colors.primary} {...props} />;
11
77
  }
12
78
 
13
79
  export default function Screen() {
14
- const searchValue = useHeaderSearchBar();
80
+ const searchValue = useHeaderSearchBar({ hideWhenScrolling: COMPONENTS.length === 0 });
15
81
 
16
82
  const data = searchValue
17
83
  ? COMPONENTS.filter((c) => c.name.toLowerCase().includes(searchValue.toLowerCase()))
18
84
  : COMPONENTS;
19
85
 
20
- const screens = searchValue
21
- ? FULL_SCREEN_COMPONENTS.filter((c) => c.name.toLowerCase().includes(searchValue.toLowerCase()))
22
- : FULL_SCREEN_COMPONENTS;
23
-
24
86
  return (
25
- <FlatList
87
+ <FlashList
26
88
  contentInsetAdjustmentBehavior="automatic"
89
+ keyboardShouldPersistTaps="handled"
27
90
  data={data}
28
- contentContainerClassName="flex flex-1 py-4 items-center justify-center"
91
+ estimatedItemSize={200}
92
+ contentContainerClassName="py-4"
29
93
  extraData={searchValue}
94
+ <% if (props.stylingPackage?.options.selectedComponents.includes('selectable-text')) { %>
30
95
  removeClippedSubviews={false} // used for selecting text on android
31
- keyExtractor={(item) => item.name}
32
- ItemSeparatorComponent={() => <View className="p-2" />}
33
- renderItem={({ item }) => {
34
- return (
35
- <Card title={item.name}>
36
- <item.component />
37
- </Card>
38
- );
39
- }}
40
- ListEmptyComponent={() => {
41
- return (
42
- <View className='px-4'>
43
- <Text variant="title3" className="text-center font-bold">
44
- No Components Installed
45
- </Text>
46
- <Text color="tertiary" variant="body" className="text-center pb-4">
47
- You can install any of the free components from the NativeWindUI website.
48
- </Text>
49
- <DefaultButton title="Open NativeWindUI" onPress={() => Linking.openURL('https://nativewindui.com')} />
50
- </View>
51
- )
52
- }}
96
+ <% } %>
97
+ keyExtractor={keyExtractor}
98
+ ItemSeparatorComponent={renderItemSeparator}
99
+ renderItem={renderItem}
100
+ ListEmptyComponent={COMPONENTS.length === 0 ? ListEmptyComponent : undefined}
53
101
  />
54
102
  );
55
103
  }
56
104
 
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 };
134
+
135
+ function keyExtractor(item: ComponentItem) {
136
+ return item.name;
137
+ }
138
+
139
+ function renderItemSeparator() {
140
+ return <View className="p-2" />;
141
+ }
142
+
143
+ function renderItem({ item }: { item: ComponentItem }) {
144
+ return (
145
+ <Card title={item.name}>
146
+ <item.component />
147
+ </Card>
148
+ );
149
+ }
150
+
57
151
  function Card({ children, title }: { children: React.ReactNode; title: string }) {
58
152
  return (
59
153
  <View className="px-4">
60
- <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">
61
155
  <Text className="text-center text-sm font-medium tracking-wider opacity-60">{title}</Text>
62
156
  {children}
63
157
  </View>
@@ -65,20 +159,525 @@ function Card({ children, title }: { children: React.ReactNode; title: string })
65
159
  );
66
160
  }
67
161
 
68
- const COMPONENTS = [
69
- ] as const;
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;
70
482
 
71
- const FULL_SCREEN_COMPONENTS = [
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')) { %>
72
605
  {
73
- name: 'Drawer Navigation',
74
- href: '/drawer/',
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
+ },
75
634
  },
635
+ <% } %>
636
+ <% if (props.stylingPackage?.options.selectedComponents.includes('bottom-sheet')) { %>
76
637
  {
77
- name: 'Bottom Tabs Navigation',
78
- href: '/bottom-tabs/',
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
+ },
79
662
  },
663
+ <% } %>
664
+ <% if (props.stylingPackage?.options.selectedComponents.includes('avatar')) { %>
80
665
  {
81
- name: 'Top Tabs Navigation',
82
- href: '/top-tabs/',
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
+ },
83
680
  },
84
- ] as const;
681
+ <% } %>
682
+ ];
683
+