@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.7.0",
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
- * Navigate to a route
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 = 1500 } = options;
30
+ const { isAppReady, duration } = options;
19
31
  const [isInitialized, setIsInitialized] = useState(false);
20
32
 
21
33
  useEffect(() => {
22
- const timer = setTimeout(() => {
23
- setIsInitialized(true);
24
- DeviceEventEmitter.emit('splash-ready');
25
- }, duration);
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
- return () => clearTimeout(timer);
28
- }, [duration]);
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
  };