@umituz/react-native-design-system 2.6.103 → 2.6.105

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.
@@ -1,104 +0,0 @@
1
- /**
2
- * AtomicCard Component
3
- *
4
- * A simple, styled card container component
5
- */
6
-
7
- import React from 'react';
8
- import {
9
- View,
10
- Pressable,
11
- StyleSheet,
12
- type ViewStyle,
13
- type StyleProp,
14
- type GestureResponderEvent,
15
- } from 'react-native';
16
- import { useAppDesignTokens } from '../theme';
17
-
18
- export type AtomicCardVariant = 'elevated' | 'outlined' | 'filled';
19
- export type AtomicCardPadding = 'none' | 'sm' | 'md' | 'lg';
20
-
21
- export interface AtomicCardProps {
22
- children: React.ReactNode;
23
- variant?: AtomicCardVariant;
24
- padding?: AtomicCardPadding;
25
- style?: StyleProp<ViewStyle>;
26
- testID?: string;
27
- onPress?: (event: GestureResponderEvent) => void;
28
- disabled?: boolean;
29
- }
30
-
31
- export const AtomicCard: React.FC<AtomicCardProps> = ({
32
- children,
33
- variant = 'elevated',
34
- padding = 'md',
35
- style,
36
- testID,
37
- onPress,
38
- disabled,
39
- }) => {
40
- const tokens = useAppDesignTokens();
41
-
42
- const paddingValues: Record<AtomicCardPadding, number> = {
43
- none: 0,
44
- sm: tokens.spacing.sm,
45
- md: tokens.spacing.md,
46
- lg: tokens.spacing.lg,
47
- };
48
-
49
- const getVariantStyle = (): ViewStyle => {
50
- switch (variant) {
51
- case 'elevated':
52
- return {
53
- backgroundColor: tokens.colors.surface,
54
- borderWidth: 1,
55
- borderColor: tokens.colors.outlineVariant || tokens.colors.outline,
56
- };
57
- case 'outlined':
58
- return {
59
- backgroundColor: tokens.colors.surface,
60
- borderWidth: 1,
61
- borderColor: tokens.colors.outline,
62
- };
63
- case 'filled':
64
- return {
65
- backgroundColor: tokens.colors.surfaceVariant,
66
- };
67
- default:
68
- return {};
69
- }
70
- };
71
-
72
- const cardStyle = [
73
- styles.card,
74
- { borderRadius: tokens.borders.radius.md },
75
- { padding: paddingValues[padding] },
76
- getVariantStyle(),
77
- style,
78
- ];
79
-
80
- if (onPress) {
81
- return (
82
- <Pressable
83
- style={cardStyle}
84
- testID={testID}
85
- onPress={onPress}
86
- disabled={disabled}
87
- >
88
- {children}
89
- </Pressable>
90
- );
91
- }
92
-
93
- return (
94
- <View style={cardStyle} testID={testID}>
95
- {children}
96
- </View>
97
- );
98
- };
99
-
100
- const styles = StyleSheet.create({
101
- card: {
102
- overflow: 'hidden',
103
- },
104
- });
@@ -1,81 +0,0 @@
1
- import React from 'react';
2
- import { View, StyleSheet, StyleProp, ViewStyle, Pressable, GestureResponderEvent } from 'react-native';
3
- import { useAppDesignTokens } from '../../theme';
4
-
5
- export interface GlowingCardProps {
6
- children: React.ReactNode;
7
- glowColor?: string;
8
- intensity?: number; // 0 to 1, default 1
9
- style?: StyleProp<ViewStyle>;
10
- onPress?: (event: GestureResponderEvent) => void;
11
- testID?: string;
12
- }
13
-
14
- /**
15
- * GlowingCard
16
- *
17
- * A card component with a neon-like glow effect using shadows.
18
- */
19
- export const GlowingCard: React.FC<GlowingCardProps> = ({
20
- children,
21
- glowColor,
22
- intensity = 1,
23
- style,
24
- onPress,
25
- testID,
26
- }) => {
27
- const tokens = useAppDesignTokens();
28
- const resolvedColor = glowColor || tokens.colors.primary;
29
-
30
- const shadowStyle: ViewStyle = {
31
- shadowColor: resolvedColor,
32
- shadowOffset: { width: 0, height: 0 },
33
- shadowOpacity: 0.6 * intensity,
34
- shadowRadius: 10 * intensity,
35
- elevation: 8 * intensity, // Android elevation
36
- // We allow the style prop to override backgroundColor, default to surface if not provided
37
- backgroundColor: tokens.colors.surface,
38
- borderRadius: tokens.borders.radius.md,
39
- borderColor: resolvedColor,
40
- borderWidth: 1,
41
- };
42
-
43
- // Extract background color from style if present to override default
44
- const styleObj = StyleSheet.flatten(style) || {};
45
- const finalBackgroundColor = styleObj.backgroundColor || shadowStyle.backgroundColor;
46
-
47
- const containerStyle = [
48
- styles.container,
49
- shadowStyle,
50
- style,
51
- // Ensure background color is consistent
52
- { backgroundColor: finalBackgroundColor }
53
- ];
54
-
55
- if (onPress) {
56
- return (
57
- <Pressable
58
- style={({ pressed }) => [
59
- containerStyle,
60
- pressed && { opacity: 0.9, transform: [{ scale: 0.98 }] }
61
- ]}
62
- onPress={onPress}
63
- testID={testID}
64
- >
65
- {children}
66
- </Pressable>
67
- );
68
- }
69
-
70
- return (
71
- <View style={containerStyle} testID={testID}>
72
- {children}
73
- </View>
74
- );
75
- };
76
-
77
- const styles = StyleSheet.create({
78
- container: {
79
- overflow: 'hidden', // Clip content to border radius
80
- },
81
- });
@@ -1,306 +0,0 @@
1
- # GlowingCard
2
-
3
- A card component with neon-like glowing shadow effect for highlighting important content and creating visual emphasis.
4
-
5
- ## Import & Usage
6
-
7
- ```typescript
8
- import { GlowingCard } from 'react-native-design-system/src/molecules/GlowingCard';
9
- ```
10
-
11
- **Location:** `src/molecules/GlowingCard/GlowingCard.tsx`
12
-
13
- ## Basic Usage
14
-
15
- ```tsx
16
- <GlowingCard glowColor="#6366f1" intensity={0.5}>
17
- <YourContent />
18
- </GlowingCard>
19
- ```
20
-
21
- ## Strategy
22
-
23
- **Purpose**: Create visual emphasis and draw attention to specific content through glowing effects.
24
-
25
- **When to Use**:
26
- - Featured products or items
27
- - Premium content highlighting
28
- - Important announcements
29
- - Achievement badges
30
- - Limited-time offers
31
- - User highlights (verified users, contributors)
32
-
33
- **When NOT to Use**:
34
- - Regular content cards (use AtomicCard instead)
35
- - Multiple items on same screen (causes visual clutter)
36
- - Background elements
37
- - Non-essential content
38
-
39
- ## Rules
40
-
41
- ### Required
42
-
43
- 1. **MUST** provide a `glowColor` prop
44
- 2. **MUST** keep `intensity` between 0.3 and 0.8
45
- 3. **ALWAYS** use sparingly (max 1-2 per screen)
46
- 4. **MUST** ensure sufficient contrast with glow color
47
- 5. **SHOULD** have purpose (highlight featured content)
48
-
49
- ### Intensity Guidelines
50
-
51
- 1. **Subtle emphasis**: 0.3 - 0.5
52
- 2. **Medium emphasis**: 0.5 - 0.7
53
- 3. **Strong emphasis**: 0.7 - 0.8
54
-
55
- **Never use intensity > 0.8** (too distracting)
56
-
57
- ### Color Selection
58
-
59
- 1. **MUST** use theme colors when possible
60
- 2. **SHOULD** match content purpose
61
- 3. **NEVER** use pure neon colors (#00FF00, #FF00FF, etc.)
62
-
63
- ## Forbidden
64
-
65
- ❌ **NEVER** do these:
66
-
67
- ```tsx
68
- // ❌ No glow color
69
- <GlowingCard>
70
- <Content />
71
- </GlowingCard>
72
-
73
- // ❌ Too high intensity
74
- <GlowingCard glowColor="#6366f1" intensity={1.0}>
75
- <Content />
76
- </GlowingCard>
77
-
78
- // ❌ Too many glowing cards
79
- <View>
80
- <GlowingCard glowColor="#6366f1"><Content1 /></GlowingCard>
81
- <GlowingCard glowColor="#10b981"><Content2 /></GlowingCard>
82
- <GlowingCard glowColor="#f59e0b"><Content3 /></GlowingCard>
83
- {/* ❌ Max 1-2 per screen */}
84
- </View>
85
-
86
- // ❌ Neon colors
87
- <GlowingCard glowColor="#00FF00" intensity={0.8}>
88
- <Content />
89
- </GlowingCard>
90
-
91
- // ❌ Non-essential content
92
- <GlowingCard glowColor="#6366f1">
93
- <RegularContent /> {/* ❌ Use AtomicCard instead */}
94
- </GlowingCard>
95
-
96
- // ❌ Nested GlowingCards
97
- <GlowingCard glowColor="#6366f1">
98
- <GlowingCard glowColor="#10b981">
99
- <Content />
100
- </GlowingCard>
101
- </GlowingCard>
102
- ```
103
-
104
- ## Best Practices
105
-
106
- ### Featured Content
107
-
108
- ✅ **DO**:
109
- ```tsx
110
- <GlowingCard
111
- glowColor={tokens.colors.primary}
112
- intensity={0.6}
113
- onPress={() => navigateTo(featuredItem)}
114
- >
115
- <FeaturedProductCard product={featuredProduct} />
116
- </GlowingCard>
117
- ```
118
-
119
- ❌ **DON'T**:
120
- ```tsx
121
- <GlowingCard glowColor="#ff0000" intensity={0.9}>
122
- <RegularProduct />
123
- </GlowingCard>
124
- ```
125
-
126
- ### Achievement Badges
127
-
128
- ✅ **DO**:
129
- ```tsx
130
- <GlowingCard
131
- glowColor="#f59e0b"
132
- intensity={0.5}
133
- style={{ width: 120, height: 120 }}
134
- >
135
- <AchievementBadge achievement={achievement} />
136
- </GlowingCard>
137
- ```
138
-
139
- ### User Highlights
140
-
141
- ✅ **DO**:
142
- ```tsx
143
- <GlowingCard glowColor="#8b5cf6" intensity={0.4}>
144
- <UserHighlight user={verifiedUser} />
145
- </GlowingCard>
146
- ```
147
-
148
- ### Color by Purpose
149
-
150
- ✅ **DO**:
151
- - Primary actions: Theme primary color
152
- - Success: Green (#10b981, #22c55e)
153
- - Warning: Orange/Amber (#f59e0b, #f97316)
154
- - Error: Red (#ef4444, #dc2626)
155
- - Info: Blue (#3b82f6, #2563eb)
156
-
157
- ❌ **DON'T**:
158
- ```tsx
159
- // ❌ Random colors
160
- <GlowingCard glowColor="#123456" />
161
-
162
- // ❌ Too bright
163
- <GlowingCard glowColor="#00FF00" />
164
- ```
165
-
166
- ## AI Coding Guidelines
167
-
168
- ### For AI Agents
169
-
170
- When generating GlowingCard components, follow these rules:
171
-
172
- 1. **Always import from correct path**:
173
- ```typescript
174
- import { GlowingCard } from 'react-native-design-system/src/molecules/GlowingCard';
175
- ```
176
-
177
- 2. **Always specify glowColor**:
178
- ```tsx
179
- <GlowingCard
180
- glowColor={根据内容选择合适的颜色}
181
- intensity={0.5-0.7之间的值}
182
- >
183
- {content}
184
- </GlowingCard>
185
- ```
186
-
187
- 3. **Never use without purpose**:
188
- ```tsx
189
- // ❌ Bad - arbitrary use
190
- <GlowingCard glowColor="#6366f1">
191
- <RegularContent />
192
- </GlowingCard>
193
-
194
- // ✅ Good - featured content
195
- {isFeatured && (
196
- <GlowingCard glowColor="#6366f1" intensity={0.6}>
197
- <FeaturedContent />
198
- </GlowingCard>
199
- )}
200
- ```
201
-
202
- 4. **Always limit usage on screen**:
203
- ```tsx
204
- // ✅ Good - conditional highlighting
205
- <View>
206
- {items.map((item, index) =>
207
- item.isFeatured ? (
208
- <GlowingCard key={item.id} glowColor="#6366f1" intensity={0.6}>
209
- <ItemCard item={item} />
210
- </GlowingCard>
211
- ) : (
212
- <AtomicCard key={item.id}>
213
- <ItemCard item={item} />
214
- </AtomicCard>
215
- )
216
- )}
217
- </View>
218
- ```
219
-
220
- 5. **Always use semantic colors**:
221
- ```tsx
222
- // ✅ Good - color by purpose
223
- const getGlowColor = (type: 'success' | 'warning' | 'error') => {
224
- switch (type) {
225
- case 'success': return '#10b981';
226
- case 'warning': return '#f59e0b';
227
- case 'error': return '#ef4444';
228
- default: return tokens.colors.primary;
229
- }
230
- };
231
-
232
- <GlowingCard glowColor={getGlowColor(type)} />
233
- ```
234
-
235
- ### Common Patterns
236
-
237
- #### Featured Product
238
- ```tsx
239
- <GlowingCard
240
- glowColor="#6366f1"
241
- intensity={0.6}
242
- onPress={() => navigation.navigate('Product', { productId: product.id })}
243
- >
244
- <ProductCard product={product} variant="featured" />
245
- </GlowingCard>
246
- ```
247
-
248
- #### Achievement Badge
249
- ```tsx
250
- <GlowingCard
251
- glowColor="#f59e0b"
252
- intensity={0.5}
253
- style={{ margin: 8 }}
254
- >
255
- <AchievementBadge achievement={achievement} />
256
- </GlowingCard>
257
- ```
258
-
259
- #### Notification Card
260
- ```tsx
261
- <GlowingCard
262
- glowColor={notification.urgency === 'high' ? '#ef4444' : '#3b82f6'}
263
- intensity={notification.urgency === 'high' ? 0.7 : 0.4}
264
- onPress={() => markAsRead(notification.id)}
265
- >
266
- <NotificationCard notification={notification} />
267
- </GlowingCard>
268
- ```
269
-
270
- ## Props Reference
271
-
272
- | Prop | Type | Required | Default | Description |
273
- |------|------|----------|---------|-------------|
274
- | `glowColor` | `string` | **Yes** | Theme primary color | Glow color (hex) |
275
- | `intensity` | `number` | No | `0.5` | Glow intensity (0-1) |
276
- | `borderWidth` | `number` | No | `0` | Border width |
277
- | `borderColor` | `string` | No | Same as glowColor | Border color |
278
- | `onPress` | `() => void` | No | - | Press callback |
279
- | `style` | `ViewStyle` | No | - | Custom container style |
280
- | `children` | `ReactNode` | **Yes** | - | Card content |
281
-
282
- ## Accessibility
283
-
284
- - ✅ Screen reader announces card content
285
- - ✅ Touch target size maintained (min 44x44pt)
286
- - ✅ Focus indicators for pressable cards
287
- - ✅ Sufficient color contrast with glow
288
- - ✅ Semantic structure preserved
289
-
290
- ## Performance Tips
291
-
292
- 1. **Use sparingly**: Only for highlights (1-2 per screen max)
293
- 2. **Lower intensity**: Better performance with 0.3-0.5
294
- 3. **Avoid animation**: Static glow more performant
295
- 4. **Conditional rendering**: Don't use for every card
296
- 5. **Memo content**: Memo card content to prevent re-renders
297
-
298
- ## Related Components
299
-
300
- - [`AtomicCard`](../../atoms/AtomicCard/README.md) - Base card component
301
- - [`MediaCard`](../media-card/README.md) - Media card component
302
- - [`AtomicIcon`](../../atoms/AtomicIcon/README.md) - Icon component
303
-
304
- ## License
305
-
306
- MIT
@@ -1 +0,0 @@
1
- export * from './GlowingCard';
@@ -1,44 +0,0 @@
1
-
2
- import React from 'react';
3
- import { View, StyleSheet } from 'react-native';
4
- import { AtomicText } from '../../atoms/AtomicText';
5
- import { useAppDesignTokens } from '../../theme';
6
- import type { InfoCardProps } from './types';
7
-
8
- export const InfoCard: React.FC<InfoCardProps> = ({
9
- title,
10
- content,
11
- style,
12
- }) => {
13
- const tokens = useAppDesignTokens();
14
-
15
- const styles = StyleSheet.create({
16
- container: {
17
- backgroundColor: tokens.colors.surface,
18
- borderRadius: tokens.borders.radius.xl,
19
- padding: tokens.spacing.lg,
20
- borderWidth: 1,
21
- borderColor: tokens.colors.outlineVariant,
22
- },
23
- title: {
24
- ...tokens.typography.labelLarge,
25
- color: tokens.colors.primary,
26
- fontWeight: '800', // Using string as expected by RN
27
- textTransform: 'uppercase',
28
- letterSpacing: 1,
29
- marginBottom: tokens.spacing.xs,
30
- },
31
- content: {
32
- ...tokens.typography.bodyMedium,
33
- color: tokens.colors.textPrimary,
34
- lineHeight: 22,
35
- },
36
- });
37
-
38
- return (
39
- <View style={[styles.container, style]}>
40
- <AtomicText style={styles.title}>{title}</AtomicText>
41
- <AtomicText style={styles.content}>{content}</AtomicText>
42
- </View>
43
- );
44
- };
@@ -1,3 +0,0 @@
1
-
2
- export * from './InfoCard';
3
- export * from './types';
@@ -1,9 +0,0 @@
1
-
2
- import React from 'react';
3
- import { ViewStyle, StyleProp } from 'react-native';
4
-
5
- export interface InfoCardProps {
6
- title: string;
7
- content: string;
8
- style?: StyleProp<ViewStyle>;
9
- }
@@ -1,157 +0,0 @@
1
- /**
2
- * AtomicMediaCard - Reusable media card component
3
- *
4
- * Displays an image with optional overlay text, badge, and selection state.
5
- * Used for grids of images, memes, templates, etc.
6
- */
7
-
8
- import React from 'react';
9
- import {
10
- View,
11
- StyleSheet,
12
- TouchableOpacity,
13
- Image,
14
- type ImageStyle,
15
- } from 'react-native';
16
- import { AtomicText, AtomicIcon } from '../../atoms';
17
- import { useAppDesignTokens } from '../../theme';
18
-
19
- import type { MediaCardProps } from './types';
20
-
21
- export const MediaCard: React.FC<MediaCardProps> = ({
22
- uri,
23
- title,
24
- subtitle,
25
- badge,
26
- selected = false,
27
- size = 'md',
28
- aspectRatio = 0.8,
29
- overlayPosition = 'bottom',
30
- showOverlay = true,
31
- onPress,
32
- width,
33
- testID,
34
- }) => {
35
- const tokens = useAppDesignTokens();
36
-
37
- const sizeConfig = {
38
- sm: { width: width || 120, borderRadius: tokens.radius.sm },
39
- md: { width: width || 144, borderRadius: tokens.radius.md },
40
- lg: { width: width || 160, borderRadius: tokens.radius.lg },
41
- };
42
-
43
- const config = sizeConfig[size];
44
- const height = config.width / aspectRatio;
45
-
46
- const styles = StyleSheet.create({
47
- container: {
48
- width: config.width,
49
- height,
50
- borderRadius: config.borderRadius,
51
- overflow: 'hidden',
52
- backgroundColor: tokens.colors.surfaceVariant,
53
- borderWidth: selected ? tokens.borders.width.medium : tokens.borders.width.thin,
54
- borderColor: selected ? tokens.colors.primary : tokens.colors.outline,
55
- },
56
- image: {
57
- width: '100%',
58
- height: '100%',
59
- } as ImageStyle,
60
- badge: {
61
- position: 'absolute',
62
- top: tokens.spacing.sm,
63
- right: tokens.spacing.sm,
64
- backgroundColor: tokens.colors.primary,
65
- paddingHorizontal: tokens.spacing.sm,
66
- paddingVertical: tokens.spacing.xs,
67
- borderRadius: tokens.borders.radius.full,
68
- zIndex: 10,
69
- },
70
- badgeText: {
71
- color: tokens.colors.onPrimary,
72
- fontSize: tokens.typography.labelSmall.fontSize,
73
- fontWeight: 'bold',
74
- },
75
- overlay: {
76
- position: 'absolute',
77
- bottom: 0,
78
- left: 0,
79
- right: 0,
80
- backgroundColor: tokens.colors.surfaceVariant,
81
- opacity: 0.95,
82
- justifyContent: 'flex-end',
83
- paddingVertical: tokens.spacing.md,
84
- paddingHorizontal: tokens.spacing.sm,
85
- },
86
- textContainer: {
87
- width: '100%',
88
- },
89
- title: {
90
- fontSize: tokens.typography.bodyMedium.fontSize,
91
- fontWeight: 'bold',
92
- color: tokens.colors.textInverse,
93
- textAlign: 'left',
94
- marginBottom: tokens.spacing.xs,
95
- },
96
- subtitle: {
97
- fontSize: tokens.typography.bodySmall.fontSize,
98
- color: tokens.colors.textSecondary,
99
- opacity: 0.9,
100
- textAlign: 'left',
101
- },
102
- checkCircle: {
103
- position: 'absolute',
104
- top: tokens.spacing.sm,
105
- right: tokens.spacing.sm,
106
- backgroundColor: tokens.colors.primary,
107
- borderRadius: tokens.borders.radius.full,
108
- width: tokens.spacing.lg,
109
- height: tokens.spacing.lg,
110
- alignItems: 'center',
111
- justifyContent: 'center',
112
- },
113
- });
114
-
115
- const CardWrapper = onPress ? TouchableOpacity : View;
116
- const wrapperProps = onPress
117
- ? {
118
- onPress,
119
- activeOpacity: 0.8,
120
- testID,
121
- }
122
- : { testID };
123
-
124
- return (
125
- <CardWrapper style={styles.container} {...wrapperProps}>
126
- {badge && (
127
- <View style={styles.badge}>
128
- <AtomicText style={styles.badgeText}>{badge}</AtomicText>
129
- </View>
130
- )}
131
- <Image source={{ uri }} style={styles.image} resizeMode="cover" />
132
-
133
- {showOverlay && (title || subtitle) && (
134
- <View style={styles.overlay}>
135
- <View style={styles.textContainer}>
136
- {title && (
137
- <AtomicText style={styles.title} numberOfLines={1}>
138
- {title}
139
- </AtomicText>
140
- )}
141
- {subtitle && (
142
- <AtomicText style={styles.subtitle} numberOfLines={1}>
143
- {subtitle}
144
- </AtomicText>
145
- )}
146
- </View>
147
- </View>
148
- )}
149
-
150
- {selected && (
151
- <View style={styles.checkCircle}>
152
- <AtomicIcon name="checkmark-outline" size="sm" color="onPrimary" />
153
- </View>
154
- )}
155
- </CardWrapper>
156
- );
157
- };