@umituz/react-native-design-system 4.23.80 → 4.23.81

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.
Files changed (76) hide show
  1. package/package.json +1 -1
  2. package/src/atoms/AtomicInput.tsx +11 -48
  3. package/src/atoms/AtomicPicker.tsx +19 -94
  4. package/src/atoms/EmptyState.tsx +1 -1
  5. package/src/atoms/icon/AtomicIcon.tsx +0 -1
  6. package/src/atoms/icon/iconStore.ts +0 -2
  7. package/src/atoms/picker/components/PickerModal.tsx +40 -121
  8. package/src/device/infrastructure/services/PersistentDeviceIdService.ts +0 -4
  9. package/src/device/presentation/hooks/useDeviceInfo.ts +55 -149
  10. package/src/haptics/infrastructure/services/HapticService.ts +0 -1
  11. package/src/image/index.ts +2 -1
  12. package/src/image/presentation/hooks/useImageBatch.ts +2 -1
  13. package/src/infinite-scroll/presentation/components/infinite-scroll-list.tsx +1 -1
  14. package/src/infinite-scroll/presentation/hooks/pagination.helper.ts +0 -5
  15. package/src/infinite-scroll/presentation/hooks/useInfiniteScroll.ts +4 -54
  16. package/src/init/createAppInitializer.ts +0 -1
  17. package/src/init/env/createEnvConfig.ts +0 -1
  18. package/src/init/useAppInitialization.ts +0 -1
  19. package/src/layouts/ScreenHeader/ScreenHeader.tsx +1 -1
  20. package/src/media/infrastructure/services/CardMediaOptimizerService.ts +0 -1
  21. package/src/media/infrastructure/services/CardMediaUploadService.ts +0 -1
  22. package/src/media/presentation/hooks/useCardMediaGeneration.ts +1 -1
  23. package/src/media/presentation/hooks/useCardMediaUpload.ts +1 -1
  24. package/src/media/presentation/hooks/useCardMediaValidation.ts +1 -1
  25. package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +1 -1
  26. package/src/media/presentation/hooks/useMedia.ts +0 -1
  27. package/src/media/presentation/hooks/useMediaGeneration.ts +1 -1
  28. package/src/media/presentation/hooks/useMediaUpload.ts +1 -1
  29. package/src/media/presentation/hooks/useMediaValidation.ts +1 -1
  30. package/src/media/presentation/hooks/useMultimediaFlashcard.ts +1 -1
  31. package/src/molecules/BaseModal.tsx +1 -3
  32. package/src/molecules/ConfirmationModalContent.tsx +1 -1
  33. package/src/molecules/ConfirmationModalMain.tsx +1 -1
  34. package/src/molecules/bottom-sheet/components/BottomSheetModal.tsx +0 -3
  35. package/src/molecules/bottom-sheet/components/filter/FilterBottomSheet.tsx +100 -179
  36. package/src/molecules/calendar/infrastructure/stores/useCalendarEvents.ts +0 -1
  37. package/src/molecules/confirmation-modal/useConfirmationModal.ts +1 -1
  38. package/src/molecules/countdown/components/Countdown.tsx +1 -1
  39. package/src/molecules/navigation/StackNavigator.tsx +0 -1
  40. package/src/molecules/navigation/TabsNavigator.tsx +0 -1
  41. package/src/molecules/navigation/utils/AppNavigation.ts +0 -8
  42. package/src/molecules/splash/components/SplashScreen.tsx +0 -4
  43. package/src/offline/infrastructure/events/NetworkEvents.ts +0 -1
  44. package/src/offline/infrastructure/utils/healthCheck.ts +0 -5
  45. package/src/offline/presentation/hooks/useOffline.ts +0 -1
  46. package/src/offline/presentation/hooks/useOfflineWithMutations.ts +0 -2
  47. package/src/onboarding/index.ts +0 -1
  48. package/src/onboarding/infrastructure/hooks/useOnboardingNavigation.ts +0 -1
  49. package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +0 -2
  50. package/src/onboarding/presentation/hooks/useOnboardingScreenHandlers.ts +0 -2
  51. package/src/onboarding/presentation/hooks/useOnboardingScreenState.ts +0 -1
  52. package/src/onboarding/presentation/screens/OnboardingScreen.tsx +0 -3
  53. package/src/organisms/FormContainer.tsx +1 -1
  54. package/src/services/api/ApiClient.ts +42 -135
  55. package/src/storage/cache/domain/Cache.ts +0 -2
  56. package/src/storage/cache/infrastructure/TTLCache.ts +0 -3
  57. package/src/storage/domain/utils/devUtils.ts +0 -3
  58. package/src/storage/infrastructure/adapters/StorageService.ts +0 -3
  59. package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +0 -1
  60. package/src/tanstack/domain/config/QueryClientAccessor.ts +0 -1
  61. package/src/tanstack/domain/repositories/BaseRepository.ts +4 -4
  62. package/src/tanstack/domain/repositories/IBaseRepository.ts +3 -5
  63. package/src/tanstack/domain/repositories/RepositoryFactory.ts +0 -2
  64. package/src/tanstack/domain/repositories/mixins/repositoryInvalidationMethods.ts +10 -11
  65. package/src/tanstack/domain/repositories/mixins/repositoryQueryMethods.ts +11 -11
  66. package/src/tanstack/domain/utils/ErrorHelpers.ts +0 -1
  67. package/src/tanstack/infrastructure/config/PersisterConfig.ts +0 -7
  68. package/src/tanstack/infrastructure/config/QueryClientConfig.ts +0 -1
  69. package/src/tanstack/infrastructure/monitoring/DevMonitorLogger.ts +0 -6
  70. package/src/tanstack/presentation/hooks/useInvalidateQueries.ts +0 -4
  71. package/src/tanstack/presentation/hooks/useOptimisticUpdate.ts +0 -2
  72. package/src/tanstack/presentation/hooks/usePrefetch.ts +18 -119
  73. package/src/theme/core/CustomColors.ts +4 -122
  74. package/src/theme/infrastructure/storage/ThemeStorage.ts +0 -1
  75. package/src/typography/presentation/utils/textColorUtils.ts +36 -163
  76. package/src/tanstack/presentation/hooks/utils/prefetchLogger.ts +0 -27
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "4.23.80",
3
+ "version": "4.23.81",
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",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -9,18 +9,6 @@ import { InputLabel } from './input/components/InputLabel';
9
9
  import { InputIcon } from './input/components/InputIcon';
10
10
  import { InputHelper } from './input/components/InputHelper';
11
11
 
12
- /**
13
- * AtomicInput - Pure React Native Text Input
14
- *
15
- * Features:
16
- * - Pure React Native implementation (no Paper dependency)
17
- * - Icon support via AtomicIcon (app provides renderer)
18
- * - Outlined/filled/flat variants
19
- * - Error, success, disabled states
20
- * - Character counter
21
- * - Responsive sizing
22
- * - Full accessibility support
23
- */
24
12
  export const AtomicInput = React.forwardRef<React.ElementRef<typeof TextInput>, AtomicInputProps>(({
25
13
  variant = 'outlined',
26
14
  state = 'default',
@@ -79,22 +67,10 @@ export const AtomicInput = React.forwardRef<React.ElementRef<typeof TextInput>,
79
67
  const hasSuccess = state === 'success';
80
68
 
81
69
  const sizeConfig = getSizeConfig({ size, tokens });
82
- const variantStyle = getVariantStyle({
83
- variant,
84
- isFocused,
85
- hasError,
86
- hasSuccess,
87
- isDisabled,
88
- tokens,
89
- });
90
- const textColor = getTextColor({
91
- isDisabled,
92
- hasError,
93
- hasSuccess,
94
- tokens,
95
- });
96
-
70
+ const variantStyle = getVariantStyle({ variant, isFocused, hasError, hasSuccess, isDisabled, tokens });
71
+ const textColor = getTextColor({ isDisabled, hasError, hasSuccess, tokens });
97
72
  const iconColor = isDisabled ? tokens.colors.textDisabled : tokens.colors.textSecondary;
73
+ const iconPadding = sizeConfig.iconSize + 8;
98
74
 
99
75
  const containerStyle: StyleProp<ViewStyle> = [
100
76
  inputStyles.container,
@@ -117,9 +93,9 @@ export const AtomicInput = React.forwardRef<React.ElementRef<typeof TextInput>,
117
93
  lineHeight: (sizeConfig.fontSize || 16) * 1.2,
118
94
  color: textColor,
119
95
  paddingVertical: 4,
96
+ paddingLeft: leadingIcon ? iconPadding : undefined,
97
+ paddingRight: (trailingIcon || showPasswordToggle) ? iconPadding : undefined,
120
98
  },
121
- leadingIcon ? { paddingLeft: sizeConfig.iconSize + 8 } : undefined,
122
- (trailingIcon || showPasswordToggle) ? { paddingRight: sizeConfig.iconSize + 8 } : undefined,
123
99
  inputStyle,
124
100
  ];
125
101
 
@@ -128,14 +104,7 @@ export const AtomicInput = React.forwardRef<React.ElementRef<typeof TextInput>,
128
104
  <InputLabel label={label} state={state} />
129
105
 
130
106
  <View style={containerStyle}>
131
- {leadingIcon && (
132
- <InputIcon
133
- name={leadingIcon }
134
- size={sizeConfig.iconSize}
135
- color={iconColor}
136
- position="leading"
137
- />
138
- )}
107
+ {leadingIcon && <InputIcon name={leadingIcon} size={sizeConfig.iconSize} color={iconColor} position="leading" />}
139
108
 
140
109
  <TextInput
141
110
  ref={ref}
@@ -158,31 +127,25 @@ export const AtomicInput = React.forwardRef<React.ElementRef<typeof TextInput>,
158
127
  numberOfLines={numberOfLines}
159
128
  textContentType={textContentType}
160
129
  style={textInputStyle}
161
- onBlur={() => {
162
- setIsFocused(false);
163
- onBlur?.();
164
- }}
165
- onFocus={() => {
166
- setIsFocused(true);
167
- onFocus?.();
168
- }}
130
+ onBlur={() => { setIsFocused(false); onBlur?.(); }}
131
+ onFocus={() => { setIsFocused(true); onFocus?.(); }}
169
132
  testID={testID ? `${testID}-input` : undefined}
170
133
  />
171
134
 
172
- {(showPasswordToggle && secureTextEntry) && (
135
+ {showPasswordToggle && secureTextEntry && (
173
136
  <InputIcon
174
137
  name={isPasswordVisible ? "eye-off-outline" : "eye-outline"}
175
138
  size={sizeConfig.iconSize}
176
139
  color={iconColor}
177
140
  position="trailing"
178
- onPress={() => togglePasswordVisibility()}
141
+ onPress={togglePasswordVisibility}
179
142
  testID={testID ? `${testID}-toggle-password` : undefined}
180
143
  />
181
144
  )}
182
145
 
183
146
  {trailingIcon && !showPasswordToggle && (
184
147
  <InputIcon
185
- name={trailingIcon }
148
+ name={trailingIcon}
186
149
  size={sizeConfig.iconSize}
187
150
  color={iconColor}
188
151
  position="trailing"
@@ -2,53 +2,12 @@
2
2
  * AtomicPicker Component
3
3
  *
4
4
  * A reusable option picker/dropdown component for selecting from a list of options.
5
- *
6
- * Features:
7
- * - Single and multi-select support
8
- * - Modal display mode (full-screen on mobile)
9
- * - Optional search/filter capability
10
- * - Error and disabled states
11
- * - Theme-aware styling
12
- * - Icons for options
13
- * - Clearable selection
14
- * - react-hook-form integration ready
15
- *
16
- * Architecture:
17
- * - Follows AtomicButton pattern with separated types and styles
18
- * - Uses helper functions from picker/styles/pickerStyles.ts
19
- * - Types defined in picker/types/index.ts
20
- * - Zero inline StyleSheet.create()
21
- *
22
- * Usage:
23
- * ```tsx
24
- * const [partyType, setPartyType] = useState('birthday');
25
- *
26
- * <AtomicPicker
27
- * value={partyType}
28
- * onChange={setPartyType}
29
- * options={[
30
- * { label: 'Birthday Party', value: 'birthday', icon: 'cake' },
31
- * { label: 'Wedding', value: 'wedding', icon: 'heart' },
32
- * { label: 'Corporate Event', value: 'corporate', icon: 'briefcase' },
33
- * ]}
34
- * label="Party Type"
35
- * placeholder="Select party type"
36
- * searchable
37
- * />
38
- * ```
39
- *
40
- * @module AtomicPicker
41
5
  */
42
6
 
43
7
  import React from 'react';
44
- import {
45
- View,
46
- TouchableOpacity,
47
- StyleSheet,
48
- } from 'react-native';
8
+ import { View, TouchableOpacity, StyleSheet } from 'react-native';
49
9
  import { useAppDesignTokens } from '../theme';
50
10
  import { AtomicPickerProps } from './picker/types';
51
-
52
11
  import { AtomicText } from './AtomicText';
53
12
  import { PickerModal } from './picker/components/PickerModal';
54
13
  import { PickerChips } from './picker/components/PickerChips';
@@ -64,12 +23,6 @@ import { usePickerState } from './picker/hooks/usePickerState';
64
23
 
65
24
  export type { AtomicPickerProps, PickerOption, PickerSize } from './picker/types';
66
25
 
67
- /**
68
- * AtomicPicker - Universal option picker component
69
- *
70
- * Displays a button that opens a modal for selection.
71
- * Supports single/multi-select, search, and custom rendering.
72
- */
73
26
  export const AtomicPicker: React.FC<AtomicPickerProps> = ({
74
27
  value,
75
28
  onChange,
@@ -93,70 +46,45 @@ export const AtomicPicker: React.FC<AtomicPickerProps> = ({
93
46
  testID,
94
47
  }) => {
95
48
  const tokens = useAppDesignTokens();
49
+ const pickerState = usePickerState({ value, multiple, options, placeholder, autoClose, onChange });
96
50
 
97
- const pickerState = usePickerState({
98
- value,
99
- multiple,
100
- options,
101
- placeholder,
102
- autoClose,
103
- onChange,
104
- });
105
-
106
- // Get style helpers with design tokens
107
51
  const containerStyles = getPickerContainerStyles(tokens);
108
52
  const labelStyles = getPickerLabelStyles(tokens);
109
53
  const placeholderStyles = getPickerPlaceholderStyles(tokens);
110
54
  const valueStyles = getPickerValueStyles(tokens);
111
55
  const errorStyles = getPickerErrorStyles(tokens);
112
56
 
113
- const pickerContainerStyle = StyleSheet.flatten([
114
- containerStyles.base,
115
- containerStyles.size[size],
116
- error ? containerStyles.state.error : undefined,
117
- disabled ? containerStyles.state.disabled : undefined,
118
- style,
119
- ]);
120
-
121
- const pickerLabelStyle = StyleSheet.flatten([
122
- labelStyles.base,
123
- labelStyles.size[size],
124
- labelStyle,
125
- ]);
126
-
127
- const pickerValueStyle = StyleSheet.flatten([
128
- pickerState.selectedOptions.length > 0 ? valueStyles.base : placeholderStyles.base,
129
- pickerState.selectedOptions.length > 0
130
- ? valueStyles.size[size]
131
- : placeholderStyles.size[size],
132
- ]);
133
-
134
- const handleOpenModal = () => {
135
- if (disabled) return;
136
- pickerState.openModal();
137
- };
57
+ const hasSelection = pickerState.selectedOptions.length > 0;
138
58
 
139
59
  return (
140
60
  <View>
141
- {/* Label */}
142
- {label && <AtomicText style={pickerLabelStyle}>{label}</AtomicText>}
61
+ {label && <AtomicText style={StyleSheet.flatten([labelStyles.base, labelStyles.size[size], labelStyle])}>{label}</AtomicText>}
143
62
 
144
- {/* Picker Button */}
145
63
  <TouchableOpacity
146
- onPress={handleOpenModal}
64
+ onPress={() => !disabled && pickerState.openModal()}
147
65
  disabled={disabled}
148
66
  accessibilityRole="button"
149
67
  accessibilityLabel={label || placeholder}
150
68
  accessibilityState={{ disabled }}
151
69
  testID={testID}
152
- style={pickerContainerStyle}
70
+ style={StyleSheet.flatten([
71
+ containerStyles.base,
72
+ containerStyles.size[size],
73
+ error && containerStyles.state.error,
74
+ disabled && containerStyles.state.disabled,
75
+ style,
76
+ ])}
153
77
  >
154
- {/* Display Text */}
155
- <AtomicText style={pickerValueStyle} numberOfLines={1}>
78
+ <AtomicText
79
+ style={StyleSheet.flatten([
80
+ hasSelection ? valueStyles.base : placeholderStyles.base,
81
+ hasSelection ? valueStyles.size[size] : placeholderStyles.size[size],
82
+ ])}
83
+ numberOfLines={1}
84
+ >
156
85
  {pickerState.displayText}
157
86
  </AtomicText>
158
87
 
159
- {/* Icons */}
160
88
  <PickerIcons
161
89
  clearable={clearable}
162
90
  disabled={disabled}
@@ -168,17 +96,14 @@ export const AtomicPicker: React.FC<AtomicPickerProps> = ({
168
96
  />
169
97
  </TouchableOpacity>
170
98
 
171
- {/* Selected Chips (Multi-select) */}
172
99
  <PickerChips
173
100
  selectedOptions={pickerState.selectedOptions}
174
101
  onRemoveChip={pickerState.handleChipRemove}
175
102
  testID={testID}
176
103
  />
177
104
 
178
- {/* Error Message */}
179
105
  {error && <AtomicText style={errorStyles}>{error}</AtomicText>}
180
106
 
181
- {/* Selection Modal */}
182
107
  <PickerModal
183
108
  visible={pickerState.modalVisible}
184
109
  onClose={pickerState.closeModal}
@@ -7,7 +7,7 @@
7
7
  * Purpose: Empty state indication across all apps
8
8
  */
9
9
 
10
- import React, { useState, useEffect, useCallback, useMemo, useRef, useContext } from 'react';
10
+ import React, { useMemo } from 'react';
11
11
  import { View, StyleSheet, TouchableOpacity, ViewStyle } from 'react-native';
12
12
  import { AtomicIcon } from './icon';
13
13
  import { AtomicText } from './AtomicText';
@@ -122,7 +122,6 @@ export const AtomicIcon: React.FC<AtomicIconProps> = React.memo(
122
122
  // No icon renderer provided - warn in dev and render nothing
123
123
  if (!iconRenderer) {
124
124
  if (__DEV__) {
125
- console.warn(
126
125
  '[DesignSystem] AtomicIcon requires an iconRenderer in DesignSystemProvider.\n' +
127
126
  'Example:\n' +
128
127
  '<DesignSystemProvider\n' +
@@ -75,7 +75,6 @@ export const useIconStore = create<IconStore>((set) => ({
75
75
  if (__DEV__) {
76
76
  const missingKeys = REQUIRED_ICON_KEYS.filter(key => !iconNames[key]);
77
77
  if (missingKeys.length > 0) {
78
- console.error(
79
78
  `[DesignSystem] Missing icon names: ${missingKeys.join(', ')}`
80
79
  );
81
80
  }
@@ -101,7 +100,6 @@ export const useIconName = (key: keyof IconNames): string => {
101
100
 
102
101
  if (!iconNames) {
103
102
  if (__DEV__) {
104
- console.warn(
105
103
  `[DesignSystem] useIconName("${key}") - iconNames not configured.`
106
104
  );
107
105
  }
@@ -1,16 +1,9 @@
1
1
  /**
2
2
  * PickerModal - Selection modal for AtomicPicker
3
- * Handles search, filtering, and option selection.
4
3
  */
5
4
 
6
5
  import React from 'react';
7
- import {
8
- View,
9
- Modal,
10
- FlatList,
11
- TextInput,
12
- TouchableOpacity,
13
- } from 'react-native';
6
+ import { View, Modal, FlatList, TextInput, TouchableOpacity } from 'react-native';
14
7
  import { useSafeAreaInsets } from '../../../safe-area';
15
8
  import { useAppDesignTokens } from '../../../theme';
16
9
  import { PickerOption } from '../types';
@@ -42,9 +35,9 @@ interface PickerModalProps {
42
35
  onSearchChange: (query: string) => void;
43
36
  filteredOptions: PickerOption[];
44
37
  multiple?: boolean;
45
- emptyMessage?: string; // Translated string
46
- searchPlaceholder?: string; // Translated string
47
- closeAccessibilityLabel?: string; // Translated string
38
+ emptyMessage?: string;
39
+ searchPlaceholder?: string;
40
+ closeAccessibilityLabel?: string;
48
41
  testID?: string;
49
42
  }
50
43
 
@@ -65,145 +58,71 @@ export const PickerModal: React.FC<PickerModalProps> = React.memo(({
65
58
  }) => {
66
59
  const tokens = useAppDesignTokens();
67
60
  const insets = useSafeAreaInsets();
68
- const checkCircleIcon = useIconName('checkCircle');
69
- const searchIcon = useIconName('search');
70
- const closeIcon = useIconName('close');
71
- const infoIcon = useIconName('info');
72
-
73
- const modalOverlayStyles = getModalOverlayStyles();
74
- const modalContainerStyles = getModalContainerStyles(tokens, 0);
75
- const modalHeaderStyles = getModalHeaderStyles(tokens);
76
- const modalTitleStyles = getModalTitleStyles(tokens);
77
- const searchContainerStyles = getSearchContainerStyles(tokens);
78
- const searchInputStyles = getSearchInputStyles(tokens);
79
- const emptyStateStyles = getEmptyStateStyles(tokens);
80
- const emptyStateTextStyles = getEmptyStateTextStyles(tokens);
81
-
82
- const safeSelectedValues = selectedValues ?? [];
61
+ const icons = { checkCircle: useIconName('checkCircle'), search: useIconName('search'), close: useIconName('close'), info: useIconName('info') };
83
62
 
84
- const isSelected = (optionValue: string): boolean => {
85
- return safeSelectedValues.includes(optionValue);
63
+ const styles = {
64
+ overlay: getModalOverlayStyles(),
65
+ container: getModalContainerStyles(tokens, 0),
66
+ header: getModalHeaderStyles(tokens),
67
+ title: getModalTitleStyles(tokens),
68
+ search: getSearchContainerStyles(tokens),
69
+ searchInput: getSearchInputStyles(tokens),
70
+ empty: getEmptyStateStyles(tokens),
71
+ emptyText: getEmptyStateTextStyles(tokens),
86
72
  };
87
73
 
74
+ const isSelected = (value: string) => selectedValues?.includes(value) ?? false;
75
+
88
76
  const renderOption = ({ item }: { item: PickerOption }) => {
89
77
  const selected = isSelected(item.value);
90
- const itemDisabled = item.disabled || false;
91
-
92
- const optionContainerStyle = getOptionContainerStyles(
93
- tokens,
94
- selected,
95
- itemDisabled
96
- );
97
- const optionTextStyle = getOptionTextStyles(tokens, selected);
98
- const optionDescriptionStyle = getOptionDescriptionStyles(tokens);
78
+ const disabled = item.disabled || false;
99
79
 
100
80
  return (
101
81
  <TouchableOpacity
102
- onPress={() => !itemDisabled && onSelect(item.value)}
103
- disabled={itemDisabled}
82
+ onPress={() => !disabled && onSelect(item.value)}
83
+ disabled={disabled}
104
84
  testID={item.testID || `${testID}-option-${item.value}`}
105
- style={optionContainerStyle}
85
+ style={getOptionContainerStyles(tokens, selected, disabled)}
106
86
  >
107
- {/* Option Icon */}
108
- {item.icon && (
109
- <AtomicIcon
110
- name={item.icon}
111
- size="md"
112
- color={selected ? 'primary' : 'secondary'}
113
- />
114
- )}
115
-
116
- {/* Option Content */}
87
+ {item.icon && <AtomicIcon name={item.icon} size="md" color={selected ? 'primary' : 'secondary'} />}
117
88
  <View style={{ flex: 1 }}>
118
- <AtomicText style={optionTextStyle}>{item.label}</AtomicText>
119
- {item.description && (
120
- <AtomicText style={optionDescriptionStyle}>
121
- {item.description}
122
- </AtomicText>
123
- )}
89
+ <AtomicText style={getOptionTextStyles(tokens, selected)}>{item.label}</AtomicText>
90
+ {item.description && <AtomicText style={getOptionDescriptionStyles(tokens)}>{item.description}</AtomicText>}
124
91
  </View>
125
-
126
- {/* Selected Indicator */}
127
- {selected && (
128
- <AtomicIcon name={checkCircleIcon} size="md" color="primary" />
129
- )}
92
+ {selected && <AtomicIcon name={icons.checkCircle} size="md" color="primary" />}
130
93
  </TouchableOpacity>
131
94
  );
132
95
  };
133
96
 
134
97
  return (
135
- <Modal
136
- visible={visible}
137
- animationType="none"
138
- transparent
139
- onRequestClose={onClose}
140
- testID={`${testID}-modal`}
141
- >
142
- <View style={modalOverlayStyles}>
143
- <View
144
- style={[
145
- modalContainerStyles,
146
- { paddingBottom: insets.bottom + tokens.spacing.md },
147
- ]}
148
- >
149
- {/* Modal Header */}
150
- <View style={modalHeaderStyles}>
151
- {/* Title */}
152
- <AtomicText style={modalTitleStyles}>
153
- {title || 'Select'}
154
- </AtomicText>
155
-
156
- {/* Close Button */}
157
- <TouchableOpacity
158
- onPress={onClose}
159
- hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
160
- accessibilityRole="button"
161
- accessibilityLabel={closeAccessibilityLabel}
162
- testID={`${testID}-close`}
163
- >
164
- <AtomicIcon name={closeIcon} size="md" color="primary" />
98
+ <Modal visible={visible} animationType="none" transparent onRequestClose={onClose} testID={`${testID}-modal`}>
99
+ <View style={styles.overlay}>
100
+ <View style={[styles.container, { paddingBottom: insets.bottom + tokens.spacing.md }]}>
101
+ <View style={styles.header}>
102
+ <AtomicText style={styles.title}>{title || 'Select'}</AtomicText>
103
+ <TouchableOpacity onPress={onClose} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} accessibilityRole="button" accessibilityLabel={closeAccessibilityLabel} testID={`${testID}-close`}>
104
+ <AtomicIcon name={icons.close} size="md" color="primary" />
165
105
  </TouchableOpacity>
166
106
  </View>
167
107
 
168
- {/* Search Bar */}
169
108
  {searchable && (
170
- <View style={searchContainerStyles}>
171
- <AtomicIcon name={searchIcon} size="sm" color="secondary" />
172
- <TextInput
173
- value={searchQuery}
174
- onChangeText={onSearchChange}
175
- placeholder={searchPlaceholder}
176
- placeholderTextColor={tokens.colors.textSecondary}
177
- style={searchInputStyles}
178
- testID={`${testID}-search`}
179
- />
180
- {searchQuery.length > 0 && (
181
- <TouchableOpacity onPress={() => onSearchChange('')}>
182
- <AtomicIcon name={closeIcon} size="sm" color="secondary" />
183
- </TouchableOpacity>
184
- )}
109
+ <View style={styles.search}>
110
+ <AtomicIcon name={icons.search} size="sm" color="secondary" />
111
+ <TextInput value={searchQuery} onChangeText={onSearchChange} placeholder={searchPlaceholder} placeholderTextColor={tokens.colors.textSecondary} style={styles.searchInput} testID={`${testID}-search`} />
112
+ {searchQuery.length > 0 && <TouchableOpacity onPress={() => onSearchChange('')}><AtomicIcon name={icons.close} size="sm" color="secondary" /></TouchableOpacity>}
185
113
  </View>
186
114
  )}
187
115
 
188
- {/* Options List */}
189
116
  {filteredOptions.length > 0 ? (
190
- <FlatList
191
- data={filteredOptions}
192
- keyExtractor={(item: PickerOption) => item.value}
193
- renderItem={renderOption}
194
- showsVerticalScrollIndicator
195
- testID={`${testID}-list`}
196
- />
117
+ <FlatList data={filteredOptions} keyExtractor={(item: PickerOption) => item.value} renderItem={renderOption} showsVerticalScrollIndicator testID={`${testID}-list`} />
197
118
  ) : (
198
- <View style={emptyStateStyles}>
199
- <AtomicIcon name={infoIcon} size="xl" color="secondary" />
200
- <AtomicText style={emptyStateTextStyles}>
201
- {emptyMessage}
202
- </AtomicText>
119
+ <View style={styles.empty}>
120
+ <AtomicIcon name={icons.info} size="xl" color="secondary" />
121
+ <AtomicText style={styles.emptyText}>{emptyMessage}</AtomicText>
203
122
  </View>
204
123
  )}
205
124
  </View>
206
125
  </View>
207
126
  </Modal>
208
127
  );
209
- });
128
+ });
@@ -43,7 +43,6 @@ export class PersistentDeviceIdService {
43
43
 
44
44
  if (secureId) {
45
45
  if (__DEV__) {
46
- console.log('[PersistentDeviceIdService] Found secure device ID:', secureId);
47
46
  }
48
47
  cachedDeviceId = secureId;
49
48
  return secureId;
@@ -54,14 +53,12 @@ export class PersistentDeviceIdService {
54
53
  await this.secureRepo.set(newId);
55
54
 
56
55
  if (__DEV__) {
57
- console.log('[PersistentDeviceIdService] Created new persistent ID:', newId);
58
56
  }
59
57
 
60
58
  cachedDeviceId = newId;
61
59
  return newId;
62
60
  } catch (error) {
63
61
  if (__DEV__) {
64
- console.error('[PersistentDeviceIdService] Initialization failed, using fallback:', error);
65
62
  }
66
63
  const fallbackId = `fallback_${generateUUID()}`;
67
64
  cachedDeviceId = fallbackId;
@@ -103,7 +100,6 @@ export class PersistentDeviceIdService {
103
100
  cachedDeviceId = null;
104
101
  initializationPromise = null;
105
102
  if (__DEV__) {
106
- console.log('[PersistentDeviceIdService] All device identifiers cleared');
107
103
  }
108
104
  } catch {
109
105
  // Silent fail