diff --git a/example/src/App.tsx b/example/src/App.tsx index 91f70edf..6189e7ab 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,29 +1,83 @@ -import * as React from 'react'; +import * as React from "react"; +import { StyleSheet } from "react-native"; -import { StyleSheet, View, Text } from 'react-native'; -import { RNIModalView } from 'react-native-ios-modal'; +import { NavigationContainer } from "@react-navigation/native"; +import { createNativeStackNavigator } from "@react-navigation/native-stack"; +import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; + +import { HomeScreen } from "./components/HomeScreen"; + +import { SHARED_ENV } from "./constants/SharedEnv"; +import { ROUTE_ITEMS } from "./constants/Routes"; +import { ROUTE_KEYS } from "./constants/RouteKeys"; + +const shouldEnableTabs = + SHARED_ENV.enableReactNavigation && SHARED_ENV.enableTabNavigation; + + +function Tab1StackScreen() { + if (shouldEnableTabs) { + const Tab1Stack = createNativeStackNavigator(); + + return ( + + + + ); + } else { + return null; + } +} export default function App() { - return ( - - - - Hello World - - - - ); + if (shouldEnableTabs) { + const TabNavigator = createBottomTabNavigator(); + + return ( + + + + + + + ); + } else if (SHARED_ENV.enableReactNavigation) { + const Stack = createNativeStackNavigator(); + + return ( + + + {ROUTE_ITEMS.map((item) => ( + + ))} + + + ); + } + + return ; } const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - }, - box: { - width: 60, - height: 60, - marginVertical: 20, - }, }); diff --git a/example/src/components/ExampleList.tsx b/example/src/components/ExampleList.tsx new file mode 100644 index 00000000..327936d8 --- /dev/null +++ b/example/src/components/ExampleList.tsx @@ -0,0 +1,97 @@ +import * as React from "react"; + +import { + StyleSheet, + FlatList, + type ListRenderItem, + type ViewStyle, +} from "react-native"; + +import { CardButton, ExampleItemCard } from "react-native-ios-utilities"; +import { useNavigation } from "@react-navigation/native"; + +import { SHARED_ENV } from "../constants/SharedEnv"; +import { EXAMPLE_ITEMS, type ExampleListItem } from "../constants/ExampleCardItems"; + + +const EXAMPLE_LIST_ITEMS = EXAMPLE_ITEMS.map( + (item, index) => { + switch(item.type) { + case 'screen': + return ({ + id: index + 1, + component: (props: Record) => { + // @ts-ignore + // eslint-disable-next-line react-hooks/rules-of-hooks + const navigation = SHARED_ENV.enableReactNavigation && useNavigation(); + + return ( + + { + // @ts-ignore + navigation?.push(item.routeKey); + }} + /> + + ); + }, + }); + + default: + return ({ + id: index + 1, + component: item.component as any, + }); + }; + } +); + +export function ExampleList(props: { + style: ViewStyle; + contentContainerStyle: ViewStyle; +}) { + const renderItem: ListRenderItem = ({item}) => ( + React.createElement(item.component, { + index: item.id, + style: styles.exampleListItem, + }) + ); + + return ( + `item-${item.id}`} + /> + ); +} + +const styles = StyleSheet.create({ + rootContainer: { + flex: 1, + backgroundColor: 'white', + }, + scrollView: { + flex: 1, + }, + scrollContentContainer: { + paddingHorizontal: 10, + paddingBottom: 100, + paddingTop: 20, + }, + exampleListItem: { + marginBottom: 15, + }, +}); diff --git a/example/src/components/HomeScreen.tsx b/example/src/components/HomeScreen.tsx new file mode 100644 index 00000000..fbd60cdc --- /dev/null +++ b/example/src/components/HomeScreen.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { StyleSheet, SafeAreaView } from "react-native"; +import { ExampleList } from "./ExampleList"; + + +export function HomeScreen() { + return ( + + + + ); +} + +const styles = StyleSheet.create({ + rootContainer: { + flex: 1, + backgroundColor: 'white', + }, + scrollView: { + flex: 1, + }, + scrollContentContainer: { + paddingHorizontal: 10, + paddingBottom: 100, + paddingTop: 20, + }, + exampleListItem: { + marginBottom: 15, + }, +}); diff --git a/example/src/constants/ExampleCardItems.ts b/example/src/constants/ExampleCardItems.ts new file mode 100644 index 00000000..3d12c37b --- /dev/null +++ b/example/src/constants/ExampleCardItems.ts @@ -0,0 +1,65 @@ +import { HomeScreen } from "../components/HomeScreen"; +import { AppMetadataCard } from "../examples/AppMetadataCard"; + +import { ModalSheetViewTest01 } from "../examples/ModalSheetViewTest01"; + +import type { ExampleItemProps } from "../examples/SharedExampleTypes"; +import type { RouteEntry } from "./Routes"; + + +type ExampleItemBase = { + component: unknown; +}; + +export type ExampleItemRoute = ExampleItemBase & RouteEntry & { + type: 'screen'; + title?: string; + subtitle?: string; + desc?: Array; +}; + +export type ExampleItemCard = ExampleItemBase & { + type: 'card'; +} + +export type ExampleItem = + | ExampleItemRoute + | ExampleItemCard; + +export type ExampleListItem = { + id: number; + component: React.FC; +}; + +export const EXAMPLE_ITEMS: Array = (() => { + const screenItems: Array = [ + { + component: HomeScreen, + type: 'screen', + routeKey: 'home', + desc: [ + 'Used for testing navigation events + memory leaks', + ], + }, + ]; + + const cardItems: Array = [ + { + type: 'card', + component: ModalSheetViewTest01, + }, + ]; + + // if (SHARED_ENV.enableReactNavigation) { + // items.splice(0, 0, ...[DebugControls]); + // } + + return [ + { + type: 'card', + component: AppMetadataCard, + }, + ...screenItems, + ...cardItems + ]; +})(); \ No newline at end of file diff --git a/example/src/constants/RouteKeys.ts b/example/src/constants/RouteKeys.ts new file mode 100644 index 00000000..cf92ac91 --- /dev/null +++ b/example/src/constants/RouteKeys.ts @@ -0,0 +1,7 @@ + +export const ROUTE_KEYS = { + home: 'home', + dummyTest01: 'dummyTest01', +}; + +export type RouteKey = keyof (typeof ROUTE_KEYS); \ No newline at end of file diff --git a/example/src/constants/Routes.ts b/example/src/constants/Routes.ts new file mode 100644 index 00000000..68d72a71 --- /dev/null +++ b/example/src/constants/Routes.ts @@ -0,0 +1,25 @@ +import { HomeScreen } from "../components/HomeScreen"; +import type { RouteKey } from "./RouteKeys"; + + +export type RouteEntry = { + routeKey: RouteKey + component: React.ComponentType<{}>; +}; + +export const ROUTE_ITEMS: Array = [ + { + routeKey: 'home', + component: HomeScreen, + } +]; + +export const ROUTE_MAP: Record = (() => { + const map: Record = {}; + + for (const routeItem of ROUTE_ITEMS) { + map[routeItem.routeKey] = routeItem; + }; + + return map; +})(); \ No newline at end of file diff --git a/example/src/constants/SharedEnv.ts b/example/src/constants/SharedEnv.ts new file mode 100644 index 00000000..4c7122c8 --- /dev/null +++ b/example/src/constants/SharedEnv.ts @@ -0,0 +1,8 @@ +export const SHARED_ENV = { + enableReactNavigation: true, + enableTabNavigation: false, + shouldSetAppBackground: false +}; + +export const IS_USING_NEW_ARCH = + (global as any)?.nativeFabricUIManager != null; \ No newline at end of file diff --git a/example/src/examples/AppMetadataCard.tsx b/example/src/examples/AppMetadataCard.tsx new file mode 100644 index 00000000..f856689c --- /dev/null +++ b/example/src/examples/AppMetadataCard.tsx @@ -0,0 +1,87 @@ +/* eslint-disable react-native/no-inline-styles */ +/* eslint-disable react-hooks/exhaustive-deps */ +import * as React from 'react'; +import { StyleSheet } from 'react-native'; + +import * as LibraryPackageConfig from '../../../package.json'; +import * as ExamplePackageConfig from '../../package.json'; +import { IS_USING_NEW_ARCH } from '../constants/SharedEnv'; + +import { ExampleItemCard, ObjectPropertyDisplay, Colors } from 'react-native-ios-utilities'; +import type { ExampleItemProps } from './SharedExampleTypes'; + + +export function AppMetadataCard(props: ExampleItemProps) { + + return ( + + + + ); +}; + +const styles = StyleSheet.create({ + detachedView: { + }, + detachedContentContainer: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + detachedContentContainerDetached: { + }, + counterContainer: { + alignItems: 'center', + justifyContent: 'center', + backgroundColor: 'rgba(255,255,255,0.3)', + borderRadius: 10, + marginTop: 12, + paddingHorizontal: 15, + paddingVertical: 15 + }, + counterContainerLarge: { + flex: 1, + alignSelf: 'stretch', + marginHorizontal: 24, + marginBottom: 32, + marginTop: 52, + borderRadius: 40, + }, + counterLabel: { + fontSize: 24, + fontWeight: '900', + color: 'rgba(0,0,0,0.5)', + }, + counterLabelLarge: { + fontSize: 64, + }, + counterSubtitleLabel: { + fontSize: 16, + color: 'rgba(0,0,0,0.7)', + fontWeight: '400', + }, + counterSubtitleLabelAlt: { + fontSize: 18, + marginVertical: 4, + fontWeight: '600', + color: 'rgba(0,0,0,0.5)', + }, + counterSubtitleLabelLarge: { + fontSize: 32, + }, + debugDisplayInner: { + backgroundColor: `${Colors.PURPLE[200]}99`, + }, +}); \ No newline at end of file diff --git a/example/src/examples/ModalSheetViewTest01.tsx b/example/src/examples/ModalSheetViewTest01.tsx new file mode 100644 index 00000000..50badd9a --- /dev/null +++ b/example/src/examples/ModalSheetViewTest01.tsx @@ -0,0 +1,56 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import * as React from 'react'; +import { StyleSheet, Text } from 'react-native'; + +import { ExampleItemCard, ObjectPropertyDisplay, CardButton, Colors } from 'react-native-ios-utilities'; +import { ModalSheetView, ModalSheetViewContent, type ModalSheetViewRef } from 'react-native-ios-modal'; + +import type { ExampleItemProps } from './SharedExampleTypes'; + + +export function ModalSheetViewTest01(props: ExampleItemProps) { + const modalSheetViewRef = React.useRef(null); + + return ( + + + { + }} + /> + modalSheetViewRef.current = ref} + > + + + {'Hello World'} + + + + + ); +}; + +const styles = StyleSheet.create({ + modalContent: { + alignItems: 'center', + justifyContent: 'center', + }, + debugDisplayInner: { + backgroundColor: `${Colors.PURPLE[200]}99`, + }, +}); \ No newline at end of file diff --git a/example/src/examples/SharedExampleTypes.ts b/example/src/examples/SharedExampleTypes.ts new file mode 100644 index 00000000..0c4306b8 --- /dev/null +++ b/example/src/examples/SharedExampleTypes.ts @@ -0,0 +1,7 @@ +import type { ViewStyle } from "react-native"; + + +export type ExampleItemProps = { + index: number; + style?: ViewStyle; +}; \ No newline at end of file