@haroldtran/react-native-modals 0.0.6 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +41 -65
- package/src/BottomModal.tsx +1 -3
- package/src/Modal.tsx +4 -6
- package/src/ModalPortal.tsx +108 -75
- package/src/animations/Animation.tsx +10 -12
- package/src/animations/FadeAnimation.tsx +8 -18
- package/src/animations/ScaleAnimation.tsx +14 -7
- package/src/animations/SlideAnimation.tsx +35 -13
- package/src/components/Backdrop.tsx +40 -51
- package/src/components/BaseModal.tsx +265 -228
- package/src/components/BottomModal.tsx +23 -19
- package/src/components/DraggableView.tsx +192 -227
- package/src/components/ModalButton.tsx +15 -24
- package/src/components/ModalContent.tsx +4 -13
- package/src/components/ModalFooter.tsx +13 -24
- package/src/components/ModalTitle.tsx +11 -19
- package/src/index.tsx +14 -14
- package/src/type.ts +16 -16
- package/src/components/SlideAnimation.tsx +0 -91
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
2
|
import { StyleSheet } from 'react-native';
|
|
5
|
-
import type { ModalProps } from '../type';
|
|
6
3
|
import SlideAnimation from '../animations/SlideAnimation';
|
|
4
|
+
import type { ModalProps } from '../type';
|
|
7
5
|
import BaseModal from './BaseModal';
|
|
8
6
|
|
|
9
7
|
const styles = StyleSheet.create({
|
|
@@ -16,21 +14,27 @@ const styles = StyleSheet.create({
|
|
|
16
14
|
},
|
|
17
15
|
});
|
|
18
16
|
|
|
19
|
-
const BottomModal = ({
|
|
20
|
-
style,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
17
|
+
const BottomModal = (props: ModalProps) => {
|
|
18
|
+
const { style, modalStyle, ...restProps } = props;
|
|
19
|
+
|
|
20
|
+
const modalAnimation = React.useMemo(
|
|
21
|
+
() =>
|
|
22
|
+
new SlideAnimation({
|
|
23
|
+
slideFrom: 'bottom',
|
|
24
|
+
}),
|
|
25
|
+
[],
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<BaseModal
|
|
30
|
+
modalAnimation={modalAnimation}
|
|
31
|
+
{...restProps}
|
|
32
|
+
style={StyleSheet.flatten([styles.container, style])}
|
|
33
|
+
modalStyle={StyleSheet.flatten([styles.modal, modalStyle])}
|
|
34
|
+
width={1}
|
|
35
|
+
swipeDirection="down"
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
35
39
|
|
|
36
40
|
export default BottomModal;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { Animated,
|
|
3
|
-
import type { DragEvent, SwipeDirection } from
|
|
1
|
+
import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { Animated, PanResponder, PanResponderGestureState, useWindowDimensions } from 'react-native';
|
|
3
|
+
import type { DragEvent, SwipeDirection } from '../type';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
style?: any;
|
|
@@ -11,238 +11,203 @@ type Props = {
|
|
|
11
11
|
onSwipeOut?: (event: DragEvent) => void;
|
|
12
12
|
swipeThreshold?: number;
|
|
13
13
|
swipeDirection?: SwipeDirection | Array<SwipeDirection>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
pan,
|
|
17
|
-
}: {
|
|
18
|
-
onLayout: (event: any) => void;
|
|
19
|
-
pan: Animated.ValueXY;
|
|
20
|
-
}) => React.ReactNode;
|
|
14
|
+
pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only';
|
|
15
|
+
children: (args: { onLayout: (event: any) => void; pan: Animated.ValueXY }) => React.ReactNode;
|
|
21
16
|
};
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
style
|
|
26
|
-
onMove
|
|
27
|
-
onSwiping
|
|
28
|
-
onSwipingOut
|
|
29
|
-
onSwipeOut
|
|
30
|
-
onRelease
|
|
31
|
-
swipeThreshold
|
|
32
|
-
swipeDirection
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
onLayout = (event: any) => {
|
|
67
|
-
this.layout = event.nativeEvent.layout;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
getSwipeDirection(gestureState: any): SwipeDirection | null {
|
|
71
|
-
if (this.isValidHorizontalSwipe(gestureState)) {
|
|
72
|
-
return gestureState.dx > 0 ? "right" : "left";
|
|
73
|
-
} else if (this.isValidVerticalSwipe(gestureState)) {
|
|
74
|
-
return gestureState.dy > 0 ? "down" : "up";
|
|
75
|
-
}
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getDisappearDirection() {
|
|
80
|
-
const { width, height } = Dimensions.get("window");
|
|
81
|
-
const vertical = height / 2 + (this.layout ? this.layout.height / 2 : 0);
|
|
82
|
-
const horizontal = width / 2 + (this.layout ? this.layout.width / 2 : 0);
|
|
83
|
-
let toValue;
|
|
84
|
-
if (this.currentSwipeDirection === "up") {
|
|
85
|
-
toValue = {
|
|
86
|
-
x: 0,
|
|
87
|
-
y: -vertical,
|
|
88
|
-
};
|
|
89
|
-
} else if (this.currentSwipeDirection === "down") {
|
|
90
|
-
toValue = {
|
|
91
|
-
x: 0,
|
|
92
|
-
y: vertical,
|
|
93
|
-
};
|
|
94
|
-
} else if (this.currentSwipeDirection === "left") {
|
|
95
|
-
toValue = {
|
|
96
|
-
x: -horizontal,
|
|
97
|
-
y: 0,
|
|
98
|
-
};
|
|
99
|
-
} else if (this.currentSwipeDirection === "right") {
|
|
100
|
-
toValue = {
|
|
101
|
-
x: horizontal,
|
|
102
|
-
y: 0,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
return toValue;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
isValidHorizontalSwipe({ vx, dy }: any) {
|
|
109
|
-
return this.isValidSwipe(vx, dy);
|
|
110
|
-
}
|
|
18
|
+
const DraggableView = memo((props: Props) => {
|
|
19
|
+
const {
|
|
20
|
+
style = null,
|
|
21
|
+
onMove = () => {},
|
|
22
|
+
onSwiping = () => {},
|
|
23
|
+
onSwipingOut = () => {},
|
|
24
|
+
onSwipeOut = null,
|
|
25
|
+
onRelease = () => {},
|
|
26
|
+
swipeThreshold = 100,
|
|
27
|
+
swipeDirection = [],
|
|
28
|
+
pointerEvents = 'auto',
|
|
29
|
+
children: renderContent,
|
|
30
|
+
} = props;
|
|
31
|
+
|
|
32
|
+
const { width: screenWidth, height: screenHeight } = useWindowDimensions();
|
|
33
|
+
|
|
34
|
+
const pan = useRef(new Animated.ValueXY()).current;
|
|
35
|
+
const layoutRef = useRef<{ x: number; y: number; width: number; height: number } | null>(null);
|
|
36
|
+
const currentSwipeDirectionRef = useRef<SwipeDirection | null>(null);
|
|
37
|
+
|
|
38
|
+
// Track pan values without using ._value
|
|
39
|
+
const propsRef = useRef(props);
|
|
40
|
+
propsRef.current = props;
|
|
41
|
+
|
|
42
|
+
const panValueRef = useRef({ x: 0, y: 0 });
|
|
43
|
+
|
|
44
|
+
const allowedDirections = useMemo(
|
|
45
|
+
() => ([] as SwipeDirection[]).concat(props.swipeDirection || []),
|
|
46
|
+
[props.swipeDirection],
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const panListenerId = pan.addListener((value) => {
|
|
51
|
+
panValueRef.current = value;
|
|
52
|
+
propsRef.current.onMove?.({
|
|
53
|
+
axis: value,
|
|
54
|
+
layout: layoutRef.current,
|
|
55
|
+
swipeDirection: currentSwipeDirectionRef.current,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
return () => pan.removeListener(panListenerId);
|
|
59
|
+
}, [pan]);
|
|
111
60
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
61
|
+
const onLayout = useCallback((event: any) => {
|
|
62
|
+
layoutRef.current = event.nativeEvent.layout;
|
|
63
|
+
}, []);
|
|
115
64
|
|
|
116
|
-
|
|
117
|
-
|
|
65
|
+
const getSwipeDirection = useCallback((gestureState: PanResponderGestureState): SwipeDirection | null => {
|
|
66
|
+
const { dx, dy, vx, vy } = gestureState;
|
|
118
67
|
const velocityThreshold = 0.3;
|
|
119
68
|
const directionalOffsetThreshold = 80;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
isAllowedDirection({ dy, dx }: any) {
|
|
128
|
-
const draggedDown = dy > 0;
|
|
129
|
-
const draggedUp = dy < 0;
|
|
130
|
-
const draggedLeft = dx < 0;
|
|
131
|
-
const draggedRight = dx > 0;
|
|
132
|
-
const isAllowedDirection = (d: SwipeDirection) =>
|
|
133
|
-
this.currentSwipeDirection === d && this.allowedDirections.includes(d);
|
|
134
|
-
if (draggedDown && isAllowedDirection("down")) {
|
|
135
|
-
return true;
|
|
136
|
-
} else if (draggedUp && isAllowedDirection("up")) {
|
|
137
|
-
return true;
|
|
138
|
-
} else if (draggedLeft && isAllowedDirection("left")) {
|
|
139
|
-
return true;
|
|
140
|
-
} else if (draggedRight && isAllowedDirection("right")) {
|
|
141
|
-
return true;
|
|
69
|
+
|
|
70
|
+
if (Math.abs(vx) > velocityThreshold && Math.abs(dy) < directionalOffsetThreshold) {
|
|
71
|
+
return dx > 0 ? 'right' : 'left';
|
|
72
|
+
} else if (Math.abs(vy) > velocityThreshold && Math.abs(dx) < directionalOffsetThreshold) {
|
|
73
|
+
return dy > 0 ? 'down' : 'up';
|
|
142
74
|
}
|
|
143
|
-
return
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
if (animEvent) {
|
|
182
|
-
Animated.event([null, animEvent], { useNativeDriver: false })(
|
|
183
|
-
event,
|
|
184
|
-
gestureState,
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
this.props.onSwiping?.(
|
|
188
|
-
this.createDragEvent({
|
|
189
|
-
x: (this.pan.x as any)._value,
|
|
190
|
-
y: (this.pan.y as any)._value,
|
|
191
|
-
}),
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
onPanResponderRelease: () => {
|
|
196
|
-
this.pan.flattenOffset();
|
|
197
|
-
const event = this.createDragEvent({
|
|
198
|
-
x: (this.pan.x as any)._value,
|
|
199
|
-
y: (this.pan.y as any)._value,
|
|
200
|
-
});
|
|
201
|
-
// on swipe out
|
|
202
|
-
const threshold = this.props.swipeThreshold ?? 0;
|
|
203
|
-
if (
|
|
204
|
-
(this.props.onSwipeOut &&
|
|
205
|
-
Math.abs((this.pan.y as any)._value) > threshold) ||
|
|
206
|
-
Math.abs((this.pan.x as any)._value) > threshold
|
|
207
|
-
) {
|
|
208
|
-
const toValue = this.getDisappearDirection();
|
|
209
|
-
this.props.onSwipingOut?.(event);
|
|
210
|
-
if (!toValue) return;
|
|
211
|
-
Animated.spring(this.pan, {
|
|
212
|
-
toValue,
|
|
213
|
-
velocity: 0,
|
|
214
|
-
tension: 65,
|
|
215
|
-
friction: 11,
|
|
216
|
-
useNativeDriver: false,
|
|
217
|
-
}).start(() => {
|
|
218
|
-
this.props.onSwipeOut?.(event);
|
|
219
|
-
});
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
// on release
|
|
223
|
-
this.currentSwipeDirection = null;
|
|
224
|
-
this.props.onRelease?.(event);
|
|
225
|
-
Animated.spring(this.pan, {
|
|
226
|
-
toValue: { x: 0, y: 0 },
|
|
227
|
-
velocity: 0,
|
|
228
|
-
tension: 65,
|
|
229
|
-
friction: 11,
|
|
230
|
-
useNativeDriver: false,
|
|
231
|
-
}).start();
|
|
75
|
+
return null;
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
const getDisappearDirection = useCallback(() => {
|
|
79
|
+
const vertical = screenHeight / 2 + (layoutRef.current ? layoutRef.current.height / 2 : 0);
|
|
80
|
+
const horizontal = screenWidth / 2 + (layoutRef.current ? layoutRef.current.width / 2 : 0);
|
|
81
|
+
|
|
82
|
+
switch (currentSwipeDirectionRef.current) {
|
|
83
|
+
case 'up':
|
|
84
|
+
return { x: 0, y: -vertical };
|
|
85
|
+
case 'down':
|
|
86
|
+
return { x: 0, y: vertical };
|
|
87
|
+
case 'left':
|
|
88
|
+
return { x: -horizontal, y: 0 };
|
|
89
|
+
case 'right':
|
|
90
|
+
return { x: horizontal, y: 0 };
|
|
91
|
+
default:
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}, [screenWidth, screenHeight]);
|
|
95
|
+
|
|
96
|
+
const isAllowedDirection = useCallback(
|
|
97
|
+
(gestureState: PanResponderGestureState) => {
|
|
98
|
+
const { dx, dy } = gestureState;
|
|
99
|
+
const draggedDown = dy > 0;
|
|
100
|
+
const draggedUp = dy < 0;
|
|
101
|
+
const draggedLeft = dx < 0;
|
|
102
|
+
const draggedRight = dx > 0;
|
|
103
|
+
|
|
104
|
+
const isCurrent = (d: SwipeDirection) => currentSwipeDirectionRef.current === d && allowedDirections.includes(d);
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
(draggedDown && isCurrent('down')) ||
|
|
108
|
+
(draggedUp && isCurrent('up')) ||
|
|
109
|
+
(draggedLeft && isCurrent('left')) ||
|
|
110
|
+
(draggedRight && isCurrent('right'))
|
|
111
|
+
);
|
|
232
112
|
},
|
|
113
|
+
[allowedDirections],
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const createDragEvent = useCallback(
|
|
117
|
+
(): DragEvent => ({
|
|
118
|
+
axis: panValueRef.current,
|
|
119
|
+
layout: layoutRef.current,
|
|
120
|
+
swipeDirection: currentSwipeDirectionRef.current,
|
|
121
|
+
}),
|
|
122
|
+
[],
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const panResponder = useMemo(
|
|
126
|
+
() =>
|
|
127
|
+
PanResponder.create({
|
|
128
|
+
onStartShouldSetPanResponder: () =>
|
|
129
|
+
allowedDirections.length > 0,
|
|
130
|
+
onMoveShouldSetPanResponder: (_, gestureState) =>
|
|
131
|
+
allowedDirections.length > 0 &&
|
|
132
|
+
(gestureState.dx !== 0 || gestureState.dy !== 0),
|
|
133
|
+
onPanResponderMove: (event, gestureState) => {
|
|
134
|
+
const isVertical = (d: SwipeDirection | null) => d === 'up' || d === 'down';
|
|
135
|
+
const isHorizontal = (d: SwipeDirection | null) => d === 'left' || d === 'right';
|
|
136
|
+
|
|
137
|
+
const newDir = getSwipeDirection(gestureState);
|
|
138
|
+
const isSame =
|
|
139
|
+
isVertical(currentSwipeDirectionRef.current) === isVertical(newDir) ||
|
|
140
|
+
isHorizontal(currentSwipeDirectionRef.current) === isHorizontal(newDir);
|
|
141
|
+
|
|
142
|
+
if (newDir && isSame) {
|
|
143
|
+
currentSwipeDirectionRef.current = newDir;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (isAllowedDirection(gestureState)) {
|
|
147
|
+
let animEvent: any;
|
|
148
|
+
if (isVertical(currentSwipeDirectionRef.current)) {
|
|
149
|
+
animEvent = { dy: pan.y };
|
|
150
|
+
} else if (isHorizontal(currentSwipeDirectionRef.current)) {
|
|
151
|
+
animEvent = { dx: pan.x };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (animEvent) {
|
|
155
|
+
Animated.event([null, animEvent], { useNativeDriver: false })(event, gestureState);
|
|
156
|
+
}
|
|
157
|
+
propsRef.current.onSwiping?.(createDragEvent());
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
onPanResponderRelease: () => {
|
|
161
|
+
pan.flattenOffset();
|
|
162
|
+
const event = createDragEvent();
|
|
163
|
+
const threshold = propsRef.current.swipeThreshold ?? 100;
|
|
164
|
+
|
|
165
|
+
if (
|
|
166
|
+
(propsRef.current.onSwipeOut && Math.abs(panValueRef.current.y) > threshold) ||
|
|
167
|
+
Math.abs(panValueRef.current.x) > threshold
|
|
168
|
+
) {
|
|
169
|
+
const toValue = getDisappearDirection();
|
|
170
|
+
propsRef.current.onSwipingOut?.(event);
|
|
171
|
+
if (!toValue) return;
|
|
172
|
+
|
|
173
|
+
Animated.spring(pan, {
|
|
174
|
+
toValue,
|
|
175
|
+
velocity: 0,
|
|
176
|
+
tension: 65,
|
|
177
|
+
friction: 11,
|
|
178
|
+
useNativeDriver: false,
|
|
179
|
+
}).start(() => {
|
|
180
|
+
propsRef.current.onSwipeOut?.(event);
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
currentSwipeDirectionRef.current = null;
|
|
186
|
+
propsRef.current.onRelease?.(event);
|
|
187
|
+
Animated.spring(pan, {
|
|
188
|
+
toValue: { x: 0, y: 0 },
|
|
189
|
+
velocity: 0,
|
|
190
|
+
tension: 65,
|
|
191
|
+
friction: 11,
|
|
192
|
+
useNativeDriver: false,
|
|
193
|
+
}).start();
|
|
194
|
+
},
|
|
195
|
+
}),
|
|
196
|
+
[getSwipeDirection, isAllowedDirection, pan, createDragEvent, getDisappearDirection],
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const content = renderContent({
|
|
200
|
+
pan,
|
|
201
|
+
onLayout,
|
|
233
202
|
});
|
|
234
203
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
204
|
+
return (
|
|
205
|
+
<Animated.View {...panResponder.panHandlers} style={style} pointerEvents={pointerEvents}>
|
|
206
|
+
{content}
|
|
207
|
+
</Animated.View>
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
DraggableView.displayName = 'DraggableView';
|
|
241
212
|
|
|
242
|
-
|
|
243
|
-
<Animated.View {...this.panResponder.panHandlers} style={style}>
|
|
244
|
-
{content}
|
|
245
|
-
</Animated.View>
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
213
|
+
export default DraggableView;
|
|
@@ -1,39 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { PixelRatio, Platform, StyleSheet, Text, TouchableHighlight } from 'react-native';
|
|
3
|
+
import { Positions } from '../constants/Constants';
|
|
4
|
+
import type { ModalButtonProps } from '../type';
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
PixelRatio,
|
|
6
|
-
Platform,
|
|
7
|
-
StyleSheet,
|
|
8
|
-
Text,
|
|
9
|
-
TouchableHighlight,
|
|
10
|
-
} from "react-native";
|
|
11
|
-
import { Positions } from "../constants/Constants";
|
|
12
|
-
import type { ModalButtonProps } from "../type";
|
|
13
|
-
|
|
14
|
-
const isAndroid = Platform.OS === "android";
|
|
6
|
+
const isAndroid = Platform.OS === 'android';
|
|
15
7
|
|
|
16
8
|
const styles = StyleSheet.create({
|
|
17
9
|
button: {
|
|
18
10
|
flex: 1,
|
|
19
|
-
width:
|
|
20
|
-
justifyContent:
|
|
21
|
-
alignItems:
|
|
11
|
+
width: '100%',
|
|
12
|
+
justifyContent: 'center',
|
|
13
|
+
alignItems: 'center',
|
|
22
14
|
paddingTop: 16,
|
|
23
15
|
paddingBottom: 16,
|
|
24
16
|
},
|
|
25
17
|
border: {
|
|
26
|
-
borderLeftColor:
|
|
18
|
+
borderLeftColor: '#CCD0D5',
|
|
27
19
|
borderLeftWidth: 1 / PixelRatio.get(),
|
|
28
20
|
},
|
|
29
21
|
text: {
|
|
30
|
-
fontWeight: isAndroid ?
|
|
31
|
-
fontFamily: isAndroid ?
|
|
22
|
+
fontWeight: isAndroid ? '400' : '500',
|
|
23
|
+
fontFamily: isAndroid ? 'sans-serif-medium' : 'System',
|
|
32
24
|
fontSize: isAndroid ? 19 : 16,
|
|
33
|
-
color:
|
|
25
|
+
color: '#044DE0',
|
|
34
26
|
},
|
|
35
27
|
disable: {
|
|
36
|
-
color:
|
|
28
|
+
color: '#C5C6C5',
|
|
37
29
|
},
|
|
38
30
|
});
|
|
39
31
|
|
|
@@ -43,7 +35,7 @@ const ModalButton = ({
|
|
|
43
35
|
style,
|
|
44
36
|
textStyle,
|
|
45
37
|
activeOpacity = 0.6,
|
|
46
|
-
align =
|
|
38
|
+
align = 'center',
|
|
47
39
|
disabled = false,
|
|
48
40
|
bordered = false,
|
|
49
41
|
}: ModalButtonProps) => {
|
|
@@ -57,8 +49,7 @@ const ModalButton = ({
|
|
|
57
49
|
onPress={onPress}
|
|
58
50
|
disabled={disabled}
|
|
59
51
|
activeOpacity={activeOpacity}
|
|
60
|
-
style={[styles.button, buttonAlign, border, style]}
|
|
61
|
-
>
|
|
52
|
+
style={[styles.button, buttonAlign, border, style]}>
|
|
62
53
|
<Text style={[styles.text, disable, textStyle]}>{text}</Text>
|
|
63
54
|
</TouchableHighlight>
|
|
64
55
|
);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import ModalContext from './ModalContext';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
6
3
|
import type { ModalContentProps } from '../type';
|
|
4
|
+
import ModalContext from './ModalContext';
|
|
7
5
|
|
|
8
6
|
const styles = StyleSheet.create({
|
|
9
7
|
content: {
|
|
@@ -15,16 +13,9 @@ const styles = StyleSheet.create({
|
|
|
15
13
|
},
|
|
16
14
|
});
|
|
17
15
|
|
|
18
|
-
const ModalContent = ({
|
|
19
|
-
style,
|
|
20
|
-
children,
|
|
21
|
-
}: ModalContentProps) => (
|
|
16
|
+
const ModalContent = ({ style, children }: ModalContentProps) => (
|
|
22
17
|
<ModalContext.Consumer>
|
|
23
|
-
{({ hasTitle }) =>
|
|
24
|
-
<View style={[styles.content, hasTitle && styles.noPaddingTop, style]}>
|
|
25
|
-
{children}
|
|
26
|
-
</View>
|
|
27
|
-
)}
|
|
18
|
+
{({ hasTitle }) => <View style={[styles.content, hasTitle && styles.noPaddingTop, style]}>{children}</View>}
|
|
28
19
|
</ModalContext.Consumer>
|
|
29
20
|
);
|
|
30
21
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
1
|
import React, { Children, cloneElement } from 'react';
|
|
4
|
-
import {
|
|
2
|
+
import { PixelRatio, StyleSheet, View } from 'react-native';
|
|
5
3
|
import type { ModalFooterProps } from '../type';
|
|
6
4
|
|
|
7
5
|
const styles = StyleSheet.create({
|
|
@@ -18,31 +16,22 @@ const styles = StyleSheet.create({
|
|
|
18
16
|
},
|
|
19
17
|
});
|
|
20
18
|
|
|
21
|
-
const ModalActionList = ({
|
|
22
|
-
|
|
23
|
-
children,
|
|
24
|
-
bordered = true,
|
|
25
|
-
}: ModalFooterProps) => {
|
|
26
|
-
const containerStyle = children.length > 2
|
|
27
|
-
? styles.actionsVertical
|
|
28
|
-
: styles.actionsHorizontal;
|
|
19
|
+
const ModalActionList = ({ style, children, bordered = true }: ModalFooterProps) => {
|
|
20
|
+
const containerStyle = children.length > 2 ? styles.actionsVertical : styles.actionsHorizontal;
|
|
29
21
|
|
|
30
|
-
const border = bordered
|
|
31
|
-
? styles.border
|
|
32
|
-
: null;
|
|
22
|
+
const border = bordered ? styles.border : null;
|
|
33
23
|
|
|
34
24
|
// apply horizontal border if actions legnth is 2 & bordered is true
|
|
35
|
-
const content =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
const content =
|
|
26
|
+
children.length === 2
|
|
27
|
+
? Children.map(children, (child, index) =>
|
|
28
|
+
cloneElement(child, {
|
|
29
|
+
bordered: 1 % index === 0 && bordered,
|
|
30
|
+
}),
|
|
31
|
+
)
|
|
32
|
+
: children;
|
|
40
33
|
|
|
41
|
-
return
|
|
42
|
-
<View style={[containerStyle, border, style]}>
|
|
43
|
-
{content}
|
|
44
|
-
</View>
|
|
45
|
-
);
|
|
34
|
+
return <View style={[containerStyle, border, style]}>{content}</View>;
|
|
46
35
|
};
|
|
47
36
|
|
|
48
37
|
export default ModalActionList;
|