Skip to content

Commit 9d36900

Browse files
authored
Merge pull request #4 from Soomgo-Mobile/develop
Develop
2 parents cebbd8e + c212aa4 commit 9d36900

14 files changed

+579
-38
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,30 @@ The goal of `react-native-use-modal` is to make all the functions of `react-nati
1818
- No need to explicitly place modal at component tree
1919
- Fully customizable
2020

21+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
22+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
23+
## Table of Contents
24+
25+
- [Installation](#installation)
26+
- [Place `ModalProvider` at your app's root component](#place-modalprovider-at-your-apps-root-component)
27+
- [Usage](#usage)
28+
- [Declare modal as hook with `createUseModal`](#declare-modal-as-hook-with-createusemodal)
29+
- [Show modal using hook](#show-modal-using-hook)
30+
- [Handling the modal's result](#handling-the-modals-result)
31+
- [Declare modal that require parameters](#declare-modal-that-require-parameters)
32+
- [Show modal that require parameters](#show-modal-that-require-parameters)
33+
- [Declare modal that return values](#declare-modal-that-return-values)
34+
- [Handling the modal's result with value](#handling-the-modals-result-with-value)
35+
- [Customize modal config](#customize-modal-config)
36+
- [Make cancelable when press backdrop or back button](#make-cancelable-when-press-backdrop-or-back-button)
37+
- [Creating a preconfigured createUseModal](#creating-a-preconfigured-createusemodal)
38+
- [Making a third-party modal or an existing modal into a 'hook'](#making-a-third-party-modal-or-an-existing-modal-into-a-hook)
39+
- [Workflow example](#workflow-example)
40+
- [Contributing](#contributing)
41+
- [License](#license)
42+
43+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
44+
2145
## Installation
2246

2347
```sh
@@ -263,6 +287,18 @@ export const useSimpleModal = createUseModal(
263287
);
264288
```
265289

290+
### Creating a preconfigured createUseModal
291+
You can use the `createCreateUseModal` function to create createUseModal with predefined options.
292+
For example, if you need to create several bottom sheet modal, you can use it in a way such as defining the modalOption value for creating a bottom sheet modal in advance.
293+
294+
An example usage can be found at [create-use-bottom-sheet-modal.tsx](src/create-use-bottom-sheet-modal.tsx).
295+
296+
### Making a third-party modal or an existing modal into a 'hook'
297+
Using `createUseForwardedModal`, You can make a normal modal (modal that receives the visible property as props) a 'hook'.
298+
It can be used when you want to make a modal component provided by the design component library into a 'hook' or to make an existing modal component into a 'hook' with minimal effort.
299+
300+
An example usage can be found at [forwarded-alert-modal-example-screen.tsx](example/src/forwarded-alert-modal-example/forwarded-alert-modal-example-screen.tsx).
301+
266302
## Workflow example
267303

268304
You can clone this project and test examples by running the following command:

example/src/App.tsx

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {TextInputModalExampleScreen} from './text-input-modal-example';
1111
import {AlertModalExampleScreen} from './alert-modal-example';
1212
import {ShowModalContinuouslyExampleScreen} from './show-modal-continuously-example';
1313
import {ForwardedAlertModalExampleScreen} from './forwarded-alert-modal-example/forwarded-alert-modal-example-screen';
14+
import {SimpleBottomSheetModalExampleScreen} from './simple-bottom-sheet-modal-example';
15+
import {SafeAreaProvider} from 'react-native-safe-area-context';
1416

1517
type RootStackParamList = {
1618
SIMPLE_MODAL_EXAMPLE: undefined;
@@ -19,6 +21,7 @@ type RootStackParamList = {
1921
ALERT_MODAL_EXAMPLE: undefined;
2022
SHOW_MODAL_CONTINUOUSLY_EXAMPLE: undefined;
2123
FORWARDED_ALERT_MODAL_EXAMPLE: undefined;
24+
SIMPLE_BOTTOM_SHEET_MODAL_EXAMPLE: undefined;
2225
};
2326

2427
export type RootStackNavigationProp = StackNavigationProp<RootStackParamList>;
@@ -27,32 +30,38 @@ const Stack = createStackNavigator<RootStackParamList>();
2730

2831
export default function App() {
2932
return (
30-
<ModalProvider>
31-
<NavigationContainer>
32-
<Stack.Navigator initialRouteName={'HOME'}>
33-
<Stack.Screen name={'HOME'} component={HomeScreen} />
34-
<Stack.Screen
35-
name={'SIMPLE_MODAL_EXAMPLE'}
36-
component={SimpleModalExampleScreen}
37-
/>
38-
<Stack.Screen
39-
name={'TEXT_INPUT_MODAL_EXAMPLE'}
40-
component={TextInputModalExampleScreen}
41-
/>
42-
<Stack.Screen
43-
name={'ALERT_MODAL_EXAMPLE'}
44-
component={AlertModalExampleScreen}
45-
/>
46-
<Stack.Screen
47-
name={'SHOW_MODAL_CONTINUOUSLY_EXAMPLE'}
48-
component={ShowModalContinuouslyExampleScreen}
49-
/>
50-
<Stack.Screen
51-
name={'FORWARDED_ALERT_MODAL_EXAMPLE'}
52-
component={ForwardedAlertModalExampleScreen}
53-
/>
54-
</Stack.Navigator>
55-
</NavigationContainer>
56-
</ModalProvider>
33+
<SafeAreaProvider>
34+
<ModalProvider>
35+
<NavigationContainer>
36+
<Stack.Navigator initialRouteName={'HOME'}>
37+
<Stack.Screen name={'HOME'} component={HomeScreen} />
38+
<Stack.Screen
39+
name={'SIMPLE_MODAL_EXAMPLE'}
40+
component={SimpleModalExampleScreen}
41+
/>
42+
<Stack.Screen
43+
name={'TEXT_INPUT_MODAL_EXAMPLE'}
44+
component={TextInputModalExampleScreen}
45+
/>
46+
<Stack.Screen
47+
name={'ALERT_MODAL_EXAMPLE'}
48+
component={AlertModalExampleScreen}
49+
/>
50+
<Stack.Screen
51+
name={'SHOW_MODAL_CONTINUOUSLY_EXAMPLE'}
52+
component={ShowModalContinuouslyExampleScreen}
53+
/>
54+
<Stack.Screen
55+
name={'FORWARDED_ALERT_MODAL_EXAMPLE'}
56+
component={ForwardedAlertModalExampleScreen}
57+
/>
58+
<Stack.Screen
59+
name={'SIMPLE_BOTTOM_SHEET_MODAL_EXAMPLE'}
60+
component={SimpleBottomSheetModalExampleScreen}
61+
/>
62+
</Stack.Navigator>
63+
</NavigationContainer>
64+
</ModalProvider>
65+
</SafeAreaProvider>
5766
);
5867
}

example/src/home-screen.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ export const HomeScreen = () => {
3939
navigation.push('FORWARDED_ALERT_MODAL_EXAMPLE');
4040
}}
4141
/>
42+
<Button
43+
title={'Bottom sheet modal'}
44+
onPress={() => {
45+
navigation.push('SIMPLE_BOTTOM_SHEET_MODAL_EXAMPLE');
46+
}}
47+
/>
4248
</ScrollView>
4349
</View>
4450
);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './simple-bottom-sheet-modal-example-screen';
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {Button, StyleSheet, View} from 'react-native';
2+
import React, {useCallback} from 'react';
3+
import {useSimpleBottomSheetModal} from './simple-bottom-sheet-modal';
4+
import {Title} from 'react-native-paper';
5+
6+
export const SimpleBottomSheetModalExampleScreen = () => {
7+
const simpleModal = useSimpleBottomSheetModal();
8+
9+
const handlePress = useCallback(() => {
10+
simpleModal.show();
11+
}, [simpleModal]);
12+
13+
return (
14+
<View style={styles.container}>
15+
<Title>Simple Bottom Sheet</Title>
16+
<View style={styles.space} />
17+
<Button title={'show'} onPress={handlePress} />
18+
</View>
19+
);
20+
};
21+
22+
const styles = StyleSheet.create({
23+
container: {
24+
flex: 1,
25+
justifyContent: 'center',
26+
alignItems: 'center',
27+
},
28+
space: {
29+
height: 48,
30+
},
31+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import {StyleSheet, View} from 'react-native';
2+
import React from 'react';
3+
import {Button, Paragraph, Title} from 'react-native-paper';
4+
import {createUseBottomSheetModal} from 'react-native-use-modal';
5+
import {useSafeAreaInsets} from 'react-native-safe-area-context';
6+
7+
export const useSimpleBottomSheetModal = createUseBottomSheetModal(
8+
({confirm, cancel}) => {
9+
const safeAreaInsets = useSafeAreaInsets();
10+
return (
11+
<View
12+
style={[
13+
styles.container,
14+
{
15+
paddingBottom: safeAreaInsets.bottom,
16+
},
17+
]}>
18+
<Title>Title of modal</Title>
19+
<Paragraph>
20+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sed ex
21+
scelerisque, consectetur magna id, pulvinar mauris. Duis eu aliquet
22+
diam. Vestibulum congue est lacus, eu ullamcorper arcu eleifend a.
23+
Pellentesque habitant morbi tristique senectus et netus et malesuada
24+
fames ac turpis egestas. Pellentesque habitant morbi tristique
25+
senectus et netus et malesuada fames ac turpis egestas. Sed vitae nunc
26+
in nibh venenatis luctus.
27+
</Paragraph>
28+
<View style={styles.buttonContainer}>
29+
<Button onPress={confirm}>Ok</Button>
30+
<Button onPress={cancel}>Cancel</Button>
31+
</View>
32+
</View>
33+
);
34+
},
35+
);
36+
37+
const styles = StyleSheet.create({
38+
container: {
39+
backgroundColor: '#fff',
40+
borderRadius: 12,
41+
paddingHorizontal: 16,
42+
paddingVertical: 8,
43+
},
44+
buttonContainer: {
45+
flexDirection: 'row',
46+
alignSelf: 'flex-end',
47+
},
48+
});

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"release": "release-it",
3030
"example": "yarn --cwd example",
3131
"pods": "cd example && pod-install --quiet",
32-
"bootstrap": "yarn example && yarn && yarn pods"
32+
"bootstrap": "yarn example && yarn && yarn pods",
33+
"update:readme": "doctoc README.md --title '## Table of Contents'"
3334
},
3435
"keywords": [
3536
"react-native",
@@ -51,9 +52,11 @@
5152
"@react-native-community/eslint-config": "^2.0.0",
5253
"@release-it/conventional-changelog": "^2.0.0",
5354
"@types/jest": "^26.0.0",
55+
"@types/lodash": "^4.14.171",
5456
"@types/react": "^16.9.19",
5557
"@types/react-native": "0.62.13",
5658
"commitlint": "^11.0.0",
59+
"doctoc": "^2.0.1",
5760
"eslint": "^7.2.0",
5861
"eslint-config-prettier": "^7.0.0",
5962
"eslint-plugin-prettier": "^3.1.3",
@@ -151,6 +154,7 @@
151154
]
152155
},
153156
"dependencies": {
157+
"lodash": "^4.17.21",
154158
"react-native-modal": "^11.10.0",
155159
"rxjs": "^7.1.0"
156160
}

src/create-create-use-modal.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { createUseModal } from './create-use-modal';
2+
import type { CreateModalOption } from './create-modal';
3+
import _ from 'lodash';
4+
5+
/**
6+
* createUseModal creation function with default value of option argument set
7+
*/
8+
export const createCreateUseModal =
9+
(_option: CreateModalOption): typeof createUseModal =>
10+
(...param) => {
11+
const [Content, option] = param;
12+
const composedOption = _.defaultsDeep(option, _option);
13+
return createUseModal(Content, composedOption);
14+
};

src/create-modal.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import { useModalViewModel } from './use-modal-view-model';
66
import { StyleSheet } from 'react-native';
77
import type { ModalInstance } from './modal-instance';
88

9+
export type CreateModalOption = {
10+
cancelOnBackdropPress?: boolean; // 배경 클릭시 취소 여부
11+
cancelOnBackButtonPress?: boolean; // 뒤로가기 버튼 클릭시 취소 여부
12+
modalProps?: Omit<Partial<ModalProps>, 'isVisible'>;
13+
};
14+
915
export type CreateModalFunctionParam<
1016
Data extends unknown = void, // 모달 결과로 받을 값의 타입
1117
Param extends unknown = void
@@ -16,11 +22,7 @@ export type CreateModalFunctionParam<
1622
cancel: () => void; // 모달 종료 함수 (취소)
1723
param: Param;
1824
}>,
19-
option?: {
20-
cancelOnBackdropPress?: boolean; // 배경 클릭시 취소 여부
21-
cancelOnBackButtonPress?: boolean; // 뒤로가기 버튼 클릭시 취소 여부
22-
modalProps?: Omit<Partial<ModalProps>, 'isVisible'>;
23-
}
25+
option?: CreateModalOption
2426
];
2527

2628
/**

src/create-use-bottom-sheet-modal.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { createCreateUseModal } from './create-create-use-modal';
2+
3+
/**
4+
* Modal hook creation function with default set to BottomSheet style
5+
*/
6+
export const createUseBottomSheetModal = createCreateUseModal({
7+
modalProps: {
8+
style: {
9+
margin: 0,
10+
padding: 0,
11+
justifyContent: 'flex-end',
12+
},
13+
animationIn: 'slideInUp',
14+
animationOut: 'slideOutDown',
15+
},
16+
cancelOnBackButtonPress: true,
17+
cancelOnBackdropPress: true,
18+
});

src/create-use-modal.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { createModal, CreateModalFunctionParam } from './create-modal';
22
import { useModal } from './use-modal';
33
import React from 'react';
44

5+
/**
6+
* A function that creates a custom hook that returns an object with a modal display function.
7+
*/
58
export const createUseModal = <
69
Data extends unknown = void,
710
Param extends unknown = void

src/create-use-notification-modal.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createCreateUseModal } from './create-create-use-modal';
2+
3+
/**
4+
* Modal hook creation function with default set to BottomSheet style
5+
*/
6+
export const createUseNotificationModal = createCreateUseModal({
7+
modalProps: {
8+
style: {
9+
margin: 0,
10+
padding: 0,
11+
justifyContent: 'flex-start',
12+
},
13+
animationIn: 'slideOutDown',
14+
animationOut: 'slideInUp',
15+
},
16+
});

src/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ export * from './modal-result-type';
55
export * from './create-use-modal';
66
export * from './create-use-forwarded-modal';
77
export * from './create-forwarded-modal';
8+
export * from './create-create-use-modal';
9+
export * from './create-use-bottom-sheet-modal';
10+
export * from './create-use-notification-modal';

0 commit comments

Comments
 (0)