create-expo-stack 2.7.0-next.ba3b85d → 2.7.0-next.ba4f707

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 +16 -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 +638 -121
  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/{Text.tsx.ejs → nativewind-ui/Text.tsx.ejs} +26 -2
  19. package/build/templates/packages/nativewindui/components/{ThemeToggle.tsx.ejs → nativewind-ui/ThemeToggle.tsx.ejs} +7 -9
  20. package/build/templates/packages/nativewindui/components/{Toggle.tsx.ejs → nativewind-ui/Toggle.tsx.ejs} +3 -3
  21. package/build/templates/packages/nativewindui/global.css.ejs +3 -3
  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 +42 -13
  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,165 +1,682 @@
1
- import { Icon } from '@roninoss/icons';
2
- import { Link } from 'expo-router';
1
+ import { useHeaderHeight } from '@react-navigation/elements';
2
+ import { FlashList } from '@shopify/flash-list';
3
+ import { cssInterop } from 'nativewind';
3
4
  import * as React from 'react';
4
- import { FlatList, Pressable, 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
 
6
- import { Text } from '@/components/Text';
7
- import { Toggle } from '@/components/Toggle';
8
- import { cn } from '@/lib/cn';
9
- import { useColorScheme } from '@/lib/useColorScheme';
10
- 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';
11
67
 
12
- export default function Screen() {
68
+
69
+ cssInterop(FlashList, {
70
+ className: 'style',
71
+ contentContainerClassName: 'contentContainerStyle',
72
+ });
73
+
74
+ function DefaultButton({ color, ...props }: ButtonProps) {
13
75
  const { colors } = useColorScheme();
14
- const searchValue = useHeaderSearchBar();
76
+ return <RNButton color={color ?? colors.primary} {...props} />;
77
+ }
78
+
79
+ export default function Screen() {
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}
91
+ estimatedItemSize={200}
28
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
- ListFooterComponent={() => {
41
- return (
42
- <FlatList
43
- ListHeaderComponent={() => (
44
- <View className={cn('px-4 pb-2 pt-6', screens.length === 0 && 'hidden')}>
45
- <Text className="text-xs font-semibold opacity-50 ">NAVIGATORS</Text>
46
- </View>
47
- )}
48
- scrollToOverflowEnabled
49
- scrollEnabled={false}
50
- contentInsetAdjustmentBehavior="automatic"
51
- data={screens}
52
- className="ios:px-4"
53
- extraData={searchValue}
54
- keyExtractor={(item) => item.name}
55
- renderItem={({ index, item }) => {
56
- const isLast = index === screens.length - 1;
57
- return (
58
- <Link href={item.href} asChild>
59
- <Pressable
60
- className={cn(
61
- index === 0 && 'ios:rounded-t-xl border-t',
62
- isLast && 'ios:rounded-b-xl border-b',
63
- 'bg-card ios:border-l ios:border-r border-border flex-row active:opacity-80'
64
- )}>
65
- <View
66
- className={cn(
67
- !isLast && 'border-border border-b',
68
- 'flex-1 flex-row items-center justify-between px-4 py-3'
69
- )}>
70
- <Text>{item.name}</Text>
71
- <Icon name="chevron-right" size={18} color={colors.grey} />
72
- </View>
73
- </Pressable>
74
- </Link>
75
- );
76
- }}
77
- />
78
- );
79
- }}
96
+ <% } %>
97
+ keyExtractor={keyExtractor}
98
+ ItemSeparatorComponent={renderItemSeparator}
99
+ renderItem={renderItem}
100
+ ListEmptyComponent={COMPONENTS.length === 0 ? ListEmptyComponent : undefined}
80
101
  />
81
102
  );
82
103
  }
83
104
 
84
- function Card({ children, title }: { children: React.ReactNode; title: string }) {
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
+
85
112
  return (
86
- <View className="px-4">
87
- <View className="bg-card border-border gap-4 rounded-xl border p-4 pb-6 shadow-sm shadow-black/10 dark:shadow-none">
88
- <Text className="text-center text-sm font-medium tracking-wider opacity-60">{title}</Text>
89
- {children}
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>
90
129
  </View>
91
- </View>
92
130
  );
93
131
  }
94
132
 
95
- function ToggleExample() {
96
- const [switchValue, setSwitchValue] = React.useState(true);
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
+
151
+ function Card({ children, title }: { children: React.ReactNode; title: string }) {
97
152
  return (
98
- <View className="items-center">
99
- <Toggle value={switchValue} onValueChange={setSwitchValue} />
153
+ <View className="px-4">
154
+ <View className="gap-4 rounded-xl border border-border bg-card p-4 pb-6 shadow-sm shadow-black/10 dark:shadow-none">
155
+ <Text className="text-center text-sm font-medium tracking-wider opacity-60">{title}</Text>
156
+ {children}
157
+ </View>
100
158
  </View>
101
159
  );
102
160
  }
103
161
 
104
- const COMPONENTS = [
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')) { %>
105
249
  {
106
250
  name: 'Toggle',
107
- component: ToggleExample,
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
+ },
108
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');
109
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')) { %>
110
497
  {
111
498
  name: 'Text',
112
- component: () => (
113
- <View className="gap-2">
114
- <Text variant="largeTitle" className="text-center">
115
- Large Title
116
- </Text>
117
- <Text variant="title1" className="text-center">
118
- Title 1
119
- </Text>
120
- <Text variant="title2" className="text-center">
121
- Title 2
122
- </Text>
123
- <Text variant="title3" className="text-center">
124
- Title 3
125
- </Text>
126
- <Text variant="heading" className="text-center">
127
- Heading
128
- </Text>
129
- <Text variant="body" className="text-center">
130
- Body
131
- </Text>
132
- <Text variant="callout" className="text-center">
133
- Callout
134
- </Text>
135
- <Text variant="subhead" className="text-center">
136
- Subhead
137
- </Text>
138
- <Text variant="footnote" className="text-center">
139
- Footnote
140
- </Text>
141
- <Text variant="caption1" className="text-center">
142
- Caption 1
143
- </Text>
144
- <Text variant="caption2" className="text-center">
145
- Caption 2
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: 'Actionable Text',
543
+ component: function SelectableTextExample() {
544
+ return (
545
+ <Text uiTextView selectable>
546
+ Long press or double press this text
146
547
  </Text>
147
- </View>
148
- ),
548
+ );
549
+ },
149
550
  },
150
- ] as const;
551
+ <% } %>
552
+ <% if (props.stylingPackage?.options.selectedComponents.includes('ratings-indicator')) { %>
553
+ {
554
+ name: 'Ratings Indicator',
555
+ component: function RatingsIndicatorExample() {
556
+ React.useEffect(() => {
557
+ async function showRequestReview() {
558
+ if (await StoreReview.hasAction()) {
559
+ StoreReview.requestReview();
560
+ }
561
+ }
562
+ const timeout = setTimeout(() => {
563
+ showRequestReview();
564
+ wasAskedRef.current = true;
565
+ }, 1000);
566
+
567
+ return () => clearTimeout(timeout);
568
+ }, []);
151
569
 
152
- const FULL_SCREEN_COMPONENTS = [
570
+ return (
571
+ <View className="gap-3">
572
+ <Text className="pb-2 text-center font-semibold">Please follow the guidelines.</Text>
573
+ <View className="flex-row">
574
+ <Text className="w-6 text-center text-muted-foreground">·</Text>
575
+ <View className="flex-1">
576
+ <Text variant="caption1" className="text-muted-foreground">
577
+ Don't call StoreReview.requestReview() from a button
578
+ </Text>
579
+ </View>
580
+ </View>
581
+ <View className="flex-row">
582
+ <Text className="w-6 text-center text-muted-foreground">·</Text>
583
+ <View className="flex-1">
584
+ <Text variant="caption1" className="text-muted-foreground">
585
+ Don't request a review when the user is doing something time sensitive.
586
+ </Text>
587
+ </View>
588
+ </View>
589
+ <View className="flex-row">
590
+ <Text className="w-6 text-center text-muted-foreground">·</Text>
591
+ <View className="flex-1">
592
+ <Text variant="caption1" className="text-muted-foreground">
593
+ Don't ask the user any questions before or while presenting the rating button or
594
+ card.
595
+ </Text>
596
+ </View>
597
+ </View>
598
+ </View>
599
+ );
600
+ },
601
+ },
602
+ <% } %>
603
+ <% if (props.stylingPackage?.options.selectedComponents.includes('activity-view')) { %>
153
604
  {
154
- name: 'Drawer Navigation',
155
- href: '/drawer/',
605
+ name: 'Activity View',
606
+ component: function ActivityViewExample() {
607
+ return (
608
+ <View className='items-center'>
609
+ <DefaultButton
610
+ onPress={async () => {
611
+ try {
612
+ const result = await Share.share({
613
+ message: 'NativeWindUI | Familiar interface, native feel.',
614
+ });
615
+ if (result.action === Share.sharedAction) {
616
+ if (result.activityType) {
617
+ // shared with activity type of result.activityType
618
+ } else {
619
+ // shared
620
+ }
621
+ } else if (result.action === Share.dismissedAction) {
622
+ // dismissed
623
+ }
624
+ } catch (error: any) {
625
+ Alert.alert(error.message);
626
+ }
627
+ }}
628
+ title='Share a message'
629
+ />
630
+ </View>
631
+ );
632
+ },
156
633
  },
634
+ <% } %>
635
+ <% if (props.stylingPackage?.options.selectedComponents.includes('bottom-sheet')) { %>
157
636
  {
158
- name: 'Bottom Tabs Navigation',
159
- href: '/bottom-tabs/',
637
+ name: 'Bottom Sheet',
638
+ component: function BottomSheetExample() {
639
+ const { colorScheme } = useColorScheme();
640
+ const bottomSheetModalRef = useSheetRef();
641
+
642
+ return (
643
+ <View className='items-center'>
644
+ <DefaultButton
645
+ color={
646
+ colorScheme === 'dark' && Platform.OS === 'ios'
647
+ ? 'white'
648
+ : 'black'
649
+ }
650
+ title='Open Bottom Sheet'
651
+ onPress={() => bottomSheetModalRef.current?.present()}
652
+ />
653
+ <Sheet ref={bottomSheetModalRef} snapPoints={[200]}>
654
+ <View className='flex-1 justify-center items-center pb-8'>
655
+ <Text>@gorhom/bottom-sheet 🎉</Text>
656
+ </View>
657
+ </Sheet>
658
+ </View>
659
+ );
660
+ },
160
661
  },
662
+ <% } %>
663
+ <% if (props.stylingPackage?.options.selectedComponents.includes('avatar')) { %>
161
664
  {
162
- name: 'Top Tabs Navigation',
163
- href: '/top-tabs/',
665
+ name: 'Avatar',
666
+ component: function AvatarExample() {
667
+ const GITHUB_AVATAR_URI = 'https://github.com/mrzachnugent.png';
668
+ return (
669
+ <View className='items-center'>
670
+ <Avatar alt="Zach Nugent's Avatar">
671
+ <AvatarImage source={{ uri: GITHUB_AVATAR_URI }} />
672
+ <AvatarFallback>
673
+ <Text>ZN</Text>
674
+ </AvatarFallback>
675
+ </Avatar>
676
+ </View>
677
+ );
678
+ },
164
679
  },
165
- ] as const;
680
+ <% } %>
681
+ ];
682
+