@umituz/react-native-design-system 2.11.2 → 2.11.4
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/AtomicFab.tsx +1 -1
- package/src/atoms/EmptyState.tsx +1 -1
- package/src/atoms/{AtomicBadge.tsx → badge/AtomicBadge.tsx} +3 -3
- package/src/atoms/badge/index.ts +6 -0
- package/src/atoms/button/AtomicButton.tsx +1 -1
- package/src/atoms/button/types/index.ts +1 -1
- package/src/atoms/card/AtomicCard.tsx +3 -2
- package/src/atoms/chip/AtomicChip.tsx +1 -1
- package/src/atoms/chip/types/index.ts +1 -1
- package/src/atoms/datepicker/components/DatePickerButton.tsx +3 -2
- package/src/atoms/{AtomicIcon.tsx → icon/AtomicIcon.tsx} +2 -2
- package/src/atoms/icon/iconStore.ts +119 -0
- package/src/atoms/icon/index.ts +35 -0
- package/src/atoms/index.ts +14 -9
- package/src/atoms/input/components/InputIcon.tsx +1 -1
- package/src/atoms/input/types.ts +1 -1
- package/src/atoms/picker/components/PickerChips.tsx +3 -2
- package/src/atoms/picker/components/PickerIcons.tsx +6 -3
- package/src/atoms/picker/components/PickerModal.tsx +10 -6
- package/src/atoms/picker/types/index.ts +1 -1
- package/src/exception/presentation/components/ExceptionErrorState.tsx +7 -3
- package/src/exports/atoms.ts +6 -3
- package/src/image/presentation/components/editor/FilterPickerSheet.tsx +6 -5
- package/src/image/presentation/components/editor/TextEditorSheet.tsx +1 -1
- package/src/image/presentation/components/editor/TextEditorTabs.tsx +1 -2
- package/src/media/infrastructure/services/MediaSaveService.ts +1 -2
- package/src/molecules/SearchBar/SearchBar.tsx +5 -3
- package/src/molecules/SearchBar/SearchHistory.tsx +5 -3
- package/src/molecules/action-footer/ActionFooter.tsx +1 -1
- package/src/molecules/alerts/AlertBanner.tsx +3 -2
- package/src/molecules/alerts/AlertToast.tsx +3 -2
- package/src/molecules/bottom-sheet/components/filter/FilterBottomSheet.tsx +5 -3
- package/src/molecules/bottom-sheet/components/filter/FilterSheetComponents/FilterSheetHeader.tsx +13 -9
- package/src/molecules/bottom-sheet/components/filter/FilterSheetComponents/FilterSheetOption.tsx +8 -4
- package/src/molecules/circular-menu/CircularMenuCloseButton.tsx +3 -2
- package/src/molecules/countdown/components/Countdown.tsx +1 -1
- package/src/molecules/countdown/components/CountdownHeader.tsx +4 -3
- package/src/molecules/info-grid/InfoGrid.tsx +1 -1
- package/src/molecules/navigation/components/NavigationHeader.tsx +3 -2
- package/src/molecules/navigation/hooks/useTabConfig.ts +1 -1
- package/src/molecules/navigation/types.ts +1 -1
- package/src/molecules/navigation/utils/IconRenderer.ts +1 -2
- package/src/onboarding/presentation/components/OnboardingHeader.tsx +3 -2
- package/src/onboarding/presentation/components/OnboardingResetSetting.tsx +1 -2
- package/src/onboarding/presentation/components/OnboardingSlide.tsx +3 -2
- package/src/onboarding/presentation/components/QuestionSlideHeader.tsx +1 -2
- package/src/onboarding/presentation/components/questions/QuestionOptionItem.tsx +1 -2
- package/src/onboarding/presentation/components/questions/RatingQuestion.tsx +1 -2
- package/src/onboarding/presentation/components/questions/SingleChoiceQuestion.tsx +1 -2
- package/src/theme/core/TokenFactory.ts +1 -1
- package/src/theme/index.ts +1 -1
- package/src/theme/infrastructure/providers/DesignSystemProvider.tsx +15 -85
- package/src/atoms/IconRegistry.tsx +0 -102
- /package/src/atoms/{AtomicIcon.types.ts → icon/AtomicIcon.types.ts} +0 -0
|
@@ -8,71 +8,29 @@ import { useDesignSystemTheme, type ThemeMode } from '../globalThemeStore';
|
|
|
8
8
|
import type { CustomThemeColors } from '../../core/CustomColors';
|
|
9
9
|
import { SplashScreen } from '../../../molecules/splash';
|
|
10
10
|
import type { SplashScreenProps } from '../../../molecules/splash/types';
|
|
11
|
-
import {
|
|
11
|
+
import { useIconStore, type IconRenderer, type IconNames } from '../../../atoms/icon';
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
interface DesignSystemProviderProps {
|
|
15
|
-
/** App content */
|
|
16
15
|
children: ReactNode;
|
|
17
|
-
/**
|
|
18
|
-
* Custom theme colors to override defaults
|
|
19
|
-
* Apps can override ANY color key from the palette
|
|
20
|
-
* @example
|
|
21
|
-
* customColors={{
|
|
22
|
-
* primary: '#FF6B6B',
|
|
23
|
-
* onPrimary: '#FFFFFF',
|
|
24
|
-
* backgroundPrimary: '#FFFFFF',
|
|
25
|
-
* textPrimary: '#1A1A1A',
|
|
26
|
-
* }}
|
|
27
|
-
*/
|
|
28
16
|
customColors?: CustomThemeColors;
|
|
29
|
-
/**
|
|
30
|
-
* Initial theme mode for the app
|
|
31
|
-
* Apps control whether they start in light or dark mode
|
|
32
|
-
* @default 'light'
|
|
33
|
-
*/
|
|
34
17
|
initialThemeMode?: ThemeMode;
|
|
35
|
-
/** Custom fonts to load (name -> source map) */
|
|
36
18
|
fonts?: Record<string, any>;
|
|
37
|
-
/** Show loading indicator while initializing (default: true) */
|
|
38
19
|
showLoadingIndicator?: boolean;
|
|
39
|
-
/** Splash screen configuration (used when showLoadingIndicator is true) */
|
|
40
20
|
splashConfig?: Pick<SplashScreenProps, 'appName' | 'tagline' | 'icon' | 'colors'>;
|
|
41
|
-
/** Custom loading component (overrides splash screen) */
|
|
42
21
|
loadingComponent?: ReactNode;
|
|
43
|
-
/** Callback when initialization completes */
|
|
44
22
|
onInitialized?: () => void;
|
|
45
|
-
/** Callback when initialization fails */
|
|
46
23
|
onError?: (error: unknown) => void;
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
* iconRenderer={({ name, size, color }) => (
|
|
52
|
-
* <LucideIcons name={name} size={size} color={color} />
|
|
53
|
-
* )}
|
|
54
|
-
*/
|
|
55
|
-
iconRenderer?: IconRenderer;
|
|
24
|
+
/** Icon renderer - REQUIRED */
|
|
25
|
+
iconRenderer: IconRenderer;
|
|
26
|
+
/** Icon names mapping - REQUIRED */
|
|
27
|
+
iconNames: IconNames;
|
|
56
28
|
}
|
|
57
29
|
|
|
58
|
-
/**
|
|
59
|
-
* DesignSystemProvider
|
|
60
|
-
*
|
|
61
|
-
* Main provider for the design system. Wraps your app and provides:
|
|
62
|
-
* - Theme (colors, spacing, typography)
|
|
63
|
-
* - Custom icon rendering
|
|
64
|
-
* - Safe area handling
|
|
65
|
-
* - Gesture handling
|
|
66
|
-
*
|
|
67
|
-
* ARCHITECTURE (based on Shopify Restyle, React Native Paper, Tamagui):
|
|
68
|
-
* - Apps provide customColors to override default palette
|
|
69
|
-
* - Apps set initialThemeMode to control light/dark mode
|
|
70
|
-
* - All design system components use these values via useAppDesignTokens
|
|
71
|
-
*/
|
|
72
30
|
export const DesignSystemProvider: React.FC<DesignSystemProviderProps> = ({
|
|
73
31
|
children,
|
|
74
32
|
customColors,
|
|
75
|
-
initialThemeMode = 'light',
|
|
33
|
+
initialThemeMode = 'light',
|
|
76
34
|
fonts,
|
|
77
35
|
showLoadingIndicator = true,
|
|
78
36
|
splashConfig,
|
|
@@ -80,75 +38,54 @@ export const DesignSystemProvider: React.FC<DesignSystemProviderProps> = ({
|
|
|
80
38
|
onInitialized,
|
|
81
39
|
onError,
|
|
82
40
|
iconRenderer,
|
|
83
|
-
|
|
41
|
+
iconNames,
|
|
42
|
+
}) => {
|
|
84
43
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
85
|
-
|
|
86
|
-
// Load fonts if provided
|
|
87
44
|
const [fontsLoaded, fontError] = fonts ? useFonts(fonts) : [true, null];
|
|
88
45
|
|
|
89
46
|
const initialize = useThemeStore((state) => state.initialize);
|
|
90
47
|
const setThemeMode = useThemeStore((state) => state.setThemeMode);
|
|
91
48
|
const setCustomColors = useDesignSystemTheme((state) => state.setCustomColors);
|
|
92
49
|
const setGlobalThemeMode = useDesignSystemTheme((state) => state.setThemeMode);
|
|
50
|
+
const setIconConfig = useIconStore((state) => state.setConfig);
|
|
93
51
|
|
|
94
52
|
useEffect(() => {
|
|
95
|
-
//
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
'[DesignSystem] ⚠️ customColors is REQUIRED!\n' +
|
|
99
|
-
'Your app must provide theme colors to DesignSystemProvider.\n' +
|
|
100
|
-
'Example:\n' +
|
|
101
|
-
'<DesignSystemProvider\n' +
|
|
102
|
-
' customColors={{\n' +
|
|
103
|
-
' primary: "#FF6B6B",\n' +
|
|
104
|
-
' onPrimary: "#FFFFFF",\n' +
|
|
105
|
-
' backgroundPrimary: "#FFFFFF",\n' +
|
|
106
|
-
' textPrimary: "#1A1A1A",\n' +
|
|
107
|
-
' }}\n' +
|
|
108
|
-
' initialThemeMode="light"\n' +
|
|
109
|
-
'>'
|
|
110
|
-
);
|
|
53
|
+
// Set icon config (required)
|
|
54
|
+
if (iconRenderer && iconNames) {
|
|
55
|
+
setIconConfig(iconNames, iconRenderer);
|
|
111
56
|
}
|
|
112
57
|
|
|
113
|
-
// Apply custom colors if provided
|
|
114
58
|
if (customColors) {
|
|
115
59
|
setCustomColors(customColors);
|
|
116
60
|
}
|
|
117
61
|
|
|
118
|
-
// Set initial theme mode from app
|
|
119
62
|
setGlobalThemeMode(initialThemeMode);
|
|
120
63
|
|
|
121
|
-
// Initialize theme store with the initial theme mode
|
|
122
64
|
initialize()
|
|
123
65
|
.then(async () => {
|
|
124
|
-
// After initialization, set the theme mode from app config
|
|
125
66
|
await setThemeMode(initialThemeMode);
|
|
126
67
|
setIsInitialized(true);
|
|
127
68
|
})
|
|
128
69
|
.catch((error) => {
|
|
129
|
-
setIsInitialized(true);
|
|
70
|
+
setIsInitialized(true);
|
|
130
71
|
onError?.(error);
|
|
131
72
|
});
|
|
132
|
-
}, [initialize, customColors, initialThemeMode, setCustomColors, setGlobalThemeMode, setThemeMode, onError]);
|
|
73
|
+
}, [initialize, customColors, iconNames, iconRenderer, initialThemeMode, setCustomColors, setGlobalThemeMode, setThemeMode, setIconConfig, onError]);
|
|
133
74
|
|
|
134
|
-
// Handle initialization completion when both theme and fonts are ready
|
|
135
75
|
useEffect(() => {
|
|
136
76
|
if (isInitialized && fontsLoaded) {
|
|
137
77
|
onInitialized?.();
|
|
138
78
|
}
|
|
139
79
|
}, [isInitialized, fontsLoaded, onInitialized]);
|
|
140
80
|
|
|
141
|
-
// Handle font errors
|
|
142
81
|
useEffect(() => {
|
|
143
82
|
if (fontError) {
|
|
144
83
|
onError?.(fontError);
|
|
145
84
|
}
|
|
146
85
|
}, [fontError, onError]);
|
|
147
86
|
|
|
148
|
-
// Determine if we should show loading state
|
|
149
87
|
const isLoading = showLoadingIndicator && (!isInitialized || !fontsLoaded);
|
|
150
88
|
|
|
151
|
-
// Determine content to render based on loading state
|
|
152
89
|
let content: ReactNode;
|
|
153
90
|
|
|
154
91
|
if (isLoading) {
|
|
@@ -167,17 +104,10 @@ export const DesignSystemProvider: React.FC<DesignSystemProviderProps> = ({
|
|
|
167
104
|
content = children;
|
|
168
105
|
}
|
|
169
106
|
|
|
170
|
-
// Wrap with IconProvider if custom renderer provided
|
|
171
|
-
const wrappedContent = iconRenderer ? (
|
|
172
|
-
<IconProvider renderIcon={iconRenderer}>{content}</IconProvider>
|
|
173
|
-
) : (
|
|
174
|
-
content
|
|
175
|
-
);
|
|
176
|
-
|
|
177
107
|
return (
|
|
178
108
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
179
109
|
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
|
180
|
-
{
|
|
110
|
+
{content}
|
|
181
111
|
</SafeAreaProvider>
|
|
182
112
|
</GestureHandlerRootView>
|
|
183
113
|
);
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IconRegistry - Customizable Icon Rendering
|
|
3
|
-
*
|
|
4
|
-
* Allows apps to inject their own icon renderer instead of using
|
|
5
|
-
* the default Ionicons. This enables design system adoption without
|
|
6
|
-
* forcing a specific icon library.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* // App provides custom renderer
|
|
10
|
-
* import { MaterialIcons } from '@expo/vector-icons';
|
|
11
|
-
*
|
|
12
|
-
* const myRenderer = ({ name, size, color }) => (
|
|
13
|
-
* <MaterialIcons name={name} size={size} color={color} />
|
|
14
|
-
* );
|
|
15
|
-
*
|
|
16
|
-
* <DesignSystemProvider iconRenderer={myRenderer}>
|
|
17
|
-
* <App />
|
|
18
|
-
* </DesignSystemProvider>
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
import React, { createContext, useContext, ReactNode } from "react";
|
|
22
|
-
import type { StyleProp, ViewStyle } from "react-native";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Props passed to the icon renderer function
|
|
26
|
-
* These are generic and not tied to any specific icon library
|
|
27
|
-
*/
|
|
28
|
-
export interface IconRenderProps {
|
|
29
|
-
/** Icon name - app interprets this based on their icon library */
|
|
30
|
-
name: string;
|
|
31
|
-
/** Size in pixels */
|
|
32
|
-
size: number;
|
|
33
|
-
/** Color (hex, rgba, named color, etc.) */
|
|
34
|
-
color: string;
|
|
35
|
-
/** Optional style */
|
|
36
|
-
style?: StyleProp<ViewStyle>;
|
|
37
|
-
/** Test ID for testing */
|
|
38
|
-
testID?: string;
|
|
39
|
-
/** Accessibility label */
|
|
40
|
-
accessibilityLabel?: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Icon renderer function type
|
|
45
|
-
* Apps provide this function to render icons with their preferred library
|
|
46
|
-
*/
|
|
47
|
-
export type IconRenderer = (props: IconRenderProps) => ReactNode;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Internal registry store
|
|
51
|
-
*/
|
|
52
|
-
interface IconRegistryValue {
|
|
53
|
-
renderIcon: IconRenderer;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const IconRegistryStore = createContext<IconRegistryValue | null>(null);
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Icon provider props
|
|
60
|
-
*/
|
|
61
|
-
interface IconProviderProps {
|
|
62
|
-
/** Icon renderer function */
|
|
63
|
-
renderIcon: IconRenderer;
|
|
64
|
-
/** Children */
|
|
65
|
-
children: ReactNode;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* IconProvider - Provides custom icon renderer to the component tree
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* <IconProvider renderIcon={myCustomRenderer}>
|
|
73
|
-
* <App />
|
|
74
|
-
* </IconProvider>
|
|
75
|
-
*/
|
|
76
|
-
export const IconProvider: React.FC<IconProviderProps> = ({
|
|
77
|
-
renderIcon,
|
|
78
|
-
children,
|
|
79
|
-
}) => {
|
|
80
|
-
return (
|
|
81
|
-
<IconRegistryStore.Provider value={{ renderIcon }}>
|
|
82
|
-
{children}
|
|
83
|
-
</IconRegistryStore.Provider>
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Hook to access the icon renderer
|
|
89
|
-
* Returns null if no custom renderer is provided (fallback to Ionicons)
|
|
90
|
-
*/
|
|
91
|
-
export const useIconRenderer = (): IconRenderer | null => {
|
|
92
|
-
const registry = useContext(IconRegistryStore);
|
|
93
|
-
return registry?.renderIcon ?? null;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Hook to check if a custom icon renderer is available
|
|
98
|
-
*/
|
|
99
|
-
export const useHasCustomIconRenderer = (): boolean => {
|
|
100
|
-
const registry = useContext(IconRegistryStore);
|
|
101
|
-
return registry !== null;
|
|
102
|
-
};
|
|
File without changes
|