@umituz/react-native-design-system 4.23.103 → 4.23.105
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/image/presentation/hooks/useImageGallery.ts +18 -11
- package/src/molecules/calendar/presentation/hooks/useCalendar.ts +9 -3
- package/src/onboarding/infrastructure/hooks/useOnboardingNavigation.ts +14 -8
- package/src/onboarding/presentation/hooks/useOnboardingGestures.ts +22 -1
- package/src/tanstack/presentation/hooks/usePrefetch.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.105",
|
|
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",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Presentation - Image Gallery Hook
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { useState, useCallback, useMemo } from 'react';
|
|
5
|
+
import { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
|
6
6
|
import { ImageViewerService } from '../../infrastructure/services/ImageViewerService';
|
|
7
7
|
import type {
|
|
8
8
|
ImageViewerItem,
|
|
@@ -29,6 +29,13 @@ export const useImageGallery = (
|
|
|
29
29
|
defaultOptions || ImageViewerService.getDefaultOptions()
|
|
30
30
|
);
|
|
31
31
|
|
|
32
|
+
// Use ref to track latest options and avoid stale closures
|
|
33
|
+
const optionsRef = useRef(galleryOptions);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
optionsRef.current = galleryOptions;
|
|
37
|
+
}, [galleryOptions]);
|
|
38
|
+
|
|
32
39
|
const open = useCallback(
|
|
33
40
|
(
|
|
34
41
|
imageData: ImageViewerItem[] | string[],
|
|
@@ -44,32 +51,32 @@ export const useImageGallery = (
|
|
|
44
51
|
setCurrentIndex(options?.index ?? startIndex);
|
|
45
52
|
|
|
46
53
|
if (options) {
|
|
47
|
-
setGalleryOptions({
|
|
48
|
-
...
|
|
54
|
+
setGalleryOptions(prev => ({
|
|
55
|
+
...prev,
|
|
49
56
|
...options,
|
|
50
|
-
});
|
|
57
|
+
}));
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
setVisible(true);
|
|
54
61
|
},
|
|
55
|
-
[
|
|
62
|
+
[]
|
|
56
63
|
);
|
|
57
64
|
|
|
58
65
|
const close = useCallback(() => {
|
|
59
66
|
setVisible(false);
|
|
60
67
|
|
|
61
|
-
if (
|
|
62
|
-
|
|
68
|
+
if (optionsRef.current.onDismiss) {
|
|
69
|
+
optionsRef.current.onDismiss();
|
|
63
70
|
}
|
|
64
|
-
}, [
|
|
71
|
+
}, []);
|
|
65
72
|
|
|
66
73
|
const setIndex = useCallback((index: number) => {
|
|
67
74
|
setCurrentIndex(index);
|
|
68
75
|
|
|
69
|
-
if (
|
|
70
|
-
|
|
76
|
+
if (optionsRef.current.onIndexChange) {
|
|
77
|
+
optionsRef.current.onIndexChange(index);
|
|
71
78
|
}
|
|
72
|
-
}, [
|
|
79
|
+
}, []);
|
|
73
80
|
|
|
74
81
|
const options = useMemo(() => ({
|
|
75
82
|
backgroundColor: galleryOptions.backgroundColor || '#000000',
|
|
@@ -88,18 +88,24 @@ export const useCalendarPresentation = (): UseCalendarReturn => {
|
|
|
88
88
|
// Load events on mount
|
|
89
89
|
useEffect(() => {
|
|
90
90
|
actions.loadEvents();
|
|
91
|
-
}, []);
|
|
91
|
+
}, [actions.loadEvents]);
|
|
92
92
|
|
|
93
93
|
// Get events for selected date
|
|
94
94
|
const selectedDateEvents = useMemo(() => {
|
|
95
|
-
return
|
|
95
|
+
return events.filter(event => {
|
|
96
|
+
const eventDate = new Date(event.date);
|
|
97
|
+
return eventDate.toDateString() === selectedDate.toDateString();
|
|
98
|
+
});
|
|
96
99
|
}, [selectedDate, events]);
|
|
97
100
|
|
|
98
101
|
// Get events for current month
|
|
99
102
|
const currentMonthEvents = useMemo(() => {
|
|
100
103
|
const year = currentMonth.getFullYear();
|
|
101
104
|
const month = currentMonth.getMonth();
|
|
102
|
-
return
|
|
105
|
+
return events.filter(event => {
|
|
106
|
+
const eventDate = new Date(event.date);
|
|
107
|
+
return eventDate.getFullYear() === year && eventDate.getMonth() === month;
|
|
108
|
+
});
|
|
103
109
|
}, [currentMonth, events]);
|
|
104
110
|
|
|
105
111
|
return {
|
|
@@ -33,16 +33,22 @@ export const useOnboardingNavigation = (
|
|
|
33
33
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
34
34
|
|
|
35
35
|
const goToNext = useCallback(() => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
setCurrentIndex(prev => {
|
|
37
|
+
if (prev < totalSlides - 1) {
|
|
38
|
+
return prev + 1;
|
|
39
|
+
}
|
|
40
|
+
return prev;
|
|
41
|
+
});
|
|
42
|
+
}, [totalSlides]);
|
|
40
43
|
|
|
41
44
|
const goToPrevious = useCallback(() => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
setCurrentIndex(prev => {
|
|
46
|
+
if (prev > 0) {
|
|
47
|
+
return prev - 1;
|
|
48
|
+
}
|
|
49
|
+
return prev;
|
|
50
|
+
});
|
|
51
|
+
}, []);
|
|
46
52
|
|
|
47
53
|
const complete = useCallback(async () => {
|
|
48
54
|
if (onComplete) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Handles swipe gestures for onboarding navigation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useRef } from "react";
|
|
6
|
+
import { useRef, useEffect } from "react";
|
|
7
7
|
import { PanResponder } from "react-native";
|
|
8
8
|
|
|
9
9
|
interface UseOnboardingGesturesProps {
|
|
@@ -19,6 +19,24 @@ export const useOnboardingGestures = ({
|
|
|
19
19
|
onNext,
|
|
20
20
|
onBack,
|
|
21
21
|
}: UseOnboardingGesturesProps) => {
|
|
22
|
+
// Use refs to track latest values and avoid stale closures
|
|
23
|
+
const latestPropsRef = useRef({
|
|
24
|
+
isFirstSlide,
|
|
25
|
+
isAnswerValid,
|
|
26
|
+
onNext,
|
|
27
|
+
onBack,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Update refs on every render to ensure PanResponder has fresh values
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
latestPropsRef.current = {
|
|
33
|
+
isFirstSlide,
|
|
34
|
+
isAnswerValid,
|
|
35
|
+
onNext,
|
|
36
|
+
onBack,
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
22
40
|
const panResponder = useRef(
|
|
23
41
|
PanResponder.create({
|
|
24
42
|
onMoveShouldSetPanResponder: (_, gestureState) => {
|
|
@@ -26,6 +44,9 @@ export const useOnboardingGestures = ({
|
|
|
26
44
|
return Math.abs(gestureState.dx) > 20 && Math.abs(gestureState.dy) < 40;
|
|
27
45
|
},
|
|
28
46
|
onPanResponderRelease: (_, gestureState) => {
|
|
47
|
+
// Read from ref to get latest values
|
|
48
|
+
const { isFirstSlide, isAnswerValid, onNext, onBack } = latestPropsRef.current;
|
|
49
|
+
|
|
29
50
|
if (gestureState.dx > 50) {
|
|
30
51
|
// Swipe Right -> Previous
|
|
31
52
|
if (!isFirstSlide) {
|
|
@@ -86,8 +86,12 @@ export function usePrefetchOnMount<TData = unknown>(
|
|
|
86
86
|
options: PrefetchOptions = {},
|
|
87
87
|
) {
|
|
88
88
|
const queryClient = useQueryClient();
|
|
89
|
+
const hasPrefetchedRef = useRef(false);
|
|
89
90
|
|
|
90
91
|
useEffect(() => {
|
|
92
|
+
if (hasPrefetchedRef.current) return;
|
|
93
|
+
|
|
94
|
+
hasPrefetchedRef.current = true;
|
|
91
95
|
queryClient.prefetchQuery({
|
|
92
96
|
queryKey,
|
|
93
97
|
queryFn,
|