@umituz/react-native-design-system 4.27.17 → 4.27.18

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": "4.27.17",
3
+ "version": "4.27.18",
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, onboarding, and loading utilities - TanStack persistence and expo-image-manipulator now lazy loaded",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./dist/index.d.ts",
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { Image as RNImage, type StyleProp, type ImageStyle } from 'react-native';
2
+ import { Image as RNImage, type StyleProp, type ImageStyle, ImageSourcePropType } from 'react-native';
3
3
 
4
4
  // Lazy-load expo-image (optional peer dep) — falls back to React Native Image
5
+ // biome-ignore lint/suspicious/noExplicitAny: ExpoImage type is dynamic from optional peer dependency
5
6
  let ExpoImage: React.ComponentType<any> | null = null;
6
7
  try {
7
8
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -10,13 +11,18 @@ try {
10
11
  // expo-image not installed — using React Native Image fallback
11
12
  }
12
13
 
14
+ /**
15
+ * Image source type compatible with both React Native and expo-image
16
+ * Supports: require() assets, URI strings, and image source objects
17
+ */
18
+ export type ImageSource = ImageSourcePropType;
19
+
13
20
  export type AtomicImageProps = {
14
- source?: any;
21
+ source?: ImageSource;
15
22
  style?: StyleProp<ImageStyle>;
16
23
  rounded?: boolean;
17
24
  contentFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
18
25
  cachePolicy?: 'none' | 'disk' | 'memory' | 'memory-disk';
19
- [key: string]: any;
20
26
  };
21
27
 
22
28
  const RESIZE_MODE_MAP: Record<string, 'cover' | 'contain' | 'stretch' | 'center'> = {
@@ -93,11 +93,17 @@ function InfiniteScrollListComponent<T>({
93
93
  return emptyComponent || <Empty />;
94
94
  }
95
95
 
96
+ // Memoize renderItem wrapper to prevent unnecessary re-renders
97
+ const memoizedRenderItem = useCallback(
98
+ ({ item, index }: { item: T; index: number }) => renderItem(item, index),
99
+ [renderItem]
100
+ );
101
+
96
102
  // Render list
97
103
  return (
98
104
  <FlatList
99
105
  data={items}
100
- renderItem={({ item, index }) => renderItem(item, index)}
106
+ renderItem={memoizedRenderItem}
101
107
  keyExtractor={(item, index) => getItemKey(item, index)}
102
108
  onEndReached={handleEndReached}
103
109
  onEndReachedThreshold={calculateEndReachedThreshold(config.threshold)}
@@ -32,16 +32,18 @@ export const FilterGroup = React.memo(function FilterGroup<T = string>({
32
32
  // Memoize selected items to prevent unnecessary re-renders
33
33
  const selectedSet = useMemo(() => {
34
34
  if (multiSelect && Array.isArray(selectedValue)) {
35
- return new Set(selectedValue);
35
+ return new Set<T>(selectedValue);
36
36
  }
37
- return new Set(selectedValue !== undefined ? [selectedValue] : []);
37
+ // Single selection: wrap in array if present
38
+ const singleValue = selectedValue !== undefined ? [selectedValue] : [];
39
+ return new Set<T>(singleValue as T[]);
38
40
  }, [selectedValue, multiSelect]);
39
41
 
40
42
  // Memoize isSelected calculation for each item
41
- const isSelected = useCallback((value: any) => selectedSet.has(value), [selectedSet]);
43
+ const isSelected = useCallback((value: T) => selectedSet.has(value), [selectedSet]);
42
44
 
43
45
  // Memoized chip renderer
44
- const renderChip = useCallback((item: any) => (
46
+ const renderChip = useCallback((item: { value: T; label: string; testID?: string }) => (
45
47
  <AtomicChip
46
48
  key={String(item.value)}
47
49
  variant={isSelected(item.value) ? 'filled' : 'outlined'}
@@ -30,9 +30,9 @@ export interface BaseScreen<T extends ParamListBase = ParamListBase> {
30
30
  /** Unique name identifier for the screen */
31
31
  name: Extract<keyof T, string>;
32
32
  /** React component to render for this screen */
33
- component?: React.ComponentType<any>;
33
+ component?: React.ComponentType<{ navigation: unknown; route: unknown }>;
34
34
  /** Render function for children (alternative to component) */
35
- children?: (props: any) => React.ReactNode;
35
+ children?: (props: { navigation: unknown; route: unknown }) => React.ReactNode;
36
36
  }
37
37
 
38
38
  /**
@@ -55,13 +55,18 @@ const BackgroundContent: React.FC<BackgroundContentProps> = ({
55
55
  }
56
56
 
57
57
  if (slide.backgroundImage) {
58
+ // Normalize ImageSourceType to ImageSourcePropType
59
+ // ImageSourceType supports string URIs, but ImageSourcePropType requires { uri: string } objects
60
+ const normalizedSource = typeof slide.backgroundImage === 'string'
61
+ ? { uri: slide.backgroundImage }
62
+ : slide.backgroundImage;
63
+
58
64
  return (
59
65
  <AtomicImage
60
- source={slide.backgroundImage}
66
+ source={normalizedSource}
61
67
  style={StyleSheet.absoluteFill}
62
68
  contentFit="cover"
63
69
  cachePolicy="memory-disk"
64
- priority="high"
65
70
  />
66
71
  );
67
72
  }