@umituz/react-native-design-system 2.9.9 → 2.9.11
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 +1 -1
- package/src/atoms/datepicker/components/DatePickerModal.tsx +1 -1
- package/src/atoms/picker/components/PickerModal.tsx +1 -1
- package/src/image/presentation/components/ImageGallery.tsx +2 -2
- package/src/molecules/BaseModal.tsx +20 -2
- package/src/molecules/alerts/AlertModal.tsx +1 -1
- package/src/molecules/bottom-sheet/components/BottomSheet.tsx +1 -1
- package/src/molecules/bottom-sheet/components/BottomSheetModal.tsx +1 -1
- package/src/molecules/bottom-sheet/components/filter/FilterSheet.tsx +1 -1
- package/src/molecules/emoji/presentation/components/EmojiPicker.tsx +0 -2
- package/src/offline/presentation/components/OfflineBanner.tsx +14 -69
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.11",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, and onboarding utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -62,7 +62,7 @@ export const ImageGallery: React.FC<ImageGalleryProps> = ({
|
|
|
62
62
|
source={{ uri: item.uri }}
|
|
63
63
|
style={styles.fullImage}
|
|
64
64
|
contentFit="contain"
|
|
65
|
-
transition={
|
|
65
|
+
transition={0}
|
|
66
66
|
cachePolicy="memory-disk"
|
|
67
67
|
/>
|
|
68
68
|
</View>
|
|
@@ -74,7 +74,7 @@ export const ImageGallery: React.FC<ImageGalleryProps> = ({
|
|
|
74
74
|
<Modal
|
|
75
75
|
visible={visible}
|
|
76
76
|
transparent
|
|
77
|
-
animationType="
|
|
77
|
+
animationType="none"
|
|
78
78
|
onRequestClose={onDismiss}
|
|
79
79
|
statusBarTranslucent
|
|
80
80
|
>
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* Used across all modals in the app for consistency
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React from 'react';
|
|
7
|
+
import React, { useEffect } from 'react';
|
|
8
8
|
import { View, Modal, StyleSheet, TouchableOpacity, ViewStyle } from 'react-native';
|
|
9
9
|
import { useAppDesignTokens } from '../theme';
|
|
10
10
|
import { useResponsive } from '../responsive';
|
|
11
11
|
|
|
12
|
+
declare const __DEV__: boolean;
|
|
13
|
+
|
|
12
14
|
export interface BaseModalProps {
|
|
13
15
|
visible: boolean;
|
|
14
16
|
onClose: () => void;
|
|
@@ -29,6 +31,18 @@ export const BaseModal: React.FC<BaseModalProps> = ({
|
|
|
29
31
|
const tokens = useAppDesignTokens();
|
|
30
32
|
const { modalLayout } = useResponsive();
|
|
31
33
|
|
|
34
|
+
// Debug logging for modal visibility
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
37
|
+
console.log("[BaseModal] Visibility changed:", {
|
|
38
|
+
visible,
|
|
39
|
+
testID,
|
|
40
|
+
modalWidth: modalLayout.width,
|
|
41
|
+
modalHeight: modalLayout.height,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}, [visible, testID, modalLayout.width, modalLayout.height]);
|
|
45
|
+
|
|
32
46
|
const handleBackdropPress = React.useCallback(() => {
|
|
33
47
|
if (dismissOnBackdrop) {
|
|
34
48
|
onClose();
|
|
@@ -37,11 +51,15 @@ export const BaseModal: React.FC<BaseModalProps> = ({
|
|
|
37
51
|
|
|
38
52
|
if (!visible) return null;
|
|
39
53
|
|
|
54
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
55
|
+
console.log("[BaseModal] Rendering modal content:", { testID });
|
|
56
|
+
}
|
|
57
|
+
|
|
40
58
|
return (
|
|
41
59
|
<Modal
|
|
42
60
|
visible={visible}
|
|
43
61
|
transparent
|
|
44
|
-
animationType="
|
|
62
|
+
animationType="none"
|
|
45
63
|
onRequestClose={onClose}
|
|
46
64
|
statusBarTranslucent
|
|
47
65
|
testID={testID}
|
|
@@ -43,7 +43,7 @@ export const FilterSheet: React.FC<FilterSheetProps> = ({
|
|
|
43
43
|
}, [onFilterPress, onClose]);
|
|
44
44
|
|
|
45
45
|
return (
|
|
46
|
-
<Modal visible={visible} transparent animationType="
|
|
46
|
+
<Modal visible={visible} transparent animationType="none" onRequestClose={onClose}>
|
|
47
47
|
<Pressable style={styles.backdrop} onPress={onClose}>
|
|
48
48
|
<Pressable
|
|
49
49
|
style={[styles.sheet, { backgroundColor: tokens.colors.surface, paddingBottom: insets.bottom }]}
|
|
@@ -89,8 +89,6 @@ export const EmojiPicker: React.FC<EmojiPickerProps> = ({
|
|
|
89
89
|
onEmojiSelected={handleEmojiSelect}
|
|
90
90
|
open={open}
|
|
91
91
|
onClose={onClose}
|
|
92
|
-
enableCategoryChangeAnimation={true}
|
|
93
|
-
enableSearchAnimation={true}
|
|
94
92
|
categoryPosition="top"
|
|
95
93
|
enableRecentlyUsed={config?.enableRecentlyUsed ?? true}
|
|
96
94
|
enableSearchBar={config?.enableSearch ?? true}
|
|
@@ -2,22 +2,17 @@
|
|
|
2
2
|
* OfflineBanner Component
|
|
3
3
|
*
|
|
4
4
|
* Displays a banner when the device is offline.
|
|
5
|
-
*
|
|
5
|
+
* Simple conditional rendering - NO animations per CLAUDE.md
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```tsx
|
|
9
|
-
* import { OfflineBanner, useOffline } from '@umituz/react-native-
|
|
9
|
+
* import { OfflineBanner, useOffline } from '@umituz/react-native-design-system';
|
|
10
10
|
*
|
|
11
11
|
* const App = () => {
|
|
12
12
|
* const { isOffline } = useOffline();
|
|
13
|
-
*
|
|
14
13
|
* return (
|
|
15
14
|
* <>
|
|
16
|
-
* <OfflineBanner
|
|
17
|
-
* visible={isOffline}
|
|
18
|
-
* message="No internet connection"
|
|
19
|
-
* backgroundColor="#FF6B6B"
|
|
20
|
-
* />
|
|
15
|
+
* <OfflineBanner visible={isOffline} message="No internet connection" />
|
|
21
16
|
* <YourContent />
|
|
22
17
|
* </>
|
|
23
18
|
* );
|
|
@@ -25,14 +20,8 @@
|
|
|
25
20
|
* ```
|
|
26
21
|
*/
|
|
27
22
|
|
|
28
|
-
import React, {
|
|
29
|
-
import {
|
|
30
|
-
View,
|
|
31
|
-
Animated,
|
|
32
|
-
StyleSheet,
|
|
33
|
-
type ViewStyle,
|
|
34
|
-
type TextStyle,
|
|
35
|
-
} from 'react-native';
|
|
23
|
+
import React, { memo } from 'react';
|
|
24
|
+
import { View, StyleSheet, type ViewStyle, type TextStyle } from 'react-native';
|
|
36
25
|
import { AtomicText } from '../../../atoms';
|
|
37
26
|
|
|
38
27
|
export interface OfflineBannerProps {
|
|
@@ -52,14 +41,11 @@ export interface OfflineBannerProps {
|
|
|
52
41
|
style?: ViewStyle;
|
|
53
42
|
/** Custom text style */
|
|
54
43
|
textStyle?: TextStyle;
|
|
55
|
-
/** Animation duration in ms */
|
|
56
|
-
animationDuration?: number;
|
|
57
44
|
/** Height of the banner */
|
|
58
45
|
height?: number;
|
|
59
46
|
}
|
|
60
47
|
|
|
61
48
|
const DEFAULT_HEIGHT = 44;
|
|
62
|
-
const DEFAULT_ANIMATION_DURATION = 300;
|
|
63
49
|
|
|
64
50
|
export const OfflineBanner: React.FC<OfflineBannerProps> = memo(({
|
|
65
51
|
visible,
|
|
@@ -70,59 +56,23 @@ export const OfflineBanner: React.FC<OfflineBannerProps> = memo(({
|
|
|
70
56
|
position = 'top',
|
|
71
57
|
style,
|
|
72
58
|
textStyle,
|
|
73
|
-
animationDuration = DEFAULT_ANIMATION_DURATION,
|
|
74
59
|
height = DEFAULT_HEIGHT,
|
|
75
60
|
}) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (isFirstRender.current) {
|
|
81
|
-
isFirstRender.current = false;
|
|
82
|
-
animatedValue.setValue(visible ? 1 : 0);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
Animated.timing(animatedValue, {
|
|
87
|
-
toValue: visible ? 1 : 0,
|
|
88
|
-
duration: animationDuration,
|
|
89
|
-
useNativeDriver: false,
|
|
90
|
-
}).start();
|
|
91
|
-
}, [visible, animatedValue, animationDuration]);
|
|
92
|
-
|
|
93
|
-
const translateY = animatedValue.interpolate({
|
|
94
|
-
inputRange: [0, 1],
|
|
95
|
-
outputRange: [position === 'top' ? -height : height, 0],
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
const animatedHeight = animatedValue.interpolate({
|
|
99
|
-
inputRange: [0, 1],
|
|
100
|
-
outputRange: [0, height],
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const opacity = animatedValue.interpolate({
|
|
104
|
-
inputRange: [0, 0.5, 1],
|
|
105
|
-
outputRange: [0, 0.8, 1],
|
|
106
|
-
});
|
|
61
|
+
// Simple conditional rendering - no animations
|
|
62
|
+
if (!visible) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
107
65
|
|
|
108
|
-
const positionStyle: ViewStyle = position === 'top'
|
|
109
|
-
? { top: 0 }
|
|
110
|
-
: { bottom: 0 };
|
|
66
|
+
const positionStyle: ViewStyle = position === 'top' ? { top: 0 } : { bottom: 0 };
|
|
111
67
|
|
|
112
68
|
return (
|
|
113
|
-
<
|
|
69
|
+
<View
|
|
114
70
|
style={[
|
|
115
71
|
styles.container,
|
|
116
72
|
positionStyle,
|
|
117
|
-
{
|
|
118
|
-
backgroundColor,
|
|
119
|
-
height: animatedHeight,
|
|
120
|
-
transform: [{ translateY }],
|
|
121
|
-
opacity,
|
|
122
|
-
},
|
|
73
|
+
{ backgroundColor, height },
|
|
123
74
|
style,
|
|
124
75
|
]}
|
|
125
|
-
pointerEvents={visible ? 'auto' : 'none'}
|
|
126
76
|
>
|
|
127
77
|
<View style={styles.content}>
|
|
128
78
|
{typeof icon === 'string' ? (
|
|
@@ -131,17 +81,13 @@ export const OfflineBanner: React.FC<OfflineBannerProps> = memo(({
|
|
|
131
81
|
icon
|
|
132
82
|
)}
|
|
133
83
|
<AtomicText
|
|
134
|
-
style={[
|
|
135
|
-
styles.message,
|
|
136
|
-
{ color: textColor },
|
|
137
|
-
textStyle,
|
|
138
|
-
]}
|
|
84
|
+
style={[styles.message, { color: textColor }, textStyle]}
|
|
139
85
|
numberOfLines={1}
|
|
140
86
|
>
|
|
141
87
|
{message}
|
|
142
88
|
</AtomicText>
|
|
143
89
|
</View>
|
|
144
|
-
</
|
|
90
|
+
</View>
|
|
145
91
|
);
|
|
146
92
|
});
|
|
147
93
|
|
|
@@ -153,7 +99,6 @@ const styles = StyleSheet.create({
|
|
|
153
99
|
left: 0,
|
|
154
100
|
right: 0,
|
|
155
101
|
zIndex: 9999,
|
|
156
|
-
overflow: 'hidden',
|
|
157
102
|
},
|
|
158
103
|
content: {
|
|
159
104
|
flex: 1,
|