@umituz/react-native-design-system 2.3.13 → 2.3.15
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 +32 -13
- package/src/index.ts +116 -0
- package/src/layouts/ScreenLayout/ScreenLayout.example.tsx +2 -2
- package/src/layouts/ScreenLayout/ScreenLayout.tsx +1 -1
- package/src/molecules/animation/core/AnimationCore.ts +29 -0
- package/src/molecules/animation/domain/entities/Animation.ts +81 -0
- package/src/molecules/animation/domain/entities/Fireworks.ts +44 -0
- package/src/molecules/animation/domain/entities/Theme.ts +76 -0
- package/src/molecules/animation/index.ts +146 -0
- package/src/molecules/animation/infrastructure/services/AnimationConfigService.ts +35 -0
- package/src/molecules/animation/infrastructure/services/SpringAnimationConfigService.ts +67 -0
- package/src/molecules/animation/infrastructure/services/TimingAnimationConfigService.ts +57 -0
- package/src/molecules/animation/infrastructure/services/__tests__/SpringAnimationConfigService.test.ts +114 -0
- package/src/molecules/animation/infrastructure/services/__tests__/TimingAnimationConfigService.test.ts +105 -0
- package/src/molecules/animation/presentation/components/Fireworks.tsx +126 -0
- package/src/molecules/animation/presentation/components/__tests__/Fireworks.test.tsx +189 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useAnimation.integration.test.ts +216 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useFireworks.test.ts +242 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useGesture.test.ts +111 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useSpringAnimation.test.ts +131 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useTimingAnimation.test.ts +175 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useTransformAnimation.test.ts +137 -0
- package/src/molecules/animation/presentation/hooks/useAnimation.ts +77 -0
- package/src/molecules/animation/presentation/hooks/useFireworks.ts +141 -0
- package/src/molecules/animation/presentation/hooks/useGesture.ts +61 -0
- package/src/molecules/animation/presentation/hooks/useGestureCreators.ts +163 -0
- package/src/molecules/animation/presentation/hooks/useGestureState.ts +53 -0
- package/src/molecules/animation/presentation/hooks/useIconAnimations.ts +119 -0
- package/src/molecules/animation/presentation/hooks/useModalAnimations.ts +124 -0
- package/src/molecules/animation/presentation/hooks/useReanimatedReady.ts +60 -0
- package/src/molecules/animation/presentation/hooks/useSpringAnimation.ts +69 -0
- package/src/molecules/animation/presentation/hooks/useTimingAnimation.ts +111 -0
- package/src/molecules/animation/presentation/hooks/useTransformAnimation.ts +57 -0
- package/src/molecules/animation/presentation/providers/AnimationThemeProvider.tsx +62 -0
- package/src/molecules/animation/presentation/providers/__tests__/AnimationThemeProvider.test.tsx +165 -0
- package/src/molecules/animation/types/global.d.ts +97 -0
- package/src/molecules/calendar/domain/entities/CalendarDay.entity.ts +115 -0
- package/src/molecules/calendar/domain/entities/CalendarEvent.entity.ts +202 -0
- package/src/molecules/calendar/domain/repositories/ICalendarRepository.ts +120 -0
- package/src/molecules/calendar/index.ts +98 -0
- package/src/molecules/calendar/infrastructure/services/CalendarEvents.ts +196 -0
- package/src/molecules/calendar/infrastructure/services/CalendarGeneration.ts +172 -0
- package/src/molecules/calendar/infrastructure/services/CalendarPermissions.ts +92 -0
- package/src/molecules/calendar/infrastructure/services/CalendarService.ts +161 -0
- package/src/molecules/calendar/infrastructure/services/CalendarSync.ts +205 -0
- package/src/molecules/calendar/infrastructure/storage/CalendarStore.ts +307 -0
- package/src/molecules/calendar/infrastructure/utils/DateUtilities.ts +128 -0
- package/src/molecules/calendar/presentation/components/AtomicCalendar.tsx +279 -0
- package/src/molecules/calendar/presentation/hooks/useCalendar.ts +356 -0
- package/src/molecules/celebration/domain/entities/CelebrationConfig.ts +17 -0
- package/src/molecules/celebration/domain/entities/FireworksConfig.ts +32 -0
- package/src/molecules/celebration/index.ts +93 -0
- package/src/molecules/celebration/infrastructure/services/FireworksConfigService.ts +49 -0
- package/src/molecules/celebration/presentation/components/CelebrationFireworksOverlay.tsx +33 -0
- package/src/molecules/celebration/presentation/components/CelebrationModal.tsx +78 -0
- package/src/molecules/celebration/presentation/components/CelebrationModalContent.tsx +90 -0
- package/src/molecules/celebration/presentation/hooks/useCelebrationModalAnimation.ts +49 -0
- package/src/molecules/celebration/presentation/hooks/useCelebrationState.ts +45 -0
- package/src/molecules/celebration/presentation/styles/CelebrationModalStyles.ts +65 -0
- package/src/molecules/countdown/components/Countdown.tsx +128 -0
- package/src/molecules/countdown/components/CountdownHeader.tsx +84 -0
- package/src/molecules/countdown/components/TimeUnit.tsx +73 -0
- package/src/molecules/countdown/hooks/useCountdown.ts +107 -0
- package/src/molecules/countdown/index.ts +25 -0
- package/src/molecules/countdown/types/CountdownTypes.ts +31 -0
- package/src/molecules/countdown/utils/TimeCalculator.ts +46 -0
- package/src/molecules/emoji/domain/entities/Emoji.ts +129 -0
- package/src/molecules/emoji/index.ts +177 -0
- package/src/molecules/emoji/presentation/components/EmojiPicker.tsx +102 -0
- package/src/molecules/emoji/presentation/hooks/useEmojiPicker.ts +171 -0
- package/src/molecules/index.ts +24 -0
- package/src/molecules/long-press-menu/domain/entities/MenuAction.ts +37 -0
- package/src/molecules/long-press-menu/index.ts +16 -0
- package/src/molecules/navigation/StackNavigator.tsx +75 -0
- package/src/molecules/navigation/TabsNavigator.tsx +94 -0
- package/src/molecules/navigation/components/FabButton.tsx +45 -0
- package/src/molecules/navigation/components/TabLabel.tsx +47 -0
- package/src/molecules/navigation/createStackNavigator.ts +20 -0
- package/src/molecules/navigation/createTabNavigator.ts +20 -0
- package/src/molecules/navigation/hooks/useTabBarStyles.ts +54 -0
- package/src/molecules/navigation/index.ts +37 -0
- package/src/molecules/navigation/types.ts +118 -0
- package/src/molecules/navigation/utils/AppNavigation.ts +101 -0
- package/src/molecules/navigation/utils/IconRenderer.ts +50 -0
- package/src/molecules/navigation/utils/LabelProcessor.ts +70 -0
- package/src/molecules/navigation/utils/NavigationCleanup.ts +62 -0
- package/src/molecules/navigation/utils/NavigationTheme.ts +21 -0
- package/src/molecules/navigation/utils/NavigationValidator.ts +61 -0
- package/src/molecules/navigation/utils/ScreenFactory.ts +115 -0
- package/src/molecules/navigation/utils/__tests__/IconRenderer.getIconName.test.ts +109 -0
- package/src/molecules/navigation/utils/__tests__/IconRenderer.renderIcon.test.ts +116 -0
- package/src/molecules/navigation/utils/__tests__/LabelProcessor.processLabel.test.ts +116 -0
- package/src/molecules/navigation/utils/__tests__/LabelProcessor.processTitle.test.ts +59 -0
- package/src/molecules/navigation/utils/__tests__/NavigationCleanup.test.ts +271 -0
- package/src/molecules/navigation/utils/__tests__/NavigationValidator.test.ts +252 -0
- package/src/molecules/swipe-actions/domain/entities/SwipeAction.ts +194 -0
- package/src/molecules/swipe-actions/index.ts +6 -0
- package/src/molecules/swipe-actions/presentation/components/SwipeActionButton.tsx +131 -0
- package/src/theme/hooks/useResponsiveDesignTokens.ts +1 -1
- package/src/utilities/clipboard/ClipboardUtils.ts +71 -0
- package/src/utilities/clipboard/index.ts +5 -0
- package/src/utilities/index.ts +6 -0
- package/src/utilities/sharing/domain/entities/Share.ts +210 -0
- package/src/utilities/sharing/index.ts +205 -0
- package/src/utilities/sharing/infrastructure/services/SharingService.ts +165 -0
- package/src/utilities/sharing/presentation/hooks/useSharing.ts +154 -0
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
if (__DEV__) {
|
|
54
|
+
console.warn('useAnimationTheme must be used within AnimationThemeProvider');
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
theme: DEFAULT_ANIMATION_THEME,
|
|
58
|
+
setTheme: () => {},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return context;
|
|
62
|
+
};
|
package/src/molecules/animation/presentation/providers/__tests__/AnimationThemeProvider.test.tsx
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AnimationThemeProvider Tests
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for theme system functionality.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { render, screen } from '@testing-library/react-native';
|
|
9
|
+
import { AnimationThemeProvider, useAnimationTheme } from '../AnimationThemeProvider';
|
|
10
|
+
import { DEFAULT_ANIMATION_THEME } from '../../../domain/entities/AnimationTheme';
|
|
11
|
+
|
|
12
|
+
// Mock console.warn
|
|
13
|
+
const originalWarn = console.warn;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
console.warn = jest.fn();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
console.warn = originalWarn;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('AnimationThemeProvider', () => {
|
|
23
|
+
it('should render children', () => {
|
|
24
|
+
const TestComponent = () => <div>Test Child</div>;
|
|
25
|
+
|
|
26
|
+
render(
|
|
27
|
+
<AnimationThemeProvider>
|
|
28
|
+
<TestComponent />
|
|
29
|
+
</AnimationThemeProvider>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(screen.getByText('Test Child')).toBeTruthy();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should provide default theme when no custom theme provided', () => {
|
|
36
|
+
const TestComponent = () => {
|
|
37
|
+
const { theme } = useAnimationTheme();
|
|
38
|
+
return <div>{theme.colors.primary}</div>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
render(
|
|
42
|
+
<AnimationThemeProvider>
|
|
43
|
+
<TestComponent />
|
|
44
|
+
</AnimationThemeProvider>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(screen.getByText(DEFAULT_ANIMATION_THEME.colors.primary)).toBeTruthy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should merge custom theme with default theme', () => {
|
|
51
|
+
const customTheme = {
|
|
52
|
+
colors: {
|
|
53
|
+
primary: '#custom-color',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const TestComponent = () => {
|
|
58
|
+
const { theme } = useAnimationTheme();
|
|
59
|
+
return <div>{theme.colors.primary}</div>;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
render(
|
|
63
|
+
<AnimationThemeProvider theme={customTheme}>
|
|
64
|
+
<TestComponent />
|
|
65
|
+
</AnimationThemeProvider>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(screen.getByText('#custom-color')).toBeTruthy();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should preserve default values for non-overridden properties', () => {
|
|
72
|
+
const customTheme = {
|
|
73
|
+
colors: {
|
|
74
|
+
primary: '#custom-color',
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const TestComponent = () => {
|
|
79
|
+
const { theme } = useAnimationTheme();
|
|
80
|
+
return <div>{theme.colors.secondary}</div>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
render(
|
|
84
|
+
<AnimationThemeProvider theme={customTheme}>
|
|
85
|
+
<TestComponent />
|
|
86
|
+
</AnimationThemeProvider>
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
expect(screen.getByText(DEFAULT_ANIMATION_THEME.colors.secondary)).toBeTruthy();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should allow theme updates', () => {
|
|
93
|
+
const TestComponent = () => {
|
|
94
|
+
const { theme, setTheme } = useAnimationTheme();
|
|
95
|
+
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
setTheme({ colors: { primary: '#updated-color' } });
|
|
98
|
+
}, [setTheme]);
|
|
99
|
+
|
|
100
|
+
return <div>{theme.colors.primary}</div>;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
render(
|
|
104
|
+
<AnimationThemeProvider>
|
|
105
|
+
<TestComponent />
|
|
106
|
+
</AnimationThemeProvider>
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
expect(screen.getByText('#updated-color')).toBeTruthy();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('useAnimationTheme', () => {
|
|
114
|
+
it('should return theme and setTheme', () => {
|
|
115
|
+
const TestComponent = () => {
|
|
116
|
+
const { theme, setTheme } = useAnimationTheme();
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div>
|
|
120
|
+
<div testID="theme">{JSON.stringify(theme)}</div>
|
|
121
|
+
<div testID="set-theme">{typeof setTheme}</div>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
render(
|
|
127
|
+
<AnimationThemeProvider>
|
|
128
|
+
<TestComponent />
|
|
129
|
+
</AnimationThemeProvider>
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(screen.getByTestId('set-theme')).toHaveTextContent('function');
|
|
133
|
+
|
|
134
|
+
const themeElement = screen.getByTestId('theme');
|
|
135
|
+
const theme = JSON.parse(themeElement.props.children);
|
|
136
|
+
expect(theme).toHaveProperty('colors');
|
|
137
|
+
expect(theme).toHaveProperty('spacing');
|
|
138
|
+
expect(theme).toHaveProperty('borderRadius');
|
|
139
|
+
expect(theme).toHaveProperty('opacity');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should warn when used outside provider', () => {
|
|
143
|
+
const TestComponent = () => {
|
|
144
|
+
const { theme } = useAnimationTheme();
|
|
145
|
+
return <div>{theme.colors.primary}</div>;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
render(<TestComponent />);
|
|
149
|
+
|
|
150
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
151
|
+
'useAnimationTheme must be used within AnimationThemeProvider'
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should return default theme when used outside provider', () => {
|
|
156
|
+
const TestComponent = () => {
|
|
157
|
+
const { theme } = useAnimationTheme();
|
|
158
|
+
return <div>{theme.colors.primary}</div>;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
render(<TestComponent />);
|
|
162
|
+
|
|
163
|
+
expect(screen.getByText(DEFAULT_ANIMATION_THEME.colors.primary)).toBeTruthy();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/// <reference types="react-native" />
|
|
3
|
+
|
|
4
|
+
declare module 'react-native-reanimated' {
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { ViewProps, ViewStyle } from 'react-native';
|
|
7
|
+
|
|
8
|
+
export interface WithTimingConfig {
|
|
9
|
+
duration?: number;
|
|
10
|
+
easing?: (value: number) => number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface WithSpringConfig {
|
|
14
|
+
damping?: number;
|
|
15
|
+
stiffness?: number;
|
|
16
|
+
mass?: number;
|
|
17
|
+
overshootClamping?: boolean;
|
|
18
|
+
restDisplacementThreshold?: number;
|
|
19
|
+
restSpeedThreshold?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface SharedValue<T> {
|
|
23
|
+
value: T;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Animated: {
|
|
27
|
+
View: React.ComponentType<any>;
|
|
28
|
+
Text: React.ComponentType<any>;
|
|
29
|
+
Image: React.ComponentType<any>;
|
|
30
|
+
ScrollView: React.ComponentType<any>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function useSharedValue<T>(initialValue: T): SharedValue<T>;
|
|
34
|
+
export function useAnimatedStyle<T>(styleFactory: () => T): T;
|
|
35
|
+
export function withTiming(toValue: any, config?: WithTimingConfig): any;
|
|
36
|
+
export function withSpring(toValue: any, config?: WithSpringConfig): any;
|
|
37
|
+
export function withSequence(...animations: any[]): any;
|
|
38
|
+
export function withRepeat(animation: any, count?: number, reverse?: boolean): any;
|
|
39
|
+
export function runOnUI<T>(fn: () => T): () => T;
|
|
40
|
+
export function runOnJS<T extends (...args: any[]) => any>(fn: T): T;
|
|
41
|
+
export function cancelAnimation(sharedValue: SharedValue<any>): void;
|
|
42
|
+
|
|
43
|
+
export const Easing: {
|
|
44
|
+
linear: (t: number) => number;
|
|
45
|
+
ease: (t: number) => number;
|
|
46
|
+
easeIn: (t: number) => number;
|
|
47
|
+
easeOut: (t: number) => number;
|
|
48
|
+
easeInOut: (t: number) => number;
|
|
49
|
+
step0: (t: number) => number;
|
|
50
|
+
step1: (t: number) => number;
|
|
51
|
+
bezier: (x1: number, y1: number, x2: number, y2: number) => (t: number) => number;
|
|
52
|
+
cubic: (x1: number, y1: number, x2: number, y2: number) => (t: number) => number;
|
|
53
|
+
in: (easing: (t: number) => number) => (t: number) => number;
|
|
54
|
+
out: (easing: (t: number) => number) => (t: number) => number;
|
|
55
|
+
inOut: (easing: (t: number) => number) => (t: number) => number;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
declare module 'react-native-gesture-handler' {
|
|
60
|
+
import React from 'react';
|
|
61
|
+
import { ViewStyle } from 'react-native';
|
|
62
|
+
|
|
63
|
+
export interface PanGestureHandlerProps {
|
|
64
|
+
onGestureEvent?: (event: any) => void;
|
|
65
|
+
onHandlerStateChange?: (event: any) => void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface TapGestureHandlerProps {
|
|
69
|
+
onHandlerStateChange?: (event: any) => void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface PinchGestureHandlerProps {
|
|
73
|
+
onGestureEvent?: (event: any) => void;
|
|
74
|
+
onHandlerStateChange?: (event: any) => void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface LongPressGestureHandlerProps {
|
|
78
|
+
onHandlerStateChange?: (event: any) => void;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const GestureDetector: React.FC<{
|
|
82
|
+
gesture: any;
|
|
83
|
+
children: React.ReactNode;
|
|
84
|
+
}>;
|
|
85
|
+
|
|
86
|
+
export const Gesture: {
|
|
87
|
+
Tap: () => any;
|
|
88
|
+
Pan: () => any;
|
|
89
|
+
Pinch: () => any;
|
|
90
|
+
LongPress: () => any;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const PanGestureHandler: React.FC<PanGestureHandlerProps>;
|
|
94
|
+
export const TapGestureHandler: React.FC<TapGestureHandlerProps>;
|
|
95
|
+
export const PinchGestureHandler: React.FC<PinchGestureHandlerProps>;
|
|
96
|
+
export const LongPressGestureHandler: React.FC<LongPressGestureHandlerProps>;
|
|
97
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CalendarDay Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents a single day in a calendar view with its properties and associated events.
|
|
5
|
+
*
|
|
6
|
+
* Design Philosophy:
|
|
7
|
+
* - Timezone-aware (uses timezone domain for date calculations)
|
|
8
|
+
* - Event-agnostic (works with any CalendarEvent type)
|
|
9
|
+
* - View-ready (contains all display state)
|
|
10
|
+
* - Immutable (never mutate, create new instances)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { CalendarEvent } from './CalendarEvent.entity';
|
|
14
|
+
|
|
15
|
+
export interface CalendarDay {
|
|
16
|
+
/**
|
|
17
|
+
* The date this calendar day represents
|
|
18
|
+
*/
|
|
19
|
+
date: Date;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Whether this day belongs to the currently displayed month
|
|
23
|
+
* Used to gray out days from prev/next months in calendar grid
|
|
24
|
+
*/
|
|
25
|
+
isCurrentMonth: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether this day is today (timezone-aware via timezone domain)
|
|
29
|
+
*/
|
|
30
|
+
isToday: boolean;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Whether this day is currently selected by the user
|
|
34
|
+
*/
|
|
35
|
+
isSelected: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Events scheduled for this day
|
|
39
|
+
* @default []
|
|
40
|
+
*/
|
|
41
|
+
events: CalendarEvent[];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Whether this day is disabled/non-selectable
|
|
45
|
+
* @example Past dates, dates outside valid range
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
isDisabled?: boolean;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether this day is a weekend (Saturday or Sunday)
|
|
52
|
+
* Useful for styling weekend days differently
|
|
53
|
+
*/
|
|
54
|
+
isWeekend?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Calendar Month Configuration
|
|
59
|
+
*
|
|
60
|
+
* Represents a full month view with all necessary display information
|
|
61
|
+
*/
|
|
62
|
+
export interface CalendarMonth {
|
|
63
|
+
/**
|
|
64
|
+
* Year of the month
|
|
65
|
+
*/
|
|
66
|
+
year: number;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Month (0-indexed: 0 = January, 11 = December)
|
|
70
|
+
*/
|
|
71
|
+
month: number;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* All days to display in the calendar grid (usually 42 days = 6 weeks)
|
|
75
|
+
* Includes days from previous and next months to fill the grid
|
|
76
|
+
*/
|
|
77
|
+
days: CalendarDay[];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* First day of the month
|
|
81
|
+
*/
|
|
82
|
+
firstDay: Date;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Last day of the month
|
|
86
|
+
*/
|
|
87
|
+
lastDay: Date;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Total number of days in this month
|
|
91
|
+
*/
|
|
92
|
+
daysInMonth: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Week View Configuration
|
|
97
|
+
*
|
|
98
|
+
* Represents a week view with 7 days
|
|
99
|
+
*/
|
|
100
|
+
export interface CalendarWeek {
|
|
101
|
+
/**
|
|
102
|
+
* Start date of the week (usually Sunday)
|
|
103
|
+
*/
|
|
104
|
+
startDate: Date;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* End date of the week (usually Saturday)
|
|
108
|
+
*/
|
|
109
|
+
endDate: Date;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* All 7 days in the week
|
|
113
|
+
*/
|
|
114
|
+
days: CalendarDay[];
|
|
115
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CalendarEvent Entity
|
|
3
|
+
*
|
|
4
|
+
* Generic calendar event that can represent:
|
|
5
|
+
* - Workouts (fitness apps)
|
|
6
|
+
* - Habits (habit tracking apps)
|
|
7
|
+
* - Tasks (productivity apps)
|
|
8
|
+
* - Appointments (scheduling apps)
|
|
9
|
+
* - Any other time-based event
|
|
10
|
+
*
|
|
11
|
+
* Design Philosophy:
|
|
12
|
+
* - Generic and reusable across all app types
|
|
13
|
+
* - Extensible via metadata field
|
|
14
|
+
* - Simple core properties
|
|
15
|
+
* - App-specific data in metadata
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface CalendarEvent {
|
|
19
|
+
/**
|
|
20
|
+
* Unique identifier for the event
|
|
21
|
+
*/
|
|
22
|
+
id: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Event title/name
|
|
26
|
+
* @example "Morning Workout", "Team Meeting", "Water plants"
|
|
27
|
+
*/
|
|
28
|
+
title: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Event date in YYYY-MM-DD format (timezone-aware via timezone domain)
|
|
32
|
+
* @example "2024-10-30"
|
|
33
|
+
*/
|
|
34
|
+
date: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Optional event time in HH:mm format
|
|
38
|
+
* @example "09:30", "14:00"
|
|
39
|
+
*/
|
|
40
|
+
time?: string;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Optional event color for visual distinction
|
|
44
|
+
* Uses design token color names or hex values
|
|
45
|
+
* @example "primary", "success", "#FF5733"
|
|
46
|
+
*/
|
|
47
|
+
color?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Whether the event has been completed/checked off
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
isCompleted?: boolean;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Optional duration in minutes
|
|
57
|
+
* @example 30, 60, 90
|
|
58
|
+
*/
|
|
59
|
+
duration?: number;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Optional event description/notes
|
|
63
|
+
*/
|
|
64
|
+
description?: string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Optional location for the event
|
|
68
|
+
*/
|
|
69
|
+
location?: string;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Reminders/alarms (minutes before event)
|
|
73
|
+
* @example [15, 30] → 15 mins and 30 mins before
|
|
74
|
+
*/
|
|
75
|
+
reminders?: number[];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* System calendar sync (expo-calendar integration)
|
|
79
|
+
*/
|
|
80
|
+
systemCalendar?: {
|
|
81
|
+
/**
|
|
82
|
+
* System calendar ID where event is synced
|
|
83
|
+
*/
|
|
84
|
+
calendarId: string;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* System event ID from device calendar
|
|
88
|
+
*/
|
|
89
|
+
eventId: string;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Last sync timestamp
|
|
93
|
+
*/
|
|
94
|
+
lastSyncedAt: Date;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* App-specific metadata
|
|
99
|
+
* Use this for domain-specific properties
|
|
100
|
+
* @example
|
|
101
|
+
* // Workout app:
|
|
102
|
+
* metadata: { workoutTemplateId: "abc123", exercises: [...] }
|
|
103
|
+
*
|
|
104
|
+
* // Habit app:
|
|
105
|
+
* metadata: { habitId: "xyz789", streak: 5 }
|
|
106
|
+
*/
|
|
107
|
+
metadata?: unknown;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Recurring event configuration
|
|
111
|
+
*/
|
|
112
|
+
recurring?: {
|
|
113
|
+
/**
|
|
114
|
+
* Recurrence pattern
|
|
115
|
+
*/
|
|
116
|
+
pattern: 'daily' | 'weekly' | 'monthly' | 'custom';
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Interval for recurrence
|
|
120
|
+
* @example pattern: 'weekly', interval: 2 → every 2 weeks
|
|
121
|
+
*/
|
|
122
|
+
interval?: number;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Days of week for weekly recurrence (0 = Sunday, 6 = Saturday)
|
|
126
|
+
* @example [1, 3, 5] → Monday, Wednesday, Friday
|
|
127
|
+
*/
|
|
128
|
+
daysOfWeek?: number[];
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* End date for recurrence (YYYY-MM-DD)
|
|
132
|
+
*/
|
|
133
|
+
endDate?: string;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Creation timestamp
|
|
138
|
+
*/
|
|
139
|
+
createdAt: Date;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Last update timestamp
|
|
143
|
+
*/
|
|
144
|
+
updatedAt: Date;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Request object for creating a new calendar event
|
|
149
|
+
*/
|
|
150
|
+
export interface CreateCalendarEventRequest {
|
|
151
|
+
title: string;
|
|
152
|
+
date: string;
|
|
153
|
+
time?: string;
|
|
154
|
+
color?: string;
|
|
155
|
+
duration?: number;
|
|
156
|
+
description?: string;
|
|
157
|
+
location?: string;
|
|
158
|
+
reminders?: number[];
|
|
159
|
+
metadata?: unknown;
|
|
160
|
+
recurring?: CalendarEvent['recurring'];
|
|
161
|
+
syncToSystemCalendar?: boolean; // Auto-sync to device calendar
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Request object for updating an existing calendar event
|
|
166
|
+
*/
|
|
167
|
+
export interface UpdateCalendarEventRequest {
|
|
168
|
+
id: string;
|
|
169
|
+
title?: string;
|
|
170
|
+
date?: string;
|
|
171
|
+
time?: string;
|
|
172
|
+
color?: string;
|
|
173
|
+
isCompleted?: boolean;
|
|
174
|
+
duration?: number;
|
|
175
|
+
description?: string;
|
|
176
|
+
location?: string;
|
|
177
|
+
reminders?: number[];
|
|
178
|
+
metadata?: unknown;
|
|
179
|
+
recurring?: CalendarEvent['recurring'];
|
|
180
|
+
systemCalendar?: CalendarEvent['systemCalendar'];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* System calendar list item
|
|
185
|
+
*/
|
|
186
|
+
export interface SystemCalendar {
|
|
187
|
+
id: string;
|
|
188
|
+
title: string;
|
|
189
|
+
color: string;
|
|
190
|
+
source: string;
|
|
191
|
+
isPrimary: boolean;
|
|
192
|
+
allowsModifications: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Calendar permission result
|
|
197
|
+
*/
|
|
198
|
+
export interface CalendarPermissionResult {
|
|
199
|
+
granted: boolean;
|
|
200
|
+
canAskAgain: boolean;
|
|
201
|
+
status: string;
|
|
202
|
+
}
|