@umituz/react-native-design-system 2.4.10 → 2.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "2.4.10",
3
+ "version": "2.4.11",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -418,6 +418,10 @@ export {
418
418
  PhotoUploadCard,
419
419
  type PhotoUploadCardProps,
420
420
  type PhotoUploadCardConfig,
421
+ // Image Picker
422
+ ImagePickerBox,
423
+ type ImagePickerBoxProps,
424
+ type ImagePickerBoxConfig,
421
425
  // Step Header
422
426
  StepHeader,
423
427
  type StepHeaderProps,
@@ -0,0 +1,171 @@
1
+ /**
2
+ * ImagePickerBox Component
3
+ * Generic image picker box with gradient design
4
+ * Props-driven for 100+ apps compatibility
5
+ *
6
+ * @package @umituz/react-native-design-system
7
+ */
8
+
9
+ import React, { useMemo } from "react";
10
+ import {
11
+ View,
12
+ StyleSheet,
13
+ TouchableOpacity,
14
+ Image,
15
+ type ViewStyle,
16
+ } from "react-native";
17
+ import { LinearGradient } from "expo-linear-gradient";
18
+ import { AtomicText } from "../../atoms/AtomicText";
19
+ import { AtomicIcon } from "../../atoms/AtomicIcon";
20
+ import { useAppDesignTokens } from "../../theme/hooks/useAppDesignTokens";
21
+
22
+ export interface ImagePickerBoxConfig {
23
+ readonly variant?: "portrait" | "square" | "landscape";
24
+ readonly size?: "sm" | "md" | "lg";
25
+ readonly uploadIcon?: string;
26
+ readonly editIcon?: string;
27
+ }
28
+
29
+ export interface ImagePickerBoxProps {
30
+ readonly imageUri: string | null;
31
+ readonly isDisabled?: boolean;
32
+ readonly onPress: () => void;
33
+ readonly placeholderText: string;
34
+ readonly gradientColors?: readonly [string, string, ...string[]];
35
+ readonly config?: ImagePickerBoxConfig;
36
+ }
37
+
38
+ const VARIANT_STYLES: Record<string, ViewStyle> = {
39
+ portrait: { width: 200, height: 280, borderRadius: 20 },
40
+ square: { width: "100%" as unknown as number, aspectRatio: 1, borderRadius: 24 },
41
+ landscape: { width: "100%" as unknown as number, aspectRatio: 16 / 9, borderRadius: 16 },
42
+ };
43
+
44
+ const SIZE_MULTIPLIERS = { sm: 0.7, md: 1, lg: 1.3 };
45
+
46
+ const DEFAULT_CONFIG: ImagePickerBoxConfig = {
47
+ variant: "portrait",
48
+ size: "md",
49
+ uploadIcon: "cloud-upload-outline",
50
+ editIcon: "image-outline",
51
+ };
52
+
53
+ export const ImagePickerBox: React.FC<ImagePickerBoxProps> = ({
54
+ imageUri,
55
+ isDisabled = false,
56
+ onPress,
57
+ placeholderText,
58
+ gradientColors = ["#667eea", "#764ba2"],
59
+ config = DEFAULT_CONFIG,
60
+ }) => {
61
+ const tokens = useAppDesignTokens();
62
+ const cfg = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);
63
+
64
+ const multiplier = SIZE_MULTIPLIERS[cfg.size || "md"];
65
+ const baseStyle = VARIANT_STYLES[cfg.variant || "portrait"];
66
+ const iconSize = Math.round(32 * multiplier);
67
+
68
+ const styles = useMemo(
69
+ () =>
70
+ StyleSheet.create({
71
+ container: {
72
+ marginVertical: 16,
73
+ alignItems: "center",
74
+ },
75
+ box: {
76
+ overflow: "hidden",
77
+ ...baseStyle,
78
+ backgroundColor: tokens.colors.backgroundSecondary,
79
+ },
80
+ imageContainer: {
81
+ flex: 1,
82
+ position: "relative",
83
+ },
84
+ image: {
85
+ width: "100%",
86
+ height: "100%",
87
+ },
88
+ imageOverlay: {
89
+ position: "absolute",
90
+ bottom: 0,
91
+ left: 0,
92
+ right: 0,
93
+ height: "30%",
94
+ justifyContent: "flex-end",
95
+ alignItems: "flex-end",
96
+ padding: 12,
97
+ },
98
+ editBadge: {
99
+ borderRadius: 20,
100
+ padding: 8,
101
+ backgroundColor: `${gradientColors[1]}E6`,
102
+ },
103
+ placeholder: {
104
+ flex: 1,
105
+ justifyContent: "center",
106
+ alignItems: "center",
107
+ },
108
+ placeholderContent: {
109
+ alignItems: "center",
110
+ justifyContent: "center",
111
+ paddingHorizontal: 16,
112
+ },
113
+ uploadIconContainer: {
114
+ backgroundColor: "rgba(255,255,255,0.2)",
115
+ borderRadius: 40,
116
+ padding: 16,
117
+ marginBottom: 12,
118
+ },
119
+ placeholderText: {
120
+ textAlign: "center",
121
+ fontWeight: "600",
122
+ color: "#FFFFFF",
123
+ },
124
+ }),
125
+ [tokens, baseStyle, gradientColors]
126
+ );
127
+
128
+ return (
129
+ <View style={styles.container}>
130
+ <TouchableOpacity
131
+ style={styles.box}
132
+ onPress={onPress}
133
+ disabled={isDisabled}
134
+ activeOpacity={0.8}
135
+ >
136
+ {imageUri ? (
137
+ <View style={styles.imageContainer}>
138
+ <Image source={{ uri: imageUri }} style={styles.image} />
139
+ <LinearGradient
140
+ colors={["transparent", "rgba(0,0,0,0.3)"]}
141
+ style={styles.imageOverlay}
142
+ >
143
+ <View style={styles.editBadge}>
144
+ <AtomicIcon
145
+ name={cfg.editIcon || "image-outline"}
146
+ customSize={Math.round(16 * multiplier)}
147
+ customColor="#FFFFFF"
148
+ />
149
+ </View>
150
+ </LinearGradient>
151
+ </View>
152
+ ) : (
153
+ <LinearGradient colors={gradientColors} style={styles.placeholder}>
154
+ <View style={styles.placeholderContent}>
155
+ <View style={styles.uploadIconContainer}>
156
+ <AtomicIcon
157
+ name={cfg.uploadIcon || "cloud-upload-outline"}
158
+ customSize={iconSize}
159
+ customColor="#FFFFFF"
160
+ />
161
+ </View>
162
+ <AtomicText type="bodyMedium" style={styles.placeholderText}>
163
+ {placeholderText}
164
+ </AtomicText>
165
+ </View>
166
+ </LinearGradient>
167
+ )}
168
+ </TouchableOpacity>
169
+ </View>
170
+ );
171
+ };
@@ -0,0 +1,2 @@
1
+ export { ImagePickerBox } from "./ImagePickerBox";
2
+ export type { ImagePickerBoxProps, ImagePickerBoxConfig } from "./ImagePickerBox";
@@ -51,6 +51,9 @@ export * from './long-press-menu';
51
51
  // Photo Upload
52
52
  export * from './PhotoUploadCard';
53
53
 
54
+ // Image Picker
55
+ export * from './ImagePickerBox';
56
+
54
57
  // Step Header
55
58
  export * from './StepHeader';
56
59