create-expo-stack 2.6.5 → 2.7.0-next.2960d96

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