@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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/src/atoms/skeleton/AtomicSkeleton.tsx +16 -62
  3. package/src/index.ts +0 -32
  4. package/src/molecules/bottom-sheet/components/BottomSheetModal.tsx +101 -180
  5. package/src/molecules/bottom-sheet/components/SafeBottomSheetModalProvider.tsx +8 -14
  6. package/src/molecules/index.ts +0 -6
  7. package/src/molecules/animation/core/AnimationCore.ts +0 -29
  8. package/src/molecules/animation/domain/entities/Animation.ts +0 -81
  9. package/src/molecules/animation/domain/entities/Fireworks.ts +0 -44
  10. package/src/molecules/animation/domain/entities/Theme.ts +0 -76
  11. package/src/molecules/animation/index.ts +0 -146
  12. package/src/molecules/animation/infrastructure/services/AnimationConfigService.ts +0 -35
  13. package/src/molecules/animation/infrastructure/services/SpringAnimationConfigService.ts +0 -67
  14. package/src/molecules/animation/infrastructure/services/TimingAnimationConfigService.ts +0 -57
  15. package/src/molecules/animation/infrastructure/services/__tests__/SpringAnimationConfigService.test.ts +0 -114
  16. package/src/molecules/animation/infrastructure/services/__tests__/TimingAnimationConfigService.test.ts +0 -105
  17. package/src/molecules/animation/presentation/components/Fireworks.tsx +0 -127
  18. package/src/molecules/animation/presentation/components/__tests__/Fireworks.test.tsx +0 -185
  19. package/src/molecules/animation/presentation/hooks/__tests__/useAnimation.integration.test.ts +0 -210
  20. package/src/molecules/animation/presentation/hooks/__tests__/useFireworks.test.ts +0 -242
  21. package/src/molecules/animation/presentation/hooks/__tests__/useGesture.test.ts +0 -108
  22. package/src/molecules/animation/presentation/hooks/__tests__/useSpringAnimation.test.ts +0 -127
  23. package/src/molecules/animation/presentation/hooks/__tests__/useTimingAnimation.test.ts +0 -172
  24. package/src/molecules/animation/presentation/hooks/__tests__/useTransformAnimation.test.ts +0 -133
  25. package/src/molecules/animation/presentation/hooks/useAnimation.ts +0 -77
  26. package/src/molecules/animation/presentation/hooks/useFireworks.ts +0 -144
  27. package/src/molecules/animation/presentation/hooks/useGesture.ts +0 -57
  28. package/src/molecules/animation/presentation/hooks/useGestureCreators.ts +0 -163
  29. package/src/molecules/animation/presentation/hooks/useGestureState.ts +0 -53
  30. package/src/molecules/animation/presentation/hooks/useIconAnimations.ts +0 -120
  31. package/src/molecules/animation/presentation/hooks/useModalAnimations.ts +0 -124
  32. package/src/molecules/animation/presentation/hooks/useReanimatedReady.ts +0 -60
  33. package/src/molecules/animation/presentation/hooks/useSpringAnimation.ts +0 -69
  34. package/src/molecules/animation/presentation/hooks/useTimingAnimation.ts +0 -111
  35. package/src/molecules/animation/presentation/hooks/useTransformAnimation.ts +0 -57
  36. package/src/molecules/animation/presentation/providers/AnimationThemeProvider.tsx +0 -60
  37. package/src/molecules/animation/presentation/providers/__tests__/AnimationThemeProvider.test.tsx +0 -165
  38. package/src/molecules/celebration/domain/entities/CelebrationConfig.ts +0 -17
  39. package/src/molecules/celebration/domain/entities/FireworksConfig.ts +0 -32
  40. package/src/molecules/celebration/index.ts +0 -93
  41. package/src/molecules/celebration/infrastructure/services/FireworksConfigService.ts +0 -49
  42. package/src/molecules/celebration/presentation/components/CelebrationFireworksOverlay.tsx +0 -33
  43. package/src/molecules/celebration/presentation/components/CelebrationModal.tsx +0 -81
  44. package/src/molecules/celebration/presentation/components/CelebrationModalContent.tsx +0 -88
  45. package/src/molecules/celebration/presentation/hooks/useCelebrationModalAnimation.ts +0 -49
  46. package/src/molecules/celebration/presentation/hooks/useCelebrationState.ts +0 -45
  47. 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
- };