@umituz/react-native-design-system 2.6.47 → 2.6.49
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/skeleton/AtomicSkeleton.tsx +16 -62
- package/src/index.ts +0 -32
- package/src/molecules/bottom-sheet/components/BottomSheetModal.tsx +101 -180
- package/src/molecules/bottom-sheet/components/SafeBottomSheetModalProvider.tsx +8 -14
- package/src/molecules/index.ts +0 -6
- package/src/molecules/animation/core/AnimationCore.ts +0 -29
- package/src/molecules/animation/domain/entities/Animation.ts +0 -81
- package/src/molecules/animation/domain/entities/Fireworks.ts +0 -44
- package/src/molecules/animation/domain/entities/Theme.ts +0 -76
- package/src/molecules/animation/index.ts +0 -146
- package/src/molecules/animation/infrastructure/services/AnimationConfigService.ts +0 -35
- package/src/molecules/animation/infrastructure/services/SpringAnimationConfigService.ts +0 -67
- package/src/molecules/animation/infrastructure/services/TimingAnimationConfigService.ts +0 -57
- package/src/molecules/animation/infrastructure/services/__tests__/SpringAnimationConfigService.test.ts +0 -114
- package/src/molecules/animation/infrastructure/services/__tests__/TimingAnimationConfigService.test.ts +0 -105
- package/src/molecules/animation/presentation/components/Fireworks.tsx +0 -127
- package/src/molecules/animation/presentation/components/__tests__/Fireworks.test.tsx +0 -185
- package/src/molecules/animation/presentation/hooks/__tests__/useAnimation.integration.test.ts +0 -210
- package/src/molecules/animation/presentation/hooks/__tests__/useFireworks.test.ts +0 -242
- package/src/molecules/animation/presentation/hooks/__tests__/useGesture.test.ts +0 -108
- package/src/molecules/animation/presentation/hooks/__tests__/useSpringAnimation.test.ts +0 -127
- package/src/molecules/animation/presentation/hooks/__tests__/useTimingAnimation.test.ts +0 -172
- package/src/molecules/animation/presentation/hooks/__tests__/useTransformAnimation.test.ts +0 -133
- package/src/molecules/animation/presentation/hooks/useAnimation.ts +0 -77
- package/src/molecules/animation/presentation/hooks/useFireworks.ts +0 -144
- package/src/molecules/animation/presentation/hooks/useGesture.ts +0 -57
- package/src/molecules/animation/presentation/hooks/useGestureCreators.ts +0 -163
- package/src/molecules/animation/presentation/hooks/useGestureState.ts +0 -53
- package/src/molecules/animation/presentation/hooks/useIconAnimations.ts +0 -120
- package/src/molecules/animation/presentation/hooks/useModalAnimations.ts +0 -124
- package/src/molecules/animation/presentation/hooks/useReanimatedReady.ts +0 -60
- package/src/molecules/animation/presentation/hooks/useSpringAnimation.ts +0 -69
- package/src/molecules/animation/presentation/hooks/useTimingAnimation.ts +0 -111
- package/src/molecules/animation/presentation/hooks/useTransformAnimation.ts +0 -57
- package/src/molecules/animation/presentation/providers/AnimationThemeProvider.tsx +0 -60
- package/src/molecules/animation/presentation/providers/__tests__/AnimationThemeProvider.test.tsx +0 -165
- package/src/molecules/celebration/domain/entities/CelebrationConfig.ts +0 -17
- package/src/molecules/celebration/domain/entities/FireworksConfig.ts +0 -32
- package/src/molecules/celebration/index.ts +0 -93
- package/src/molecules/celebration/infrastructure/services/FireworksConfigService.ts +0 -49
- package/src/molecules/celebration/presentation/components/CelebrationFireworksOverlay.tsx +0 -33
- package/src/molecules/celebration/presentation/components/CelebrationModal.tsx +0 -81
- package/src/molecules/celebration/presentation/components/CelebrationModalContent.tsx +0 -88
- package/src/molecules/celebration/presentation/hooks/useCelebrationModalAnimation.ts +0 -49
- package/src/molecules/celebration/presentation/hooks/useCelebrationState.ts +0 -45
- package/src/molecules/celebration/presentation/styles/CelebrationModalStyles.ts +0 -65
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useElementAnimations Hook
|
|
3
|
-
* Single Responsibility: Manage element scale and rotate animations
|
|
4
|
-
* Generic implementation for any UI element (icons, buttons, etc.)
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useEffect, useMemo } from "react";
|
|
8
|
-
import { useAnimatedStyle, withTiming, withSequence, Easing } from "react-native-reanimated";
|
|
9
|
-
import { useTransformAnimation } from "./useTransformAnimation";
|
|
10
|
-
|
|
11
|
-
export interface ElementAnimationConfig {
|
|
12
|
-
scaleMax?: number;
|
|
13
|
-
scaleBounceMax?: number; // Alias for scaleMax
|
|
14
|
-
scaleMin?: number;
|
|
15
|
-
rotateDegrees?: number;
|
|
16
|
-
delay?: number;
|
|
17
|
-
scaleDuration?: number;
|
|
18
|
-
rotateDuration?: number;
|
|
19
|
-
resetOnHide?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const DEFAULT_ELEMENT_ANIMATION_CONFIG: Required<ElementAnimationConfig> = {
|
|
23
|
-
scaleMax: 1.2,
|
|
24
|
-
scaleBounceMax: 1.2,
|
|
25
|
-
scaleMin: 1,
|
|
26
|
-
rotateDegrees: 360,
|
|
27
|
-
delay: 200,
|
|
28
|
-
scaleDuration: 300,
|
|
29
|
-
rotateDuration: 500,
|
|
30
|
-
resetOnHide: true,
|
|
31
|
-
} as const;
|
|
32
|
-
|
|
33
|
-
export interface UseElementAnimationsReturn {
|
|
34
|
-
elementStyle: ReturnType<typeof useAnimatedStyle>;
|
|
35
|
-
iconStyle: ReturnType<typeof useAnimatedStyle>; // Alias for elementStyle
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Hook for managing element animations
|
|
40
|
-
* Generic implementation suitable for icons, buttons, badges, etc.
|
|
41
|
-
*/
|
|
42
|
-
export function useElementAnimations(
|
|
43
|
-
visible: boolean,
|
|
44
|
-
isReanimatedReady: boolean,
|
|
45
|
-
config?: ElementAnimationConfig,
|
|
46
|
-
): UseElementAnimationsReturn {
|
|
47
|
-
const transform = useTransformAnimation();
|
|
48
|
-
|
|
49
|
-
const animationConfig = useMemo(
|
|
50
|
-
() => ({
|
|
51
|
-
...DEFAULT_ELEMENT_ANIMATION_CONFIG,
|
|
52
|
-
...config,
|
|
53
|
-
scaleMax: config?.scaleBounceMax ?? config?.scaleMax ?? DEFAULT_ELEMENT_ANIMATION_CONFIG.scaleMax,
|
|
54
|
-
}),
|
|
55
|
-
[
|
|
56
|
-
config?.scaleMax,
|
|
57
|
-
config?.scaleBounceMax,
|
|
58
|
-
config?.scaleMin,
|
|
59
|
-
config?.rotateDegrees,
|
|
60
|
-
config?.delay,
|
|
61
|
-
config?.scaleDuration,
|
|
62
|
-
config?.rotateDuration,
|
|
63
|
-
config?.resetOnHide,
|
|
64
|
-
],
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
if (visible && isReanimatedReady) {
|
|
69
|
-
const timeoutId = setTimeout(() => {
|
|
70
|
-
transform.scale.value = withSequence(
|
|
71
|
-
withTiming(animationConfig.scaleMax, {
|
|
72
|
-
duration: animationConfig.scaleDuration,
|
|
73
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
74
|
-
}),
|
|
75
|
-
withTiming(animationConfig.scaleMin, {
|
|
76
|
-
duration: animationConfig.scaleDuration,
|
|
77
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
78
|
-
}),
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
transform.rotate.value = withSequence(
|
|
82
|
-
withTiming(animationConfig.rotateDegrees, {
|
|
83
|
-
duration: animationConfig.rotateDuration,
|
|
84
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
85
|
-
}),
|
|
86
|
-
withTiming(0, { duration: 0 }),
|
|
87
|
-
);
|
|
88
|
-
}, animationConfig.delay);
|
|
89
|
-
|
|
90
|
-
return () => {
|
|
91
|
-
clearTimeout(timeoutId);
|
|
92
|
-
};
|
|
93
|
-
} else if (!visible && isReanimatedReady && animationConfig.resetOnHide) {
|
|
94
|
-
transform.scale.value = 1;
|
|
95
|
-
transform.rotate.value = 0;
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
98
|
-
}, [visible, isReanimatedReady, animationConfig, transform]);
|
|
99
|
-
|
|
100
|
-
const elementStyle = useAnimatedStyle(() => ({
|
|
101
|
-
transform: [
|
|
102
|
-
{ scale: transform.scale.value },
|
|
103
|
-
{ rotate: `${transform.rotate.value}deg` },
|
|
104
|
-
] as any,
|
|
105
|
-
}));
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
elementStyle,
|
|
109
|
-
iconStyle: elementStyle, // Alias for backward compatibility
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Legacy exports for backward compatibility
|
|
114
|
-
export const useIconAnimations = useElementAnimations;
|
|
115
|
-
export type IconAnimationConfig = ElementAnimationConfig;
|
|
116
|
-
export type UseIconAnimationsReturn = UseElementAnimationsReturn & {
|
|
117
|
-
iconStyle: ReturnType<typeof useAnimatedStyle>;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useOverlayAnimations Hook
|
|
3
|
-
* Single Responsibility: Manage overlay and content animations
|
|
4
|
-
* Generic implementation for any overlay-based UI component
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useEffect, useMemo, useRef } from "react";
|
|
8
|
-
import { useAnimatedStyle } from "react-native-reanimated";
|
|
9
|
-
import { useReanimatedReady } from "./useReanimatedReady";
|
|
10
|
-
import { useTimingAnimation } from "./useTimingAnimation";
|
|
11
|
-
import { useSpringAnimation } from "./useSpringAnimation";
|
|
12
|
-
|
|
13
|
-
export interface OverlayAnimationConfig {
|
|
14
|
-
overlayFadeDuration?: number;
|
|
15
|
-
contentScaleDamping?: number;
|
|
16
|
-
modalScaleDamping?: number; // Alias for contentScaleDamping
|
|
17
|
-
contentScaleStiffness?: number;
|
|
18
|
-
contentFadeDuration?: number;
|
|
19
|
-
initialScale?: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const DEFAULT_OVERLAY_ANIMATION_CONFIG: Required<OverlayAnimationConfig> = {
|
|
23
|
-
overlayFadeDuration: 300,
|
|
24
|
-
contentScaleDamping: 7,
|
|
25
|
-
modalScaleDamping: 7,
|
|
26
|
-
contentScaleStiffness: 50,
|
|
27
|
-
contentFadeDuration: 300,
|
|
28
|
-
initialScale: 0,
|
|
29
|
-
} as const;
|
|
30
|
-
|
|
31
|
-
export interface UseOverlayAnimationsReturn {
|
|
32
|
-
isReady: boolean;
|
|
33
|
-
overlayStyle: ReturnType<typeof useAnimatedStyle>;
|
|
34
|
-
contentStyle: ReturnType<typeof useAnimatedStyle>;
|
|
35
|
-
modalStyle: ReturnType<typeof useAnimatedStyle>; // Alias for contentStyle
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Hook for managing overlay and content animations
|
|
40
|
-
* Generic implementation suitable for modals, popups, tooltips, etc.
|
|
41
|
-
*/
|
|
42
|
-
export function useOverlayAnimations(
|
|
43
|
-
visible: boolean,
|
|
44
|
-
config?: OverlayAnimationConfig,
|
|
45
|
-
): UseOverlayAnimationsReturn {
|
|
46
|
-
const isReanimatedReady = useReanimatedReady();
|
|
47
|
-
const overlayTiming = useTimingAnimation();
|
|
48
|
-
const contentTiming = useTimingAnimation();
|
|
49
|
-
const spring = useSpringAnimation();
|
|
50
|
-
const previousVisibleRef = useRef<boolean>(false);
|
|
51
|
-
|
|
52
|
-
const animationConfig = useMemo(
|
|
53
|
-
() => ({
|
|
54
|
-
...DEFAULT_OVERLAY_ANIMATION_CONFIG,
|
|
55
|
-
...config,
|
|
56
|
-
contentScaleDamping: config?.modalScaleDamping ?? config?.contentScaleDamping ?? DEFAULT_OVERLAY_ANIMATION_CONFIG.contentScaleDamping,
|
|
57
|
-
}),
|
|
58
|
-
[
|
|
59
|
-
config?.overlayFadeDuration,
|
|
60
|
-
config?.contentScaleDamping,
|
|
61
|
-
config?.modalScaleDamping,
|
|
62
|
-
config?.contentScaleStiffness,
|
|
63
|
-
config?.contentFadeDuration,
|
|
64
|
-
config?.initialScale,
|
|
65
|
-
],
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if (!isReanimatedReady) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (visible === previousVisibleRef.current) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
previousVisibleRef.current = visible;
|
|
78
|
-
|
|
79
|
-
if (visible) {
|
|
80
|
-
overlayTiming.opacity.value = 0;
|
|
81
|
-
contentTiming.opacity.value = 0;
|
|
82
|
-
spring.scale.value = animationConfig.initialScale;
|
|
83
|
-
|
|
84
|
-
overlayTiming.fadeIn({ duration: animationConfig.overlayFadeDuration });
|
|
85
|
-
contentTiming.fadeIn({ duration: animationConfig.contentFadeDuration });
|
|
86
|
-
spring.scaleIn({
|
|
87
|
-
damping: animationConfig.contentScaleDamping,
|
|
88
|
-
stiffness: animationConfig.contentScaleStiffness,
|
|
89
|
-
});
|
|
90
|
-
} else {
|
|
91
|
-
overlayTiming.fadeOut({ duration: animationConfig.overlayFadeDuration });
|
|
92
|
-
contentTiming.fadeOut({ duration: animationConfig.contentFadeDuration });
|
|
93
|
-
spring.scaleOut({
|
|
94
|
-
damping: animationConfig.contentScaleDamping,
|
|
95
|
-
stiffness: animationConfig.contentScaleStiffness,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}, [visible, isReanimatedReady, animationConfig, overlayTiming, contentTiming, spring]);
|
|
99
|
-
|
|
100
|
-
const overlayStyle = useAnimatedStyle(() => ({
|
|
101
|
-
opacity: overlayTiming.opacity.value,
|
|
102
|
-
}));
|
|
103
|
-
|
|
104
|
-
const contentStyle = useAnimatedStyle(() => ({
|
|
105
|
-
opacity: contentTiming.opacity.value,
|
|
106
|
-
transform: [{ scale: spring.scale.value }],
|
|
107
|
-
}));
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
isReady: isReanimatedReady,
|
|
111
|
-
overlayStyle,
|
|
112
|
-
contentStyle,
|
|
113
|
-
modalStyle: contentStyle, // Alias for backward compatibility
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Legacy export for backward compatibility
|
|
118
|
-
export const useModalAnimations = useOverlayAnimations;
|
|
119
|
-
export type ModalAnimationConfig = OverlayAnimationConfig;
|
|
120
|
-
export type UseModalAnimationsReturn = UseOverlayAnimationsReturn & {
|
|
121
|
-
modalStyle: ReturnType<typeof useAnimatedStyle>;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useReanimatedReady Hook
|
|
3
|
-
*
|
|
4
|
-
* React hook to check if react-native-reanimated is fully initialized and ready.
|
|
5
|
-
* This prevents errors when Reanimated's internal state (like layoutState) is accessed
|
|
6
|
-
* before it's fully ready.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* ```tsx
|
|
10
|
-
* const { isReady } = useReanimatedReady();
|
|
11
|
-
*
|
|
12
|
-
* if (!isReady) {
|
|
13
|
-
* return null; // Don't render Reanimated components until ready
|
|
14
|
-
* }
|
|
15
|
-
*
|
|
16
|
-
* return <Animated.View>...</Animated.View>;
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { useState, useEffect } from 'react';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Hook to check if Reanimated is ready
|
|
24
|
-
*
|
|
25
|
-
* Returns a boolean indicating if Reanimated is fully initialized.
|
|
26
|
-
* Uses a delay + multiple animation frames to ensure Reanimated worklets are ready.
|
|
27
|
-
*
|
|
28
|
-
* @returns {boolean} True if Reanimated is ready, false otherwise
|
|
29
|
-
*/
|
|
30
|
-
export const useReanimatedReady = (): boolean => {
|
|
31
|
-
const [isReady, setIsReady] = useState(false);
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
// CRITICAL: Wait for Reanimated to be fully initialized
|
|
35
|
-
// Reanimated's internal hooks (useAnimatedLayout, useAnimatedDetents, etc.)
|
|
36
|
-
// access containerLayoutState.get during initialization
|
|
37
|
-
// If we don't wait, we get "containerLayoutState.get is not a function" errors
|
|
38
|
-
//
|
|
39
|
-
// Strategy:
|
|
40
|
-
// 1. Wait 500ms for Reanimated to initialize (minimal delay)
|
|
41
|
-
// 2. Use 3 requestAnimationFrame calls to ensure worklets are ready
|
|
42
|
-
// 3. This ensures @gorhom/bottom-sheet's internal hooks can safely access Reanimated state
|
|
43
|
-
const timer = setTimeout(() => {
|
|
44
|
-
// Use multiple animation frames to ensure Reanimated worklets are ready
|
|
45
|
-
requestAnimationFrame(() => {
|
|
46
|
-
requestAnimationFrame(() => {
|
|
47
|
-
requestAnimationFrame(() => {
|
|
48
|
-
setIsReady(true);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
}, 500); // Minimal delay to ensure Reanimated is initialized
|
|
53
|
-
|
|
54
|
-
return () => {
|
|
55
|
-
clearTimeout(timer);
|
|
56
|
-
};
|
|
57
|
-
}, []);
|
|
58
|
-
|
|
59
|
-
return isReady;
|
|
60
|
-
};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useSpringAnimation Hook
|
|
3
|
-
*
|
|
4
|
-
* Hook for spring-based animations (scale, bounce).
|
|
5
|
-
* Single Responsibility: Handle spring animations only.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useCallback } from 'react';
|
|
9
|
-
import {
|
|
10
|
-
useSharedValue,
|
|
11
|
-
withSpring,
|
|
12
|
-
withSequence,
|
|
13
|
-
} from 'react-native-reanimated';
|
|
14
|
-
import type { AnimationSpringConfig } from '../../domain/entities/Animation';
|
|
15
|
-
import {
|
|
16
|
-
AnimationPreset,
|
|
17
|
-
ANIMATION_CONSTANTS,
|
|
18
|
-
} from '../../domain/entities/Animation';
|
|
19
|
-
import { SpringAnimationConfigService } from '../../infrastructure/services/SpringAnimationConfigService';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Hook for spring-based animations
|
|
23
|
-
*/
|
|
24
|
-
export const useSpringAnimation = () => {
|
|
25
|
-
const scale = useSharedValue(1);
|
|
26
|
-
|
|
27
|
-
const scaleIn = useCallback(
|
|
28
|
-
(config?: AnimationSpringConfig) => {
|
|
29
|
-
const spring = config || SpringAnimationConfigService.getSpringConfig(AnimationPreset.SCALE_IN);
|
|
30
|
-
scale.value = 0;
|
|
31
|
-
scale.value = withSpring(1, {
|
|
32
|
-
damping: spring.damping || ANIMATION_CONSTANTS.SPRING.DAMPING,
|
|
33
|
-
stiffness: spring.stiffness || ANIMATION_CONSTANTS.SPRING.STIFFNESS,
|
|
34
|
-
});
|
|
35
|
-
},
|
|
36
|
-
[scale]
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const scaleOut = useCallback(
|
|
40
|
-
(config?: AnimationSpringConfig) => {
|
|
41
|
-
const spring = config || SpringAnimationConfigService.getSpringConfig(AnimationPreset.SCALE_OUT);
|
|
42
|
-
scale.value = withSpring(0, {
|
|
43
|
-
damping: spring.damping || ANIMATION_CONSTANTS.SPRING.DAMPING,
|
|
44
|
-
stiffness: spring.stiffness || ANIMATION_CONSTANTS.SPRING.STIFFNESS,
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
[scale]
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
const bounce = useCallback(
|
|
51
|
-
(config?: AnimationSpringConfig) => {
|
|
52
|
-
const spring = config || SpringAnimationConfigService.getSpringConfig(AnimationPreset.BOUNCE);
|
|
53
|
-
scale.value = withSequence(
|
|
54
|
-
withSpring(0.8, spring),
|
|
55
|
-
withSpring(1.2, spring),
|
|
56
|
-
withSpring(1, spring)
|
|
57
|
-
);
|
|
58
|
-
},
|
|
59
|
-
[scale]
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
scaleIn,
|
|
64
|
-
scaleOut,
|
|
65
|
-
bounce,
|
|
66
|
-
scale,
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useTimingAnimation Hook
|
|
3
|
-
*
|
|
4
|
-
* Hook for timing-based animations (fade, slide).
|
|
5
|
-
* Single Responsibility: Handle timing animations only.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useCallback } from 'react';
|
|
9
|
-
import {
|
|
10
|
-
useSharedValue,
|
|
11
|
-
withTiming,
|
|
12
|
-
Easing,
|
|
13
|
-
} from 'react-native-reanimated';
|
|
14
|
-
import type { AnimationTimingConfig } from '../../domain/entities/Animation';
|
|
15
|
-
import {
|
|
16
|
-
AnimationPreset,
|
|
17
|
-
ANIMATION_CONSTANTS,
|
|
18
|
-
} from '../../domain/entities/Animation';
|
|
19
|
-
import { TimingAnimationConfigService } from '../../infrastructure/services/TimingAnimationConfigService';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Hook for timing-based animations
|
|
23
|
-
*/
|
|
24
|
-
export const useTimingAnimation = () => {
|
|
25
|
-
const opacity = useSharedValue(1);
|
|
26
|
-
const translateY = useSharedValue(0);
|
|
27
|
-
const translateX = useSharedValue(0);
|
|
28
|
-
|
|
29
|
-
const fadeIn = useCallback(
|
|
30
|
-
(config?: AnimationTimingConfig) => {
|
|
31
|
-
const timing = config || TimingAnimationConfigService.getTimingConfig(AnimationPreset.FADE_IN);
|
|
32
|
-
opacity.value = withTiming(1, {
|
|
33
|
-
duration: timing.duration || ANIMATION_CONSTANTS.DURATION.NORMAL,
|
|
34
|
-
easing: Easing.ease,
|
|
35
|
-
});
|
|
36
|
-
},
|
|
37
|
-
[opacity]
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const fadeOut = useCallback(
|
|
41
|
-
(config?: AnimationTimingConfig) => {
|
|
42
|
-
const timing = config || TimingAnimationConfigService.getTimingConfig(AnimationPreset.FADE_OUT);
|
|
43
|
-
opacity.value = withTiming(0, {
|
|
44
|
-
duration: timing.duration || ANIMATION_CONSTANTS.DURATION.NORMAL,
|
|
45
|
-
easing: Easing.ease,
|
|
46
|
-
});
|
|
47
|
-
},
|
|
48
|
-
[opacity]
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
const slideInUp = useCallback(
|
|
52
|
-
(distance = 100, config?: AnimationTimingConfig) => {
|
|
53
|
-
const timing = config || TimingAnimationConfigService.getTimingConfig(AnimationPreset.SLIDE_IN_UP);
|
|
54
|
-
translateY.value = distance;
|
|
55
|
-
translateY.value = withTiming(0, {
|
|
56
|
-
duration: timing.duration || ANIMATION_CONSTANTS.DURATION.NORMAL,
|
|
57
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
[translateY]
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
const slideInDown = useCallback(
|
|
64
|
-
(distance = 100, config?: AnimationTimingConfig) => {
|
|
65
|
-
const timing = config || TimingAnimationConfigService.getTimingConfig(AnimationPreset.SLIDE_IN_DOWN);
|
|
66
|
-
translateY.value = -distance;
|
|
67
|
-
translateY.value = withTiming(0, {
|
|
68
|
-
duration: timing.duration || ANIMATION_CONSTANTS.DURATION.NORMAL,
|
|
69
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
[translateY]
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
const slideInLeft = useCallback(
|
|
76
|
-
(distance = 100, config?: AnimationTimingConfig) => {
|
|
77
|
-
const timing = config || TimingAnimationConfigService.getTimingConfig(AnimationPreset.SLIDE_IN_LEFT);
|
|
78
|
-
translateX.value = -distance;
|
|
79
|
-
translateX.value = withTiming(0, {
|
|
80
|
-
duration: timing.duration || ANIMATION_CONSTANTS.DURATION.NORMAL,
|
|
81
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
82
|
-
});
|
|
83
|
-
},
|
|
84
|
-
[translateX]
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const slideInRight = useCallback(
|
|
88
|
-
(distance = 100, config?: AnimationTimingConfig) => {
|
|
89
|
-
const timing = config || TimingAnimationConfigService.getTimingConfig(AnimationPreset.SLIDE_IN_RIGHT);
|
|
90
|
-
translateX.value = distance;
|
|
91
|
-
translateX.value = withTiming(0, {
|
|
92
|
-
duration: timing.duration || ANIMATION_CONSTANTS.DURATION.NORMAL,
|
|
93
|
-
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
|
|
94
|
-
});
|
|
95
|
-
},
|
|
96
|
-
[translateX]
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
fadeIn,
|
|
101
|
-
fadeOut,
|
|
102
|
-
slideInUp,
|
|
103
|
-
slideInDown,
|
|
104
|
-
slideInLeft,
|
|
105
|
-
slideInRight,
|
|
106
|
-
opacity,
|
|
107
|
-
translateY,
|
|
108
|
-
translateX,
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useTransformAnimation Hook
|
|
3
|
-
*
|
|
4
|
-
* Hook for transform-based animations (spin, pulse, shake).
|
|
5
|
-
* Single Responsibility: Handle transform animations only.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useCallback } from 'react';
|
|
9
|
-
import {
|
|
10
|
-
useSharedValue,
|
|
11
|
-
withTiming,
|
|
12
|
-
withSequence,
|
|
13
|
-
withRepeat,
|
|
14
|
-
Easing,
|
|
15
|
-
} from 'react-native-reanimated';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Hook for transform-based animations
|
|
19
|
-
*/
|
|
20
|
-
export const useTransformAnimation = () => {
|
|
21
|
-
const translateX = useSharedValue(0);
|
|
22
|
-
const scale = useSharedValue(1);
|
|
23
|
-
const rotate = useSharedValue(0);
|
|
24
|
-
|
|
25
|
-
const shake = useCallback(() => {
|
|
26
|
-
translateX.value = withSequence(
|
|
27
|
-
withTiming(-10, { duration: 50 }),
|
|
28
|
-
withRepeat(withTiming(10, { duration: 50 }), 4, true),
|
|
29
|
-
withTiming(0, { duration: 50 })
|
|
30
|
-
);
|
|
31
|
-
}, [translateX]);
|
|
32
|
-
|
|
33
|
-
const pulse = useCallback((repeatCount = -1) => {
|
|
34
|
-
scale.value = withRepeat(
|
|
35
|
-
withSequence(withTiming(1.1, { duration: 500 }), withTiming(1, { duration: 500 })),
|
|
36
|
-
repeatCount,
|
|
37
|
-
false
|
|
38
|
-
);
|
|
39
|
-
}, [scale]);
|
|
40
|
-
|
|
41
|
-
const spin = useCallback((repeatCount = -1) => {
|
|
42
|
-
rotate.value = withRepeat(
|
|
43
|
-
withTiming(360, { duration: 1000, easing: Easing.linear }),
|
|
44
|
-
repeatCount,
|
|
45
|
-
false
|
|
46
|
-
);
|
|
47
|
-
}, [rotate]);
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
shake,
|
|
51
|
-
pulse,
|
|
52
|
-
spin,
|
|
53
|
-
translateX,
|
|
54
|
-
scale,
|
|
55
|
-
rotate,
|
|
56
|
-
};
|
|
57
|
-
};
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme Provider for Animation Package
|
|
3
|
-
*
|
|
4
|
-
* React context provider for theme management.
|
|
5
|
-
* Allows consumers to customize animation appearance.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
|
9
|
-
import type { AnimationTheme, ThemeContext } from '../../domain/entities/Theme';
|
|
10
|
-
import { DEFAULT_ANIMATION_THEME } from '../../domain/entities/Theme';
|
|
11
|
-
|
|
12
|
-
const ThemeContext = createContext<ThemeContext | undefined>(undefined);
|
|
13
|
-
|
|
14
|
-
export interface AnimationThemeProviderProps {
|
|
15
|
-
children: ReactNode;
|
|
16
|
-
theme?: Partial<AnimationTheme>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Theme provider component
|
|
21
|
-
*/
|
|
22
|
-
export const AnimationThemeProvider: React.FC<AnimationThemeProviderProps> = ({
|
|
23
|
-
children,
|
|
24
|
-
theme: initialTheme,
|
|
25
|
-
}) => {
|
|
26
|
-
const [theme, setTheme] = useState<AnimationTheme>(() => ({
|
|
27
|
-
...DEFAULT_ANIMATION_THEME,
|
|
28
|
-
...initialTheme,
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
const updateTheme = (newTheme: Partial<AnimationTheme>) => {
|
|
32
|
-
setTheme(prev => ({ ...prev, ...newTheme }));
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const contextValue: ThemeContext = {
|
|
36
|
-
theme,
|
|
37
|
-
setTheme: updateTheme,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<ThemeContext.Provider value={contextValue}>
|
|
42
|
-
{children}
|
|
43
|
-
</ThemeContext.Provider>
|
|
44
|
-
);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Hook to use theme
|
|
49
|
-
*/
|
|
50
|
-
export const useAnimationTheme = (): ThemeContext => {
|
|
51
|
-
const context = useContext(ThemeContext);
|
|
52
|
-
if (!context) {
|
|
53
|
-
// Return default theme if used outside provider
|
|
54
|
-
return {
|
|
55
|
-
theme: DEFAULT_ANIMATION_THEME,
|
|
56
|
-
setTheme: () => {},
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return context;
|
|
60
|
-
};
|