@umituz/react-native-design-system 2.7.0 → 2.8.1
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.
|
|
3
|
+
"version": "2.8.1",
|
|
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, and onboarding utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -37,3 +37,7 @@ export { useTabConfig, type UseTabConfigProps } from "./hooks/useTabConfig";
|
|
|
37
37
|
|
|
38
38
|
// Navigation Theme
|
|
39
39
|
export { createNavigationTheme } from "./utils/NavigationTheme";
|
|
40
|
+
|
|
41
|
+
// Screen Options
|
|
42
|
+
export { createScreenOptions, createCenteredHeaderOptions } from "./utils/createScreenOptions";
|
|
43
|
+
export type { ScreenOptionsParams } from "./utils/createScreenOptions";
|
|
@@ -3,58 +3,47 @@ import { NavigationContainerRef, CommonActions, StackActions } from '@react-navi
|
|
|
3
3
|
export class AppNavigation {
|
|
4
4
|
private static navigationRef: NavigationContainerRef<any> | null = null;
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Set the global navigation reference
|
|
8
|
-
*/
|
|
9
6
|
static setRef(ref: NavigationContainerRef<any> | null): void {
|
|
10
7
|
this.navigationRef = ref;
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
/**
|
|
14
|
-
* Set the global navigation reference (alias for setRef)
|
|
15
11
|
* @deprecated Use setRef instead
|
|
16
12
|
*/
|
|
17
13
|
static setNavigationRef(ref: NavigationContainerRef<any> | null): void {
|
|
18
14
|
this.setRef(ref);
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
/**
|
|
22
|
-
* Get the global navigation reference
|
|
23
|
-
*/
|
|
24
17
|
static getRef(): NavigationContainerRef<any> | null {
|
|
25
18
|
return this.navigationRef;
|
|
26
19
|
}
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
static isReady(): boolean {
|
|
22
|
+
return this.navigationRef?.isReady() ?? false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static canGoBack(): boolean {
|
|
26
|
+
return this.navigationRef?.canGoBack() ?? false;
|
|
27
|
+
}
|
|
28
|
+
|
|
31
29
|
static navigate(name: string, params?: object): void {
|
|
32
30
|
if (this.navigationRef?.isReady()) {
|
|
33
31
|
this.navigationRef.navigate(name, params);
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
/**
|
|
38
|
-
* Push a route onto the stack
|
|
39
|
-
*/
|
|
40
35
|
static push(name: string, params?: object): void {
|
|
41
36
|
if (this.navigationRef?.isReady()) {
|
|
42
37
|
this.navigationRef.dispatch(StackActions.push(name, params));
|
|
43
38
|
}
|
|
44
39
|
}
|
|
45
40
|
|
|
46
|
-
/**
|
|
47
|
-
* Go back to the previous screen
|
|
48
|
-
*/
|
|
49
41
|
static goBack(): void {
|
|
50
42
|
if (this.navigationRef?.isReady() && this.navigationRef.canGoBack()) {
|
|
51
43
|
this.navigationRef.goBack();
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
46
|
|
|
55
|
-
/**
|
|
56
|
-
* Reset the navigation state
|
|
57
|
-
*/
|
|
58
47
|
static reset(name: string, params?: object): void {
|
|
59
48
|
if (this.navigationRef?.isReady()) {
|
|
60
49
|
this.navigationRef.dispatch(
|
|
@@ -66,27 +55,18 @@ export class AppNavigation {
|
|
|
66
55
|
}
|
|
67
56
|
}
|
|
68
57
|
|
|
69
|
-
/**
|
|
70
|
-
* Replace the current route
|
|
71
|
-
*/
|
|
72
58
|
static replace(name: string, params?: object): void {
|
|
73
59
|
if (this.navigationRef?.isReady()) {
|
|
74
60
|
this.navigationRef.dispatch(StackActions.replace(name, params));
|
|
75
61
|
}
|
|
76
62
|
}
|
|
77
63
|
|
|
78
|
-
/**
|
|
79
|
-
* Navigate to a screen in a nested navigator (e.g. Tab > Stack > Screen)
|
|
80
|
-
*/
|
|
81
64
|
static navigateToNested(parentParams: { screen: string; params?: any }): void {
|
|
82
65
|
if (this.navigationRef?.isReady()) {
|
|
83
66
|
this.navigationRef.navigate(parentParams.screen, parentParams.params);
|
|
84
67
|
}
|
|
85
68
|
}
|
|
86
69
|
|
|
87
|
-
/**
|
|
88
|
-
* Navigate to a screen in the parent navigator
|
|
89
|
-
*/
|
|
90
70
|
static navigateToParent(name: string, params?: object): void {
|
|
91
71
|
if (this.navigationRef?.isReady()) {
|
|
92
72
|
const parent = this.navigationRef.getParent();
|
|
@@ -95,4 +75,49 @@ export class AppNavigation {
|
|
|
95
75
|
}
|
|
96
76
|
}
|
|
97
77
|
}
|
|
78
|
+
|
|
79
|
+
static popToTop(): void {
|
|
80
|
+
if (this.navigationRef?.isReady()) {
|
|
81
|
+
this.navigationRef.dispatch(StackActions.popToTop());
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static pop(count: number = 1): void {
|
|
86
|
+
if (this.navigationRef?.isReady()) {
|
|
87
|
+
this.navigationRef.dispatch(StackActions.pop(count));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static getCurrentRoute(): string | undefined {
|
|
92
|
+
return this.navigationRef?.getCurrentRoute()?.name;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static getCurrentParams<T extends object>(): T | undefined {
|
|
96
|
+
return this.navigationRef?.getCurrentRoute()?.params as T | undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static goToSettings(): void {
|
|
100
|
+
this.navigate('Settings');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static goToProfile(): void {
|
|
104
|
+
this.navigate('Profile');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static goToHome(): void {
|
|
108
|
+
this.navigate('Home');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static openModal(name: string, params?: object): void {
|
|
112
|
+
this.navigateToParent(name, params);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static closeModal(): void {
|
|
116
|
+
if (this.navigationRef?.isReady()) {
|
|
117
|
+
const parent = this.navigationRef.getParent();
|
|
118
|
+
if (parent?.canGoBack()) {
|
|
119
|
+
parent.goBack();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
98
123
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screen Options Creator
|
|
3
|
+
* Creates React Navigation screen options with design tokens
|
|
4
|
+
* Used by all packages for consistent navigation headers
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { StackNavigationOptions } from '@react-navigation/stack';
|
|
8
|
+
|
|
9
|
+
export interface ScreenOptionsParams {
|
|
10
|
+
colors: {
|
|
11
|
+
surface: string;
|
|
12
|
+
textPrimary: string;
|
|
13
|
+
borderLight: string;
|
|
14
|
+
};
|
|
15
|
+
backTitle?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates standard screen options for React Navigation
|
|
20
|
+
* @param params - Design tokens and back title
|
|
21
|
+
* @returns React Navigation screen options
|
|
22
|
+
*/
|
|
23
|
+
export const createScreenOptions = (params: ScreenOptionsParams): StackNavigationOptions => {
|
|
24
|
+
const { colors, backTitle } = params;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
headerStyle: {
|
|
28
|
+
backgroundColor: colors.surface,
|
|
29
|
+
borderBottomColor: colors.borderLight,
|
|
30
|
+
borderBottomWidth: 1,
|
|
31
|
+
},
|
|
32
|
+
headerTitleStyle: {
|
|
33
|
+
fontSize: 18,
|
|
34
|
+
fontWeight: '600',
|
|
35
|
+
color: colors.textPrimary,
|
|
36
|
+
},
|
|
37
|
+
headerTintColor: colors.textPrimary,
|
|
38
|
+
...(backTitle && {
|
|
39
|
+
headerBackTitle: backTitle,
|
|
40
|
+
headerBackTitleStyle: {
|
|
41
|
+
fontSize: 16,
|
|
42
|
+
color: colors.textPrimary,
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates screen options for centered header title
|
|
50
|
+
*/
|
|
51
|
+
export const createCenteredHeaderOptions = (
|
|
52
|
+
title: string,
|
|
53
|
+
colors: ScreenOptionsParams['colors']
|
|
54
|
+
): StackNavigationOptions => ({
|
|
55
|
+
headerShown: true,
|
|
56
|
+
headerTitle: title,
|
|
57
|
+
headerTitleAlign: 'center',
|
|
58
|
+
headerStyle: {
|
|
59
|
+
backgroundColor: colors.surface,
|
|
60
|
+
borderBottomColor: colors.borderLight,
|
|
61
|
+
borderBottomWidth: 1,
|
|
62
|
+
},
|
|
63
|
+
headerTitleStyle: {
|
|
64
|
+
fontSize: 18,
|
|
65
|
+
fontWeight: '600',
|
|
66
|
+
color: colors.textPrimary,
|
|
67
|
+
},
|
|
68
|
+
headerTintColor: colors.textPrimary,
|
|
69
|
+
});
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Splash Flow Hook
|
|
3
3
|
* Manages splash screen initialization state
|
|
4
|
+
*
|
|
5
|
+
* IMPORTANT: Use isAppReady prop instead of duration for real initialization tracking.
|
|
6
|
+
* Artificial delays cause poor UX - the splash should transition as soon as app is ready.
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
import { useState, useEffect } from 'react';
|
|
7
10
|
import { DeviceEventEmitter } from 'react-native';
|
|
8
11
|
|
|
9
12
|
export interface UseSplashFlowOptions {
|
|
13
|
+
/**
|
|
14
|
+
* External readiness signal from app initialization
|
|
15
|
+
* When true, splash will transition to main content
|
|
16
|
+
*/
|
|
17
|
+
isAppReady?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated Use isAppReady instead. Artificial delays cause poor UX.
|
|
20
|
+
* Only use for fallback/timeout scenarios.
|
|
21
|
+
*/
|
|
10
22
|
duration?: number;
|
|
11
23
|
}
|
|
12
24
|
|
|
@@ -15,17 +27,31 @@ export interface UseSplashFlowResult {
|
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
export const useSplashFlow = (options: UseSplashFlowOptions = {}): UseSplashFlowResult => {
|
|
18
|
-
const { duration
|
|
30
|
+
const { isAppReady, duration } = options;
|
|
19
31
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
20
32
|
|
|
21
33
|
useEffect(() => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
// Primary: Use external app ready signal (preferred)
|
|
35
|
+
if (isAppReady !== undefined) {
|
|
36
|
+
if (isAppReady && !isInitialized) {
|
|
37
|
+
setIsInitialized(true);
|
|
38
|
+
DeviceEventEmitter.emit('splash-ready');
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
26
42
|
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
// Fallback: Use duration timer if isAppReady not provided (legacy support)
|
|
44
|
+
if (duration !== undefined) {
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
setIsInitialized(true);
|
|
47
|
+
DeviceEventEmitter.emit('splash-ready');
|
|
48
|
+
}, duration);
|
|
49
|
+
|
|
50
|
+
return () => clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return undefined;
|
|
54
|
+
}, [isAppReady, duration, isInitialized]);
|
|
29
55
|
|
|
30
56
|
return { isInitialized };
|
|
31
57
|
};
|