Skip to content

Commit 5c78095

Browse files
authored
fix(components): modal - backdrop behavior
1 parent 00b3d1d commit 5c78095

14 files changed

+120
-268
lines changed

src/components/theme/modal/modal.service.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
*
3535
* const showModal = () => {
3636
* const contentElement = this.renderModalContentElement();
37-
* this.modalID = ModalService.show(contentElement, { allowBackdrop: true, onBackdropPress: this.hideModal });
37+
* this.modalID = ModalService.show(contentElement, { onBackdropPress: this.hideModal });
3838
* };
3939
*
4040
* const hideModal = () => {
@@ -90,7 +90,6 @@ class ModalServiceType {
9090
}
9191

9292
export interface ModalPresentingConfig {
93-
allowBackdrop?: boolean;
9493
backdropStyle?: StyleProp<ViewStyle>;
9594
onBackdropPress?: () => void;
9695
}

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ export class ModalPanel extends React.Component<ModalPanelProps, ModalPanelState
7272

7373
const childElement: React.ReactElement = panelChild.element;
7474

75-
panelChild.element = React.cloneElement(childElement, {
76-
children: children,
77-
});
75+
panelChild.element = React.cloneElement(childElement, childElement.props, children);
7876

7977
const components: Map<string, ModalPanelChild> = this.state.components;
8078
components.delete(identifier);
@@ -93,11 +91,9 @@ export class ModalPanel extends React.Component<ModalPanelProps, ModalPanelState
9391
private renderModal = (config: ModalPanelChild, index: number): React.ReactElement<ModalResolverProps> => {
9492
return (
9593
<ModalResolver
96-
{...config.element.props}
97-
style={config.backdropStyle}
98-
visible={true}
9994
key={index}
100-
allowBackdrop={config.allowBackdrop}
95+
visible={true}
96+
backdropStyle={config.backdropStyle}
10197
onBackdropPress={config.onBackdropPress}>
10298
{config.element}
10399
</ModalResolver>

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ describe('@modal-service: service checks', () => {
3838
textTestId={textId(1)}
3939
/>,
4040
{
41-
allowBackdrop: false,
4241
onBackdropPress: () => null,
4342
},
4443
);
@@ -52,7 +51,6 @@ describe('@modal-service: service checks', () => {
5251
textTestId={textId(1)}
5352
/>,
5453
{
55-
allowBackdrop: false,
5654
onBackdropPress: () => null,
5755
},
5856
);
@@ -64,7 +62,6 @@ describe('@modal-service: service checks', () => {
6462
textTestId={textId(2)}
6563
/>,
6664
{
67-
allowBackdrop: false,
6865
onBackdropPress: () => null,
6966
},
7067
);
@@ -78,7 +75,6 @@ describe('@modal-service: service checks', () => {
7875
textTestId={textId(0)}
7976
/>,
8077
{
81-
allowBackdrop: true,
8278
onBackdropPress: () => null,
8379
},
8480
);
@@ -215,7 +211,6 @@ describe('@modal panel checks', () => {
215211
this.modalId = ModalService.show(
216212
<TestModal onBackdropPress={this.hideModal}/>,
217213
{
218-
allowBackdrop: true,
219214
onBackdropPress: () => null,
220215
},
221216
);

src/components/theme/modal/modalResolver.component.tsx

Lines changed: 21 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,117 +6,57 @@
66

77
import React from 'react';
88
import {
9-
View,
10-
ViewProps,
9+
StyleProp,
1110
StyleSheet,
1211
TouchableOpacity,
13-
TouchableOpacityProps,
12+
View,
13+
ViewProps,
14+
ViewStyle,
1415
} from 'react-native';
16+
import { ModalPresentingConfig } from './modal.service';
1517

1618
type ChildElement = React.ReactElement;
1719
type ChildrenProp = ChildElement | ChildElement[];
1820

19-
interface ComponentProps {
21+
export interface ModalResolverProps extends ViewProps, ModalPresentingConfig {
2022
visible: boolean;
2123
children: ChildrenProp;
22-
allowBackdrop: boolean;
24+
backdropStyle: StyleProp<ViewStyle>;
2325
onBackdropPress: () => void;
2426
}
2527

26-
export type ModalResolverProps = ViewProps & ComponentProps;
27-
2828
export class ModalResolver extends React.Component<ModalResolverProps> {
2929

3030
static defaultProps: Partial<ModalResolverProps> = {
3131
visible: false,
3232
};
3333

34-
private onBackdropPress = (): void => {
35-
const { allowBackdrop, onBackdropPress } = this.props;
36-
37-
if (allowBackdrop) {
38-
onBackdropPress();
39-
}
40-
};
41-
42-
private onStartShouldSetResponder = (): boolean => {
43-
return true;
44-
};
45-
46-
private onResponderRelease = (): void => {
47-
return;
48-
};
49-
50-
private onStartShouldSetResponderCapture = (): boolean => {
51-
return false;
52-
};
53-
54-
private renderComponentChild = (source: React.ReactElement): React.ReactElement => {
34+
private renderChildElement = (source: ChildElement): ChildElement => {
5535
return React.cloneElement(source, {
5636
style: [source.props.style, this.props.style],
5737
});
5838
};
5939

60-
private renderComponentChildren = (source: React.ReactNode): React.ReactElement[] => {
61-
return React.Children.map(source, this.renderComponentChild);
40+
private renderComponentChildren = (source: ChildrenProp): ChildElement[] => {
41+
return React.Children.map(source, this.renderChildElement);
6242
};
6343

64-
private renderWithBackDrop = (component: React.ReactElement<ViewProps>):
65-
React.ReactElement<TouchableOpacityProps> => {
66-
67-
return (
68-
<TouchableOpacity
69-
style={[styles.container, this.props.style]}
70-
onPress={this.onBackdropPress}
71-
activeOpacity={1}>
72-
{component}
73-
</TouchableOpacity>
74-
);
75-
};
44+
private renderComponent = (): React.ReactElement<ViewProps> => {
45+
const componentChildren = this.renderComponentChildren(this.props.children);
7646

77-
private renderWithoutBackDrop = (component: React.ReactElement<ViewProps>): React.ReactElement<ViewProps> => {
7847
return (
79-
<View style={styles.notVisibleWrapper}>
80-
<View
81-
style={styles.container}
82-
pointerEvents='none'/>
83-
{component}
48+
<View style={StyleSheet.absoluteFill}>
49+
<TouchableOpacity
50+
style={[StyleSheet.absoluteFill, this.props.backdropStyle]}
51+
activeOpacity={1.0}
52+
onPress={this.props.onBackdropPress}
53+
/>
54+
{componentChildren}
8455
</View>
8556
);
8657
};
8758

88-
private renderComponent = (): React.ReactElement<TouchableOpacityProps | ViewProps> => {
89-
const { children, allowBackdrop, ...derivedProps } = this.props;
90-
const componentChildren: React.ReactElement[] = this.renderComponentChildren(children);
91-
92-
const dialog: React.ReactElement<ViewProps> =
93-
<View
94-
{...derivedProps}
95-
style={styles.contentWrapper}
96-
onStartShouldSetResponder={this.onStartShouldSetResponder}
97-
onResponderRelease={this.onResponderRelease}
98-
onStartShouldSetResponderCapture={this.onStartShouldSetResponderCapture}
99-
pointerEvents='box-none'>
100-
{componentChildren}
101-
</View>;
102-
103-
return allowBackdrop ?
104-
this.renderWithBackDrop(dialog) : this.renderWithoutBackDrop(dialog);
105-
};
106-
107-
public render(): React.ReactElement<ViewProps | TouchableOpacityProps> | null {
108-
return this.props.visible ? this.renderComponent() : null;
59+
public render(): React.ReactElement<ViewProps> | undefined {
60+
return this.props.visible && this.renderComponent();
10961
}
11062
}
111-
112-
const styles = StyleSheet.create({
113-
container: StyleSheet.absoluteFillObject,
114-
notVisibleWrapper: {
115-
position: 'absolute',
116-
width: 0,
117-
height: 0,
118-
},
119-
contentWrapper: {
120-
alignSelf: 'flex-start',
121-
},
122-
});

src/components/theme/modal/modalResolver.spec.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ describe('@modal resolver component checks', () => {
1818

1919
it('* modal resolver component renders properly', () => {
2020
const modal1: RenderAPI = render(
21-
<ModalResolver
22-
visible={true}
23-
allowBackdrop={false}>
21+
<ModalResolver visible={true}>
2422
<View>
2523
<Text>
2624
Test1
@@ -30,9 +28,7 @@ describe('@modal resolver component checks', () => {
3028
);
3129

3230
const modal2: RenderAPI = render(
33-
<ModalResolver
34-
visible={false}
35-
allowBackdrop={false}>
31+
<ModalResolver visible={false}>
3632
<View>
3733
<Text>
3834
Test2
@@ -51,21 +47,17 @@ describe('@modal resolver component checks', () => {
5147
it('* modal resolver component props checks', () => {
5248
const modalPassingProps = {
5349
visible: true,
54-
allowBackdrop: false,
5550
};
5651
const modal = <ModalResolver {...modalPassingProps}/>;
5752

5853
expect(modal.props.visible).toBe(modalPassingProps.visible);
59-
expect(modal.props.allowBackdrop).toBe(modalPassingProps.allowBackdrop);
6054
});
6155

6256
it('* modal resolver backdrop press calling checks', () => {
6357
const onBackdropPress = jest.fn();
6458

6559
const component: RenderAPI = render(
66-
<ModalResolver
67-
visible={true}
68-
allowBackdrop={true}>
60+
<ModalResolver visible={true}>
6961
<View>
7062
<Text>Test1</Text>
7163
<Button

src/components/theme/modal/modalResolver.spec.tsx.snap

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,42 @@ exports[`@modal resolver component checks * modal resolver component renders pro
44
<View
55
style={
66
Object {
7-
"height": 0,
7+
"bottom": 0,
8+
"left": 0,
89
"position": "absolute",
9-
"width": 0,
10+
"right": 0,
11+
"top": 0,
1012
}
1113
}
1214
>
13-
<View
14-
pointerEvents="none"
15+
<TouchableOpacity
16+
activeOpacity={1}
1517
style={
16-
Object {
17-
"bottom": 0,
18-
"left": 0,
19-
"position": "absolute",
20-
"right": 0,
21-
"top": 0,
22-
}
18+
Array [
19+
Object {
20+
"bottom": 0,
21+
"left": 0,
22+
"position": "absolute",
23+
"right": 0,
24+
"top": 0,
25+
},
26+
undefined,
27+
]
2328
}
2429
/>
2530
<View
26-
onResponderRelease={[Function]}
27-
onStartShouldSetResponder={[Function]}
28-
onStartShouldSetResponderCapture={[Function]}
29-
pointerEvents="box-none"
3031
style={
31-
Object {
32-
"alignSelf": "flex-start",
33-
}
32+
Array [
33+
undefined,
34+
undefined,
35+
]
3436
}
35-
visible={true}
3637
>
37-
<View
38-
style={
39-
Array [
40-
undefined,
41-
undefined,
42-
]
43-
}
44-
>
45-
<Text>
46-
Test1
47-
</Text>
48-
</View>
38+
<Text>
39+
Test1
40+
</Text>
4941
</View>
5042
</View>
5143
`;
5244

53-
exports[`@modal resolver component checks * modal resolver component renders properly 2`] = `null`;
45+
exports[`@modal resolver component checks * modal resolver component renders properly 2`] = `false`;

src/components/ui/measure/measure.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,11 @@ describe('* frame', () => {
4747
expect(y).toEqual(2);
4848
});
4949

50+
it('* center of', () => {
51+
const { origin: { x, y } } = rhsFrame.centerOf(lhsFrame);
52+
53+
expect(x).toEqual(2);
54+
expect(y).toEqual(2);
55+
});
56+
5057
});

src/components/ui/measure/type.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ export class Frame {
120120
);
121121
}
122122

123+
public centerOf(other: Frame): Frame {
124+
return new Frame(
125+
other.origin.x + (other.size.width - this.size.width) / 2,
126+
other.origin.y + (other.size.height - this.size.height) / 2,
127+
this.size.width,
128+
this.size.height,
129+
);
130+
}
131+
123132
static zero(): Frame {
124133
return new Frame(0, 0, 0, 0);
125134
}

0 commit comments

Comments
 (0)