Skip to content

Commit 6aea312

Browse files
authored
refactor(ui): modal-based components API refactor
1 parent 97afa07 commit 6aea312

22 files changed

+174
-522
lines changed

src/framework/theme/index.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ export {
2020
ThemeProvider,
2121
ThemeProviderProps,
2222
} from './theme/themeProvider.component';
23-
export {
24-
ModalService,
25-
ModalComponentCloseProps,
26-
} from './modal/modal.service';
23+
export { ModalService } from './modal/modal.service';
2724
export {
2825
Interaction,
2926
State,

src/framework/theme/modal/modal.service.tsx

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,40 @@
55
*/
66

77
import React from 'react';
8+
import { ModalPresentingBased } from '../../ui/support/typings';
89

910
/**
1011
* Singleton service designed to manage modal components.
1112
*
1213
* @type ModalServiceType
1314
*
14-
* @method {(element: React.ReactElement<ModalComponentCloseProps>,
15-
* closeOnBackDrop: boolean = false) => string} show - Shows component in a modal window.
15+
* @method {(element: React.ReactElement<ModalPresentingBased>, config: ModalPresentingConfig) => string} show -
16+
* Shows component in a modal window. Returns its id.
1617
*
17-
* @method {(identifier: string) => void} hide - Hides component from a modal window.
18+
* @method {(identifier: string) => string} hide - Hides component from a modal window and returns empty string.
1819
*
1920
* @example Simple Usage example
2021
*
2122
* ```
2223
* import React from 'react';
23-
* import { View, ViewProps } from 'react-native';
24-
* import { Button, Text, ModalService } from 'react-native-ui-kitten';
24+
* import {
25+
* View,
26+
* ViewProps,
27+
* } from 'react-native';
28+
* import {
29+
* Button,
30+
* Text,
31+
* ModalService,
32+
* } from 'react-native-ui-kitten';
2533
*
2634
* export const ModalServiceShowcase = (): React.ReactElement<ViewProps> => {
2735
*
2836
* const modalID: string = '';
2937
*
3038
* const showModal = () => {
31-
* const component: React.ReactElement<ViewProps> =
39+
* const component: React.ReactElement<ViewProps> = this.renderModalContentElement();
3240
*
33-
* this.modalID = ModalService.show(this.renderModalContentElement);
41+
* this.modalID = ModalService.show(component, { allowBackdrop: true, onBackdropPress: this.hideModal });
3442
* };
3543
*
3644
* const hideModal = () => {
@@ -71,30 +79,31 @@ class ModalServiceType {
7179
this.panel = null;
7280
}
7381

74-
public show(element: React.ReactElement<ModalComponentCloseProps>,
75-
closeOnBackDrop: boolean = false): string {
82+
public show(element: React.ReactElement<ModalPresentingBased>,
83+
config: ModalPresentingConfig): string {
84+
7685
if (this.panel) {
77-
return this.panel.show(element, closeOnBackDrop);
86+
return this.panel.show(element, config);
7887
}
7988
}
8089

81-
public hide(identifier: string): void {
90+
public hide(identifier: string): string {
8291
if (this.panel) {
83-
this.panel.hide(identifier);
92+
return this.panel.hide(identifier);
8493
}
8594
}
8695
}
8796

88-
export interface ModalComponentCloseProps {
89-
[key: string]: any;
90-
onRequestClose: () => void;
97+
export interface ModalPresentingConfig {
98+
allowBackdrop: boolean;
99+
onBackdropPress: () => void;
91100
}
92101

93102
export interface ModalPresenting {
94-
show(element: React.ReactElement<ModalComponentCloseProps>,
95-
closeOnBackDrop: boolean): string;
103+
show(element: React.ReactElement<ModalPresentingBased>,
104+
config: ModalPresentingConfig): string;
96105

97-
hide(identifier: string): void;
106+
hide(identifier: string): string;
98107
}
99108

100109
export const ModalService = new ModalServiceType();

src/framework/theme/modal/modalPanel.component.tsx

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,42 @@
1+
/**
2+
* @license
3+
* Copyright Akveo. All Rights Reserved.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
17
import React from 'react';
28
import {
39
View,
410
StyleSheet,
511
ViewProps,
612
} from 'react-native';
7-
import { ModalResolver } from './modalResolver.component';
13+
import {
14+
ModalResolver,
15+
ModalResolverProps,
16+
} from './modalResolver.component';
817
import {
918
ModalService,
1019
ModalPresenting,
11-
ModalComponentCloseProps,
20+
ModalPresentingConfig,
1221
} from './modal.service';
22+
import { ModalPresentingBased } from '../../ui/support/typings';
23+
24+
interface ModalPanelChild extends ModalPresentingConfig {
25+
element: React.ReactElement<ModalPresentingBased>;
26+
}
1327

1428
export interface ModalPanelProps {
1529
children: React.ReactNode;
1630
}
1731

1832
interface ModalPanelState {
19-
components: Map<string, React.ReactElement<ModalComponentCloseProps>>;
20-
backdrops: Map<string, boolean>;
33+
components: Map<string, ModalPanelChild>;
2134
}
2235

2336
export class ModalPanel extends React.Component<ModalPanelProps, ModalPanelState> implements ModalPresenting {
2437

2538
public state: ModalPanelState = {
2639
components: new Map(),
27-
backdrops: new Map(),
2840
};
2941

3042
public componentDidMount(): void {
@@ -35,66 +47,49 @@ export class ModalPanel extends React.Component<ModalPanelProps, ModalPanelState
3547
ModalService.unmount();
3648
}
3749

38-
public hide = (identifier: string): void => {
39-
const component: React.ReactElement<ModalComponentCloseProps> = this.state.components
40-
.get(identifier);
41-
if (component) {
42-
component.props.onRequestClose && component.props.onRequestClose();
43-
}
44-
const components: Map<string, React.ReactElement<any>> = this.state.components;
50+
public hide = (identifier: string): string => {
51+
const components: Map<string, ModalPanelChild> = this.state.components;
4552
components.delete(identifier);
46-
const backdrops: Map<string, boolean> = this.state.backdrops;
47-
backdrops.delete(identifier);
48-
this.setState({
49-
components: components,
50-
backdrops: backdrops,
51-
});
53+
this.setState({ components });
54+
return '';
5255
};
5356

54-
public show(dialogComponent: React.ReactElement<any>, closeOnBackDrop: boolean): string {
57+
public show(element: React.ReactElement<ModalPresentingBased>,
58+
config: ModalPresentingConfig): string {
59+
5560
const key: string = this.generateUniqueComponentKey();
56-
const componentsMap: Map<string, React.ReactElement<any>> = this.state.components
57-
.set(key, dialogComponent);
58-
const backdrops: Map<string, boolean> = this.state.backdrops.set(key, closeOnBackDrop);
59-
this.setState({
60-
components: componentsMap,
61-
backdrops: backdrops,
62-
});
61+
const components: Map<string, ModalPanelChild> = this.state.components
62+
.set(key, { ...config, element });
63+
64+
this.setState({ components });
65+
6366
return key;
6467
}
6568

6669
private generateUniqueComponentKey = (): string => {
6770
return Math.random().toString(36).substring(2);
6871
};
6972

70-
private areThereAnyComponents(): boolean {
73+
private areThereAnyComponents = (): boolean => {
7174
return this.state.components && this.state.components.size !== 0;
72-
}
75+
};
7376

74-
private renderModal(modal: React.ReactElement<any>, index: number) {
75-
const allModalKeys: string[] = Array.from(this.state.components.keys());
76-
const identifier: string = allModalKeys
77-
.find(item => this.state.components.get(item) === modal);
78-
const closeOnBackdrop: boolean = this.state.backdrops.get(identifier);
77+
private renderModal = (config: ModalPanelChild, index: number): React.ReactElement<ModalResolverProps> => {
7978
return (
8079
<ModalResolver
81-
{...modal.props}
80+
{...config.element.props}
8281
visible={true}
83-
isBackDropAllowed={closeOnBackdrop}
8482
key={index}
85-
identifier={identifier}
86-
onCloseModal={this.hide}
87-
>
88-
{modal}
83+
allowBackdrop={config.allowBackdrop}
84+
onBackdropPress={config.onBackdropPress}>
85+
{config.element}
8986
</ModalResolver>
9087
);
91-
}
88+
};
9289

93-
private renderModals() {
94-
return Array.from(this.state.components.values())
95-
.map((component: React.ReactElement<any>, i: number) =>
96-
this.renderModal(component, i));
97-
}
90+
private renderModals = (): React.ReactElement<ModalResolverProps>[] => {
91+
return Array.from(this.state.components.values()).map(this.renderModal);
92+
};
9893

9994
public render(): React.ReactElement<ViewProps> {
10095
return (

src/framework/theme/modal/modalPanel.spec.tsx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@ import {
1313
TouchableOpacity,
1414
} from 'react-native';
1515
import { ModalPanel } from './modalPanel.component';
16-
import {
17-
ModalService,
18-
ModalComponentCloseProps,
19-
} from './modal.service';
16+
import { ModalService } from './modal.service';
17+
import { ModalPresentingBased } from '../../ui/support/typings';
2018

2119
describe('@modal-service: service checks', () => {
2220

@@ -37,6 +35,10 @@ describe('@modal-service: service checks', () => {
3735
onCloseModal={this.props.onCloseModal}
3836
textTestId={textId(1)}
3937
/>,
38+
{
39+
allowBackdrop: false,
40+
onBackdropPress: () => null,
41+
},
4042
);
4143
};
4244

@@ -47,6 +49,10 @@ describe('@modal-service: service checks', () => {
4749
onCloseModal={this.props.onCloseModal}
4850
textTestId={textId(1)}
4951
/>,
52+
{
53+
allowBackdrop: false,
54+
onBackdropPress: () => null,
55+
},
5056
);
5157

5258
ModalService.show(
@@ -55,6 +61,10 @@ describe('@modal-service: service checks', () => {
5561
onCloseModal={this.props.onCloseModal}
5662
textTestId={textId(2)}
5763
/>,
64+
{
65+
allowBackdrop: false,
66+
onBackdropPress: () => null,
67+
},
5868
);
5969
};
6070

@@ -64,7 +74,12 @@ describe('@modal-service: service checks', () => {
6474
text={textId(0)}
6575
onCloseModal={this.props.onCloseModal}
6676
textTestId={textId(0)}
67-
/>, true);
77+
/>,
78+
{
79+
allowBackdrop: true,
80+
onBackdropPress: () => null,
81+
},
82+
);
6883
};
6984

7085
public render(): React.ReactNode {
@@ -196,7 +211,11 @@ describe('@modal panel checks', () => {
196211

197212
public showModal() {
198213
this.modalId = ModalService.show(
199-
<TestModal onRequestClose={() => 1}/>, true,
214+
<TestModal onBackdropPress={this.hideModal}/>,
215+
{
216+
allowBackdrop: true,
217+
onBackdropPress: () => null,
218+
},
200219
);
201220
}
202221

@@ -227,14 +246,14 @@ describe('@modal panel checks', () => {
227246
}
228247
}
229248

230-
class TestModal extends React.Component<ModalComponentCloseProps> {
249+
class TestModal extends React.Component<ModalPresentingBased> {
231250

232251
public render(): React.ReactNode {
233252
return (
234253
<View>
235254
<Button
236255
title='Close Modal'
237-
onPress={this.props.onCloseModal}
256+
onPress={this.props.onBackdropPress}
238257
testID={hideModalTestIdInner}
239258
/>
240259
</View>

0 commit comments

Comments
 (0)