refactor: reorganize examples with shared package (#306)

* feat(expo-example): update to match example app structure

- Add promise-based present/dismiss to TrueSheet.web.tsx
- Remove tabs navigation, use stack-based routing
- Add screens: Map, Standard, Modal, Test
- Add shared components and sheet components
- Add utils (constants, times, random)
- Add react-native-maps dependency

* feat(expo-example): add Map component and SheetStack with withLayoutContext

- Add platform-specific Map component (native MapView, web View fallback)
- Add sheet-stack route using expo-router's withLayoutContext
- Integrate createTrueSheetNavigator with expo-router file-based routing

* refactor: create shared example-shared package for common components

- Create @truesheet/example-shared workspace package
- Move common components (Button, Header, Footer, etc.) to shared
- Move sheet components (BasicSheet, PromptSheet, etc.) to shared
- Move utils (constants, times, random) to shared
- Update example and expo-example to re-export from shared

* chore: reorganize examples into examples/ folder

- Move example/ to examples/bare/
- Move expo-example/ to examples/expo/
- Move example-shared/ to examples/shared/
- Update workspace paths in root package.json
- Rename packages to @truesheet/bare-example, @truesheet/expo-example
- Update script names (example -> bare, expo)

* chore: update config paths for examples folder reorganization

* chore: rename examples to example and update package names to @example/*

* chore: move screen components to shared package

- Add MapScreen, ModalScreen, StandardScreen, TestScreen to shared
- Make screens navigation-agnostic with callback props
- Add MapComponent prop to MapScreen for platform-specific map
- Create Map component in bare example
- Update expo and bare examples to use shared screens

* chore: import screens directly from @example/shared/screens

* chore: import components and utils directly from @example/shared

* chore: remove unused sheets index files

* chore: move Map component to shared package

* chore: remove unused constants folder from expo example

* chore: remove unused ReanimatedExample component

* chore: update scripts for new example folder structure

* chore: exclude example folder from jest test paths

* chore: add expo prebuild step to clean script

* fix: update config paths for new example folder structure

* chore: categorize steps in clean script

* fix: use workspace:* for example dependencies

- Change @lodev09/react-native-true-sheet from * to workspace:* in bare and expo examples
- Fixes duplicate view registration error caused by npm version being installed alongside workspace
- Silence clean.sh script output while preserving error visibility
This commit is contained in:
Jovanni Lo 2025-12-12 03:08:20 +08:00 committed by GitHub
parent a52d09baa9
commit 4606a1bee9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
132 changed files with 698 additions and 870 deletions

4
.gitignore vendored
View File

@ -43,10 +43,10 @@ android.iml
# Cocoapods
#
example/ios/Pods
example/bare/ios/Pods
# Ruby
example/vendor/
example/bare/vendor/
# node.js
#

View File

@ -22,7 +22,9 @@ src/
├── specs/ # TurboModule spec
├── reanimated/ # Reanimated integration
├── navigation/ # React Navigation integration
│ └── screen/ # Screen components for navigator
├── TrueSheet.tsx # Main React component
├── TrueSheetProvider.tsx
└── TrueSheet.types.ts
ios/
@ -30,9 +32,10 @@ ios/
├── TrueSheetViewController.mm # UIViewController for sheet presentation
├── TrueSheetModule.mm # TurboModule
├── TrueSheet*View.mm # Container, Content, Header, Footer views
├── core/ # Core UI components (GrabberView, BlurView)
├── events/ # Event classes
└── utils/ # Utility classes
├── TrueSheetComponentDescriptor.h
├── core/ # GrabberView, BlurView
├── events/ # Lifecycle, State, Drag, Focus events
└── utils/ # Layout, Gesture, Window utilities
android/.../truesheet/
├── TrueSheetView.kt # Host view
@ -40,13 +43,14 @@ android/.../truesheet/
├── TrueSheetModule.kt # TurboModule
├── TrueSheet*View.kt # Container, Content, Header, Footer views
├── TrueSheet*ViewManager.kt # View managers
├── core/ # Core components (GrabberView, DialogObserver, etc.)
├── events/ # Event classes
└── utils/ # Utility classes
├── TrueSheetPackage.kt
├── core/ # GrabberView, DialogObserver, RNScreensFragmentObserver
├── events/ # Lifecycle, State, Drag, Focus events
└── utils/ # ScreenUtils
common/cpp/.../TrueSheetSpec/
├── TrueSheetViewState.h/.cpp # Shared state
├── TrueSheetViewShadowNode.h/.cpp # Custom shadow node
├── TrueSheetViewState.cpp/.h
├── TrueSheetViewShadowNode.cpp/.h
└── TrueSheetViewComponentDescriptor.h
```

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -1,8 +1,8 @@
const path = require('path')
const { getConfig } = require('react-native-builder-bob/babel-config')
const pkg = require('../package.json')
const pkg = require('../../package.json')
const root = path.resolve(__dirname, '..')
const root = path.resolve(__dirname, '../..')
module.exports = getConfig(
{

View File

@ -2845,7 +2845,7 @@ DEPENDENCIES:
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNTrueSheet (from `../..`)
- RNTrueSheet (from `../../..`)
- RNWorklets (from `../node_modules/react-native-worklets`)
- SocketRocket (~> 0.7.1)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@ -3011,7 +3011,7 @@ EXTERNAL SOURCES:
RNScreens:
:path: "../node_modules/react-native-screens"
RNTrueSheet:
:path: "../.."
:path: "../../.."
RNWorklets:
:path: "../node_modules/react-native-worklets"
Yoga:

View File

@ -2,8 +2,8 @@ const path = require('path')
const { getDefaultConfig } = require('@react-native/metro-config')
const { withMetroConfig } = require('react-native-monorepo-config')
const root = path.resolve(__dirname, '..')
const pkg = require('../package.json')
const root = path.resolve(__dirname, '../..')
const pkg = require('../../package.json')
/**
* Metro configuration

View File

@ -1,5 +1,5 @@
{
"name": "react-native-true-sheet-example",
"name": "@example/bare",
"version": "0.0.1",
"private": true,
"scripts": {
@ -11,6 +11,8 @@
"doctor": "react-native doctor"
},
"dependencies": {
"@example/shared": "*",
"@lodev09/react-native-true-sheet": "workspace:*",
"@react-navigation/native": "^7.1.21",
"@react-navigation/native-stack": "^7.7.0",
"react": "19.1.1",

View File

@ -1,5 +1,5 @@
const path = require('path');
const pkg = require('../package.json');
const pkg = require('../../package.json');
module.exports = {
project: {
@ -9,7 +9,7 @@ module.exports = {
},
dependencies: {
[pkg.name]: {
root: path.join(__dirname, '..'),
root: path.join(__dirname, '../..'),
platforms: {
ios: {},
},

View File

@ -0,0 +1,27 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { useNavigation } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { ModalScreen, TestScreen } from '@example/shared/screens';
import type { ModalStackParamList } from '../types';
const ModalStack = createNativeStackNavigator<ModalStackParamList>();
const ModalScreenWrapper = () => {
const navigation = useNavigation<NativeStackNavigationProp<ModalStackParamList>>();
return (
<ModalScreen
onNavigateToTest={() => navigation.navigate('Test')}
onDismiss={() => navigation.goBack()}
/>
);
};
export const ModalStackNavigator = () => {
return (
<ModalStack.Navigator screenOptions={{ headerTransparent: true, headerTintColor: 'white' }}>
<ModalStack.Screen name="Modal" component={ModalScreenWrapper} />
<ModalStack.Screen name="Test" component={TestScreen} />
</ModalStack.Navigator>
);
};

View File

@ -1,14 +1,38 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { MapScreen, StandardScreen, TestScreen } from '../screens';
import { MapScreen, StandardScreen, TestScreen } from '@example/shared/screens';
import { Map } from '@example/shared/components';
import { ModalStackNavigator } from './ModalStackNavigator';
import { SheetNavigator } from './SheetNavigator';
import type { AppStackParamList } from '../types';
import { useAppNavigation } from '../hooks';
const Stack = createNativeStackNavigator<AppStackParamList>();
const INITIAL_ROUTE_NAME: keyof AppStackParamList = 'Map';
const MapScreenWrapper = () => {
const navigation = useAppNavigation();
return (
<MapScreen
MapComponent={Map}
onNavigateToModal={() => navigation.navigate('ModalStack')}
onNavigateToSheetStack={() => navigation.navigate('SheetStack')}
/>
);
};
const StandardScreenWrapper = () => {
const navigation = useAppNavigation();
return (
<StandardScreen
onNavigateToTest={() => navigation.navigate('Test')}
onNavigateToModal={() => navigation.navigate('ModalStack')}
onNavigateToMap={() => navigation.navigate('Map')}
/>
);
};
export const RootNavigator = () => {
return (
<Stack.Navigator
@ -20,11 +44,11 @@ export const RootNavigator = () => {
name="SheetStack"
component={SheetNavigator}
/>
<Stack.Screen options={{ headerShown: false }} name="Map" component={MapScreen} />
<Stack.Screen options={{ headerShown: false }} name="Map" component={MapScreenWrapper} />
<Stack.Screen
options={{ headerShown: false, title: 'Standard' }}
name="Standard"
component={StandardScreen}
component={StandardScreenWrapper}
/>
<Stack.Screen name="Test" component={TestScreen} />
<Stack.Screen

View File

@ -6,8 +6,8 @@ import {
createTrueSheetNavigator,
useTrueSheetNavigation,
} from '@lodev09/react-native-true-sheet/navigation';
import { Button, DemoContent } from '../components';
import { BLUE, DARK, GAP, LIGHT_GRAY, SPACING } from '../utils';
import { Button, DemoContent } from '@example/shared/components';
import { BLUE, DARK, GAP, LIGHT_GRAY, SPACING } from '@example/shared/utils';
import type { AppStackParamList, SheetStackParamList } from '../types';
const Sheet = createTrueSheetNavigator<SheetStackParamList>();

View File

@ -4,19 +4,17 @@ import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
import { TrueSheetProvider } from '@lodev09/react-native-true-sheet';
import { useColorScheme } from 'react-native';
import { ReanimatedTrueSheetProvider } from '@lodev09/react-native-true-sheet/reanimated';
import 'react-native-reanimated';
import { useColorScheme } from '../components/useColorScheme';
export {
// Catch any errors thrown by the Layout component.
ErrorBoundary,
} from 'expo-router';
export const unstable_settings = {
// Ensure that reloading on `/modal` keeps a back button present.
initialRouteName: '(tabs)',
initialRouteName: 'index',
};
// Prevent the splash screen from auto-hiding before asset loading is complete.
@ -51,12 +49,21 @@ function RootLayoutNav() {
return (
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<TrueSheetProvider>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
<ReanimatedTrueSheetProvider>
<Stack screenOptions={{ headerTransparent: true, headerTintColor: 'white' }}>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="standard" options={{ headerShown: false, title: 'Standard' }} />
<Stack.Screen name="test" options={{ title: 'Test' }} />
<Stack.Screen
name="modal"
options={{ presentation: 'fullScreenModal', headerShown: false }}
/>
<Stack.Screen
name="sheet-stack"
options={{ presentation: 'fullScreenModal', headerShown: false }}
/>
</Stack>
</TrueSheetProvider>
</ReanimatedTrueSheetProvider>
</ThemeProvider>
);
}

View File

@ -0,0 +1,16 @@
import { useRouter } from 'expo-router';
import { MapScreen } from '@example/shared/screens';
import { Map } from '@example/shared/components';
export default function Index() {
const router = useRouter();
return (
<MapScreen
MapComponent={Map}
onNavigateToModal={() => router.push('/modal')}
onNavigateToSheetStack={() => router.push('/sheet-stack')}
/>
);
}

View File

@ -0,0 +1,11 @@
import { useRouter } from 'expo-router';
import { ModalScreen } from '@example/shared/screens';
export default function Modal() {
const router = useRouter();
return (
<ModalScreen onNavigateToTest={() => router.push('/test')} onDismiss={() => router.back()} />
);
}

View File

@ -0,0 +1,70 @@
import { withLayoutContext } from 'expo-router';
import { createTrueSheetNavigator } from '@lodev09/react-native-true-sheet/navigation';
import { DARK } from '@example/shared/utils';
const { Navigator } = createTrueSheetNavigator();
export const Sheet = withLayoutContext(Navigator);
export default function SheetStackLayout() {
return (
<Sheet
screenListeners={{
sheetWillPresent: (e) => {
console.log(`[SheetNavigator] sheetWillPresent: index=${e.data.index}`);
},
sheetDidPresent: (e) => {
console.log(`[SheetNavigator] sheetDidPresent: index=${e.data.index}`);
},
sheetWillDismiss: () => {
console.log('[SheetNavigator] sheetWillDismiss');
},
sheetDidDismiss: () => {
console.log('[SheetNavigator] sheetDidDismiss');
},
sheetDetentChange: (e) => {
console.log(`[SheetNavigator] sheetDetentChange: index=${e.data.index}`);
},
sheetDragBegin: (e) => {
console.log(`[SheetNavigator] sheetDragBegin: index=${e.data.index}`);
},
sheetDragChange: (e) => {
console.log(`[SheetNavigator] sheetDragChange: position=${e.data.position.toFixed(0)}`);
},
sheetDragEnd: (e) => {
console.log(`[SheetNavigator] sheetDragEnd: index=${e.data.index}`);
},
sheetWillFocus: () => {
console.log('[SheetNavigator] sheetWillFocus');
},
sheetDidFocus: () => {
console.log('[SheetNavigator] sheetDidFocus');
},
sheetWillBlur: () => {
console.log('[SheetNavigator] sheetWillBlur');
},
sheetDidBlur: () => {
console.log('[SheetNavigator] sheetDidBlur');
},
}}
>
<Sheet.Screen name="index" />
<Sheet.Screen
name="details"
options={{
detents: ['auto', 1],
cornerRadius: 16,
}}
/>
<Sheet.Screen
name="settings"
options={{
detents: ['auto', 1],
backgroundColor: DARK,
cornerRadius: 16,
}}
/>
</Sheet>
);
}

View File

@ -0,0 +1,43 @@
import { StyleSheet, Text, View } from 'react-native';
import { useTrueSheetNavigation } from '@lodev09/react-native-true-sheet/navigation';
import { Button, DemoContent } from '@example/shared/components';
import { GAP, LIGHT_GRAY, SPACING } from '@example/shared/utils';
export default function DetailsSheet() {
const navigation = useTrueSheetNavigation();
return (
<View style={styles.sheetContent}>
<Text style={styles.sheetTitle}>Details Sheet</Text>
<Text style={styles.sheetSubtitle}>This is a sheet screen using expo-router.</Text>
<DemoContent />
<View style={styles.buttons}>
<Button text="Resize to 100%" onPress={() => navigation.resize(1)} />
<Button text="Open Settings" onPress={() => navigation.navigate('settings')} />
<Button text="Go Back" onPress={() => navigation.goBack()} />
</View>
</View>
);
}
const styles = StyleSheet.create({
sheetContent: {
padding: SPACING,
gap: GAP,
},
sheetTitle: {
fontSize: 20,
fontWeight: '600',
color: 'white',
},
sheetSubtitle: {
fontSize: 14,
color: LIGHT_GRAY,
marginBottom: SPACING,
},
buttons: {
gap: GAP,
marginTop: SPACING,
},
});

View File

@ -0,0 +1,49 @@
import { StyleSheet, Text, View } from 'react-native';
import { useRouter } from 'expo-router';
import { useTrueSheetNavigation } from '@lodev09/react-native-true-sheet/navigation';
import { Button } from '@example/shared/components';
import { BLUE, GAP, LIGHT_GRAY, SPACING } from '@example/shared/utils';
export default function SheetHomeScreen() {
const navigation = useTrueSheetNavigation();
const router = useRouter();
return (
<View style={styles.content}>
<View style={styles.heading}>
<Text style={styles.title}>Sheet Navigator</Text>
<Text style={styles.subtitle}>
Using createTrueSheetNavigator with expo-router's withLayoutContext.
</Text>
</View>
<Button text="Open Details Sheet" onPress={() => navigation.navigate('details')} />
<Button text="Open Settings Sheet" onPress={() => navigation.navigate('settings')} />
<Button text="Navigate to Test" onPress={() => router.push('/test')} />
<Button text="Go Back" onPress={() => router.back()} />
</View>
);
}
const styles = StyleSheet.create({
content: {
backgroundColor: BLUE,
justifyContent: 'center',
flex: 1,
padding: SPACING,
gap: GAP,
},
heading: {
marginBottom: SPACING * 2,
},
title: {
fontSize: 24,
lineHeight: 30,
fontWeight: '500',
color: 'white',
},
subtitle: {
lineHeight: 24,
color: LIGHT_GRAY,
},
});

View File

@ -0,0 +1,42 @@
import { StyleSheet, Text, View } from 'react-native';
import { useTrueSheetNavigation } from '@lodev09/react-native-true-sheet/navigation';
import { Button, DemoContent } from '@example/shared/components';
import { GAP, LIGHT_GRAY, SPACING } from '@example/shared/utils';
export default function SettingsSheet() {
const navigation = useTrueSheetNavigation();
return (
<View style={styles.sheetContent}>
<Text style={styles.sheetTitle}>Settings Sheet</Text>
<Text style={styles.sheetSubtitle}>Another sheet in the navigation stack.</Text>
<DemoContent />
<View style={styles.buttons}>
<Button text="Resize to 100%" onPress={() => navigation.resize(1)} />
<Button text="Go Back" onPress={() => navigation.goBack()} />
</View>
</View>
);
}
const styles = StyleSheet.create({
sheetContent: {
padding: SPACING,
gap: GAP,
},
sheetTitle: {
fontSize: 20,
fontWeight: '600',
color: 'white',
},
sheetSubtitle: {
fontSize: 14,
color: LIGHT_GRAY,
marginBottom: SPACING,
},
buttons: {
gap: GAP,
marginTop: SPACING,
},
});

View File

@ -0,0 +1,15 @@
import { useRouter } from 'expo-router';
import { StandardScreen } from '@example/shared/screens';
export default function Standard() {
const router = useRouter();
return (
<StandardScreen
onNavigateToTest={() => router.push('/test')}
onNavigateToModal={() => router.push('/modal')}
onNavigateToMap={() => router.push('/')}
/>
);
}

View File

@ -0,0 +1,5 @@
import { TestScreen } from '@example/shared/screens';
export default function Test() {
return <TestScreen />;
}

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -2,8 +2,8 @@ const path = require('path');
const { getDefaultConfig } = require('expo/metro-config');
const { withMetroConfig } = require('react-native-monorepo-config');
const root = path.resolve(__dirname, '..');
const pkg = require('../package.json');
const root = path.resolve(__dirname, '../..');
const pkg = require('../../package.json');
/**
* Metro configuration

View File

@ -1,5 +1,5 @@
{
"name": "expo-example",
"name": "@example/expo",
"main": "expo-router/entry",
"version": "1.0.0",
"scripts": {
@ -11,9 +11,10 @@
"prebuild:clean": "expo prebuild --clean"
},
"dependencies": {
"@example/shared": "*",
"@expo/vector-icons": "^15.0.3",
"@gorhom/bottom-sheet": "^5.2.8",
"@lodev09/react-native-true-sheet": "*",
"@lodev09/react-native-true-sheet": "workspace:*",
"@react-navigation/native": "^7.1.8",
"expo": "~54.0.27",
"expo-constants": "~18.0.11",
@ -22,11 +23,13 @@
"expo-router": "~6.0.17",
"expo-splash-screen": "~31.0.12",
"expo-status-bar": "~3.0.9",
"expo-system-ui": "~6.0.9",
"expo-web-browser": "~15.0.10",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
"react-native-maps": "^1.26.20",
"react-native-reanimated": "^4.2.0",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
@ -35,6 +38,7 @@
},
"devDependencies": {
"@types/react": "~19.1.0",
"@types/react-native-maps": "^0.24.2",
"react-native-monorepo-config": "^0.1.9",
"react-test-renderer": "19.1.0",
"typescript": "~5.9.2"

View File

@ -0,0 +1,32 @@
{
"name": "@example/shared",
"version": "0.0.0",
"private": true,
"source": "./src/index.ts",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./components": "./src/components/index.ts",
"./sheets": "./src/components/sheets/index.ts",
"./screens": "./src/screens/index.ts",
"./utils": "./src/utils/index.ts"
},
"peerDependencies": {
"@lodev09/react-native-true-sheet": "*",
"react": "*",
"react-native": "*",
"react-native-gesture-handler": "*",
"react-native-maps": "*",
"react-native-reanimated": "*",
"react-native-safe-area-context": "*"
},
"devDependencies": {
"@types/react": "19.1.1",
"react-native-gesture-handler": "^2.29.1",
"react-native-maps": "^1.26.20",
"react-native-reanimated": "^4.2.0",
"react-native-safe-area-context": "^5.5.2",
"typescript": "^5.9.2"
}
}

View File

@ -11,10 +11,10 @@ export const Button = (props: ButtonProps) => {
const { text, style, loading, ...rest } = props;
return (
<Pressable
style={({ pressed }) => [
style={(state) => [
styles.button,
pressed && styles.pressed,
typeof style === 'function' ? style({ pressed }) : style,
state.pressed && styles.pressed,
typeof style === 'function' ? style(state) : style,
]}
{...rest}
>

View File

@ -1,8 +1,8 @@
import { StyleSheet, Platform, type ViewProps } from 'react-native';
import Animated from 'react-native-reanimated';
import { HEADER_HEIGHT, SPACING } from '../utils';
import { Input } from './Input';
import Animated from 'react-native-reanimated';
type HeaderProps = ViewProps;

View File

@ -0,0 +1,33 @@
import { StyleSheet } from 'react-native';
import MapView, { type MapViewProps } from 'react-native-maps';
import { BLUE } from '../utils';
export const Map = (props: MapViewProps) => {
const { style, ...rest } = props;
return (
<MapView
style={[styles.map, style]}
initialCamera={{
altitude: 18000,
zoom: 14,
center: {
latitude: 9.306743705457553,
longitude: 123.30474002203727,
},
pitch: 0,
heading: 0,
}}
userInterfaceStyle="dark"
{...rest}
/>
);
};
const styles = StyleSheet.create({
map: {
flex: 1,
backgroundColor: BLUE,
},
});

View File

@ -0,0 +1,16 @@
import { StyleSheet, View, type ViewProps } from 'react-native';
import { BLUE } from '../utils';
export const Map = (props: ViewProps) => {
const { style, ...rest } = props;
return <View style={[styles.map, style]} {...rest} />;
};
const styles = StyleSheet.create({
map: {
flex: 1,
backgroundColor: BLUE,
},
});

View File

@ -4,3 +4,4 @@ export * from './DemoContent';
export * from './Button';
export * from './Spacer';
export * from './Input';
export * from './Map';

View File

@ -7,15 +7,16 @@ import { DemoContent } from '../DemoContent';
import { Footer } from '../Footer';
import { Button } from '../Button';
import { Spacer } from '../Spacer';
import { useAppNavigation } from '../../hooks';
interface BasicSheetProps extends TrueSheetProps {}
interface BasicSheetProps extends TrueSheetProps {
onNavigateToModal?: () => void;
}
export const BasicSheet = forwardRef((props: BasicSheetProps, ref: Ref<TrueSheet>) => {
const { onNavigateToModal, ...rest } = props;
const sheetRef = useRef<TrueSheet>(null);
const childSheet = useRef<TrueSheet>(null);
const [contentCount, setContentCount] = useState(0);
const navigation = useAppNavigation();
const resize = async (index: number) => {
await sheetRef.current?.resize(index);
@ -28,16 +29,12 @@ export const BasicSheet = forwardRef((props: BasicSheetProps, ref: Ref<TrueSheet
};
const presentChild = async () => {
// Note: no need to dismiss this sheet 😎
await childSheet.current?.present();
console.log('Child sheet presented!');
};
const presentPromptSheet = async () => {
// Note: we need to dismiss this sheet first
await sheetRef.current?.dismiss();
await TrueSheet.present('prompt-sheet');
};
@ -92,11 +89,10 @@ export const BasicSheet = forwardRef((props: BasicSheetProps, ref: Ref<TrueSheet
)
}
onMount={() => {
// sheetRef.current?.present(1)
console.log('BasicSheet is ready!');
}}
footer={<Footer />}
{...props}
{...rest}
>
{Array.from({ length: contentCount }, (_, i) => (
<DemoContent key={i} color={DARK_BLUE} />
@ -110,7 +106,7 @@ export const BasicSheet = forwardRef((props: BasicSheetProps, ref: Ref<TrueSheet
<Spacer />
<Button text="Present Child Sheet" onPress={presentChild} />
<Button text="Present PromptSheet" onPress={presentPromptSheet} />
<Button text="Navigate to Modal" onPress={() => navigation.navigate('ModalStack')} />
{onNavigateToModal && <Button text="Navigate to Modal" onPress={onNavigateToModal} />}
<Spacer />
<Button text="Dismiss" onPress={dismiss} />

View File

@ -1,4 +1,4 @@
import { forwardRef, type Ref } from 'react';
import { forwardRef } from 'react';
import { StyleSheet, Text } from 'react-native';
import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet';
@ -6,7 +6,7 @@ import { DARK, SPACING } from '../../utils';
interface BlankSheetProps extends TrueSheetProps {}
export const BlankSheet = forwardRef((props: BlankSheetProps, ref: Ref<TrueSheet>) => {
export const BlankSheet = forwardRef<TrueSheet, BlankSheetProps>((props, ref) => {
return (
<TrueSheet
ref={ref}

View File

@ -1,4 +1,4 @@
import { forwardRef, type Ref } from 'react';
import { forwardRef } from 'react';
import { StyleSheet, FlatList, View } from 'react-native';
import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet';
@ -10,7 +10,7 @@ import { Header } from '../Header';
interface FlatListSheetProps extends TrueSheetProps {}
export const FlatListSheet = forwardRef((props: FlatListSheetProps, ref: Ref<TrueSheet>) => {
export const FlatListSheet = forwardRef<TrueSheet, FlatListSheetProps>((props, ref) => {
return (
<TrueSheet
ref={ref}

View File

@ -76,7 +76,7 @@ export const GestureSheet = forwardRef((props: GestureSheetProps, ref: Ref<TrueS
))}
</Animated.View>
</GestureDetector>
<Button text="Dismis" onPress={dismiss} />
<Button text="Dismiss" onPress={dismiss} />
</GestureHandlerRootView>
</TrueSheet>
);

View File

@ -5,24 +5,22 @@ import type { TrueSheetProps } from '@lodev09/react-native-true-sheet';
import { Button } from '../Button';
import { GAP, SPACING } from '../../utils';
import { useAppNavigation } from '../../hooks';
export const NavigationSheet = forwardRef<TrueSheet, TrueSheetProps>((props, ref) => {
const navigation = useAppNavigation();
interface NavigationSheetProps extends TrueSheetProps {
onOpenModal?: () => void;
}
const handleOpenModal = () => {
navigation.navigate('ModalStack');
};
export const NavigationSheet = forwardRef<TrueSheet, NavigationSheetProps>((props, ref) => {
const { onOpenModal, ...rest } = props;
return (
<TrueSheet ref={ref} detents={['auto']} dimmed={false} {...props}>
<TrueSheet ref={ref} detents={['auto']} dimmed={false} {...rest}>
<View style={styles.container}>
<Text style={styles.title}>Navigation Sheet</Text>
<Text style={styles.description}>
This sheet demonstrates opening a React Navigation fullScreenModal from within a
TrueSheet.
This sheet demonstrates opening a fullScreenModal from within a TrueSheet.
</Text>
<Button text="Open Full Screen Modal" onPress={handleOpenModal} />
{onOpenModal && <Button text="Open Full Screen Modal" onPress={onOpenModal} />}
</View>
</TrueSheet>
);

View File

@ -57,8 +57,6 @@ export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref<TrueShe
}
onBackPress={() => {
console.log('Back button pressed!');
// Handle custom back press behavior here
// For example, dismiss the sheet programmatically
sheetRef.current?.dismiss();
}}
footer={<Footer />}
@ -68,7 +66,7 @@ export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref<TrueShe
<Input />
{isSubmitted && <Input />}
<Button text="Submit" onPress={submit} />
<Button text="Dismis" onPress={dismiss} />
<Button text="Dismiss" onPress={dismiss} />
</TrueSheet>
);
});

View File

@ -1,4 +1,4 @@
import { forwardRef, useState, type Ref } from 'react';
import { forwardRef, useState } from 'react';
import {
StyleSheet,
ScrollView,
@ -16,7 +16,6 @@ import { Header } from '../Header';
interface ScrollViewSheetProps extends TrueSheetProps {}
// Heavy item component for testing
const HeavyItem = ({ index }: { index: number }) => {
const [imageLoaded, setImageLoaded] = useState(false);
@ -40,7 +39,7 @@ const HeavyItem = ({ index }: { index: number }) => {
);
};
export const ScrollViewSheet = forwardRef((props: ScrollViewSheetProps, ref: Ref<TrueSheet>) => {
export const ScrollViewSheet = forwardRef<TrueSheet, ScrollViewSheetProps>((props, ref) => {
return (
<TrueSheet
ref={ref}

View File

@ -0,0 +1,3 @@
export * from './components';
export * from './components/sheets';
export * from './utils';

Some files were not shown because too many files have changed in this diff Show More